在 `Num` 实例上除法 Haskell
Division in Haskell on `Num` instances
考虑 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.
中的数字转换必须明确
谢谢!
I thought that numeric conversions had to be explicit in Haskell.
这是正确的,但这里我们有 数字文字。如果你写 2
,那就是 而不是 本身是一个 Int
,或者一个 Integer
。我们当时还不知道。
如果我们再比如写2 / 3
,那么Haskell会得出我们使用的函数(/) :: Fractional a => a -> a -> a
,所以得出2
和3
应该是 Fractional
,所以在这种情况下它将使用浮点解析器来解析 2
文字。
如果您明确声明 2
是一个 Int
,那么它将出错:
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
,Haskell 无法将其解析为支持 (/)
函数的类型。
现在,如果我们分析 sum [1,2,3]
,请更具体地针对您的问题。 sum
具有类型 sum :: Num a => [a] -> a
,因此如果列表的元素是 Fractional
,则 sum ...
也具有 Fractional
类型。
对于分母,您实际上进行了 显式 转换。确实,你写fromIntegral (length [1,2,3])
。现在 length :: [a] -> Int
returns 一个 Int
。 fromIntegral
会将任何 Integral
类型转换为通用 Num
类型。所以它可以将 Int
转换为 Float
.
考虑 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.
谢谢!
I thought that numeric conversions had to be explicit in Haskell.
这是正确的,但这里我们有 数字文字。如果你写 2
,那就是 而不是 本身是一个 Int
,或者一个 Integer
。我们当时还不知道。
如果我们再比如写2 / 3
,那么Haskell会得出我们使用的函数(/) :: Fractional a => a -> a -> a
,所以得出2
和3
应该是 Fractional
,所以在这种情况下它将使用浮点解析器来解析 2
文字。
如果您明确声明 2
是一个 Int
,那么它将出错:
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
,Haskell 无法将其解析为支持 (/)
函数的类型。
现在,如果我们分析 sum [1,2,3]
,请更具体地针对您的问题。 sum
具有类型 sum :: Num a => [a] -> a
,因此如果列表的元素是 Fractional
,则 sum ...
也具有 Fractional
类型。
对于分母,您实际上进行了 显式 转换。确实,你写fromIntegral (length [1,2,3])
。现在 length :: [a] -> Int
returns 一个 Int
。 fromIntegral
会将任何 Integral
类型转换为通用 Num
类型。所以它可以将 Int
转换为 Float
.