On Mon, Apr 16, 2012 at 10:13 PM, Ben Franksen <[email protected]> wrote: > > I like your pipes package. This is very similar to what Mario Blažević wrote > about his Coroutines in the Monad.Reader (can't remember which issue; great > article, BTW, many thanks Mario for making me understand the iteratee > business (and also generators) for the first time). Your pipes-core looks > even simpler to use, maybe due to avoiding to make a type distinction > between consumer/producer/pipe (except the natural one i.e. through the > input/output types), even though the parameterization by a functor (as in > Monad.Coroutine) has its own beauty.
Yes, Mario Blažević's Transducer is the main inspiration for the original pipes package, and consequently pipes-core. > Two issues: > > (1) What is the reason for the asymmetry in > > type Producer b m = Pipe () b m > type Consumer a m = Pipe a Void m > > i.e. why does Producer use () for the input? I would expect it to use Void, > like Consumer does for its output. Calling await in a Producer resulting in > an immediate 'return ()' as you say is allowed (in the tutorial) strikes me > as not very useful. The underlying reason for the asymmetry is the fact that '()' is a terminal object in the category of haskell types and *total* functions, while 'Void' is an initial object. Here's a property that uniquely determines the definitions of 'Producer' above. Let 'X' be the type such that 'Producer b m = Pipe X b m'. For all producers 'p' there should be a unique (total) pipe 'alpha :: forall a r. Pipe a X m r' such that 'alpha >+> p' and 'p' are observationally equal. In other words, since a producer "never uses values of its input type 'a'", there should be a unique way to make it into a pipe which is polymorphic in 'a'. It's easy to see that this property immediately implies that 'X' should be a terminal object, i.e. '()', and 'alpha' is therefore 'pipe (const ())'. Dually, you obtain that 'Consumer a m' is necessarily 'Pipe a Void m', and 'alpha = pipe absurd'. > (2) The $$ operator is poorly named. I would intuitively expect an operator > that looks so similar to the standard $ to have the same direction of data > flow (i.e. right to left, like function application and composition) but > your is left to right. You could use e.g. >$> instead, which has the > additional advantage of allowing a symmetric variant for the other direction > i.e. <$<. '$$' is inspired by iteratees. Similarly to its iteratee counterpart, it discards upstream result values and only returns the output of the last pipe. That said, '>$>' looks like a clearer alternative, so I could consider changing it. Thanks for your feedback! Paolo _______________________________________________ Haskell-Cafe mailing list [email protected] http://www.haskell.org/mailman/listinfo/haskell-cafe
