[Haskell-cafe] Re: iteratee: Do I need to roll my own?

Bas van Dijk v.dijk.bas at gmail.com
Wed Mar 31 17:43:43 EDT 2010


On Wed, Mar 31, 2010 at 7:42 PM, David Leimbach <leimy2k at gmail.com> wrote:
> What I mean is let's say the stream has
> "abcd efg abcd efg"
> and then I run some kind of iteratee computation looking for "abcd"

You could adapt the 'heads' function from the iteratee package to do this:

http://hackage.haskell.org/packages/archive/iteratee/0.3.4/doc/html/src/Data-Iteratee-Base.html#heads

> and the block size was fixed to cause a read 1024 bytes, but returns as much
> as it can providing it to the iteratee to deal with.  The iteratee, which I
> want to implement Expect like behavior, would really only want to read up to
> "abcd" consuming that from the input stream.  Does the iteratee get the
> whole stream that was read by the enumerator, or is it supplied a single
> atomic unit at a time, such as a character, in which I can halt the
> consumption of the streamed data?

The iteratee will be applied to the whole stream that was read by the
enumerator. You should ensure that the part of this input stream which
is not needed for the result is saved in the 'Done' constructor so
that other iteratees may consume it.

> What I don't want to have happen is my consuming bytes from the input
> Handle, only to have them ignored, as the second instance of "abcd" could be
> important.

Note that an IterateeG has an instance for Monad which allows you to
sequentially compose iteratees. If you write a 'match' iteratee (by
adapting the 'heads' function I mentioned earlier which matches a
given string against the first part of a stream) you can compose these
sequentially:

foo = match "abcd" >> match "efg" >> foo

The first match will be applied to the stream that was read by the
enumerator. It will consume the "abcd" and saves the rest of the
stream (in the 'Done' constructor). The second match will first be
applied to the saved stream from the first match. If this stream was
not big enough the iteratee will ask for more (using the 'Cont'
constructor). The enumerator will then do a second read and applies
the continuation (stored in the 'Cont' constructor) to the new stream.

You may also consider using actual parser combinators build on top of iteratee:

http://hackage.haskell.org/package/attoparsec-iteratee
http://hackage.haskell.org/package/iteratee-parsec

(I typed this in a hurry so some things may be off a bit)

regards,

Bas


More information about the Haskell-Cafe mailing list