Reputation: 23
I'm a Haskell beginner working through an exercise in Chapter 2 of Real World Haskell, where you write a function that returns the second-to-last element of a list.
I've written the following function to attempt to solve this:
-- file: \Learn Haskell\lastButOne.hs
lastButOne xs = if length xs == 2
then head xs
else lastButOne tail xs
What I don't understand is this error the compiler throws:
lastButOne.hs:2:1: error:
• Couldn't match type ‘[a] -> [a]’ with ‘[t]’
Expected type: ([a] -> [a]) -> [t] -> t
Actual type: [t] -> t
• Relevant bindings include
lastButOne :: ([a] -> [a]) -> [t] -> t (bound at lastButOne.hs:2:1)
From what I understand, ghci thinks my function ought to have a different type than it does, but I don't understand why that's happening, or how I can fix it.
Edit: Thanks for the answers! I've updated my code to:
-- file: \Learn Haskell\lastButOne.hs
lastButOne xs = if length xs == 2
then head xs
else if length xs < 2
then error "This list does not have a second-to-last element."
else lastButOne (tail xs)
This eliminates the error where tail xs
is being interpreted as two arguments, rather than a single expression. I also added some code that ensures the list isn't too short. Willem Van Onsem's solution is nicer, but as an exercise I thought I'd come up with a solution that only used the concepts introduced so far in the book.
Upvotes: 2
Views: 133
Reputation: 477533
The problem is with the line:
else lastButOne tail xs
It should be:
else lastButOne (tail xs)
Otherwise ghci
things that you give lastButOne
two arguments: tail
and xs
.
You can however make the code more elegant:
lastButOne [x,_] = x
lastButOne xs = lastButOne $ tail xs
Furthermore you will have to find a way to resolve lists with one element, and the empty list. Right now the function will start looping. An idea could be to to error on these lists, like:
lastButOne [x,_] = x
lastButOne (_:xs) = lastButOne xs
lastButOne [] = error "The list has no last but one element."
Upvotes: 3