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.
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 $ dostep' <- runIteratee $ e12 steprunIteratee . 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 CraigOn Sun, Dec 25, 2011 at 10:20 PM, Conrad Parker <conrad@metadecks.org> wrote:
Hi Michael,On 24 December 2011 05:47, Michael Craig <mkscrg@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.
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.