为什么有些操作员在分配时会更改类型?

Dav*_*ett 3 haskell types ghci

当我问+运算符的类型时,它就像你期望的那样

Prelude> :t (+)
(+) :: Num a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

当我将操作符分配给变量时,类型签名会发生变化

Prelude> let x = (+)
Prelude> :t x
x :: Integer -> Integer -> Integer
Run Code Online (Sandbox Code Playgroud)

为什么操作员的类型在分配时会发生变化?

J. *_*son 8

这是"可怕的单态限制".基本上,当你定义一个

  1. 新的顶级名称,即
  2. 看起来不像函数定义

然后,默认情况下,Haskell试图变得聪明并为它选择一个不完全通用的类型.原因最初是为了让Haskell更容易使用(没有它可能更容易编写带有模糊类型的程序),但最近它似乎只是让每个人都绊倒,因为它是非常意外的行为.

决议?

  1. 使用GHC 7.8.版本7.8后,GHCi会话自动...
  2. 使用-XNoMonomorphismRestriction,关闭此行为,或
  3. 提供类型注释

    let { x :: Num a => a -> a -> a; x = (+) }
    
    Run Code Online (Sandbox Code Playgroud)

在普通的Haskell代码中,最强烈推荐方法(3).使用GHCi时,(1)和(2)更方便.