Concurrential-0.4.0.0: Mix concurrent and sequential computation

Copyright(c) Alexander Vieth, 2015
LicenseBSD3
Maintaineraovieth@gmail.com
Stabilityexperimental
Portabilitynon-portable (GHC only)
Safe HaskellNone
LanguageHaskell2010

Control.Concurrent.Concurrential

Description

The functions sequentially and concurrently inject IO terms into the Concurrential monad. This monad's Applicative instance will exploit as much concurrency as possible, much like the Concurrently monad from async, such that all sequentially terms will be run in the order in which they would have been run had they been typical IOs.

Synopsis

Documentation

data Concurrential m t Source

Description of computation which is composed of sequential and concurrent parts in some monad m.

type Runner f g = forall a. f a -> IO (g a) Source

This corresponds to the notion of a common type of monad transformer: there is some monad g, and then its associated transformer type f, for instance MaybeT = f and Maybe = g If we have an

      f m a
    

then we can get an

      m (g a)
    

Here we're interested in the special case where we can achieve IO (g a). This does not mean we have to be dealing with an f IO a, it could mean that the IO is buried deeper in the transformer stack!

Motivation: Async functions work with IO and only IO, but the m parameter of a Concurrential may be some other monad which is capable of performing IO, like Either String IO for instance. In order to run computations in this moand through Async, we need to know how to get a hold of an IO. That's what the runner does.

type Joiner g = forall a. g (IO a) -> IO (g a) Source

A witness of this type proves that g is in some sense compatible with IO: we can bind through it.

runConcurrential Source

Arguments

:: (Functor f, Applicative f, Monad f) 
=> Joiner f 
-> Runner m f 
-> Concurrential m t 
-> (Async (f t) -> IO (f r))

Similar contract to withAsync; the Async argument is useless outside of this function.

-> IO (f r) 

Run a Concurrential term, realizing the effects of the IO-like terms which compose it.

sequentially :: m t -> Concurrential m t Source

Create an effect which must be run sequentially. If a sequentially io appears in a Concurrential t term then it will always be run to completion before any later sequential part of the term is run. Consider the following terms:

    a = someConcurrential *> sequentially io *> someOtherConcurrential
    b = someConcurrential *> concurrently io *> someOtherConcurrential
    c = someConcurrential *> sequentially io *> concurrently otherIo
  

When running the term a, we are guaranteed that io is completed before any sequential part of someOtherConcurrential is begun, but when running the term b, this is not the case; io may be interleaved with or even run after any part of someOtherConcurrential. The term c highlights an important point: concurrently otherIo may be run before, during or after sequentially io! The ordering through applicative combinators is guaranteed only among sequential terms.

concurrently :: m t -> Concurrential m t Source

Create an effect which is run concurrently where possible, i.e. whenever it combined applicatively with other terms. For instance:

    a = concurrently io *> someConcurrential
    b = concurrently io >> someConcurrential
  

When running the term a, the IO term io will be run concurrently with someConcurrential, but not so in b, because monadic composition has been used.

wait :: Async a -> IO a

Wait for an asynchronous action to complete, and return its value. If the asynchronous action threw an exception, then the exception is re-thrown by wait.

wait = atomically . waitSTM