does this mean it takes 1 arg or 2?
To answer that, first note that =>
and ->
are different. Then, look just at the part of the signature to the right of the =>
:
a -> b
A function with such a type would have just one argument, and so does fromIntegral
. To the left =>
you do not find arguments, but type constraints. If the type of fromIntegral
was a -> b
then it would take an argument of any type and produce a result of any other type. The (Integral a, Num b)
constraint restricts the types, so that the type of argument has to be an instance of the Integral
class (that is, the argument has to be an integral number) and the result has to be an instance of Num
(that is, the result has to be some kind of number).
You need fromIntegral
whenever you have an integral number and need to use it with a function that expects a non-integral numeric argument. A simple example would be adding an Integer
to a Double
. But then, how come does the following work without fromIntegral
?
Prelude> 4 + 3.2
7.2
The answer lies in the literals:
Prelude> :t 4
4 :: Num a => a
4
is not an Int
or an Integer
, but a polymorphic Num
value. When placed in a complex expression, it gets a type appropriate to its surroundings. Given:
Prelude> :t 3.2
3.2 :: Fractional a => a
Prelude> :t (+)
(+) :: Num a => a -> a -> a
The 4
in 4 + 3.2
becomes subject to the Fractional
constraint of 3.2
, and so:
Prelude> :t 4 + 3.2
4 + 3.2 :: Fractional a => a
If there are no further constraints anywhere else in a program, a polymorphic Fractional
value will default to Double
. A brief explanation of such defaulting is given by the answer to this question.