[Haskell-cafe] Enumerators, Enumeratees and Iterators

Ertugrul Soeylemez es at ertes.de
Tue Jun 28 11:14:36 CEST 2011

Sævar Berg <s.b.saevarsson at gmail.com> wrote:

> The first question is, I think, to be solved with enumeratees but I can't
> really grok how.
> Let's say I have an iteratee that consumes all input. Is it possible to
> implement an enumeratee or something else to stick between the enumerator
> and the iteratee to basically modify the input to the iteratee to only be a
> part of the input?

Yes, this is an enumeratee.  An enumeratee is neither a data producder
nor a consumer.  It is an iteratee, which feeds another iteratee with
input based on its own input, so it acts like a kind of map operation.

> enumFile "someFile" && printFileLines -- prints file with prepended line
> numbers
> enumFile "someFile" ?? onlyGet10Lines && printFileLines -- print only 10
> lines

In fact an enumeratee can split the input stream into lines.  Another
one can zip the stream with a list.  A final one can take 10 lines from
the stream.  The code would look like this (in the 'enumerator'

    enumFile "myFile.txt" $$
    lines =$
    zipWithList [1..] =$
    take 10 =$


    lines       :: Monad m => Enumeratee Text Text m b
    zipWithList :: Monad m => [a'] -> Enumeratee a (a, a') m b
    take        :: Monad m => Int -> Enumeratee a a m b
    printLines  :: MonadIO m => Iteratee (Int, Text) m ()

This is how I would do it.

> The second question could actually have an application in the server
> I'm writing. I was wondering if it was possible to write
> iteratees/enumerators that would only generate/consume when a certain
> something was the next chunk to be processed?

You want concurrent iteratees here.  As far as I know in the
'enumerator' package there is no builtin way to do it (you may be
luckier in the 'iteratee' package, but I don't know).  However, I think
it should be possible to write a 'concurrent' function, if the iteratees
in question all have the same input type:

    concurrent :: Monad m => [Step a m b] -> Iteratee a m [b]

A version, which doesn't collect the results is probably much easier to

    concurrent_ :: Monad m => [Step a m b] -> Iteratee a m ()


nightmare = unsafePerformIO (getWrongWife >>= sex)

More information about the Haskell-Cafe mailing list