简体   繁体   中英

Division in Haskell on `Num` instances

Consider the following excerpt from 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

I understand that both sum [1,2,3] and fromIntegral (length [1,2,3]) are instances of Num . What puzzles me is, why does the compiler convert the operands to Fractional ? I thought that numeric conversions had to be explicit in Haskell.

Thanks!

I thought that numeric conversions had to be explicit in Haskell.

That is correct, but here we have numerical literals . If you write 2 , that is not per se an Int , or an Integer . We do not know it at that point.

If we then for instance write 2 / 3 , then Haskell will derive that we use a function (/) :: Fractional a => a -> a -> a , so it concludes that 2 and 3 should be Fractional , so in this case it will use a floating point parser to parse the 2 literal.

In case you would however explicitly state that 2 is an Int , then it will go wrong:

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

So by forcing Haskell to use an Int , Haskell sees no way to parse it as a type that supports the (/) function.

Now to make it more specific to your question, if we analyze sum [1,2,3] . sum has type sum :: Num a => [a] -> a , so in case the elements of the list are Fractional , then the sum ... has also a Fractional type.

For the denominator you actually make an explicit conversion. Indeed, you write fromIntegral (length [1,2,3]) . Now length :: [a] -> Int returns an Int . The fromIntegral will convert any Integral type to a generic Num type. So it can convert an Int to a Float .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM