Why is Haskell interpreting my Num type as Enum?
I am trying to compile the following function in Haskell to simulate the differentiation of a polynomial whose constants are given in a numeric list:
diff :: (Num a) => [a] -> [a]
diff [] = error "Polynomial unspecified"
diff coeff = zipWith (*) (tail coeff) [0..]
Haskell refuses to compile it, giving me the following reason:
Could not deduce (Enum a) from the context (Num a)
arising from the arithmetic sequence `0 .. ' at fp1.hs:7:38-42
Possible fix:
add (Enum a) to the context of the type signature for `diff'
In the third argument of `zipWith', namely `[0 .. ]'
In the expression: zipWith (*) (tail coeff) ([0 .. ])
In the definition of `diff':
diff coeff = zipWith (*) (tail coeff) ([0 .. ])
Why [0..]
does Haskell treat a list as an Enum type and how can I fix it. Keep in mind that I want to use lazy evaluation here, hence an infinite list.
source to share
[0..]
- syntactic sugar for enumFrom 0
, defined in the class Enum
. Since you want to generate a list a
with [0..]
, the compiler requires to a
be in a class Enum
.
You can either add Enum a
to the type signature of the function, or work around it by creating [0..] :: [Integer]
and using fromInteger
(which is defined in the class Num
) to get [a]
from that:
diff :: (Num a) => [a] -> [a]
diff [] = error "Polynomial unspecified"
diff coeff = zipWith (*) (tail coeff) (map fromInteger [0..])
source to share
Here's a quick summary of what the compiler sees when it looks at this function:
- [0 ..] is a list of things that have instances of Num and Enum. It must be Num because of "0" and it must be Enum because of ".."
- I am being asked to apply (*) to coeff and [0 ..] elements one by one. Since both arguments to (*) must be of the same type and [0 ..] is instantiated for Enum, coeff must also be instantiated for Enum.
- Mistake! The typical diff signature only mentions that coeff has an instance for Num, but I already figured it should at least have an instance for Enum too.
source to share