[Haskell-cafe] operations on lists with continuations

Evan Laforge qdunkan at gmail.com
Wed Mar 2 07:51:26 CET 2011

I have a few functions for operating on lists that take continuations:

-- | Like takeWhile but with a continuation, so you can chain takes without
-- copying.
takeWhileThen :: (a -> Bool) -> ([a] -> [a]) -> [a] -> [a]
takeWhileThen _ _ [] = []
takeWhileThen f cont (x:xs)
    | f x = x : takeWhileThen f cont xs
    | otherwise = cont (x:xs)

But of course this isn't enough, then I start wanting a takeThen.  And
then a filterThen.  That makes me think plain explicit recursion would
be clearer, but the problem I have with that is that it has an
imperative feel.  What I mean by that is that the result is a product
of the changing state of the recursing function, and it's
non-composable.  E.g.

filterUntil start end msgs = go
    go [] = []
    go (m:ms)
        | msg_start m >= start = takeWhile ((<end) . msg_start) (m : ms)
        | condition m = m : go ms
        | otherwise = go ms

Whereas with filterThen I can write:

filterUntil start end = filterThen condition ((>=start) . msg_start) .
takeWhile ((<end) . msg_start)

This looks much more functional to me, and can be composed:

filterUntilPlus1 start end = filterThen condition ((>=start) .
msg_start) $ takeWhileThen ((<end) . msg_start) $ take 1

So my question is, am I about to discover this already exists in the
Prelude, or is unnecessary because of something I'm overlooking?  I
imagine it must be a special case of some kind of generalization,
right?  Surely someone has thought of this and taken it much further
than I have.  I suppose this starts to look like maybe a CPS version
of a parser... but it seems lighter-weight for simple tasks.

More information about the Haskell-Cafe mailing list