monad-coroutine-0.5: Coroutine monad transformer for suspending and resuming monadic computationsSource codeContentsIndex
Control.Monad.Coroutine
Contents
Coroutine definition
Coroutine operations
Running Coroutine computations
Nested and coupled Coroutine computations
Description

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 coroutine suspension is a Functor containing the resumption of the coroutine. 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, 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 an example of pogoStick applied 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. The function seesaw can be used to run two interleaved computations. Another possible way is to use the functions couple or merge to weave together steps of different coroutines into a single coroutine, which can then be executed by pogoStick.

For other uses of trampoline-style coroutines, see

 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 {
resume :: m (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 x. m x -> m' x) -> Coroutine s m x -> Coroutine s m' x
mapSuspension :: forall s s' m x. (Functor s, Monad m) => (forall x. s x -> s' x) -> Coroutine s m x -> Coroutine s' m x
data Naught x
runCoroutine :: Monad m => Coroutine Naught m x -> m x
pogoStick :: Monad m => (s (Coroutine s m x) -> 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)
seesaw :: (Monad m, Functor s1, Functor s2) => (forall x y r. (x -> y -> m r) -> m x -> m y -> m r) -> SeesawResolver s1 s2 -> Coroutine s1 m x -> Coroutine s2 m y -> m (x, y)
data SeesawResolver s1 s2 = SeesawResolver {
resumeLeft :: forall t. s1 t -> t
resumeRight :: forall t. s2 t -> t
resumeAny :: forall t1 t2 r. (t1 -> r) -> (t2 -> r) -> (t1 -> t2 -> r) -> s1 t1 -> s2 t2 -> r
}
newtype NestedFunctor l r x = NestedFunctor (l (r x))
data SomeFunctor l r x
= LeftSome (l x)
| RightSome (r x)
| Both (NestedFunctor l r x)
nest :: (Functor a, Functor b) => a x -> b y -> NestedFunctor a b (x, y)
couple :: forall s1 s2 m x y r. (Monad m, Functor s1, Functor s2) => (forall x y r. (x -> y -> m r) -> m x -> m y -> m r) -> Coroutine s1 m x -> Coroutine s2 m y -> Coroutine (SomeFunctor s1 s2) m (x, y)
merge :: forall s m x. (Monad m, Functor s) => (forall x. [m x] -> m [x]) -> (forall x. [s x] -> s [x]) -> [Coroutine s m x] -> Coroutine s m [x]
Coroutine definition
newtype Coroutine s m r Source
Suspending, resumable monadic computations.
Constructors
Coroutine
resume :: m (Either (s (Coroutine s m r)) r)Run the next step of a Coroutine computation. The result of the step execution will be either a suspension or the final coroutine result.
show/hide Instances
suspend :: (Monad m, Functor s) => s (Coroutine s m x) -> Coroutine s m xSource
Suspend the current Coroutine.
Coroutine operations
mapMonad :: forall s m m' x. (Functor s, Monad m, Monad m') => (forall x. m x -> m' x) -> Coroutine s m x -> Coroutine s m' xSource
Change the base monad of a Coroutine.
mapSuspension :: forall s s' m x. (Functor s, Monad m) => (forall x. s x -> s' x) -> Coroutine s m x -> Coroutine s' m xSource
Change the suspension functor of a Coroutine.
Running Coroutine computations
data Naught x Source
The Naught functor instance doesn't contain anything and cannot be constructed. Used for building non-suspendable coroutines.
show/hide Instances
runCoroutine :: Monad m => Coroutine Naught m x -> m xSource
Convert a non-suspending Coroutine to the base monad.
pogoStick :: Monad m => (s (Coroutine s m x) -> Coroutine s m x) -> Coroutine s m x -> m xSource
Run a suspendable Coroutine, using a function that extracts the coroutine resumption from each suspension.
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.
seesaw :: (Monad m, Functor s1, Functor s2) => (forall x y r. (x -> y -> m r) -> m x -> m y -> m r) -> SeesawResolver s1 s2 -> Coroutine s1 m x -> Coroutine s2 m y -> m (x, y)Source
Runs two coroutines concurrently. The first argument is used to run the next step of each coroutine, the next to convert the left, right, or both suspensions into the corresponding resumptions.
data SeesawResolver s1 s2 Source
A simple record containing the resolver functions for all possible coroutine pair suspensions.
Constructors
SeesawResolver
resumeLeft :: forall t. s1 t -> tresolves the left suspension functor into the resumption it contains
resumeRight :: forall t. s2 t -> tresolves the right suspension into its resumption
resumeAny :: forall t1 t2 r. (t1 -> r) -> (t2 -> r) -> (t1 -> t2 -> r) -> s1 t1 -> s2 t2 -> rinvoked when both coroutines are suspended, resolves both suspensions or either one
Nested and coupled Coroutine computations
newtype NestedFunctor l r x Source
Combines two functors into one, applying both.
Constructors
NestedFunctor (l (r x))
show/hide Instances
data SomeFunctor l r x Source
Combines two functors into one, applying either or both of them. Used for coupled coroutines.
Constructors
LeftSome (l x)
RightSome (r x)
Both (NestedFunctor l r x)
show/hide Instances
nest :: (Functor a, Functor b) => a x -> b y -> NestedFunctor a b (x, y)Source
Combines two values under two functors into a pair of values under a single NestedFunctor.
couple :: forall s1 s2 m x y r. (Monad m, Functor s1, Functor s2) => (forall x y r. (x -> y -> m r) -> m x -> m y -> m r) -> Coroutine s1 m x -> Coroutine s2 m y -> Coroutine (SomeFunctor s1 s2) m (x, y)Source
Weaves two coroutines into one. The two coroutines suspend and resume in lockstep.
merge :: forall s m x. (Monad m, Functor s) => (forall x. [m x] -> m [x]) -> (forall x. [s x] -> s [x]) -> [Coroutine s m x] -> Coroutine s m [x]Source
Weaves a list of coroutines with the same suspension functor type into a single coroutine. The coroutines suspend and resume in lockstep.
Produced by Haddock version 2.7.2