streaming-0.1.0.19: README.md
streaming
=========
This library defines an optimized `FreeT` with an eye to use with
streaming libraries, namely:
data Stream f m r
= Return r
| Step !(f (Stream f m r))
| Delay (m (Stream f m r))
in place of the standard `FreeT` that we find in the `free` library, which
is approximately:
newtype FreeT f m r = FreeT {runFreeT :: m (Either r (f (FreeT f m r)))}
Rather than wrapping each step in a monadic 'layer', such a layer is
put alongside separate 'pure' constructors for a functor 'layer'
and a final return value. The maneuver is very friendly to the compiler,
but requires a bit of subtlety to protect a sound monad instance. Just such an optimization is adopted internally by the `pipes` library.
As in `pipes`, the constructors are here left in an `Internal` module;
the main `Streaming` module exporting the type itself and various
operations and instances.
There is also a still-incomplete `Prelude` of functions, some
`FreeT` or `Stream` - general, some involving the functor
`((,) a)` here called `Of a`. (`Stream (Of a) m r` like
`FreeT ((,) a) m r` is equivalent to the `pipes`
`Producer a m r` type. Similarly, `Stream (Of a) m ()` and
`FreeT ((,) a) m ()` are possible implementations
of `ListT done right`.
I ran a simple [benchmark](https://gist.github.com/michaelt/7f89dc8b366b30bb6acc) (adjusting a [script](https://github.com/jwiegley/streaming-tests) of John Weigly) using a very simple composition of functions:
toList
. filter (\x -> x `mod` 2 == 0)
. map (+1)
. drop 1000
. map (+1)
. filter even
. each
The the results were fairly pleasing:
benchmarking basic/streaming
time 84.50 ms (79.81 ms .. 87.90 ms)
benchmarking basic/iostreams
time 266.2 ms (235.6 ms .. 292.0 ms)
benchmarking basic/pipes
time 232.0 ms (206.6 ms .. 246.7 ms)
benchmarking basic/conduit
time 102.3 ms (96.24 ms .. 110.0 ms)
This sequence of pre-packaged combinators is, I think, very friendly to the
more recent conduit fusion framework. The framework of course doesn't apply to
user-defined operations, where we should expect times like those shown for pipes.
Since the combinators from `streaming` is defined with naive recursion,
more or less as the user might, we have reason to think the result is characteristic,
but much more benchmarking is needed before anything can be said with certainty.
The labor of constructor-hiding may turn up some further difficulty.