
At Fri, 6 May 2011 10:10:26 -0300, Felipe Almeida Lessa wrote:
He also says that the enumerator package's Enumerators aren't iteratees, only iterIO's enumerators are. Well, that's not what I'm reading:
-- from enumerator package newtype Iteratee a m b = Iteratee {runIteratee :: m (Step a m b)} type Enumerator a m b = Step a m b -> Iteratee a m b type Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai m b)
-- from iterIO package newtype Iter t m a = Iter {runIter :: Chunk t -> IterR t m a} type Inum tIn tOut m a = Iter tOut m a -> Iter tIn m (IterR tOut m a) type Onum t m a = Inum () t m a
The enumerator package's Enumerator *is* an iteratee, an so is its Enumeratee.
Strictly speaking, I guess that's precise if you look at the type of Enumerator. However, it's not really an iteratee in the spirit of iteratees, since it isn't really a data sink and has no input type.
The only real difference is that iterIO represents enumerators as enumeratees from () to something. In enumerator package terms, that would be
-- enumerator packages's enumerator if it was iterIO's :) -- note that Inum's "tIn" and "tOut" are reversed w.r.t Enumeratee "ao" and "ai" type Enumerator a m b = Enumeratee () a m b
Whether this representation is better or worse isn't clear for me.
Exactly. The reason it's better (and for a long time my library was more like the enumerator one) is that the mechanics of uniform error handling are complex enough as it is. When enumerators and enumeratees are two different types, you need two different mechanisms for constructing them, and then have to worry about handing errors in the two different cases. I found that unifying enumerators and enumeratees (or Inums and Onums as I call them) significantly simplified a lot of code.
Now, one big problem that iterIO has that enumerator hasn't, is that iterIO is a *big* library with many dependencies, including OpenSSL. IMHO, that package should be split into many others.
Yes, this is definitely true.
So, in the enumerator vs. iterIO challenge, the only big differences I see are:
a) iterIO has a different exception handling mechanism. b) iterIO can have pure iteratees that don't touch the monad. c) iterIO's iteratees can send control messages to ther enumerators. d) iterIO's enumerators are enumeratees, but enumerator's enumerators are simpler. e) enumerator has fewer dependencies. f) enumerator uses conventional nomenclature. g) enumerator is Haskell 98, while iterIO needs many extensions (e.g. MPTC and functional dependencies).
Anything that I missed?
The bottomline: the biggest advantage I see right now in favor of iterIO is c),
I basically agree with this list, but think you are underestimating the value of a. I would rank a as the most important difference between the packages. (a also is the reason for d.) David