GHCI will give me a type for 1 ++ 2
:
$ ghci
GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :t 1 ++ 2
1 ++ 2 :: Num [a] => [a]
But this is obviously wrong. If I try and evaluate it, instead of just type check it, things correctly fail:
Prelude> 1 ++ 2
<interactive>:3:1:
No instance for (Num [a0])
arising from the literal `1'
Possible fix: add an instance declaration for (Num [a0])
In the first argument of `(++)', namely `1'
In the expression: 1 ++ 2
In an equation for `it': it = 1 ++ 2
What gives?
But this is obviously wrong.
No, it's completely correct.
The type of (++)
is
(++) :: [a] -> [a] -> [a]
and the type of integer literals is
1 :: Num n => n
So the type [a]
that an argument of (++)
must have is unified with the type Num n => n
that a literal has, giving
1 ++ 2 :: Num [a] => [a]
and if you have a list type with a Num
instance, that expression can also be evaluated.
But, by default, there is no Num
instance for list types available, so when you try to evaluate it, ghci complains that it finds no Num
instance for [a]
.
For example:
Prelude> instance Num a => Num [a] where fromInteger n = Data.List.genericReplicate n 1
<interactive>:2:10: Warning:
No explicit method or default declaration for `+'
In the instance declaration for `Num [a]'
<interactive>:2:10: Warning:
No explicit method or default declaration for `*'
In the instance declaration for `Num [a]'
<interactive>:2:10: Warning:
No explicit method or default declaration for `abs'
In the instance declaration for `Num [a]'
<interactive>:2:10: Warning:
No explicit method or default declaration for `signum'
In the instance declaration for `Num [a]'
Prelude> 1 ++ 2 :: [Int]
[1,1,1]
Because someone could define lists to be treated as numbers:
instance Num a => Num [a] where
(+) = zipWith (+)
(*) = zipWith (*)
(-) = zipWith (-)
negate = map negate
abs = map abs
signum = map signum
fromInteger x = [fromInteger x]
Then what you typed would work, since
1++2 == fromInteger 1++fromInteger 2 == [1]++[2]
(Not that this Num
instance would make much sense..)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With