Gen Tan
Gen Tan

Reputation: 918

With Maybe | Just data type, Cannot construct the infinite type

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

Answers (1)

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

Related Questions