[Haskell-cafe] Where io-streams won't fit, comparing to conduit or pipes
Alex Hammel
ahammel87 at gmail.com
Thu Nov 5 17:48:52 UTC 2015
Thanks for the run-down. I don't know about the OP, but that was certainly
quite enlightening to me!
On Thursday, 5 November 2015 09:45:49 UTC-8, Gregory Collins wrote:
>
> *Programming style*
>
> Conduits and pipes use a categorical programming model in
> continuation-passing style, and implement Monad instances that lift over an
> arbitrary base monad. The io-streams library is not polymorphic over the
> base monad, instead preferring to fix computations to IO. It's worth
> pointing out that stream transformation in io-streams style is also
> (implicitly) categorical in style, but in the Kleisli category for IO.
>
> Conduits and pipes take responsibility for controlling the evaluation of
> the streaming computation in its entirety, while you can either treat an
> Input/OutputStream from io-streams like a Handle and feed work to it
> element-wise, or chain an Input and OutputStream together using a
> combinator like "connect" in streaming style.
>
> IO-streams only does one-way streaming, while pipes and conduits can pass
> data back and forth between different stream transducers.
>
> *Resources and exceptions*
>
> The io-streams library purposely does not do any resource management for
> you, with the exception of a few "with*" functions that do some bracketing
> for you. The fact that all io-streams computations run in the base IO monad
> makes exception handling cheap there, but with the disadvantage that you
> e.g. cannot write a stream transducer that will install an exception
> handler, yield some elements, and then expect to be notified if a
> downstream consumer throws an exception. In general, in io-streams, if
> you're an InputStream or OutputStream that has yielded or consumed its
> value, you are not guaranteed that your continuation will ever be called
> again, so there is no opportunity for you to take on a cleanup action or
> release some resources -- that work has to be done outside the streaming
> computation. You can think of io-streams as little transducers that attach
> to resources.
>
> Since pipes and conduits use continuation-passing monads, the exception
> handler problem arises there also, with the difference that since the pipes
> or conduits library is running the computation, it's possible to write a
> MonadCatch instance (or whatever) can carefully mask/unmask exceptions and
> thread an exception handler through the monad continuation for you. The
> issue with this is that every monad bind means a masking/unmasking of
> exceptions and the installation/cleanup of an exception handler. Usually
> people solve this by running in a ResourceT, which punts on the exception
> issue for resource handling by installing one exception handler and scoping
> all resource acquisition to explicit stack-like (Oleg's paper calls these
> "monadic regions") contexts.
>
> *Simplicity*
>
> Both pipes and conduits are *much* more complicated (especially re: type
> parameters), but you get additional features to go along with this
> complexity so there is an engineering tradeoff there. I designed io-streams
> to be as simple as possible and easy to understand for new Haskellers as
> possible, while giving me of the features I needed to implement our web
> programming framework.
>
> *Correctness/Laws*
>
> All three libraries do well on this front; pipes has had quite a bit of
> formal verification done to it, and purports to follow categorical laws.
> IO-streams is very simple and has 100% test coverage. Conduits is used by
> quite a few people so you can expect solidity there also (but I've never
> used it in anger).
>
> *Performance*
>
> All else being equal, an io-streams computation is likely to be slightly
> faster than the others because you pay a performance penalty at bind time
> for monadic polymorphism. Both pipes and conduits have leveraged their
> algebraic/categorical design, however, to create RULES pragmas to do some
> kinds of whole-computation stream fusion (i.e. map f . map g should get
> turned into "map (f . g)"), which might lessen this disadvantage or even
> eliminate it, depending on what kind of computation is happening.
>
> Hope this helps
> G
>
> On Thu, Nov 5, 2015 at 8:33 AM, Daisuke Fujimura <m... at fujimuradaisuke.com
> <javascript:>> wrote:
>
>> Hello cafe,
>>
>> Now I'm preparing a presentatio for meetup for stream processing in
>> functional programming(in Tokyo), and my part is something like "why stream
>> processing library".
>>
>> While preparing material, I encountered the question that why io-streams
>> is so simple comparing others, and the reason and downsides behind its
>> simplicity. I'm guessing it's due to its resource handling strategy, but
>> not so confident about it because I couldn't came up with a concrete
>> example yet.
>>
>> Do you know any good example where io-streams won't fit? Let me know if
>> you have.
>>
>> Thanks!
>>
>>
>> _______________________________________________
>> Haskell-Cafe mailing list
>> Haskel... at haskell.org <javascript:>
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>>
>>
>
>
> --
> Gregory Collins <gr... at gregorycollins.net <javascript:>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20151105/67633158/attachment.html>
More information about the Haskell-Cafe
mailing list