Question

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 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 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.

Was it helpful?

Solution

[0..] is syntactic sugar for enumFrom 0, defined in class Enum. Because you want to generate a list of as 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..])

OTHER TIPS

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.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top