I originally wrote/released the enumerator package because iteratees seemed really interesting, but I didn't like the function names or docs. That's it. The sole advantage enumerator has is that it's prettier.
Compare:
mapStream :: (Monad m, ListLike (s el) el, ListLike (s el') el', NullPoint (s el), LooseMap s el el') => (el -> el') -> Enumeratee (s el) (s el') m a
Map the stream: another iteratee transformer Given the stream of elements of the
type el and the function (el->el'), build a nested stream of elements of the type
el' and apply the given iteratee to it.
with:
map :: Monad m => (ao -> ai) -> Enumeratee ao ai m b
map f applies f to each input element and feeds the
resulting outputs to the inner iteratee.
I figured a simplified package would be useful as sort of a tutorial before people upgraded to "full" iteratees. I never planned on it becoming heavily used as itself.
I guess the biggest problem I have trying to figure out Enumeratees is that I want them to transform Enumerators into other Enumerators, but they seem to do something different, and I'm not exactly sure what. Enumeratees are actually Iteratees, but they have a strange "b" that's actually a Step. It boggles my mind somehow, probably because I'm trying to work out how that's equivalent to an Enumerator converter.
After wrestling with this since thursday, I wrote a function that's something like (wrapEnum :: Enumerator ai m b -> IO (Enumerator ao m b)), so I can convert an enumerator of one type into an enumerator of another type (I'm not looking at the code right now; that signature is obviously lacking, but it's the idea, anyhow). I think that's probably horribly wrong, but I just can't wrap my head around the type and behaviour of Enumeratees, even after reading the really pretty and simple ones that come with the snap-core package.
I think the idea is awesome, and I'm very happy about being able to use other people's Enumeratees like the various compression ones and ideas that I can express as a map or a fold, but I'm definitely missing something.
The extra complexity is for dealing with extra data. Say you're mapping ByteString->Text. The iteratee reads one char, then says it's done. What do you do with the extra bytes and text?
Making them return a Step allows both types of extra input to be stored, and possibly consumed later by other iteratees.
You can use (=$) or ($=) to modify how extra input is handled (by discarding it at certain points). Your wrapEnum is probably a special case of ($=).
I originally wrote/released the enumerator package because iteratees seemed really interesting, but I didn't like the function names or docs. That's it. The sole advantage enumerator has is that it's prettier.
Compare:
with: I figured a simplified package would be useful as sort of a tutorial before people upgraded to "full" iteratees. I never planned on it becoming heavily used as itself.