[Haskell-cafe] safe lazy IO or Iteratee?

John Millikin jmillikin at gmail.com
Fri Feb 5 10:34:55 EST 2010


I didn't count the commented-out designs in Oleg's code, only those
which are "live".

> Both designs appear to offer similar performance in aggregate,
> although there are differences for particular functions.  I haven't
> yet had a chance to test the performance of the CPS variant, although
> Oleg has indicated he expects it will be higher.

I wrote some criterion benchmarks for IterateeM vs IterateeCPS, and
the CPS version was notably slower. I don't understand enough about
CPS to diagnose why, but the additional runtime was present in even
simple cases (reading from a file, writing back out).

On Fri, Feb 5, 2010 at 06:04, John Lato <jwlato at gmail.com> wrote:
>> Subject: Re: [Haskell-cafe] safe lazy IO or Iteratee?
>>
>> Downside: iteratees are very hard to understand. I wrote a
>> decently-sized article about them trying to figure out how to make
>> them useful, and some comments in one of Oleg's implementations
>> suggest that the "iteratee" package is subtly wrong. Oleg has written
>> at least three versions (non-monadic, monadic, monadic CPS) and I've
>> no idea why or whether their differences are important. Even dons says
>> he didn't understand them until after writing his own iteratee-based
>> IO layer.
>
> More significant than, and orthogonal to, the differences between
> non-monadic and monadic are the two primary implementations Oleg has
> written.  They are[1]:
>
> Design 1:
> newtype Iteratee el m a = Iteratee{runIter:: Stream el -> m (IterV el m a)}
> data IterV el m a = IE_done a (Stream el)
>                  | IE_cont (Iteratee el m a) (Maybe ErrMsg)
>
> Design 2:
> newtype Iteratee el m a = Iteratee{runIter:: m (IterV el m a)}
> data IterV el m a = IE_done a (Stream el)
>                  | IE_cont (Stream el -> Iteratee el m a) (Maybe ErrMsg
>
> With the first design, it's impossible to get the state of an iteratee
> without feeding it a chunk.  There are other consequences too.  The
> second design seems to require some specialized combinators, that is
> (>>==) and ($$), which are not required for the first version.
> Neither situation is ideal.  The CPS version appears to remedy both
> flaws, but at the expense of introducing CPS at a low level (this can
> be hidden from the end user in many cases).  I already think of
> iteratees as holding continuations, so to me the so-called "CPS
> version" is to me a double CPS.
>
> Both designs appear to offer similar performance in aggregate,
> although there are differences for particular functions.  I haven't
> yet had a chance to test the performance of the CPS variant, although
> Oleg has indicated he expects it will be higher.
>
> The monadic/non-monadic issue is related.  Non-monadic iteratees are
> iteratees that can't perform monadic effects when they're running
> (although they can still be fed from a monadic enumerator).
> Essentially it's the difference between "fold" and "foldM".  They are
> simpler and more efficient because of this, but also much less
> powerful.  Any iteratee design can support both non-monadic and
> monadic, but *I* don't want to support both.  At least, I don't want
> to have double modules for everything for nearly identical functions,
> and polymorphic code that can handle non-monadic and monadic iteratees
> is non-trivial[2].
>
> Much of my recent work has been in the consequences of these various
> design considerations for the next version of the iteratee library.
> Currently undecided, although I'm leaning towards CPS.  It seems to
> solve a lot of problems, and the implementation details are generally
> cleaner too.
>
> Cheers,
> John
>
> [1] Both taken from
> http://okmij.org/ftp/Haskell/Iteratee/IterateeM.hs.  Design 1 is
> commented out on that page.
>
> [2] At least for me.  Maybe others can provide a better solution.
>


More information about the Haskell-Cafe mailing list