Why does Haskell interpret my Num type as an Enum?
I'm trying to compile the following function in Haskell to mimic differentiation of a polynomial whose constants are specified in a numerical 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 ded开发者_开发问答uce (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 is Haskell treating the [0..]
list as an Enum type, and how can I fix this. Bear in mind that I want to take advantage of lazy evaluation here, hence the infinite list.
[0..]
is syntactic sugar for enumFrom 0
, defined in class Enum
. Because you want to generate a list of a
s with [0..]
the compiler demands a
to be in class Enum
.
You can either add the Enum a
to the type signature of the function or work around it by generating a [0..] :: [Integer]
and using fromInteger
(which is defined in class Num
) to get a [a]
from that:
diff :: (Num a) => [a] -> [a]
diff [] = error "Polynomial unspecified"
diff coeff = zipWith (*) (tail coeff) (map fromInteger [0..])
The correct type of diff
has to be
diff :: (Num a, Enum a) => [a] -> [a]
because the usage of [x..]
requires the type to instantiate Enum
.
[0..]
is shorthand for enumFrom 0
See here
Here's a quick summary of what the compiler sees when it looks at this function:
- [0..] is a list of things that have both Num and Enum instances. It has to be a Num because of the '0', and it has to be an Enum because of the '..'
- I'm being asked to apply (*) to the elements of coeff and [0..] one by one. Since both arguments to (*) have to be the same type and [0..] has an instance for Enum, coeff must also have an instance for Enum.
- Error! The type signature of diff only mentions that coeff has an instance for Num, but I've already determined that it must at least have an instance for Enum too.
精彩评论