我在ghci 7.6.3
中尝试了以下内容 prelude> let m = map
以上作品。没有来自GHCi的错误。
但后来我试过了,
prelude> let r = read
上面的代码在GHCi中引发了一个很大的错误。这就是我得到的错误,
*Main> let r = read
<interactive>:122:9:
No instance for (Read a0) arising from a use of `read'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Read IOMode -- Defined in `GHC.IO.IOMode'
instance Read BufferMode -- Defined in `GHC.IO.Handle.Types'
instance Read Newline -- Defined in `GHC.IO.Handle.Types'
...plus 30 others
In the expression: read
In an equation for `r': r = read
然后我试了,
prelude> let r = read :: Read a => String -> a
认为类型签名可能会解决问题。但话说回来,我从GHCi那里得到了一个错误。确切的错误如下,
*Main> let r = read :: Read a => String -> a
<interactive>:123:9:
No instance for (Read a0) arising from an expression type signature
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Read IOMode -- Defined in `GHC.IO.IOMode'
instance Read BufferMode -- Defined in `GHC.IO.Handle.Types'
instance Read Newline -- Defined in `GHC.IO.Handle.Types'
...plus 30 others
In the expression: read :: Read a => String -> a
In an equation for `r': r = read :: Read a => String -> a
*Main>
有人可以告诉我发生了什么事吗?
感谢。
答案 0 :(得分:7)
这是单态限制的一个例子。默认情况下,不允许绑定多态值,因为看起来r
的值只应计算一次,但实际上每次调用它都会重新计算。
在这种情况下,read
是多态的,因为它有一个隐式参数,用于传递Read
类型类的字典,因此每次都需要重新计算r
。 map
是单态的,因为它没有任何类型类限制。
如果您改为将其写为
let r x = read x
将被允许。
您还可以添加非多态类型签名:
let r = read :: String -> Int
这使得它可以为r
的单个实例计算Read
一次。
带有类型签名的正常声明也不受单态限制的限制,因此您可以像这样编写它将被允许。
r :: Read a => String -> a
r = read
您也可以使用-XNoMonomorphismRestriction
选项或将{-# LANGUAGE NoMonomorphismRestriction #-}
添加到文件顶部来简单地关闭单态限制。通常认为这样做是安全的,尽管它会对性能产生负面影响。