Say I wanted to remove all zeros at the end of a list:
removeEndingZeros :: (Num a, Eq a) => [a] -> [a]
removeEndingZeros (xs ++ [0]) = removeEndingZeros xs
removeEndingZeros xs = xs
This does not work because of the (++)
operator in the argument. How can I determine the end of a list through pattern-matching?
There is a function in Data.List
to do this:
dropWhileEnd :: (a -> Bool) -> [a] -> [a]
dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
So you can drop the trailing zeros with
dropWhileEnd (== 0)
Another, very similar, function can be implemented like this:
dropWhileEnd2 :: (a -> Bool) -> [a] -> [a]
dropWhileEnd2 p = foldr (\x xs -> if null xs && p x then [] else x : xs) []
dropWhileEnd2 p
has exactly the same semantics as reverse . dropWhile p . reverse
, but can reasonably be expected to be faster by a constant factor. dropWhileEnd
has different, non-comparable strictness properties than the others (it's stricter in some ways and less strict in others).
Can you figure out circumstances under which each can be expected to be faster?