'Fastest way to get the last element of a list in Haskell
What is the fastest way to get the last element of a list in Haskell. Also in next iteration, I want to remove first and last element of the list. What is the most elegant way to do it? I am trying list comprehension, but that does not look very efficient!
Solution 1:[1]
You can use the last function to get the last element of a list.
As for how to remove the first and last elements, you could use (init . tail), but I don't know how efficient that is.
I think this image from Learn You A Haskell shows the list functions fairly well:
Solution 2:[2]
I'll post the Prelude implementation since it hasn't been posted yet:
listLast :: [a] -> a
listLast [x] = x --base case is when there's just one element remaining
listLast (_:xs) = listLast xs --if there's anything in the head, continue until there's one element left
listLast [] = error "Can't do last of an empty list!"
Note that I changed the function name to listLast so that it can be run without conflicting with normal Prelude. You could, of course, do import Prelude hiding(last).
Solution 3:[3]
To remove first and last:
take (len(l)-2) (drop 1 l)
or maybe
init (drop 1 l)
This also results in almost optimal code.
Solution 4:[4]
This answer focuses on dealing with weird conditions (like empty lists) in a maximally flexible way, and on building up bigger functions from smaller ones using some library functions. It's not the best answer for someone first learning about lists, but rather a couple steps past that.
For the following, you will need
import Control.Monad ((>=>))
and you will need to either use GHC 7.10 and import Data.List (uncons) or define
uncons :: [a] -> Maybe (a, [a])
uncons [] = Nothing
uncons (x:xs) = Just (x,xs)
You can write a safe form of init like this:
init' :: [x] -> Maybe [x]
init' = foldr go Nothing
where
go x mxs = Just (maybe [] (x:) mxs)
A version of tail can be written
tail' :: [a] -> Maybe [a]
tail' = fmap snd . uncons
So then you can get a maybefied
trim' :: [a] -> Maybe [a]
trim' = init' >=> tail'
The >=> is a sort of backwards monadic composition. init' >=> tail' is a function that applies init' to its argument to get a Maybe [a]. If it gets Nothing, it returns that. If it gets Just xs, it applies tail' to xs and returns that.
From this, you can easily make a trimmer that trims lists with 0, 1, or 2 elements down to empty lists:
trim :: [a] -> [a]
trim = maybe [] id . trim'
Solution 5:[5]
last' :: [a] -> a
last' ys = foldl1 (\_ -> \x -> x) ys
It is O(n), just like the built in library function list.
Solution 6:[6]
(head.reverse) [1..100]
Is an alternative to last to get the last element.
drop 1 (take (length [1..100] - 1) [1..100])
removes the first and last list element. The source for drop and take look like it might be faster than (init . tail).
(reverse.drop 1) ((reverse.drop 1) [1..100])
is another variant. But I guess slower because of the double reversal.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | George |
| Solution 2 | |
| Solution 3 | nulvinge |
| Solution 4 | |
| Solution 5 | Abhijit Gupta |
| Solution 6 | orkoden |

