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

-- | Typeclasses for representing monad transformer unlifting
--   
--   See README.md
@package monad-unlift
@version 0.2.0

-- | See overview in the README.md
module Control.Monad.Trans.Unlift

-- | A monad transformer which can be unlifted, obeying the monad morphism
--   laws.
--   
--   Since 0.1.0
class (MonadTransControl t, Forall (Identical t)) => MonadTransUnlift t

-- | A function which can move an action down the monad transformer stack,
--   by providing any necessary environment to the action.
--   
--   Note that, if ImpredicativeTypes worked reliably, this type wouldn't
--   be necessary, and askUnlift would simply include a more
--   generalized type.
--   
--   Since 0.1.0
newtype Unlift t
Unlift :: (forall a n. Monad n => t n a -> n a) -> Unlift t
[unlift] :: Unlift t -> forall a n. Monad n => t n a -> n a

-- | Get the Unlift action for the current transformer layer.
--   
--   Since 0.1.0
askUnlift :: forall t m. (MonadTransUnlift t, Monad m) => t m (Unlift t)

-- | A simplified version of askUnlift which addresses the common
--   case where polymorphism isn't necessary.
--   
--   Since 0.1.0
askRun :: (MonadTransUnlift t, Monad (t m), Monad m) => t m (t m a -> m a)

-- | A monad transformer stack which can be unlifted, obeying the monad
--   morphism laws.
--   
--   Since 0.1.0
class (MonadBaseControl b m, Forall (IdenticalBase m)) => MonadBaseUnlift b m | m -> b

-- | Similar to Unlift, but instead of moving one layer down the
--   stack, moves the action to the base monad.
--   
--   Since 0.1.0
newtype UnliftBase b m
UnliftBase :: (forall a. m a -> b a) -> UnliftBase b m
[unliftBase] :: UnliftBase b m -> forall a. m a -> b a

-- | Get the UnliftBase action for the current transformer stack.
--   
--   Since 0.1.0
askUnliftBase :: forall b m. MonadBaseUnlift b m => m (UnliftBase b m)

-- | A simplified version of askUnliftBase which addresses the
--   common case where polymorphism isn't necessary.
--   
--   Since 0.1.0
askRunBase :: MonadBaseUnlift b m => m (m a -> b a)

-- | The class of monad transformers. Instances should satisfy the
--   following laws, which state that lift is a monad
--   transformation:
--   
--   
--   
- 
lift . return = return

--   
- 
lift (m >>= f) = lift m >>=
--   (lift . f)

--   
class MonadTrans (t :: Type -> Type -> Type -> Type)

-- | Lift a computation from the argument monad to the constructed monad.
lift :: (MonadTrans t, Monad m) => m a -> t m a
class (Applicative b, Applicative m, Monad b, Monad m) => MonadBase (b :: Type -> Type) (m :: Type -> Type) | m -> b

-- | Lift a computation from the base monad
liftBase :: MonadBase b m => b α -> m α

-- | The MonadTransControl type class is a stronger version of
--   MonadTrans:
--   
--   Instances of MonadTrans know how to
--   lift actions in the base monad to the transformed
--   monad. These lifted actions, however, are completely unaware of the
--   monadic state added by the transformer.
--   
--   MonadTransControl instances are aware of the monadic
--   state of the transformer and allow to save and restore this state.
--   
--   This allows to lift functions that have a monad transformer in both
--   positive and negative position. Take, for example, the function
--   
--   
--   withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
--   
--   
--   MonadTrans instances can only lift the return type of
--   the withFile function:
--   
--   
--   withFileLifted :: MonadTrans t => FilePath -> IOMode -> (Handle -> IO r) -> t IO r
--   withFileLifted file mode action = lift (withFile file mode action)
--   
--   
--   However, MonadTrans is not powerful enough to make
--   withFileLifted accept a function that returns t IO.
--   The reason is that we need to take away the transformer layer in order
--   to pass the function to withFile.
--   MonadTransControl allows us to do this:
--   
--   
--   withFileLifted' :: (Monad (t IO), MonadTransControl t) => FilePath -> IOMode -> (Handle -> t IO r) -> t IO r
--   withFileLifted' file mode action = liftWith (\run -> withFile file mode (run . action)) >>= restoreT . return
--   
class MonadTrans t => MonadTransControl (t :: Type -> Type -> Type -> Type) where {
    
    -- | Monadic state of <tt>t</tt>.
    --   
    --   The monadic state of a monad transformer is the result type of its
    --   <tt>run</tt> function, e.g.:
    --   
    --   <pre>
    --   <a>runReaderT</a> :: <a>ReaderT</a> r m a -&gt; r -&gt; m a
    --   <a>StT</a> (<a>ReaderT</a> r) a ~ a
    --   
    --   <a>runStateT</a> :: <a>StateT</a> s m a -&gt; s -&gt; m (a, s)
    --   <a>StT</a> (<a>StateT</a> s) a ~ (a, s)
    --   
    --   <a>runMaybeT</a> :: <a>MaybeT</a> m a -&gt; m (<a>Maybe</a> a)
    --   <a>StT</a> <a>MaybeT</a> a ~ <a>Maybe</a> a
    --   </pre>
    --   
    --   Provided type instances:
    --   
    --   <pre>
    --   StT <a>IdentityT</a>    a ~ a
    --   StT <a>MaybeT</a>       a ~ <a>Maybe</a> a
    --   StT (<a>ErrorT</a> e)   a ~ <a>Error</a> e =&gt; <a>Either</a> e a
    --   StT (<a>ExceptT</a> e)  a ~ <a>Either</a> e a
    --   StT <a>ListT</a>        a ~ [a]
    --   StT (<a>ReaderT</a> r)  a ~ a
    --   StT (<a>StateT</a> s)   a ~ (a, s)
    --   StT (<a>WriterT</a> w)  a ~ <a>Monoid</a> w =&gt; (a, w)
    --   StT (<a>RWST</a> r w s) a ~ <a>Monoid</a> w =&gt; (a, s, w)
    --   </pre>
    type family StT (t :: Type -> Type -> Type -> Type) a :: Type;
}

-- | liftWith is similar to lift in that it lifts a
--   computation from the argument monad to the constructed monad.
--   
--   Instances should satisfy similar laws as the MonadTrans laws:
--   
--   
--   liftWith . const . return = return
--   
--   
--   
--   liftWith (const (m >>= f)) = liftWith (const m) >>= liftWith . const . f
--   
--   
--   The difference with lift is that before lifting the
--   m computation liftWith captures the state of
--   t. It then provides the m computation with a
--   Run function that allows running t n computations in
--   n (for all n) on the captured state, e.g.
--   
--   
--   withFileLifted :: (Monad (t IO), MonadTransControl t) => FilePath -> IOMode -> (Handle -> t IO r) -> t IO r
--   withFileLifted file mode action = liftWith (\run -> withFile file mode (run . action)) >>= restoreT . return
--   
--   
--   If the Run function is ignored, liftWith coincides
--   with lift:
--   
--   
--   lift f = liftWith (const f)
--   
--   
--   Implementations use the Run function associated with a
--   transformer:
--   
--   
--   liftWith :: Monad m => ((Monad n => ReaderT r n b -> n b) -> m a) -> ReaderT r m a
--   liftWith f = ReaderT (r -> f (action -> runReaderT action r))
--   
--   liftWith :: Monad m => ((Monad n => StateT s n b -> n (b, s)) -> m a) -> StateT s m a
--   liftWith f = StateT (s -> liftM (x -> (x, s)) (f (action -> runStateT action s)))
--   
--   liftWith :: Monad m => ((Monad n => MaybeT n b -> n (Maybe b)) -> m a) -> MaybeT m a
--   liftWith f = MaybeT (liftM Just (f runMaybeT))
--   
liftWith :: (MonadTransControl t, Monad m) => (Run t -> m a) -> t m a

-- | Construct a t computation from the monadic state of
--   t that is returned from a Run function.
--   
--   Instances should satisfy:
--   
--   
--   liftWith (\run -> run t) >>= restoreT . return = t
--   
--   
--   restoreT is usually implemented through the constructor of
--   the monad transformer:
--   
--   
--   ReaderT  :: (r -> m a) -> ReaderT r m a
--   restoreT ::       m a  -> ReaderT r m a
--   restoreT action = ReaderT { runReaderT = const action }
--   
--   StateT   :: (s -> m (a, s)) -> StateT s m a
--   restoreT ::       m (a, s)  -> StateT s m a
--   restoreT action = StateT { runStateT = const action }
--   
--   MaybeT   :: m (Maybe a) -> MaybeT m a
--   restoreT :: m (Maybe a) -> MaybeT m a
--   restoreT action = MaybeT action
--   
--   
--   Example type signatures:
--   
--   
--   restoreT :: Monad m             => m a            -> IdentityT m a
--   restoreT :: Monad m             => m (Maybe a)    -> MaybeT m a
--   restoreT :: (Monad m, Error e)  => m (Either e a) -> ErrorT e m a
--   restoreT :: Monad m             => m (Either e a) -> ExceptT e m a
--   restoreT :: Monad m             => m [a]          -> ListT m a
--   restoreT :: Monad m             => m a            -> ReaderT r m a
--   restoreT :: Monad m             => m (a, s)       -> StateT s m a
--   restoreT :: (Monad m, Monoid w) => m (a, w)       -> WriterT w m a
--   restoreT :: (Monad m, Monoid w) => m (a, s, w)    -> RWST r w s m a
--   
restoreT :: (MonadTransControl t, Monad m) => m (StT t a) -> t m a

-- | 
Writing instances
--   
--   The usual way to write a MonadBaseControl instance for
--   a transformer stack over a base monad B is to write an
--   instance MonadBaseControl B B for the base monad, and
--   MonadTransControl T instances for every transformer
--   T. Instances for MonadBaseControl are then
--   simply implemented using ComposeSt,
--   defaultLiftBaseWith, defaultRestoreM.
class MonadBase b m => MonadBaseControl (b :: Type -> Type) (m :: Type -> Type) | m -> b where {
    
    -- | Monadic state that <tt>m</tt> adds to the base monad <tt>b</tt>.
    --   
    --   For all base (non-transformed) monads, <tt>StM m a ~ a</tt>:
    --   
    --   <pre>
    --   StM <a>IO</a>         a ~ a
    --   StM <a>Maybe</a>      a ~ a
    --   StM (<a>Either</a> e) a ~ a
    --   StM []         a ~ a
    --   StM ((-&gt;) r)   a ~ a
    --   StM <a>Identity</a>   a ~ a
    --   StM <a>STM</a>        a ~ a
    --   StM (<a>ST</a> s)     a ~ a
    --   </pre>
    --   
    --   If <tt>m</tt> is a transformed monad, <tt>m ~ t b</tt>,
    --   <tt><a>StM</a></tt> is the monadic state of the transformer <tt>t</tt>
    --   (given by its <a>StT</a> from <a>MonadTransControl</a>). For a
    --   transformer stack, <tt><a>StM</a></tt> is defined recursively:
    --   
    --   <pre>
    --   StM (<a>IdentityT</a>  m) a ~ <a>ComposeSt</a> <a>IdentityT</a> m a ~ StM m a
    --   StM (<a>MaybeT</a>     m) a ~ <a>ComposeSt</a> <a>MaybeT</a>    m a ~ StM m (<a>Maybe</a> a)
    --   StM (<a>ErrorT</a> e   m) a ~ <a>ComposeSt</a> <a>ErrorT</a>    m a ~ <a>Error</a> e =&gt; StM m (<a>Either</a> e a)
    --   StM (<a>ExceptT</a> e  m) a ~ <a>ComposeSt</a> <a>ExceptT</a>   m a ~ StM m (<a>Either</a> e a)
    --   StM (<a>ListT</a>      m) a ~ <a>ComposeSt</a> <a>ListT</a>     m a ~ StM m [a]
    --   StM (<a>ReaderT</a> r  m) a ~ <a>ComposeSt</a> <a>ReaderT</a>   m a ~ StM m a
    --   StM (<a>StateT</a> s   m) a ~ <a>ComposeSt</a> <a>StateT</a>    m a ~ StM m (a, s)
    --   StM (<a>WriterT</a> w  m) a ~ <a>ComposeSt</a> <a>WriterT</a>   m a ~ <a>Monoid</a> w =&gt; StM m (a, w)
    --   StM (<a>RWST</a> r w s m) a ~ <a>ComposeSt</a> <a>RWST</a>      m a ~ <a>Monoid</a> w =&gt; StM m (a, s, w)
    --   </pre>
    type family StM (m :: Type -> Type) a :: Type;
}

-- | liftBaseWith is similar to liftIO and
--   liftBase in that it lifts a base computation to the
--   constructed monad.
--   
--   Instances should satisfy similar laws as the MonadIO and
--   MonadBase laws:
--   
--   
--   liftBaseWith . const . return = return
--   
--   
--   
--   liftBaseWith (const (m >>= f)) = liftBaseWith (const m) >>= liftBaseWith . const . f
--   
--   
--   The difference with liftBase is that before lifting the base
--   computation liftBaseWith captures the state of m. It
--   then provides the base computation with a RunInBase function
--   that allows running m computations in the base monad on the
--   captured state:
--   
--   
--   withFileLifted :: MonadBaseControl IO m => FilePath -> IOMode -> (Handle -> m a) -> m a
--   withFileLifted file mode action = liftBaseWith (\runInBase -> withFile file mode (runInBase . action)) >>= restoreM
--                                -- = control $ \runInBase -> withFile file mode (runInBase . action)
--                                -- = liftBaseOp (withFile file mode) action
--   
--   
--   liftBaseWith is usually not implemented directly, but
--   using defaultLiftBaseWith.
liftBaseWith :: MonadBaseControl b m => (RunInBase m b -> b a) -> m a

-- | Construct a m computation from the monadic state of
--   m that is returned from a RunInBase function.
--   
--   Instances should satisfy:
--   
--   
--   liftBaseWith (\runInBase -> runInBase m) >>= restoreM = m
--   
--   
--   restoreM is usually not implemented directly, but
--   using defaultRestoreM.
restoreM :: MonadBaseControl b m => StM m a -> m a
instance (Control.Monad.Trans.Control.MonadBaseControl b m, Data.Constraint.Forall.Forall (Control.Monad.Trans.Unlift.IdenticalBase m)) => Control.Monad.Trans.Unlift.MonadBaseUnlift b m
instance (Control.Monad.Trans.Control.StM m a Data.Type.Equality.~ a) => Control.Monad.Trans.Unlift.IdenticalBase m a
instance (Control.Monad.Trans.Control.MonadTransControl t, Data.Constraint.Forall.Forall (Control.Monad.Trans.Unlift.Identical t)) => Control.Monad.Trans.Unlift.MonadTransUnlift t
instance (Control.Monad.Trans.Control.StT t a Data.Type.Equality.~ a) => Control.Monad.Trans.Unlift.Identical t a
