Haskell中`Num`实例的划分

时间:2018-01-19 14:52:18

标签: haskell type-conversion division

请考虑以下GHCI的摘录:

Prelude> :t sum [1,2,3]
sum [1,2,3] :: Num a => a
Prelude> :t fromIntegral (length [1,2,3])
fromIntegral (length [1,2,3]) :: Num b => b
Prelude> :t sum [1,2,3] / fromIntegral (length [1,2,3])
sum [1,2,3] / fromIntegral (length [1,2,3]) :: Fractional a => a

我了解sum [1,2,3]fromIntegral (length [1,2,3])都是Num的实例。令我困惑的是,为什么编译器将操作数转换为Fractional?我认为数字转换必须在Haskell中明确。

谢谢!

1 个答案:

答案 0 :(得分:6)

  

我认为数字转换必须在Haskell中明确。

这是正确的,但这里我们有数字文字。如果你写2本身就是IntInteger。那时我们不知道。

如果我们然后编写2 / 3,那么Haskell将推导出我们使用函数(/) :: Fractional a => a -> a -> a,因此得出结论:23应该是{{1在这种情况下,它将使用浮点解析器来解析Fractional文字。

如果您明确声明22,那么它就会出错:

Int

因此,通过强制Haskell使用Prelude> (2 :: Int) / 3 <interactive>:4:1: error: • No instance for (Fractional Int) arising from a use of ‘/’ • In the expression: (2 :: Int) / 3 In an equation for ‘it’: it = (2 :: Int) / 3 ,Haskell认为无法将其解析为支持Int函数的类型。

现在,如果我们分析(/),请更具体地说明您的问题。 sum [1,2,3]的类型为sum,因此如果列表中的元素为sum :: Num a => [a] -> a,则Fractional也会有sum ...类型。

对于分母,您实际进行显式转换。的确,你写Fractional。现在fromIntegral (length [1,2,3])会返回length :: [a] -> IntInt会将任何fromIntegral类型转换为通用Integral类型。因此,它可以将Num转换为Int