[Haskell-cafe] ANNOUNCE: pipes-core 0.0.1
Mario Blažević
blamario at acanac.net
Sat Mar 10 20:59:14 CET 2012
On 12-03-10 05:16 AM, Paolo Capriotti wrote:
> On Sat, Mar 10, 2012 at 4:21 AM, Mario Blažević<blamario at acanac.net> wrote:
>> I like your design, it seems to strike a good balance between elegance
>> and practicality. The only thing missing for the latter is a deeper support
>> for chunking. Of course, that would probably destroy some of the elegance
>> [1]. I don't think that problem has been solved in any of the
>> enumerator/iteratee/pipe/wire/conduit libraries so far.
> Chunking is supported but not by primitive constructs. The way you
> implement chunked streams is to simply use some form of "container"
> representing a chunk as your input/output type.
>
> Of course, that means that the abstraction is now operating at the
> level of chunks instead of elements, which may be inconvenient, but I
> doubt that there exists a way to "lift" element operations to chunks
> in an efficient and general way.
>
> Another issue is how to deal with unconsumed input. For that, there is
> a ChunkPipe type (in pipes-extra) with a specialized monad instance
> that threads unconsumed input along. You can see an example of
> ChunkPipe in action in this prototype http server by Jeremy Shaw:
> http://src.seereason.com/pipes-http-2/pipes-http-2/. Note that this is
> based on a old version of pipes-core, however.
The only sane way I've found to deal with chunks is to move the
responsibility into the glue logic, which would be your (>+>) and (>>)
combinators. The upstream argument of (>+>) could then produce chunks of
any size it finds suitable, while the downstream argument would specify
exactly how much input it needs without having to worry about the
upstream chunk boundaries. How these requests are phrased is an open
question. I've developed the incremental-parser package specifically for
this purpose. Other approaches are possible, but I'm convinced that
chunking should not be left to individual components. The chunk type
probably shouldn't be reflected even in their types.
>> Did you consider adding some stream-splitting and merging pipes, like
>> those in the SCC package [2] or those described in the last Monad.Reader
>> issue [3]? Your arrow-like combinators seem well thought out, but they
>> don't go very far.
> I'm not sure why you say that they don't go very far. I looked at
> Splitter and Join in Monad.Reader 19, and they seem equivalent to
> 'splitP' and 'joinP' in pipes-core.
The main purpose of the Splitter type is to act as a conditional,
sending each input item *either* into the left or into the right output,
marking is as either true or false. Your splitterP sends each item to
*both* left and right output. It's a tee, not a split.
If your point is that the Splitter a m r type is isomorphic to Pipe
a (Either a a) m r, that is true. There is a benefit to the abstraction,
though. Once you introduce chunking into the picture, however, the
Splitter type can be changed under the hood to send an entire chunk to
its left or right output. The corresponding efficient chunked Pipe type
would be Pipe [a] (Either [a] [a]) m r, which is not at all the same as
Pipe [a] [Either a a] m r -- if you have to pack every single item of
the input chunk into an Either value, you've lost all performance
benefits of chunking. The former type is efficient but I'm not sure if
it would allow you to abstract the chunking logic out of the individual
components.
> There shouldn't be any problem implementing all the other combinators
> there in terms of monoidal primitives (e.g. 'not' is just 'swap').
I agree, with the chunking reservation above. Anyway, consider
adding the Boolean combinators to the library. I find them quite intuitive.
More information about the Haskell-Cafe
mailing list