Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module defines the Coroutine
monad transformer.
A Coroutine
monadic computation can suspend
its execution at any time, returning control to its invoker. The
returned suspension value contains the coroutine's resumption wrapped in a Functor
. Here is an example of a
coroutine in the IO
monad that suspends computation using the functor Yield
from the
Control.Monad.Coroutine.SuspensionFunctors module:
producer :: Coroutine (Yield Int) IO String producer = do yield 1 lift (putStrLn "Produced one, next is four.") yield 4 return "Finished"
To continue the execution of a suspended Coroutine
, extract it from the suspension functor and apply its resume
method. The easiest way to run a coroutine to completion is by using the pogoStick
function, which keeps resuming
the coroutine in trampolined style until it completes. Here is one way to apply pogoStick
to the producer example
above:
printProduce :: Show x => Coroutine (Yield x) IO r -> IO r printProduce producer = pogoStick (\(Yield x cont) -> lift (print x) >> cont) producer
Multiple concurrent coroutines can be run as well, and this module provides two different ways. To run two
interleaved computations, use a WeaveStepper
to weave
together steps of two different coroutines into a single
coroutine, which can then be executed by pogoStick
.
For various uses of trampoline-style coroutines, see
Coroutine Pipelines - Mario Blažević, The Monad.Reader issue 19, pages 29-50
Trampolined Style - Ganz, S. E. Friedman, D. P. Wand, M, ACM SIGPLAN NOTICES, 1999, VOL 34; NUMBER 9, pages 18-27
and
The Essence of Multitasking - William L. Harrison, Proceedings of the 11th International Conference on Algebraic Methodology and Software Technology, volume 4019 of Lecture Notes in Computer Science, 2006
- newtype Coroutine s m r = Coroutine {}
- type CoroutineStepResult s m r = Either (s (Coroutine s m r)) r
- suspend :: (Monad m, Functor s) => s (Coroutine s m x) -> Coroutine s m x
- mapMonad :: forall s m m' x. (Functor s, Monad m, Monad m') => (forall y. m y -> m' y) -> Coroutine s m x -> Coroutine s m' x
- mapSuspension :: (Functor s, Monad m) => (forall y. s y -> s' y) -> Coroutine s m x -> Coroutine s' m x
- mapFirstSuspension :: forall s m x. (Functor s, Monad m) => (forall y. s y -> s y) -> Coroutine s m x -> Coroutine s m x
- data Naught x
- runCoroutine :: Monad m => Coroutine Naught m x -> m x
- bounce :: (Monad m, Functor s) => (s (Coroutine s m x) -> Coroutine s m x) -> Coroutine s m x -> Coroutine s m x
- pogoStick :: Monad m => (s (Coroutine s m x) -> Coroutine s m x) -> Coroutine s m x -> m x
- pogoStickM :: Monad m => (s (Coroutine s m x) -> m (Coroutine s m x)) -> Coroutine s m x -> m x
- foldRun :: Monad m => (a -> s (Coroutine s m x) -> (a, Coroutine s m x)) -> a -> Coroutine s m x -> m (a, x)
- type PairBinder m = forall x y r. (x -> y -> m r) -> m x -> m y -> m r
- sequentialBinder :: Monad m => PairBinder m
- parallelBinder :: MonadParallel m => PairBinder m
- liftBinder :: forall s m. (Functor s, Monad m) => PairBinder m -> PairBinder (Coroutine s m)
- type Weaver s1 s2 s3 m x y z = Coroutine s1 m x -> Coroutine s2 m y -> Coroutine s3 m z
- type WeaveStepper s1 s2 s3 m x y z = Weaver s1 s2 s3 m x y z -> CoroutineStepResult s1 m x -> CoroutineStepResult s2 m y -> Coroutine s3 m z
- weave :: forall s1 s2 s3 m x y z. (Monad m, Functor s1, Functor s2, Functor s3) => PairBinder m -> WeaveStepper s1 s2 s3 m x y z -> Weaver s1 s2 s3 m x y z
- merge :: forall s m x. (Monad m, Functor s) => (forall y. [m y] -> m [y]) -> (forall y. [s y] -> s [y]) -> [Coroutine s m x] -> Coroutine s m [x]
Coroutine definition
newtype Coroutine s m r Source
Suspending, resumable monadic computations.
Functor s => MonadTrans (Coroutine s) | |
(Functor s, Monad m) => Monad (Coroutine s m) | |
(Functor s, Functor m) => Functor (Coroutine s m) | |
(Functor s, Functor m, Monad m) => Applicative (Coroutine s m) | |
(Functor s, MonadParallel m) => MonadParallel (Coroutine s m) | |
(Functor s, MonadIO m) => MonadIO (Coroutine s m) |
type CoroutineStepResult s m r = Either (s (Coroutine s m r)) r Source
suspend :: (Monad m, Functor s) => s (Coroutine s m x) -> Coroutine s m x Source
Suspend the current Coroutine
.
Coroutine operations
mapMonad :: forall s m m' x. (Functor s, Monad m, Monad m') => (forall y. m y -> m' y) -> Coroutine s m x -> Coroutine s m' x Source
Change the base monad of a Coroutine
.
mapSuspension :: (Functor s, Monad m) => (forall y. s y -> s' y) -> Coroutine s m x -> Coroutine s' m x Source
Change the suspension functor of a Coroutine
.
mapFirstSuspension :: forall s m x. (Functor s, Monad m) => (forall y. s y -> s y) -> Coroutine s m x -> Coroutine s m x Source
Modify the first upcoming suspension of a Coroutine
.
Running coroutines
The Naught
functor instance doesn't contain anything and cannot be constructed. Used for building non-suspendable
coroutines.
runCoroutine :: Monad m => Coroutine Naught m x -> m x Source
Convert a non-suspending Coroutine
to the base monad.
bounce :: (Monad m, Functor s) => (s (Coroutine s m x) -> Coroutine s m x) -> Coroutine s m x -> Coroutine s m x Source
Runs a single step of a suspendable Coroutine
, using a function that extracts the coroutine resumption from its
suspension functor.
pogoStick :: Monad m => (s (Coroutine s m x) -> Coroutine s m x) -> Coroutine s m x -> m x Source
Runs a suspendable Coroutine
to its completion.
pogoStickM :: Monad m => (s (Coroutine s m x) -> m (Coroutine s m x)) -> Coroutine s m x -> m x Source
Runs a suspendable Coroutine
to its completion with a monadic action.
foldRun :: Monad m => (a -> s (Coroutine s m x) -> (a, Coroutine s m x)) -> a -> Coroutine s m x -> m (a, x) Source
Runs a suspendable coroutine much like pogoStick
, but allows the resumption function to thread an arbitrary
state as well.
Weaving coroutines together
type PairBinder m = forall x y r. (x -> y -> m r) -> m x -> m y -> m r Source
Type of functions that can bind two monadic values together, used to combine two coroutines' step results. The two
functions provided here are sequentialBinder
and parallelBinder
.
sequentialBinder :: Monad m => PairBinder m Source
A PairBinder
that runs the two steps sequentially before combining their results.
parallelBinder :: MonadParallel m => PairBinder m Source
A PairBinder
that runs the two steps in parallel.
liftBinder :: forall s m. (Functor s, Monad m) => PairBinder m -> PairBinder (Coroutine s m) Source
Lifting a PairBinder
onto a Coroutine
monad transformer.
type Weaver s1 s2 s3 m x y z = Coroutine s1 m x -> Coroutine s2 m y -> Coroutine s3 m z Source
Type of functions that can weave two coroutines into a single coroutine.
type WeaveStepper s1 s2 s3 m x y z = Weaver s1 s2 s3 m x y z -> CoroutineStepResult s1 m x -> CoroutineStepResult s2 m y -> Coroutine s3 m z Source
Type of functions capable of combining two coroutines' CoroutineStepResult
values into a third one. Module
Monad.Coroutine.SuspensionFunctors contains several WeaveStepper
examples.
weave :: forall s1 s2 s3 m x y z. (Monad m, Functor s1, Functor s2, Functor s3) => PairBinder m -> WeaveStepper s1 s2 s3 m x y z -> Weaver s1 s2 s3 m x y z Source
Weaves two coroutines into one, given a PairBinder
to run the next step of each coroutine and a WeaveStepper
to
combine the results of the steps.