Reputation: 918
I have a function that is supposed to return the 2nd last element of a list. Function will return Nothing if nothing can be returned.
data Maybe a = Nothing | Just a
secondLast :: [a] -> Maybe a
secondLast [] = Nothing
secondLast [a, _] = a
secondLast (_:xs) = secondLast xs
However on compiling i receive this error
* Occurs check: cannot construct the infinite type: a ~ Maybe a
* In the expression: a
In an equation for `secondLast': secondLast [a, _] = a
* Relevant bindings include
a :: a (bound at <interactive>:92:13)
secondLast :: [a] -> Maybe a (bound at <interactive>:92:1)
What am i doing wrong here?
Upvotes: 2
Views: 111
Reputation: 2044
The different implementations of secondLast
have different return types. This is causing the compiler to try to make those types equivalent, which it cannot do.
secondLast []
returns Nothing
, which is of type Maybe a
. secondLast [a, b]
, on the other hand, returns a
, which is of type a
. The compiler, therefore, is trying to find a type that is equivalent to itself wrapped in the Maybe
monad.
The expression a ~ Maybe a
means "type a
is equivalent to type Maybe a
, which has no solution (aka the type cannot be constructed), so the compiler throws an error. It's an "infinite type" because its equivalence is in terms of itself.
To fix this error, you should change the second implementation to return Maybe a
like the first one:
secondLast [a, _] = Just a
Just
is the second constructor for Maybe
, so Just a
has the same type as Nothing
, namely Maybe a
. This will allow the type to resolve.
Your code is also missing the case where secondLast
receives a list of one element, so you should think about what should happen in that scenario.
Upvotes: 2