[英]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中是明確的。
謝謝!
我認為數字轉換必須在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
返回一個Int
。 fromIntegral
會將任何Integral
類型轉換為通用Num
類型。 因此它可以將Int
轉換為Float
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.