lastButOne xs = if null xs
then 0
else xs !! ((length xs) - 2)
I am reading Chapter 2. Types and Functions . I am doing one of their challenge questions and was asked to get the second to last item in a list.
My solution was the code attached. I don’t know what to return if a list is empty. Should I throw an error. if the list I pass in is empty.
I also noticed I recieved an error message of
• Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a. Num [a] => [a]
When I returned 2 different types from the function. What does the error mean ?
I produced this solution with the code below.
lastButOne xs = if null xs
then xs
else xs !! ((length xs) - 2)
lastButOne xs = if (length xs) < 3
then error "list is to short"
else xs !! ((length xs) - 2)
will work equally well. null xs isn’t some special thing you need to check first.
Also, 3 is overkill, (length xs) < 2 is the correct condition because length xs = 2 means xs !! 0 is what you end up, with is fine. A 2-long list is not, in fact, too short.
It’s really easy to do these off-by-one errors with hard-coded numbers like your 2…so it’s better to not write numbers at all! I would instead reverse the list and then use plain pattern matching. See if you can complete this:
lastButOne xs = case reverse xs of
-- pattern -> error "list is to short"
-- pattern binding `x` -> x
OK, getting close! I would make sure you have -Wall on. you will then see you have some unmatched patterns. I would also write a few tests (don’t bother with any fancy test suite library, just write down some (expected, result) pairs to poke at in GHCi).
Thank you again for the added challenges. I don’t understand what you mean by -Wall. Is this some sort of catch all ? Can I find this in some sort of documentation ?