At my university, we recently held an exam that covered a bit of Haskell, and a simple warm-up question at the beginning asked the students to implement last :: [a] -> a
. We did not demand a specific behaviour for last []
.
This is a survey of various solutions, only covering those that are actually correct. I elided some variation in syntax (e.g. guards vs. if
-then
-else
).
Most wrote the naive and straightforward code:
last [x] = x
last (x:xs) = last xs
Then quite a few seemed to be uncomfortable with pattern-matching and used conditional expressions. There was some variety in finding out whether a list is empty:
last (x:xs)
| null xs == True = x
| otherwise = last xs
last (x:xs)
| length (x:xs) == 1 = x
| otherwise = last xs
last (x:xs)
| length xs == 0 = x
| otherwise = last xs
last xs
| lenght xs > 1 = last (tail xs)
| otherwise = head xs
last xs
| lenght xs == 1 = head xs
| otherwise = last (tail xs)
last (x:xs)
| xs == [] = x
| otherwise = last xs
The last one is not really correct, as it has the stricter type Eq a => [a] -> a
. Also we did not expect our students to avoid the quadratic runtime caused by using length
in every step.
The next class of answers used length
to pick out the right elemet, either using (!!)
directly, or simulating it with head
and drop
:
last xs = xs !! (length xs - 1)
last xs = head (drop (length xs - 1) xs)
There were two submissions that spelled out an explicit left folding recursion:
last (x:xs) = lastHelper x xs
where
= z
lastHelper z [] :ys) = lastHelper y ys lastHelper z (y
And finally there are a few code-golfers that just plugged together some other functions:
last x = head (reverse x)
Quite a lot of ways to write last
!
Have something to say? You can post a comment by sending an e-Mail to me at <mail@joachim-breitner.de>, and I will include it here.