Haskell 如何获取函数类型定义中声明的枚举类型的最小值?
假设我想定义一个函数,它使用为给定类型定义的一个常量。我试过:Haskell 如何获取函数类型定义中声明的枚举类型的最小值?,haskell,Haskell,假设我想定义一个函数,它使用为给定类型定义的一个常量。我试过: minValue :: (Enum a,Bounded a) => a minValue = minBound::a 但是函数定义不知道a是Enum类型,因为声明中指定了Enum类型。两个合理的答案: 删除内部类型签名 minValue = minBound 虽然这是可行的,但它不能很好地“扩展”到需要做更多工作的更大的函数,在这些函数中,minBound使用哪种类型可能不太明显。这就导致我们 为类型变量启用词法范围。您可
minValue :: (Enum a,Bounded a) => a
minValue = minBound::a
但是函数定义不知道a是Enum类型,因为声明中指定了Enum类型。两个合理的答案:
minValue = minBound
虽然这是可行的,但它不能很好地“扩展”到需要做更多工作的更大的函数,在这些函数中,minBound
使用哪种类型可能不太明显。这就导致我们forall
关键字启动作用域;然后,该范围中的定义可以引用类型变量。因此:
{-# LANGUAGE ScopedTypeVariables #-}
minValue :: forall a. (Enum a, Bounded a) => a
minValue = minBound :: a
这里需要的是
ScopedTypeVariables
,其中minValue
中的a
类型签名与定义中使用的a
相同。然而,我怀疑您的用例不需要它。值minBound
是多态的,当Haskell中的某些内容是多态的时,通常称为site-polymorphic。这意味着调用方确定类型,而不是定义。例如,您可以编写如下内容
cycleBounded :: (Bounded a, Enum a, Eq a) => [a]
cycleBounded
= minBound
: map (\n -> if n == maxBound then minBound else succ n)
cycleBounded
然后你可以做一些类似于cycleBounded::[Bool]
的事情来得到与cycle[False,True]
等价的东西。但是,如果您想在比较之前使用n
上的fromnum
和maxBound
来摆脱Eq
约束,您会遇到一个问题,因为这样编译器就不知道maxBound
要使用什么a
,上下文中没有说明它必须使用与n
相同的类型,只是它是一个(枚举a,有界a)=>a
。这将是ScopedTypeVariables
的适当应用:
{-# LANGUAGE ScopedTypeVariables #-}
cycleBounded :: forall a. (Bounded a, Enum a, Eq a) => [a]
cycleBounded
= minBound
: map (\n -> if fromEnum n == fromEnum (maxBound :: a) then minBound else succ n)
cycleBounded
虽然有一些技巧可以让这些类型在不需要ScopedTypeVariables
的情况下实现统一,但大多数人可能会发现看到ScopedTypeVariables
和maxBound::a
比任何东西都更容易理解。为了完整性,以下是如何使其统一:
cycleBounded
= minBound
: map (\n -> let {m = maxBound;
x = [m, n] -- This forces `m` and `n` to have the same type
}
in if fromEnum n == fromEnum (head x)
then minBound
else succ n)
cycleBounded
在我看来,这是相当丑陋的