conduino: Lightweight composable continuation-based stream processors

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

Warnings:

A lightweight continuation-based stream processing library.

It is similar in nature to pipes and conduit, but useful if you just want something quick to manage composable stream processing without focus on IO.

See README for more information.


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.2.0.0, 0.2.1.0, 0.2.2.0, 0.2.3.0, 0.2.3.0, 0.2.4.0
Change log CHANGELOG.md
Dependencies base (>=4.11 && <5), bytestring, containers, exceptions, free, list-transformer, mtl, text, transformers [details]
License BSD-3-Clause
Copyright (c) Justin Le 2019
Author Justin Le
Maintainer justin@jle.im
Category Control
Home page https://github.com/mstksg/conduino#readme
Bug tracker https://github.com/mstksg/conduino/issues
Source repo head: git clone https://github.com/mstksg/conduino
Uploaded by jle at 2023-12-21T06:23:58Z

Modules

[Index] [Quick Jump]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Readme for conduino-0.2.3.0

[back to package description]

conduino

A lightweight continuation-based stream processing library.

It is similar in nature to pipes and conduit, but useful if you just want something quick to manage composable stream processing without focus on IO.

Why a stream processing library?

A stream processing library is a way to stream processors in a composable way: instead of defining your entire stream processing function as a single recursive loop with some global state, instead think about each "stage" of the process, and isolate each state to its own segment. Each component can contain its own isolated state:

runPipePure $ sourceList [1..10]
           .| scan (+) 0
           .| sinkList
-- [1,3,6,10,15,21,28,36,45,55]

All of these components have internal "state":

They all work together without knowing any other component's internal state, so you can write your total streaming function without concerning yourself, at each stage, with the entire part.

In addition, there are useful functions to "combine" stream processors:

Stream processing libraries are also useful for streaming composition of monadic effects (like IO or State), as well.

Details and usage

API-wise, is closer to conduit than pipes. Pull-based, where the main "running" function is:

runPipe :: Pipe () Void u m a -> m a

That is, the "production" and "consumption" is integrated into one single pipe, and then run all at once. Contrast this to pipes, where consumption is not integrated into the pipe, but rather your choice of "runner" determines how your pipe is consumed.

One extra advantage over conduit is that we have the ability to model pipes that will never stop producing output, so we can have an await function that can reliably fetch items upstream. This matches more pipes-style requests.

For a Pipe i o u m a, you have:

Some specializations:

Usually you would use it by chaining together pipes with .| and then running the result with runPipe.

runPipe $ someSource
       .| somePipe
       .| someOtherPipe
       .| someSink

Why does this package exist?

This package is taking some code I've used some closed-source projects and pulling it out as a full library. I wrote it, despite the existence of pipes and conduit, because:

  1. I wanted conduit-style semantics for stream composition (source - producer - sink all in one package).
  2. I wanted type-enforced guaranteed "awaits" based on type-enforced guaranteed infinite producers.
  3. I wanted to be able to combine stream processors "in parallel" in different ways (zipSink, for "and", and altSink, for "or").
  4. I wanted something lightweight without the dependencies dealing with IO, since I wasn't really doing resource-sensitive IO.

conduino is a small, lightweight version that is focused not necessarily on "effects" streaming, but rather on composable bits of logic. It is basically a lightweight version of conduit-style streaming. It is slightly different from pipes in terms of API.

One major difference from conduit is the u parameter, which allows for things like awaitSurely, to ensure that upstream pipes will never terminate.

If you need to do some important IO and handle things like managing resources, or leverage interoperability with existing libraries...switch to a more mature library like conduit or pipes immediately :)