Giter VIP home page Giter VIP logo

purescript-coroutines's Introduction

Coroutines

CI Release Pursuit Maintainer: garyb

Coroutines are a general control structure allowing flow control to pass cooperatively between two different routines. Coroutines in this library are computations which can suspend their execution and return control to their invoker, which can resume the computation. Coroutines can be used to implement pipelines as described in Coroutine Pipelines by Mario Blažević.

If you are creating asynchronous or concurrent pipelines you may be interested in:

If you need a featureful streaming library, you may also be interested in:

If you are looking for a FRP library, then you may be interested in:

Installation

Install coroutines with Spago:

spago install coroutines

Quick start

This quick start briefly introduces the basics of coroutines. For a more thorough, beginner-friendly introduction to the library, please see the library documentation.

The basic building block of coroutines is the coroutine type Co, which exhibits different behavior when it suspensd based on a functor f:

  • When f is the Emit o functor, the coroutine emits an output of type o and is a Producer
  • When f is the Await i functor, the coroutine waits for an input of type i and is a Consumer
  • When f is the Transform i o functor, the coroutine waits for an input of type i, and emits an output of type o, and is a Transformer.

A coroutine which emits can be thought of as a generator, where each yield produces a value. A coroutine which awaits can be thought of as an iteratee, where each yield demands a value. And a coroutine which transforms does both: it demands an input, and produces an output.

Using these three building blocks we can create some standard coroutines and form them into pipelines.

Here is a coroutine which generates natural numbers:

nats :: forall m. (Monad m) => Producer Int m Unit
nats = go 0
  where
  go i = do
    emit i
    go (i + 1)

The computation runs, emits a number, and suspends; when resumed it will emit the next number and then suspend again. It uses the emit function:

emit :: forall m o. Monad m => o -> Producer o m Unit

Here is a coroutine which accepts and prints strings:

printer :: forall a. Consumer String (Aff _) Unit
printer = forever do
  s <- await
  lift (log s)

The computation suspends, awaiting a number. When it receives a number it logs the number and then suspends, awaiting a new number. It uses the await function:

await :: forall m i. Monad m => Consumer i m i

Here is a coroutine which transforms inputs by showing them as strings:

showing :: forall a m. (Show a, Monad m) => Transformer a String m Unit
showing = forever (transform show)

The computation suspends, awaiting an a. When it receives the awaited value, it transforms it into a string, emits the new value, and suspends again, awaiting another a. It uses the transform function:

transform :: forall m i o. Monad m => (i -> o) -> Transformer i o m Unit

These coroutines can be combined together using a handful of operators, the most common of which include:

connect :: forall o f m a. MonadRec m => Parallel f m => Producer o m a -> Consumer o m a -> Process m a
infixr 2 connect as $$

transformProducer :: forall i o f m a. MonadRec m => Parallel f m => Producer i m a -> Transformer i o m a -> Producer o m a
infixr 2 transformProducer as $~

transformConsumer :: forall i o f m a. MonadRec m => Parallel f m => Transformer i o m a -> Consumer o m a -> Consumer i m a
infixr 2 transformConsumer as ~$

composeTransformers :: forall i j k f m a. MonadRec m => Parallel f m => Transformer i j m a -> Transformer j k m a -> Transformer i k m a
infixr 2 composeTransformers as ~~

Once composed, the resulting computation can be run using runFreeT. If you have used connect to connect a producer and consumer, then you can use runProcess (a helper function for running a producer/consumer pair via runFreeT).

This example transforms the nats producer so that instead of producing integers it produces strings, and then connects the resulting producer to the printer consumer. Once connect, we can use runProcess to run the pipeline:

main = launchAff $ runProcess ((nats $~ showing) $$ printer)

The producer will emit a value, then yield; this value will satisfy the await call in the consumer, which will use the value and then yield back to the producer. This process will continue indefinitely.

Documentation

coroutines documentation is stored in a few places:

  1. Module documentation is published on Pursuit.
  2. Written documentation is kept in the docs directory.
  3. Usage examples can be found in the test suite.

If you get stuck, there are several ways to get help:

Contributing

You can contribute to coroutines in several ways:

  1. If you encounter a problem or have a question, please open an issue. We'll do our best to work with you to resolve or answer it.

  2. If you would like to contribute code, tests, or documentation, please read the contributor guide. It's a short, helpful introduction to contributing to this library, including development instructions.

  3. If you have written a library, tutorial, guide, or other resource based on this package, please share it on the PureScript Discourse! Writing libraries and learning resources are a great way to help this library succeed.

purescript-coroutines's People

Contributors

anttih avatar dgendill avatar garyb avatar jordanmartinez avatar justinwoo avatar kl0tl avatar liamgoodacre avatar paf31 avatar safareli avatar th-awake avatar thomashoneyman avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.