I am learning Haskell at the moment and have come to a bit of a standstill. I'm trying to write a function that takes a predicate p
and a list xs
and returns the list of those elements of xs
which immediately follow an element which passes the predicate p
. Here is what I have :
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter x (y:ys) =
if x y
then (map head [ys])
else
afterFilter x (tail ys)
test input : afterFilter (<0) [-4,7,-4,-8,3,-3,-6,0,-9,-1]
output : [7]
The trick is to pull two elements out of the input list by pattern-matching two cons cells. If the first element passes the predicate, we stick the second on the output. But don't forget to stick the second element back on the input list when you make the recursive call.
However, a higher-level - and much more Haskellish - way to approach the problem would be to break it down into a pipeline of operations.
zip
, so we have a list of(element, next)
pairs.filter
to drop the pairs for whichelement
does not pass the predicate.map
to extract thenext
part of each surviving pair.So the code looks like this:
Or, written in point-free style:
Functions built with the composition operator
.
are read right-to-left: firstpairWithSuccessors
, thenfilter (p . fst)
, thenmap snd
over the result.GHC is good at working with lists: when compiled with optimisations, both approaches should produce roughly the same machine code - that is, there's no performance cost to the high-level solution