-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Coroutine monad transformer for suspending and resuming monadic computations -- -- This package defines a monad transformer, applicable to any monad, -- that allows the monadic computation to suspend and to be later -- resumed. The transformer is parameterized by an arbitrary functor, -- used to store the suspended computation's resumption. @package monad-coroutine @version 0.5 -- | 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
--   
module Control.Monad.Coroutine -- | Suspending, resumable monadic computations. newtype Coroutine s m r Coroutine :: m (Either (s (Coroutine s m r)) r) -> Coroutine s m 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. resume :: Coroutine s m r -> m (Either (s (Coroutine s m r)) r) -- | Suspend the current Coroutine. suspend :: (Monad m, Functor s) => s (Coroutine s m x) -> Coroutine s m x -- | Change the base monad of a Coroutine. mapMonad :: (Functor s, Monad m, Monad m') => (forall x. m x -> m' x) -> Coroutine s m x -> Coroutine s m' x -- | Change the suspension functor of a Coroutine. mapSuspension :: (Functor s, Monad m) => (forall x. s x -> s' x) -> Coroutine s m x -> Coroutine s' m x -- | The Naught functor instance doesn't contain anything and cannot -- be constructed. Used for building non-suspendable coroutines. data Naught x -- | Convert a non-suspending Coroutine to the base monad. runCoroutine :: (Monad m) => Coroutine Naught m x -> m x -- | Run a suspendable Coroutine, using a function that extracts the -- coroutine resumption from each suspension. pogoStick :: (Monad m) => (s (Coroutine s m x) -> Coroutine s m x) -> Coroutine s m x -> m x -- | Runs a suspendable coroutine much like pogoStick, but allows -- the resumption function to thread an arbitrary state as well. foldRun :: (Monad m) => (a -> s (Coroutine s m x) -> (a, Coroutine s m x)) -> a -> Coroutine s m x -> m (a, x) -- | 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. 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) -- | A simple record containing the resolver functions for all possible -- coroutine pair suspensions. data SeesawResolver s1 s2 SeesawResolver :: (forall t. s1 t -> t) -> (forall t. s2 t -> t) -> (forall t1 t2 r. (t1 -> r) -> (t2 -> r) -> (t1 -> t2 -> r) -> s1 t1 -> s2 t2 -> r) -> SeesawResolver s1 s2 -- | resolves the left suspension functor into the resumption it contains resumeLeft :: SeesawResolver s1 s2 -> forall t. s1 t -> t -- | resolves the right suspension into its resumption resumeRight :: SeesawResolver s1 s2 -> forall t. s2 t -> t -- | invoked when both coroutines are suspended, resolves both suspensions -- or either one resumeAny :: SeesawResolver s1 s2 -> forall t1 t2 r. (t1 -> r) -> (t2 -> r) -> (t1 -> t2 -> r) -> s1 t1 -> s2 t2 -> r -- | Combines two functors into one, applying both. newtype NestedFunctor l r x NestedFunctor :: (l (r x)) -> NestedFunctor l r x -- | Combines two functors into one, applying either or both of them. Used -- for coupled coroutines. data SomeFunctor l r x LeftSome :: (l x) -> SomeFunctor l r x RightSome :: (r x) -> SomeFunctor l r x Both :: (NestedFunctor l r x) -> SomeFunctor l r x -- | Combines two values under two functors into a pair of values under a -- single NestedFunctor. nest :: (Functor a, Functor b) => a x -> b y -> NestedFunctor a b (x, y) -- | Weaves two coroutines into one. The two coroutines suspend and resume -- in lockstep. couple :: (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) -- | Weaves a list of coroutines with the same suspension functor type into -- a single coroutine. The coroutines suspend and resume in lockstep. merge :: (Monad m, Functor s) => (forall x. [m x] -> m [x]) -> (forall x. [s x] -> s [x]) -> [Coroutine s m x] -> Coroutine s m [x] instance (Functor l, Functor r) => Functor (SomeFunctor l r) instance (Functor l, Functor r) => Functor (NestedFunctor l r) instance Functor Naught instance (Functor s, MonadIO m) => MonadIO (Coroutine s m) instance (Functor s) => MonadTrans (Coroutine s) instance (Functor s, MonadParallel m) => MonadParallel (Coroutine s m) instance (Functor s, Monad m) => Monad (Coroutine s m) -- | This module defines suspension functors for use with the -- Control.Monad.Coroutine module. module Control.Monad.Coroutine.SuspensionFunctors -- | The Yield functor instance is equivalent to (,) but more -- descriptive. data Yield x y Yield :: x -> y -> Yield x y -- | The Await functor instance is equivalent to (->) but more -- descriptive. newtype Await x y Await :: (x -> y) -> Await x y -- | The Request functor instance combines a Yield of a -- request with an Await for a response. data Request request response x Request :: request -> (response -> x) -> Request request response x -- | Combines two alternative functors into one, applying one or the other. -- Used for nested coroutines. data EitherFunctor l r x LeftF :: (l x) -> EitherFunctor l r x RightF :: (r x) -> EitherFunctor l r x -- | Suspend yielding a value. yield :: (Monad m) => x -> Coroutine (Yield x) m () -- | Suspend until a value is provided. await :: (Monad m) => Coroutine (Await x) m x -- | Suspend yielding a request and awaiting the response. request :: (Monad m) => x -> Coroutine (Request x y) m y instance (Functor l, Functor r) => Functor (EitherFunctor l r) instance Functor (Request x f) instance Functor (Await x) instance Functor (Yield x) -- | This module defines nestable suspension functors for use with the -- Coroutine monad transformer, as well as functions for running -- nested coroutines of this sort. -- -- Coroutines can be run from within another coroutine. In this case, the -- nested coroutines always suspend to their invoker. If a function from -- this module, such as pogoStickNested, is used to run a nested -- coroutine, the parent coroutine can be automatically suspended as -- well. A single suspension can thus suspend an entire chain of nested -- coroutines. -- -- Nestable coroutines of this kind should group their suspension -- functors into an EitherFunctor. You can adjust a normal -- suspension, such as the one produced by yield, using functions -- mapSuspension and liftOut. To run nested coroutines, use -- functions pogoStickNested, seesawNested, and -- coupleNested. module Control.Monad.Coroutine.Nested -- | Run a nested Coroutine that can suspend both itself and the -- current Coroutine. pogoStickNested :: (Functor s1, Functor s2, Monad m) => (s2 (Coroutine (EitherFunctor s1 s2) m x) -> Coroutine (EitherFunctor s1 s2) m x) -> Coroutine (EitherFunctor s1 s2) m x -> Coroutine s1 m x -- | Weaves two nested coroutines into one. coupleNested :: (Monad m, Functor s0, Monad s0, Functor s1, Functor s2) => (forall x y r. (x -> y -> m r) -> m x -> m y -> m r) -> Coroutine (EitherFunctor s0 s1) m x -> Coroutine (EitherFunctor s0 s2) m y -> Coroutine (EitherFunctor s0 (SomeFunctor s1 s2)) m (x, y) -- | Like seesaw, but for nested coroutines that are allowed to -- suspend the current coroutine as well as themselves. If both -- coroutines try to suspend the current coroutine in the same step, the -- left coroutine's suspension will have precedence. seesawNested :: (Monad m, Functor s0, Functor s1, Functor s2) => (forall x y r. (x -> y -> m r) -> m x -> m y -> m r) -> SeesawResolver s1 s2 -> Coroutine (EitherFunctor s0 s1) m x -> Coroutine (EitherFunctor s0 s2) m y -> Coroutine s0 m (x, y) -- | Class of functors that can be lifted. class (Functor a, Functor d) => AncestorFunctor a d -- | Converts a coroutine into a descendant nested coroutine. liftOut :: (Monad m, Functor a, AncestorFunctor a d) => Coroutine a m x -> Coroutine d m x instance [overlap ok] (d' ~ Parent d, Functor a, ChildFunctor d, AncestorFunctor a d') => AncestorFunctor a d instance [overlap ok] (Functor a) => AncestorFunctor a a instance [overlap ok] (Functor p, Functor s) => ChildFunctor (EitherFunctor p s)