[Haskell-cafe] ANNOUNCE: pipes-core 0.0.1

Twan van Laarhoven twanvl at gmail.com
Mon Mar 12 11:41:48 CET 2012

On 11/03/12 23:41, Chris Smith wrote:
> On Sun, Mar 11, 2012 at 2:33 PM, Twan van Laarhoven<twanvl at gmail.com>  wrote:
>> I think you should instead move unwaits in and out of the composition on the
>> left side:
>>     unawait x>>  (p1>+>  p2) === (unawait x>>  p1)>+>  p2
>> This makes idP a left-identity for (>+>), but not a right-identity, since
>> you can't move unawaits in and out of p2.
> Not sure how we got to the point of debating which of the category
> laws pipes should break... messy business there.  I'm going to be in
> favor of not breaking the laws at all.  The problem here is that
> composition of chunked pipes requires agreement on the chunk type,
> which gives the type-level guarantees you need that all chunked pipes
> in a horizontal composition (by which I mean composition in the
> category... I think you were calling that vertical?  no matter...)
> share the same chunk type.  Paolo's pipes-extra does this by inventing
> a newtype for chunked pipes, in which the input type appears in the
> result as well.  There are probably some details to quibble with, but
> I think the idea there is correct.  I don't like this idea of
> implicitly just throwing away perfectly good data because the types
> are wrong.  It shows up in the category-theoretic properties of the
> package as a result, but it also shows up in the fact that you're
> *throwing* *away* perfectly good data just because the type system
> doesn't give you a place to put it!  What's become obvious from this
> is that a (ChunkedPipe a b m r) can NOT be modelled correctly as a
> (Pipe a b m r).

Agreed. There are many things to be said for making sure that Pipe is a 
real category. I suppose the morally correct thing to do is, as you 
said, have a separate ChunkedPipe type. That would make the type system 
guarantee that there are no calls to 'unawait' in the second part of a 
categorical composition.

The API could even look something like this:

     data Chunk
     data NoChunk
     data Pipe chunkiness a b m r

     await :: Pipe anyChunk a b m a
     yield :: b -> Pipe anyChunk a b m ()
     unawait :: a -> Pipe Chunk a b m ()

     runChunkedPipe :: Pipe Chunk a b m r -> Pipe NoChunk a b m r

     -- composition in the category
     (>+>) :: Pipe NoChunk a b m r -> Pipe NoChunk b c m r
           -> Pipe NoChunk a c m r

The following generalization of category composition is still fine:

     compose :: Pipe anyChunk a b m r -> Pipe NoChunk b c m r
             -> Pipe anyChunk a c m r

But this would not be:

     almostEntirelyNotUnlikeCompose :: Pipe anyChunk a b m r
          -> Pipe discardChunksHere b c m r -> Pipe anyChunk a c m r

By the way, a ChunkedPipe can be implemented not only as
     type ChunkedPipe a b m r = StateT [a] (Pipe a b m) r
but also as
     type ChunkedPipe a b m r = CodensityT (Pipe a b m) r
by using the 'feed' function to implement unawait.


More information about the Haskell-Cafe mailing list