Haskell 了解a/b为什么不';不起作用,但fromInteger a/fromInteger b起作用

Haskell 了解a/b为什么不';不起作用,但fromInteger a/fromInteger b起作用,haskell,Haskell,在Haskell中,这是有效的: ghci>5/2 2.5 太好了。但是如果我给变量赋值5和2 Main> let a = 5 Main> let b = 2 Main> a/b <interactive>:68:2: No instance for (Fractional Integer) arising from a use of `/' Possible fix: add an instance declaration fo

在Haskell中,这是有效的:

ghci>5/2
2.5
太好了。但是如果我给变量赋值5和2

Main> let a = 5
Main> let b = 2
Main> a/b
<interactive>:68:2:
    No instance for (Fractional Integer)
      arising from a use of `/'
    Possible fix: add an instance declaration for (Fractional Integer)
    In the expression: a / b
    In an equation for `it': it = a / b
Main>
fromInteger怎么了?为什么我需要它来完成这项工作?

这是工作中的关键。
a
b
的类型默认为
Integer
,这显然不能与
/
一起使用,因为它只适用于
分数类型

您可以通过在定义
a
b
时添加类型注释来解决此问题:

> let a = 5 :: Double
> let b = 2 :: Double
> a / b
2.5
或者您可以使用默认为双精度的十进制文字:

> let a = 5.0
> let b = 2.0
> a / b
2.5
如果这三行是一起进行类型检查的,就像它们在编译模块中一样,或者如果您输入了

let a = 5; b = 2 in a / b
但是,当在GHCi中单独键入时,它们会一次检查一个类型,因此在计算
let a=5
时应用的默认值会选择
Integer
,因为此时
a
的唯一约束是
Num
。它不知道我们以后使用
/
时需要的
分数约束

Prelude> :t 5 / 2            -- The type is inferred to be a fractional
5 / 2 :: Fractional a => a
Prelude> :t (/)              -- ...because the type of (/)
(/) :: Fractional a => a -> a -> a
Prelude> let x = 5
Prelude> let y = 2
Prelude> :t x                -- In GHC there are addditional type defaulting rules
x :: Integer                 -- Instead of Num a => a, a lone integral is typed as `Integer`
Prelude> :t y
y :: Integer
Prelude> :i Fractional       -- Notice that 'Integer' is not an instance of 'Fractional'
class Num a => Fractional a where
  (/) :: a -> a -> a
  recip :: a -> a
  fromRational :: Rational -> a
    -- Defined in `GHC.Real'
instance Fractional Float -- Defined in `GHC.Float'
instance Fractional Double -- Defined in `GHC.Float'
简言之?GHCi type将let绑定变量默认为
整数
,它没有
分数
实例(因为
整数
不是分数)。在通过ghc编译的Haskell程序中,类型将统一


编辑:我应该补充一点,我试图指出,如果在更大的上下文中,而不是在GHCi中,如何将
let x=4
推断为Double。作为对Hammar答案的回应,这不仅仅是单态,还与类型缺省有关
a
b
可以是单形态的
,如在GHC编译函数中,但是,由于单态限制和逐行类型推断的组合,我们无法得到
x::Num a=>a
x::Double
——这两者都适合您的需要。

正如其他人所指出的,这是。与注释所有类型(如
(a::Double)/(b::Double)
)不同,我发现关闭它更容易:

Prelude> :set -XNoMonomorphismRestriction
Prelude> let a = 5
Prelude> let b = 2
Prelude> a / b
2.5

(您可以在中保存
:设置
操作,这样您就不必每次都编写它了)

您在哪里找到了
-XNoMonomorphismRestriction
,对于我的其他问题,我在哪里可以找到更多类似它的内容?@Imray:GHC用户指南既长又密集,但充满了这样的有用工具。尝试Haskell维基也有很多很好的信息,但它更分散。
Prelude> :set -XNoMonomorphismRestriction
Prelude> let a = 5
Prelude> let b = 2
Prelude> a / b
2.5