-- 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.9.0.3


-- | This module defines the <a>Coroutine</a> monad transformer.
--   
--   A <a>Coroutine</a> monadic computation can <a>suspend</a> its
--   execution at any time, returning control to its invoker. The returned
--   suspension value contains the coroutine's resumption wrapped in a
--   <a>Functor</a>. Here is an example of a coroutine in the <a>IO</a>
--   monad that suspends computation using the functor <tt>Yield</tt> from
--   the <a>Control.Monad.Coroutine.SuspensionFunctors</a> module:
--   
--   <pre>
--   producer :: Coroutine (Yield Int) IO String
--   producer = do yield 1
--                 lift (putStrLn "Produced one, next is four.")
--                 yield 4
--                 return "Finished"
--   </pre>
--   
--   To continue the execution of a suspended <a>Coroutine</a>, extract it
--   from the suspension functor and apply its <a>resume</a> method. The
--   easiest way to run a coroutine to completion is by using the
--   <a>pogoStick</a> function, which keeps resuming the coroutine in
--   trampolined style until it completes. Here is one way to apply
--   <a>pogoStick</a> to the <i>producer</i> example above:
--   
--   <pre>
--   printProduce :: Show x =&gt; Coroutine (Yield x) IO r -&gt; IO r
--   printProduce producer = pogoStick (\(Yield x cont) -&gt; lift (print x) &gt;&gt; cont) producer
--   </pre>
--   
--   Multiple concurrent coroutines can be run as well, and this module
--   provides two different ways. To run two interleaved computations, use
--   a <a>WeaveStepper</a> to <a>weave</a> together steps of two different
--   coroutines into a single coroutine, which can then be executed by
--   <a>pogoStick</a>.
--   
--   For various uses of trampoline-style coroutines, see
--   
--   <pre>
--   Coroutine Pipelines - Mario Blažević, The Monad.Reader issue 19, pages 29-50
--   </pre>
--   
--   <pre>
--   Trampolined Style - Ganz, S. E. Friedman, D. P. Wand, M, ACM SIGPLAN NOTICES, 1999, VOL 34; NUMBER 9, pages 18-27
--   </pre>
--   
--   and
--   
--   <pre>
--   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
--   </pre>
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 <a>Coroutine</a> 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)
type CoroutineStepResult s m r = Either (s (Coroutine s m r)) r

-- | Suspend the current <a>Coroutine</a>.
suspend :: (Monad m, Functor s) => s (Coroutine s m x) -> Coroutine s m x

-- | Change the base monad of a <a>Coroutine</a>.
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

-- | Change the suspension functor of a <a>Coroutine</a>.
mapSuspension :: (Functor s, Monad m) => (forall y. s y -> s' y) -> Coroutine s m x -> Coroutine s' m x

-- | Modify the first upcoming suspension of a <a>Coroutine</a>.
mapFirstSuspension :: forall s m x. (Functor s, Monad m) => (forall y. s y -> s y) -> Coroutine s m x -> Coroutine s m x

-- | The <a>Naught</a> functor instance doesn't contain anything and cannot
--   be constructed. Used for building non-suspendable coroutines.
data Naught x

-- | Convert a non-suspending <a>Coroutine</a> to the base monad.
runCoroutine :: Monad m => Coroutine Naught m x -> m x

-- | Runs a single step of a suspendable <a>Coroutine</a>, using a function
--   that extracts the coroutine resumption from its suspension functor.
bounce :: (Monad m, Functor s) => (s (Coroutine s m x) -> Coroutine s m x) -> Coroutine s m x -> Coroutine s m x

-- | Runs a suspendable <a>Coroutine</a> to its completion.
pogoStick :: Monad m => (s (Coroutine s m x) -> Coroutine s m x) -> Coroutine s m x -> m x

-- | Runs a suspendable <a>Coroutine</a> to its completion with a monadic
--   action.
pogoStickM :: Monad m => (s (Coroutine s m x) -> m (Coroutine s m x)) -> Coroutine s m x -> m x

-- | Runs a suspendable coroutine much like <a>pogoStick</a>, 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)

-- | Type of functions that can bind two monadic values together, used to
--   combine two coroutines' step results. The two functions provided here
--   are <a>sequentialBinder</a> and <a>parallelBinder</a>.
type PairBinder m = forall x y r. (x -> y -> m r) -> m x -> m y -> m r

-- | A <a>PairBinder</a> that runs the two steps sequentially before
--   combining their results.
sequentialBinder :: Monad m => PairBinder m

-- | A <a>PairBinder</a> that runs the two steps in parallel.
parallelBinder :: MonadParallel m => PairBinder m

-- | Lifting a <a>PairBinder</a> onto a <a>Coroutine</a> monad transformer.
liftBinder :: forall s m. (Functor s, Monad m) => PairBinder m -> PairBinder (Coroutine s m)

-- | Type of functions that can weave two coroutines into a single
--   coroutine.
type Weaver s1 s2 s3 m x y z = Coroutine s1 m x -> Coroutine s2 m y -> Coroutine s3 m z

-- | Type of functions capable of combining two coroutines'
--   <a>CoroutineStepResult</a> values into a third one. Module
--   <a>Monad.Coroutine.SuspensionFunctors</a> contains several
--   <a>WeaveStepper</a> examples.
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

-- | Weaves two coroutines into one, given a <a>PairBinder</a> to run the
--   next step of each coroutine and a <a>WeaveStepper</a> to combine the
--   results of the steps.
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

-- | Weaves a list of coroutines with the same suspension functor type into
--   a single coroutine. The coroutines suspend and resume in lockstep.
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]
instance (GHC.Base.Functor s, GHC.Base.Functor m) => GHC.Base.Functor (Control.Monad.Coroutine.Coroutine s m)
instance (GHC.Base.Functor s, GHC.Base.Functor m, GHC.Base.Monad m) => GHC.Base.Applicative (Control.Monad.Coroutine.Coroutine s m)
instance (GHC.Base.Functor s, GHC.Base.Monad m) => GHC.Base.Monad (Control.Monad.Coroutine.Coroutine s m)
instance (GHC.Base.Functor s, Control.Monad.Parallel.MonadParallel m) => Control.Monad.Parallel.MonadParallel (Control.Monad.Coroutine.Coroutine s m)
instance GHC.Base.Functor s => Control.Monad.Trans.Class.MonadTrans (Control.Monad.Coroutine.Coroutine s)
instance (GHC.Base.Functor s, Control.Monad.IO.Class.MonadIO m) => Control.Monad.IO.Class.MonadIO (Control.Monad.Coroutine.Coroutine s m)
instance GHC.Base.Functor Control.Monad.Coroutine.Naught


-- | A coroutine can choose to launch another coroutine. In this case, the
--   nested coroutines always suspend to their invoker. If a function from
--   this module, such as <a>pogoStickNested</a>, 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 a <a>Sum</a>. A simple coroutine suspension can be
--   converted to a nested one using functions <a>mapSuspension</a> and
--   <a>liftAncestor</a>. To run nested coroutines, use
--   <a>pogoStickNested</a>, or <a>weave</a> with a
--   <a>NestWeaveStepper</a>.
module Control.Monad.Coroutine.Nested

-- | Like <a>either</a> for the <a>Sum</a> data type.
eitherFunctor :: (l x -> y) -> (r x -> y) -> Sum l r x -> y

-- | Change the suspension functor of a nested <a>Coroutine</a>.
mapNestedSuspension :: (Functor s0, Functor s, Monad m) => (forall y. s y -> s' y) -> Coroutine (Sum s0 s) m x -> Coroutine (Sum s0 s') m x

-- | Run a nested <a>Coroutine</a> that can suspend both itself and the
--   current <a>Coroutine</a>.
pogoStickNested :: forall s1 s2 m x. (Functor s1, Functor s2, Monad m) => (s2 (Coroutine (Sum s1 s2) m x) -> Coroutine (Sum s1 s2) m x) -> Coroutine (Sum s1 s2) m x -> Coroutine s1 m x

-- | Type of functions capable of combining two child coroutines'
--   <a>CoroutineStepResult</a> values into a parent coroutine. Use with
--   the function <a>weave</a>.
type NestWeaveStepper s0 s1 s2 m x y z = WeaveStepper (Sum s0 s1) (Sum s0 s2) s0 m x y z

-- | Class of functors that can contain another functor.
class Functor c => ChildFunctor c where type Parent c :: * -> * where {
    type family Parent c :: * -> *;
}
wrap :: ChildFunctor c => Parent c x -> c x

-- | Class of functors that can be lifted.
class (Functor a, Functor d) => AncestorFunctor a d

-- | Convert the ancestor functor into its descendant. The descendant
--   functor typically contains the ancestor.
liftFunctor :: AncestorFunctor a d => a x -> d x

-- | Converts a coroutine into a child nested coroutine.
liftParent :: forall m p c x. (Monad m, Functor p, ChildFunctor c, p ~ Parent c) => Coroutine p m x -> Coroutine c m x

-- | Converts a coroutine into a descendant nested coroutine.
liftAncestor :: forall m a d x. (Monad m, Functor a, AncestorFunctor a d) => Coroutine a m x -> Coroutine d m x
instance (GHC.Base.Functor p, GHC.Base.Functor s) => Control.Monad.Coroutine.Nested.ChildFunctor (Data.Functor.Sum.Sum p s)
instance GHC.Base.Functor a => Control.Monad.Coroutine.Nested.AncestorFunctor a a
instance (GHC.Base.Functor a, Control.Monad.Coroutine.Nested.ChildFunctor d, d' ~ Control.Monad.Coroutine.Nested.Parent d, Control.Monad.Coroutine.Nested.AncestorFunctor a d') => Control.Monad.Coroutine.Nested.AncestorFunctor a d


-- | This module defines some common suspension functors for use with the
--   <a>Control.Monad.Coroutine</a> module.
module Control.Monad.Coroutine.SuspensionFunctors

-- | The <a>Yield</a> functor instance is equivalent to (,) but more
--   descriptive. A coroutine with this suspension functor provides a value
--   with every suspension.
data Yield x y
Yield :: x -> y -> Yield x y

-- | The <a>Await</a> functor instance is equivalent to (-&gt;) but more
--   descriptive. A coroutine with this suspension functor demands a value
--   whenever it suspends, before it can resume its execution.
newtype Await x y
Await :: (x -> y) -> Await x y

-- | The <a>Request</a> functor instance combines a <a>Yield</a> of a
--   request with an <a>Await</a> for a response.
data Request request response x
Request :: request -> (response -> x) -> Request request response x

-- | Combines a <a>Yield</a> of a <a>Reader</a> with an <a>Await</a> for a
--   <a>ReadingResult</a>.
data ReadRequest x z
data ReadingResult x py y

-- | A part of the result with the reader of more input
ResultPart :: py -> (Reader x py y) -> ReadingResult x py y

-- | Final result chunk
FinalResult :: y -> ReadingResult x py y
type Reader x py y = x -> Reading x py y
data Reading x py y

-- | Final result chunk with the unconsumed portion of the input
Final :: x -> y -> Reading x py y

-- | A part of the result with the reader of more input and the EOF
Advance :: (Reader x py y) -> y -> py -> Reading x py y

-- | Reader of more input, plus the result if there isn't any.
Deferred :: (Reader x py y) -> y -> Reading x py y

-- | Like <a>either</a> for the <a>Sum</a> data type.
eitherFunctor :: (l x -> y) -> (r x -> y) -> Sum l r x -> y

-- | Suspend the current coroutine yielding a value.
yield :: Monad m => x -> Coroutine (Yield x) m ()

-- | Suspend the current coroutine 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

-- | Suspend yielding a <a>ReadRequest</a> and awaiting the
--   <a>ReadingResult</a>.
requestRead :: (Monad m, Monoid x) => Reader x py y -> Coroutine (ReadRequest x) m (ReadingResult x py y)

-- | Converts a coroutine yielding collections of values into one yielding
--   single values.
concatYields :: (Monad m, Foldable f) => Coroutine (Yield (f x)) m r -> Coroutine (Yield x) m r

-- | Converts a coroutine awaiting single values into one awaiting
--   collections of values.
concatAwaits :: (Monad m, Foldable f) => Coroutine (Await x) m r -> Coroutine (Await (f x)) m r

-- | Weaves the suspensions of a <a>Yield</a> and an <a>Await</a> coroutine
--   together into a plain <a>Identity</a> coroutine. If the <a>Yield</a>
--   coroutine terminates first, the <a>Await</a> one is resumed using the
--   argument default value.
weaveAwaitYield :: Monad m => x -> WeaveStepper (Await x) (Yield x) Identity m r1 r2 (r1, r2)

-- | Like <a>weaveAwaitYield</a>, except the <a>Await</a> coroutine expects
--   <a>Maybe</a>-wrapped values. After the <a>Yield</a> coroutine
--   terminates, the <a>Await</a> coroutine receives only <a>Nothing</a>.
weaveAwaitMaybeYield :: Monad m => WeaveStepper (Await (Maybe x)) (Yield x) Identity m r1 r2 (r1, r2)

-- | Weaves two complementary <a>Request</a> coroutine suspensions into a
--   coroutine <a>yield</a>ing both requests. If one coroutine terminates
--   before the other, the remaining coroutine is fed the appropriate
--   default value argument.
weaveRequests :: Monad m => x -> y -> WeaveStepper (Request x y) (Request y x) (Yield (x, y)) m r1 r2 (r1, r2)

-- | The consumer coroutine requests input through <a>ReadRequest</a> and
--   gets <a>ReadingResult</a> in response. The producer coroutine receives
--   the unconsumed portion of its last requested chunk as response.
weaveReadWriteRequests :: (Monad m, Monoid x) => WeaveStepper (ReadRequest x) (Request x x) Identity m r1 r2 (r1, r2)

-- | Like <a>weaveReadWriteRequests</a> but for nested coroutines.
weaveNestedReadWriteRequests :: (Monad m, Functor s, Monoid x) => NestWeaveStepper s (ReadRequest x) (Request x x) m r1 r2 (r1, r2)
instance GHC.Base.Functor (Control.Monad.Coroutine.SuspensionFunctors.Yield x)
instance GHC.Base.Functor (Control.Monad.Coroutine.SuspensionFunctors.Await x)
instance GHC.Base.Functor (Control.Monad.Coroutine.SuspensionFunctors.Request x f)
instance GHC.Base.Functor (Control.Monad.Coroutine.SuspensionFunctors.ReadRequest x)
