Copyright | (c) Alexander Vieth, 2015 |
---|---|

License | BSD3 |

Maintainer | aovieth@gmail.com |

Stability | experimental |

Portability | non-portable (GHC only) |

Safe Haskell | None |

Language | Haskell2010 |

The functions `sequentially`

and `concurrently`

inject `IO`

terms into the
`ConcurrentialAp`

applicative functor, whose applicative instance will exploit
as much concurrency as possible such that all `sequentially`

terms will be run
in the order in which they would have been run had they been typical IOs.

Terms of `ConcurrentialAp`

can be transformed into terms of `Concurrential`

,
which is a monad. The order of sequential terms is respected even through
binds; a sequential term will not be evaluted until all binds appearing
syntactically earlier than it have been expanded.

- data Concurrential t
- newtype ConcurrentialAp t = ConcurrentialAp (Concurrential t)
- runConcurrential :: Concurrential t -> (Async t -> IO r) -> IO r
- sequentially :: IO t -> ConcurrentialAp t
- concurrently :: IO t -> ConcurrentialAp t
- concurrentially :: ConcurrentialAp t -> Concurrential t
- wait :: Async a -> IO a

# Documentation

data Concurrential t Source

Description of computation which is composed of sequential and concurrent parts.

newtype ConcurrentialAp t Source

Concurrential without a Monad instance, but an Applicative instance which exploits concurrency.

:: Concurrential t | |

-> (Async t -> IO r) | Similar contract to withAsync; the Async argument is useless outside of this function. |

-> IO r |

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

sequentially :: IO t -> ConcurrentialAp 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 :: IO t -> ConcurrentialAp 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.

concurrentially :: ConcurrentialAp t -> Concurrential t Source

Inject a ConcurrentialAp into Concurrential, losing the concurrency-enabling Applicative instance but gaining a Monad instance.