Reputation: 145
I'm reading through Real World Haskell and one of the exercises is to construct a function lastButOne, which simply returns the second to last element of a list.
My code so far:
lastButOne xs = if null xs || length xs == 1
then []
else if length xs == 2
then head xs
else lastButOne (tail xs)
My problem: The input should be a list, which then returns an empty list if it is either nonempty or is of length 1, and in other cases returns the second to last element. However, I get an error when I input a list. I don't get any errors when I input a second order nested list.
I suspected something was wrong with the type signature, and when I call the type signature, it returns
lastButOne :: [[a]] -> [a].
But I want the type signature to be [a] -> a
. I've stared at this function for a while and have explored other posts, but I can't seem to figure out why the type signature is [[a]] -> a
. Any hints would be appreciated.
Upvotes: 2
Views: 97
Reputation: 16224
You can acomplish that with pattern matching like:
lastButOne :: [a] -> a
lastButOne [] = error "not elements"
lastButOne [x] = x
lastButOne [x,_] = x
lastButOne (x:xs) = lastButOne xs
Upvotes: 5
Reputation: 196
You may explicitly declare your function's type signature by adding lastButOne :: [a] -> [a]
to your code. The function will then expect xs to be a list.
But then we would meet another error: the fact that one of the outputs of your function (head xs
) isn't in fact a list [a]
, but rather an element a
.
A similar error message will pop up if you add the signature lastButOne :: [a] -> a
, but this time because []
is not an element of type a
.
A simple solution might be to return your second to last element inside a list, using [head xs]
as an output.
Upvotes: 1