[Haskell-cafe] Enumerators, Enumeratees and Iterators

Alexander Solla alex.solla at gmail.com
Tue Jun 28 19:51:13 CEST 2011

On Mon, Jun 27, 2011 at 7:21 PM, 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.  You would want to use an enumeratee.  Consider the following  (based
on the Enumerator package).  It checks each element of the stream against a
Set.  If the element is in the set, then we do not forward the element to
the inner iteratee.  If the element is not in the set, we insert it and
forward it to the inner iteratee.

We "need" loop to carry the Set's state around.

unique :: forall a m b . (Ord a, Monad m) => Enumeratee a a m b
unique = loop Set.empty where
         loop :: (Ord a, Monad m) => Set a -> Enumeratee a a m b
         loop seen step@(Continue k) = continue go where

              go :: (Ord a, Monad m) => Stream a -> Iteratee a m (Step a m
              go EOF = return step

              go (Chunks (a:as)) = do
                    (if (a `member` seen) then k $ Chunks    as    -- drop a
if already seen
                                          else k $ Chunks (a:as))  -- keep a
if not seen
                    >>== loop (a `Set.insert` seen)

              go ch = (k ch >>== loop seen)

         loop seen step = return step

> Something like this:
> enumFile "someFile" && printFileLines -- prints file with prepended line
> numbers
> enumFile "someFile" ?? onlyGet10Lines && printFileLines -- print only 10
> lines
> 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? It's a bit hard to explain, but let me try to give you an
> example.

Perhaps, but it might be tricky depending on how much you /need/ the certain
something to be a Chunk.  Look at the 'unique' example above.  Notice how
we're pattern matching against a Chunk and its inner list.  This would be
the basis for your conditional matching.  I would suggest that you don't
want your "certain something" to be a chunk, but an element of the stream
(i.e, one of the xs contained in Chunk xs)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110628/be5b7620/attachment.htm>

More information about the Haskell-Cafe mailing list