Banging around in ghci
, I happened to notice that the expression (*) 1 [1..5]
apparently has a valid type.
:t (*) 1 [1..5]
(*) 1 [1..5] :: (Enum t, Num [t], Num t) => [t]
Apparently it is a list with several type constraints, including Num [t]
which looks impossible to me, like it should give an error.
How is this the type of the expression? Why does ghci
's :t
command not give an error here?
Let's look at how these constraints come to be to explain the type.
In Haskell a literal number is replaced with a call to fromInteger
(or fromRational
if it has a decimal point or an 'e' in it). This way one can write '1' and have it be float or a double or an int or whatever. The type of fromInteger
is
fromInteger :: Num a => a
So 1
gets desugared to fromInteger (1::Integer)
which has type Num t => t
In Haskell the syntax [a..b]
is converted into the call enumFromTo a b
and the type is enumFromTo :: Enum a => a -> a -> [a]
. Putting these together we get
[1..5] == enumFromTo (fromInteger 1) (fromInteger 5) :: (Enum a, Num a) => [a]
Now the type of (*)
is Num b => b -> b -> b
so we combine these all together to get:
(Num t,
Num a,
Enum a,
Num b,
t~b,
[a]~b) => b
Note that a~b
means the types a
and b
are the same. Combining these gives the type
(Num a, Enum a, Num [a]) => [a]