-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Extensible effects using ContT, State and variants.
--   
--   Interpreting commmands with extensible effects using Cont/Concur
--   monad, State, and variants.
@package glazier
@version 1.0.0.0

module Glazier.Command

-- | Converts a handler that result in monad transformer stack with a
--   <a>State</a> of list of commands to a handler that result in a list of
--   commands, using the current monad context, by running the State of
--   comands with mempty like Writer.
class Monad m => MonadCodify cmd m | m -> cmd
codifies :: MonadCodify cmd m => (a -> m ()) -> m (a -> [cmd])

-- | Variation of <a>codifies</a> to transform the monad stack instead of a
--   handler.
codifies' :: (MonadCodify cmd m) => m () -> m [cmd]

-- | Variation of <a>codifies</a> to output a handler that result in a
--   single command
codify :: (AsFacet [cmd] cmd, MonadCodify cmd m) => (a -> m ()) -> m (a -> cmd)

-- | Variation of <a>codify</a> to transform the monad stack instead of a
--   handler.
codify' :: (AsFacet [cmd] cmd, MonadCodify cmd m) => m () -> m cmd
type MonadCommand cmd m = (MonadState (DList cmd) m, MonadDelegate () m, MonadCodify cmd m, AsFacet [cmd] cmd)

-- | convert a request type to a command type. This is used for commands
--   that doesn't have a continuation. Ie. commands that doesn't "returns"
--   a value from running an effect. Use <a>command'</a> for commands that
--   require a continuation ("returns" a value).
command :: (AsFacet c cmd) => c -> cmd

-- | A variation of <a>command</a> for commands with a type variable
--   <tt>cmd</tt>, which is usually commands that are containers of
--   command, or commands that require a continuation Eg. commands that
--   "returns" a value from running an effect.
command' :: (AsFacet (c cmd) cmd) => c cmd -> cmd

-- | This helps allow executors of commands of a results only need to
--   execute the type <tt>c cmd</tt>, ie, when the command result in the
--   next <tt>cmd</tt>. This function is useful to fmap a command with a
--   result of unit to to a command with a result <tt>cmd</tt> type.
command_ :: (AsFacet [cmd] cmd) => () -> cmd

-- | Convert a list of commands to a command. This implementation avoids
--   nesting for lists of a single command.
commands :: (AsFacet [cmd] cmd) => [cmd] -> cmd

-- | Add a command to the list of commands for this MonadState. I basically
--   want a Writer monad, but I'm using a State monad because but I also
--   want to use it inside a ContT which only has an instance of
--   MonadState.
instruct :: (MonadState (DList cmd) m) => cmd -> m ()

-- | Adds a list of commands to the list of commands for this MonadState.
instructs :: (MonadState (DList cmd) m) => [cmd] -> m ()

-- | <pre>
--   <a>exec</a> = <a>instruct</a> . <a>command</a>
--   </pre>
exec :: (MonadState (DList cmd) m, AsFacet c cmd) => c -> m ()

-- | <pre>
--   <a>exec'</a> = <a>instruct</a> . <a>command'</a>
--   </pre>
exec' :: (MonadState (DList cmd) m, AsFacet (c cmd) cmd) => c cmd -> m ()

-- | <pre>
--   <a>exec'</a> = <a>instruct</a> . <a>command'</a>
--   </pre>
exec_ :: (Functor c, MonadState (DList cmd) m, AsFacet [cmd] cmd, AsFacet (c cmd) cmd) => c () -> m ()
eval :: (MonadCommand cmd m, AsFacet [cmd] cmd, AsFacet c cmd) => ((a -> cmd) -> c) -> m a
eval' :: (MonadCommand cmd m, AsFacet [cmd] cmd, AsFacet (c cmd) cmd) => ((a -> cmd) -> c cmd) -> m a

-- | Adds a <a>MonadCont</a> constraint. It is redundant but rules out
--   using <a>Concur</a> at the bottom of the transformer stack.
--   <a>sequentially</a> is used for operations that MUST run sequentially,
--   not concurrently. Eg. when the overhead of using <a>Concur</a>
--   <a>MVar</a> is not worth it, or when data dependencies are not
--   explicitly specified by monadic binds, Eg. A command to update mutable
--   variable must exact before a command that reads from the mutable
--   variable. In this case, the reference to the variable doesn't change,
--   so the data dependency is not explicit.
sequentially :: MonadCont m => m a -> m a

-- | Retrieves the result of a functor command.
dispatch :: (AsFacet (c cmd) cmd, MonadCommand cmd m, Functor c) => c a -> m a

-- | Retrieves the result of a functor command. A simpler variation of
--   <a>dispatch</a> that only requires a <tt>MonadState (DL.DList cmd)
--   m</tt>
dispatch_ :: (AsFacet (c cmd) cmd, AsFacet [cmd] cmd, MonadState (DList cmd) m, Functor c) => c () -> m ()
concurringly :: (MonadCommand cmd m, AsConcur cmd) => Concur cmd a -> m a

-- | This is a monad morphism that can be used to <a>hoist</a> transformer
--   stacks on <tt>Concur cmd ()</tt> A simpler variation of
--   <a>concurringly</a> that only requires a <tt>MonadState (DL.DList cmd)
--   m</tt>
concurringly_ :: (MonadState (DList cmd) m, AsConcur cmd) => Concur cmd () -> m ()
type AsConcur cmd = (AsFacet [cmd] cmd, AsFacet (Concur cmd cmd) cmd)

-- | This monad is intended to be used with <tt>ApplicativeDo</tt> to allow
--   do notation for composing commands that can be run concurrently. The
--   <a>Applicative</a> instance can merge multiple commands into the
--   internal state of <tt>DList c</tt>. The <a>Monad</a> instance creates
--   a <tt>ConcurCmd</tt> command before continuing the bind.
newtype Concur cmd a
Concur :: StateT (DList cmd) NewEmptyMVar (Either (IO a) a) -> Concur cmd a
[runConcur] :: Concur cmd a -> StateT (DList cmd) NewEmptyMVar (Either (IO a) a)

-- | NB. Don't export NewEmptyMVar constructor to guarantee that that it
--   only contains non-blocking <a>newEmptyMVar</a> IO.
data NewEmptyMVar a
unNewEmptyMVar :: NewEmptyMVar a -> IO a
instance GHC.Generics.Generic (Glazier.Command.Concur cmd a)
instance GHC.Base.Monad Glazier.Command.NewEmptyMVar
instance GHC.Base.Applicative Glazier.Command.NewEmptyMVar
instance GHC.Base.Functor Glazier.Command.NewEmptyMVar
instance Glazier.Command.AsConcur cmd => Control.Monad.State.Class.MonadState (Data.DList.DList cmd) (Glazier.Command.Concur cmd)
instance Glazier.Command.AsConcur cmd => GHC.Base.Monad (Glazier.Command.Concur cmd)
instance Glazier.Command.AsConcur cmd => Glazier.Command.MonadCodify cmd (Glazier.Command.Concur cmd)
instance Glazier.Command.AsConcur cmd => Control.Monad.Delegate.MonadDelegate () (Glazier.Command.Concur cmd)
instance GHC.Show.Show (Glazier.Command.Concur cmd a)
instance GHC.Base.Functor (Glazier.Command.Concur cmd)
instance GHC.Base.Applicative (Glazier.Command.Concur cmd)
instance Glazier.Command.MonadCodify cmd (Control.Monad.Trans.State.Strict.State (Data.DList.DList cmd))
instance Glazier.Command.MonadCodify cmd (Control.Monad.Trans.State.Lazy.State (Data.DList.DList cmd))
instance Glazier.Command.MonadCodify cmd m => Glazier.Command.MonadCodify cmd (Control.Monad.Trans.Identity.IdentityT m)
instance Glazier.Command.MonadCodify cmd m => Glazier.Command.MonadCodify cmd (Control.Monad.Trans.Cont.ContT () m)
instance Glazier.Command.MonadCodify cmd m => Glazier.Command.MonadCodify cmd (Control.Monad.Trans.Reader.ReaderT r m)
instance Glazier.Command.MonadCodify cmd m => Glazier.Command.MonadCodify cmd (Control.Monad.Trans.Maybe.MaybeT m)
instance (Control.Monad.Delegate.MonadDelegate () m, Glazier.Command.MonadCodify cmd m) => Glazier.Command.MonadCodify cmd (Control.Monad.Trans.Except.ExceptT e m)

module Glazier.Command.Exec

-- | type function to get the list of effects in a <tt>c</tt>,
--   parameterized over <tt>cmd</tt>

-- | A command type that removes the <tt>IO cmd</tt> from the
--   <tt>CmdTypes</tt> of the input <tt>cmd</tt>
newtype NoIOCmd cmd
NoIOCmd :: Which (CmdTypes (NoIOCmd cmd) (NoIOCmd cmd)) -> NoIOCmd cmd
[unNoIOCmd] :: NoIOCmd cmd -> Which (CmdTypes (NoIOCmd cmd) (NoIOCmd cmd))

-- | Create an executor for a variant in the command type. returns a
--   <a>Proxy</a> to keep track of the the types handled by the executor.
maybeExec :: (Applicative m, AsFacet a c) => (a -> m b) -> c -> MaybeT m (Proxy '[a], b)

-- | Tie an executor with itself to get the final interpreter
fixExec :: Functor m => ((cmd -> m ()) -> cmd -> MaybeT m (Proxy cmds, ())) -> cmd -> m (Proxy cmds, ())

-- | Use this function to verify at compile time that the given executor
--   will fullfill all the variant types in a command type.
--   redundant-constraints: used to constrain xs and ys
verifyExec :: (AppendUnique '[] ys ~ ys, AppendUnique xs ys ~ xs, AppendUnique ys xs ~ ys, Functor m) => (cmd -> Which xs) -> (cmd -> m (Proxy ys, b)) -> (cmd -> m b)
verifyFixExec :: (AppendUnique '[] ys ~ ys, AppendUnique xs ys ~ xs, AppendUnique ys xs ~ ys, Functor m, Functor m) => (cmd -> Which xs) -> ((cmd -> m ()) -> cmd -> MaybeT m (Proxy ys, ())) -> cmd -> m ()

-- | Combines executors, keeping track of the combined list of types
--   handled. redundant-constraints: used to constrain a''
orMaybeExec :: (Monad m, a'' ~ Append a a') => MaybeT m (Proxy a, b) -> MaybeT m (Proxy a', b) -> MaybeT m (Proxy a'', b)
infixl 3 `orMaybeExec`
execConcur :: MonadUnliftIO m => (cmd -> m ()) -> Concur cmd a -> m a
instance forall k a (cmd :: k). Data.Diverse.Lens.Which.AsFacet a (Data.Diverse.Which.Internal.Which (Glazier.Command.Exec.CmdTypes (Glazier.Command.Exec.NoIOCmd cmd) (Glazier.Command.Exec.NoIOCmd cmd))) => Data.Diverse.Lens.Which.AsFacet a (Glazier.Command.Exec.NoIOCmd cmd)
