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
Synopsis
- 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.
Instances
Functor s => MonadTrans (Coroutine s) Source # | |
Defined in Control.Monad.Coroutine | |
(Functor s, Monad m) => Monad (Coroutine s m) Source # | |
(Functor s, Functor m) => Functor (Coroutine s m) Source # | |
(Functor s, MonadFail m) => MonadFail (Coroutine s m) Source # | |
Defined in Control.Monad.Coroutine | |
(Functor s, Functor m, Monad m) => Applicative (Coroutine s m) Source # | |
Defined in Control.Monad.Coroutine pure :: a -> Coroutine s m a # (<*>) :: Coroutine s m (a -> b) -> Coroutine s m a -> Coroutine s m b # liftA2 :: (a -> b -> c) -> Coroutine s m a -> Coroutine s m b -> Coroutine s m c # (*>) :: Coroutine s m a -> Coroutine s m b -> Coroutine s m b # (<*) :: Coroutine s m a -> Coroutine s m b -> Coroutine s m a # | |
(Functor s, MonadIO m) => MonadIO (Coroutine s m) Source # | |
Defined in Control.Monad.Coroutine | |
(Functor s, MonadParallel m) => MonadParallel (Coroutine s m) Source # | |
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.