我想编写一个函数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
现在,我不清楚为什么咖喱版应该含糊不清,为什么显而易见的参数不是。
另外,如果从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
答案 0 :(得分:5)
和你之前的许多人一样,你被可怕的单态限制所困扰。对此的规则大致如下:
mapsucc :: Enum b => [b] - >并[b]
在ghc(但不是ghci)中,如果值没有显式参数(比如你的第二个版本),那么它不是多态的。所以ghc试图弄清楚b
是什么类型,并发现它不能。因此错误信息。
在ghci中没有单态限制,所以你的第二个例子在那里工作,它的类型与第一个相同。
有关详细信息,包括此规则存在原因的说明,see here。
答案 1 :(得分:3)
你正在遇到所谓的单态限制。
较新的GHC版本提供了稍微好一点的错误消息:
test.hs:1:9: error:
• Ambiguous type variable ‘b0’ arising from a use of ‘succ’
prevents the constraint ‘(Enum b0)’ from being solved.
Relevant bindings include f :: [b0] -> [b0] (bound at test.hs:1:1)
Probable fix: use a type annotation to specify what ‘b0’ should be.
These potential instances exist:
instance Enum Ordering -- Defined in ‘GHC.Enum’
instance Enum Integer -- Defined in ‘GHC.Enum’
instance Enum () -- Defined in ‘GHC.Enum’
...plus six others
...plus two instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the first argument of ‘map’, namely ‘succ’
In the expression: map succ
In an equation for ‘f’: f = map succ
|
1 | f = map succ
| ^^^^
正如你所看到的,这里它直接给出了写一个类型签名的建议,这在这里确实是正确的解决方案。