阅读vs ghci中的地图

时间:2013-06-24 12:26:19

标签: haskell ghci

我在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> 

有人可以告诉我发生了什么事吗?

感谢。

1 个答案:

答案 0 :(得分:7)

这是单态限制的一个例子。默认情况下,不允许绑定多态值,因为看起来r的值只应计算一次,但实际上每次调用它都会重新计算。

在这种情况下,read是多态的,因为它有一个隐式参数,用于传递Read类型类的字典,因此每次都需要重新计算rmap是单态的,因为它没有任何类型类限制。

如果您改为将其写为

let r x = read x

将被允许。

您还可以添加非多态类型签名:

let r = read :: String -> Int

这使得它可以为r的单个实例计算Read一次。

带有类型签名的正常声明也不受单态限制的限制,因此您可以像这样编写它将被允许。

r :: Read a => String -> a
r = read

您也可以使用-XNoMonomorphismRestriction选项或将{-# LANGUAGE NoMonomorphismRestriction #-}添加到文件顶部来简单地关闭单态限制。通常认为这样做是安全的,尽管它会对性能产生负面影响。