Why is Haskell throwing a 'cannot construct infinite type' error?
-
20-09-2019 - |
Question
I wrote the following code in Haskell to compute the dot product of two vectors, but cannot compile it due to the following error:
cannot construct infinite type: a = [a] When generalising the type(s) for dot'
dot :: (Num a) => [a] -> [a] -> a
[] `dot` [] = 0
x@[xi,xs] `dot` y@[yi,ys] = xi*yi + (xs `dot` ys)
I've taken a look at this question in advance for guidance. As far as I can tell, the types are correct. x, y and the two []'s are lists, and the function returns a number.
What's wrong?
Solution
You're confusing the syntax for a two element list [x, y]
with the syntax for splitting a list into the first element and the rest of the list (x:y)
. Try this instead:
dot :: (Num a) => [a] -> [a] -> a
[] `dot` [] = 0
x@(xi:xs) `dot` y@(yi:ys) = xi*yi + (xs `dot` ys)
The @
patterns are also unnecessary, btw.
OTHER TIPS
Ganesh' answer is spot on. Let me briefly elaborate on the meaning of an "infinite type".
dot
has this type definition:
dot :: (Num a) => [a] -> [a] -> a
This means that dot
takes two lists of Num
elements and returns a Num
. Your definition includes this line:
x@[xi,xs] `dot` y@[yi,ys] = xi*yi + (xs `dot` ys)
Since, as Ganesh points out, [xi,xs]
is a list consisting of two elements, xi
and xs
should be Num
s. Same for yi
and ys
. But then they are passed as arguments to dot
:
xs `dot` ys
This means that xs
and ys
must be lists of Num
s. That leads to a contradiction.
Another way to look at this, is to for a moment forget about the type definition of dot
. This line,
x@[xi,xs] `dot` y@[yi,ys] = xi*yi + (xs `dot` ys)
states that dot
takes two lists whose elements are appropriate arguments to dot
. But the only way for that to make sense, is if these lists are infinitely nested. That is not allowed nor sensible.