I want to filter the last element of a list that does not satisfy a property. An example would be
smallerOne :: a->Bool
smallerOne x = x < 1
What you want to do is reverse the list and take elements while they dont satisfy the property. The moment an element satisfies a property, you drop it and take the rest of the list. This translates pretty naturally into haskell code.
filterLast :: (a -> Bool) -> [a] -> [a]
filterLast p = reverse . uncurry (++) . dropHeadSnd . span p . reverse
where
dropHeadSnd (x, y) = (x, tail' y)
tail' [] = []
tail' (x:xs) = xs
The (++) reduces the efficiency of your code and while its not the asymptotic efficiency, eliminating the (++) will improve your performance.
filterLast :: (a -> Bool) -> [a] -> [a]
filterLast p = reverse . helper . reverse
where
helper [] = []
helper (x:xs) | p x = xs
| otherwise = x:helper xs
Both of the above functions use two iterations over the list. However remember with recursion you can get information from both behind and ahead. We use the recursive call to figure out if there are any subsequent elements for which 'p' is satisfied.
f :: (a -> Bool) -> [a] -> [a]
f p = snd . helper
where
helper [] = (False, [])
helper (a:as) | p a && flag = (flag, a:as')
| p a = (True, as')
| otherwise = (flag, a:as')
where
(flag, as') = helper as