2

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?

7
  • 6
    secondLast [x, _] = x returns an a, not a Maybe a. Commented Sep 18, 2020 at 9:04
  • 3
    Hint: what's the type of 'a'? What's the type of Just 'a'? Commented Sep 18, 2020 at 9:05
  • My best understanding: 'a' is a Maybe data type, can be represented with Nothing or a. When we use a, we are returning a Nothing | Just a value. However, Haskell expects an explicit Just a if the only thing that can be returned is an a type? Commented Sep 18, 2020 at 9:13
  • 4
    Type a isn't equivalent type Maybe a. They are different types. Function secondLast take a list of values of type a and return a value of type Maybe a, so you can't return value of type a instead. But you know that values Nothing and Just a where a is value of type a have type Maybe a where a is type. Only way to return value a of type a from function is constructing a value of type Maybe a through calling type construction Just with the value you want return (in this case it is a) Commented Sep 18, 2020 at 9:30
  • @GenTan exactly - all you need to do is change the a to Just a, so the function always returns a value of type Maybe a. Commented Sep 18, 2020 at 10:01

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.