I wound up emailing John Millikin about this and he made a good case against these kinds of simplified operators, which is basically the problem of handling left-over input. The joinI and joinE combinators discard the left-over Stream that is yielded by the inner iteratee. (As John explains it, this is a trade-off between ease of use and programming complexity.) Simplified operators (like $=, =$, and now =$=) use repeated joinI's, so left-over input may be lost in various places. When using simple iteratees that never yield left-over input, this isn't a problem and the operators make sense.
For more complex pipelines, John advocates a style like this: joinI (foo $$ (bar $$ baz)) so that left over data is only discarded once after the computation is otherwise complete. In any case, there's now a new release of enumerator (0.4.17) which includes an enumeratee composition operator: (=$=) :: Monad m => Enumeratee a1 a2 m (Step a3 m b) -> Enumeratee a2 a3 m b -> Enumeratee a1 a3 m b. Cheers, Mike Craig On Tue, Dec 27, 2011 at 10:12 AM, Michael Craig <mks...@gmail.com> wrote: > Thanks for the replies, all. It's good to see that the other iteratee > packages out there are addressing this issue. > > I still don't get why it's an issue in the first place. It seems to me > like a pretty simple thing to implement: > > (=$=) :: (Monad m) > => Enumeratee a0 a1 m (Step a2 m b) -> Enumeratee a1 a2 m b > -> Enumeratee a0 a2 m b > (=$=) e01 e12 step = Iteratee $ do > step' <- runIteratee $ e12 step > runIteratee . joinI $ e01 step' > > This puts a type restriction on the LHS enumeratee, but enumeratees are > generally polymorphic in the last type param anyway. (And joinE has a > similar restriction when composing an enumerator with an enumeratee.) > > Is there a good reason why enumerator doesn't export this or something > analogous? > > Mike Craig > > > > On Sun, Dec 25, 2011 at 10:20 PM, Conrad Parker <con...@metadecks.org>wrote: > >> On 24 December 2011 05:47, Michael Craig <mks...@gmail.com> wrote: >> > I've been looking for a way to compose enumeratees in the enumerator >> > package, but I've come up with nothing so far. I want this function >> > >> > (=$=) :: Monad m => Enumeratee a0 a1 m b -> Enumeratee a1 a2 m b -> >> > Enumeratee a0 a2 m b >> > >> > I'm building a modular library on top of enumerator that facilitates >> reading >> > time series data from a DB, applying any number of transformations to >> it, >> > and then writing it back / doing something else with it. I'd like to be >> able >> > to write simple transformations (enumeratees) and compose them without >> > binding them to either a db reader (enumerator) or db writer (iteratee). >> > >> > I've been looking at the iterIO package as a possible alternative, >> because >> > it seems to allow easy composition of Inums (enumeratees). I'm a little >> > skittish of it because it seems unpopular next to enumerator. >> >> Hi Michael, >> >> You could also look at the iteratee package. This is the signature of >> the (><>) operator: >> >> (><>) :: (Nullable s1, Monad m) => (forall x. Enumeratee s1 s2 m x) -> >> Enumeratee s2 s3 m a -> Enumeratee s1 s3 m a >> >> it's quite useful for composing enumeratees, likewise its friend (<><) >> swims the other way. >> >> >> http://hackage.haskell.org/packages/archive/iteratee/0.8.7.5/doc/html/Data-Iteratee-Iteratee.html >> >> cheers, >> >> Conrad. >> > >
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe