Haskell中的succ:模糊类型变量

Arc*_*gel 0 haskell

我想编写一个函数mapsucc,它生成列表中每个项的后继.很容易:

    mapsucc xs = map succ xs
Run Code Online (Sandbox Code Playgroud)

工作得很好.我想我可以使用Currying来使这个定义更短:

    mapsucc = map succ
Run Code Online (Sandbox Code Playgroud)

但我得到:

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
Run Code Online (Sandbox Code Playgroud)

现在,我不清楚为什么curried版本应该是模糊的,相反,为什么具有显式参数的那个不是.

另外,如果从ghci我使用let声明mapsucc,它可以完美地工作:

Prelude> let mapsucc = map succ
Prelude> mapsucc "hello"
"ifmmp"
Run Code Online (Sandbox Code Playgroud)

如果我重新定义succ,行为相同:

mysucc x = succ x
Run Code Online (Sandbox Code Playgroud)

完美的,同时

mysucc = succ
Run Code Online (Sandbox Code Playgroud)

给出了同样的错误:

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
Run Code Online (Sandbox Code Playgroud)

而且,如果我通过let定义了ghci中的mysucc,它可以完美地运行:

Prelude> let mysucc = succ
Prelude> mysucc 3
4
Run Code Online (Sandbox Code Playgroud)

Pau*_*son 5

像你之前的许多人一样,你被可怕的单态限制所困扰.对此的规则大致如下:

  • 如果值具有显式参数,那么它将以您期望的方式自动变为多态.这就是你的第一个版本有效的原因:它有类型

mapsucc :: Enum b => [b] - > [b]

  • 在ghc(但不是ghci)中,如果值没有显式参数(比如你的第二个版本),那么它不是多态的.所以ghc试图弄清楚它是什么类型b,并发现它不能.因此错误消息.

  • 在ghci中没有单态限制,所以你的第二个例子在那里工作,它与第一个有相同的类型.

有关详细信息,包括此规则存在的原因的说明,请参阅此处.