
On Sat, Jun 12, 2010 at 1:12 PM, Tilo Wiklund
I am probably missing something obvious or something relating to optimisation/server software but defining iteratees as "Iteratee s a = Cont (s -> Either (s, a) (Iteratee s a))" seems to lead to a more natural monad instance, and does not suffer from (what seems to me to be an issue) having to make predictions about the stream it will be passed.
If you forget about the monad transformer, your iteratee is essentially the same as the current iteratee in the iteratee package[1]: newtype IterateeG c el m a = IterateeG{ runIter :: StreamG c el -> m (IterGV c el m a) } data IterGV c el m a = Done a (StreamG c el) | Cont (IterateeG c el m a) (Maybe ErrMsg) So a function from a stream to a result which is either done or needs more data. The current iteratee design from Oleg Kiselyov[2] is slightly different however: data Iteratee a = IE_done a Stream | IE_cont (Stream -> Iteratee a) (Maybe ErrMsg) The main advantage of this design is that you can create an iteratee which returns a value without consuming input: return x = IE_done x (Chunk "") instead of: return x = IterateeG (\s -> return $ Done x s) You may also want to read the latest issue of The Monad Reader[3] (issue 16) which contains an article by John W. Lato (author of the iteratee package) which introduces iteratees. [1] http://hackage.haskell.org/packages/archive/iteratee/0.3.5/doc/html/Data-Ite... [2] http://okmij.org/ftp/Haskell/Iteratee/Iteratee.hs [3] http://themonadreader.wordpress.com/2010/05/12/issue-16/