这个问题在这里已有答案:
我想编写一个函数mapsucc,它生成列表中每个项目的后继 . 很容易:
mapsucc xs = map succ xs
工作得很好 . 我想我可以使用Currying来使这个定义更短:
mapsucc = map succ
但我得到:
No instance for (Enum b0) arising from a use of ‘succ’
The type variable ‘b0’ is ambiguous
Relevant bindings include
mapsucc :: [b0] -> [b0] (bound at mapsucc.hs:1:1)
Note: there are several potential instances:
instance Enum Ordering -- Defined in ‘GHC.Enum’
instance Enum Integer -- Defined in ‘GHC.Enum’
instance Enum () -- Defined in ‘GHC.Enum’
...plus six others
In the first argument of ‘map’, namely ‘succ’
In the expression: map succ
In an equation for ‘mapsucc’: mapsucc = map succ
现在,我不清楚为什么curried版本应该是模糊的,相反,为什么具有显式参数的那个不是 .
另外,如果从ghci我使用let声明mapsucc,它可以完美地工作:
Prelude> let mapsucc = map succ
Prelude> mapsucc "hello"
"ifmmp"
如果我重新定义succ,行为相同:
mysucc x = succ x
完美,但同时
mysucc = succ
给出了同样的错误:
No instance for (Enum a0) arising from a use of ‘succ’
The type variable ‘a0’ is ambiguous
Relevant bindings include
mysucc :: a0 -> a0 (bound at mapsucc.hs:3:1)
Note: there are several potential instances:
instance Enum Ordering -- Defined in ‘GHC.Enum’
instance Enum Integer -- Defined in ‘GHC.Enum’
instance Enum () -- Defined in ‘GHC.Enum’
...plus six others
In the expression: succ
In an equation for ‘mysucc’: mysucc = succ
而且,如果我通过let定义了ghci中的mysucc,它可以完美地运行:
Prelude> let mysucc = succ
Prelude> mysucc 3
4
2 回答
像你之前的许多人一样,你被可怕的单态限制所困扰 . 对此的规则大致如下:
在ghc(但不是ghci)中,如果值没有显式参数(比如你的第二个版本),那么它不是多态的 . 所以ghc试图找出
b
是什么类型,并发现它不能 . 因此错误消息 .在ghci中没有单态限制,所以你的第二个例子在那里工作,它与第一个有相同的类型 .
有关详细信息,包括对此规则存在的原因的解释,see here .
你正在遇到所谓的单态限制 .
较新的GHC版本提供稍微更好的错误消息:
正如您所看到的,这里它直接给出了写一个类型签名的建议,这在这里确实是正确的解决方案 .