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


-- | mtl flavoured typeful hierarchical structured logging for di-core.
--   
--   mtl flavoured typeful hierarchical structured logging for di-core.
@package di-monad
@version 1.3


-- | This module offers a monadic alternative to the “bare” logging API
--   offered by <a>Di.Core</a>.
--   
--   Whereas <a>Di.Core</a> expects you to explicitly pass around a
--   <a>Di</a> object, <a>Di.Monad</a> offers a <a>MonadDi</a> typeclass,
--   as well functions operating on <a>MonadDi</a> instances, as its public
--   facing API.
--   
--   <a>Di.Monad</a> exports <a>MonadDi</a> instances for all of the monad
--   transformer types in <a>transformers</a> and <a>pipes</a>.
--   
--   Nevertheless, be aware that these two APIs are compatible, so you may
--   choose to use the monadic API for some parts of your application, the
--   “bare” API for some other parts, and everything will compose and
--   behave as expected. Usually, <a>runDiT</a> is the boundary between
--   these two <tt>APIs</tt>.
--   
--   <a>Di.Monad</a> also provides a <a>DiT</a> monad transformer that has
--   an instance of the <a>MonadDi</a> typeclass and you can readily use
--   out of the box. <a>DiT</a> also implements instances for all of the
--   typeclasses in <a>base</a>, <a>mtl</a>, and <a>exceptions</a>.
--   
--   Import this module as follows:
--   
--   <pre>
--   import <a>Di.Core</a> as Di (<a>new</a>)
--   import <a>Di.Monad</a> as Di
--   </pre>
module Di.Monad

-- | A <a>MonadDi</a> allows interacting with a <a>Di</a> through a
--   <a>mtl</a>-like monadic API, rather than through the “bare” API
--   proposed by <a>Di.Core</a>.
--   
--   Nevertheless, be aware that these two APIs are compatible, so you may
--   choose to use the monadic API for some parts of your application, the
--   “bare” API for some other parts, and everything will compose and
--   behave as expected. Usually, <a>runDiT</a> is the boundary between
--   these two <tt>APIs</tt>, although not necessarily.
--   
--   Semantically, <tt><a>MonadDi</a> m</tt> is a “reader monad” that
--   carries as its environment a <a>Di</a> and natural transformation from
--   <a>STM</a> to <tt>m</tt>.
class Monad m => MonadDi level path msg m | m -> level path msg

-- | Get the <a>Di</a> inside <tt>m</tt>, unmodified.
--   
--   Idempotence law:
--   
--   <pre>
--   <a>ask</a> <a>&gt;&gt;</a> <a>ask</a>  ==  <a>ask</a>
--   </pre>
ask :: MonadDi level path msg m => m (Di level path msg)

-- | Get the <a>Di</a> inside <tt>m</tt>, unmodified.
--   
--   Idempotence law:
--   
--   <pre>
--   <a>ask</a> <a>&gt;&gt;</a> <a>ask</a>  ==  <a>ask</a>
--   </pre>
ask :: (MonadDi level path msg m, MonadTrans t, MonadDi level path msg n, m ~ t n) => m (Di level path msg)

-- | Run <tt>m a</tt> with a modified <a>Di</a>:
--   
--   <pre>
--   <a>local</a> (<a>const</a> x) <a>ask</a>  ==  <a>pure</a> x
--   </pre>
--   
--   Identity law:
--   
--   <pre>
--   <a>local</a> <a>id</a> x  ==  x
--   </pre>
--   
--   Distributive law:
--   
--   <pre>
--   <a>local</a> f <a>.</a> <a>local</a> g  ==  <a>local</a> (f <a>.</a> g)
--   </pre>
--   
--   Idempotence law:
--   
--   <pre>
--   <a>local</a> f (<a>pure</a> ()) <a>&gt;&gt;</a> x  ==  x
--   </pre>
local :: MonadDi level path msg m => (Di level path msg -> Di level path msg) -> m a -> m a

-- | Natural transformation from <a>STM</a> to <tt>m</tt>.
--   
--   Notice that <i>it is not necessary</i> for this natural transformation
--   to be a monad morphism as well. That is, <a>atomically</a> is
--   acceptable.
natSTM :: MonadDi level path msg m => STM a -> m a

-- | Natural transformation from <a>STM</a> to <tt>m</tt>.
--   
--   Notice that <i>it is not necessary</i> for this natural transformation
--   to be a monad morphism as well. That is, <a>atomically</a> is
--   acceptable.
natSTM :: (MonadDi level path msg m, MonadTrans t, MonadDi level path msg n, m ~ t n) => STM a -> m a

-- | Log a message with the given importance <tt>level</tt>.
--   
--   This function returns immediately after queing the message for
--   logging. The actual printing of the log message will happen in a
--   different thread, asynchronously. If you want to explicitly wait for
--   the message to be logged, then call <a>flush</a> afterwards.
--   
--   Log messages are rendered in FIFO order, and their timestamp records
--   the time when this <a>log</a> function was called, rather than the
--   time when the log message is printed in the future.
--   
--   <i>Note regarding exceptions:</i> Any exception thrown by
--   <a>natSTM</a> will be thrown here. <i>Synchronous</i> exceptions that
--   happen due to failures in the actual committing of the log message,
--   which itself is performed in a different thread, are ignored (they
--   should be handled in the function passed to <tt>new</tt> instead). If
--   an asynchronous exception kills the logging thread, then you will
--   synchronously get <a>ExceptionInLoggingWorker</a> here, but by the
--   time that happens, that same exception will have already already been
--   thrown asynchronously to this same thread anyway, so unless you did
--   something funny to recover from that exception, you will have died
--   already.
log :: MonadDi level path msg m => level -> msg -> m ()

-- | Block until all messages being logged have finished processing.
--   
--   Manually calling <a>flush</a> is not usually necessary because all log
--   messages are processed as soon as possible, and <tt>with</tt> ensures
--   that no log message is left unprocessed. However, the actual printing
--   of log messages happens asynchronously, meaning there might be log
--   messages still waiting to be processed. A call to <a>flush</a> will
--   block until all pending log messages have been processed.
--   
--   Please see <a>log</a> to understand how exceptions behave in this
--   function (hint: they behave unsurprisingly).
flush :: MonadDi level path msg m => m ()

-- | Run the given action under a deeper <tt>path</tt>.
push :: MonadDi level path msg m => path -> m a -> m a

-- | Require that any logged messages within the given action satisfy the
--   given predicate in order to be accepted for processing. Logged
--   messages that don't satisfy the predicate will be silently discarded.
--   
--   Identity:
--   
--   <pre>
--   <a>filter</a> (\_ _ _ -&gt; <a>True</a>)  ==  <a>id</a>
--   </pre>
--   
--   Composition:
--   
--   <pre>
--   <a>filter</a> (\l ps m -&gt; f l ps m <a>&amp;&amp;</a> g l ps m)  ==  <a>filter</a> f . <a>filter</a> g
--   </pre>
--   
--   Commutativity:
--   
--   <pre>
--   <a>filter</a> f . <a>filter</a> g  ==  <a>filter</a> g . <a>filter</a> f
--   </pre>
filter :: MonadDi level path msg m => (level -> Seq path -> msg -> Bool) -> m a -> m a

-- | Throw an <a>Exception</a>, but not without logging it first according
--   to the rules established by <a>onException</a>, and further restricted
--   by the rules established by <a>filter</a>.
--   
--   If the exception doesn't need to be logged, according to the policy
--   set with <a>onException</a>, then this function behaves just as
--   <a>throwSTM</a>.
--   
--   WARNING: Note that when <tt>m</tt> is <a>STM</a>, or ultimately runs
--   on <a>STM</a>, then <a>throw</a> <i>will not log</i> the exception,
--   just throw it. This might change in the future if we figure out how to
--   make it work safely.
throw :: (MonadDi level path msg m, Exception e) => e -> m a

-- | Within the passed given <tt>m a</tt>, exceptions thrown with
--   <a>throw</a> could could be logged as a <tt>msg</tt> with a particular
--   <tt>level</tt> if both the passed in function returns <a>Just</a>, and
--   <a>filter</a> so allows it afterwards.
--   
--   If the given function returns <a>Nothing</a>, then no logging is
--   performed.
--   
--   The returned <tt><a>Seq</a> path</tt> will extend the <tt>path</tt> at
--   the <a>throw</a> call site before sending the log. The leftmost
--   <tt>path</tt> is closest to the root.
--   
--   Composition:
--   
--   <pre>
--   <a>onException</a> f . <a>onException</a> g   ==   <a>onException</a> (g e *&gt; f e)
--   </pre>
--   
--   Notice that the <tt>level</tt>, <tt>path</tt>s and <tt>msg</tt>
--   resulting from <tt>g</tt> are discarded, yet its policy regarding
--   whether to log or not is preserved in the same way as <a>filter</a>.
--   That is, <a>onException</a> can't accept an exception already rejected
--   by a previous use of <a>onException</a>, but it can reject a
--   previously accepted one.
onException :: MonadDi level path msg m => (SomeException -> Maybe (level, Seq path, msg)) -> m a -> m a

-- | A <tt><a>DiT</a> level path msg m</tt> is a “reader monad” that
--   carries as its environment a <tt><a>Di</a> level path msg</tt> and
--   natural transformation from <a>STM</a> to <tt>m</tt>.
--   
--   The most primitive way to build a <a>DiT</a> is through <a>diT</a>.
--   
--   The most primitive way to run a <a>DiT</a> is through <a>runDiT'</a>.
data DiT level path msg m a

-- | Build a <a>DiT</a>.
--   
--   <pre>
--   forall nat di.
--      <a>runDiT'</a> nat di (<a>diT</a> (\nat' di' -&gt; pure (nat', di')))
--          == <a>pure</a> (nat, di)
--   </pre>
diT :: ((forall x. STM x -> m x) -> Di level path msg -> m a) -> DiT level path msg m a

-- | Run a <a>DiT</a>.
--   
--   <pre>
--   forall di.
--      <a>runDiT</a> di (<a>diT</a> (\nat' di' -&gt; pure (nat', di')))
--          == <a>pure</a> (<a>natSTM</a>, di)
--   </pre>
--   
--   This is like <a>runDiT'</a>, but specialized to run with an underlying
--   <a>MonadIO</a>.
--   
--   <pre>
--   <a>runDiT</a>  ==  <a>runDiT'</a> (<a>liftIO</a> . <a>atomically</a>)
--   </pre>
--   
--   Please notice that <a>runDiT</a> doesn't perform a <a>flush</a> on the
--   given <a>Di</a> before returning. You are responsible for doing that
--   (or, more likely, <a>new</a> will do it for you).
--   
--   Also, notice that <a>runDiT</a> is a <i>monad morphism</i> from
--   <tt><a>DiT</a> m</tt> to <tt>m</tt>.
runDiT :: MonadIO m => Di level path msg -> DiT level path msg m a -> m a

-- | Run a <a>DiT</a>.
--   
--   <pre>
--   forall nat di.
--      <a>runDiT'</a> nat di (<a>diT</a> (\nat' di' -&gt; pure (nat', di')))
--          == <a>pure</a> (nat, di)
--   </pre>
--   
--   <a>runDiT'</a> is like <a>runDiT</a>. However it doesn't require a
--   <a>MonadIO</a> constraint. Instead, it takes the natural
--   transformation that will be used by <a>natSTM</a> as an argument.
--   
--   First, this allows any monad that wraps <a>IO</a> without necessarily
--   having a <a>MonadIO</a> instance to work with <a>MonadDi</a>. For
--   example:
--   
--   <pre>
--   newtype Foo = Foo (<a>IO</a> a)
--     deriving (<a>Functor</a>, <a>Applicative</a>, <a>Monad</a>)
--   
--   <a>runDiT'</a> (Foo . <a>atomically</a>)
--        :: <a>Di</a> level path msg
--        -&gt; <a>DiT</a> level path msg Foo a
--        -&gt; Foo a
--   </pre>
--   
--   Second, this allows <tt>m</tt> to be <a>STM</a> itself:
--   
--   <pre>
--   <a>runDiT'</a> <a>id</a>
--        :: <a>Di</a> level path msg
--        -&gt; <a>DiT</a> level path msg <a>STM</a> a
--        -&gt; <a>STM</a> a
--   </pre>
--   
--   The semantics of logging from within <a>STM</a> are those of any other
--   <a>STM</a> transaction: That is, a log message is commited only once
--   to the outside world if and when the <a>STM</a> transaction succeeds.
--   That is, the following example will only ever commit the log
--   containing <tt>ly</tt> and <tt>my</tt>, and not the one containing
--   <tt>lx</tt> and <tt>mx</tt>.
--   
--   <pre>
--   <a>atomically</a> $ <a>runDiT'</a> <a>id</a> $ do
--      (<a>log</a> <a>id</a> lx mx &gt;&gt; <a>lift</a> <a>retry</a>) &lt;|&gt;
--      (<a>log</a> <a>id</a> ly my)
--   </pre>
--   
--   Of course, <a>runDiT'</a> works as well if you decide to wrap
--   <a>STM</a> with your own monad type:
--   
--   <pre>
--   newtype Bar = Bar (<a>STM</a> a)
--     deriving (<a>Functor</a>, <a>Applicative</a>, <a>Monad</a>)
--   
--   <a>runDiT'</a> Bar
--        :: <a>Di</a> level path msg
--        -&gt; <a>DiT</a> level path msg Bar a
--        -&gt; Bar a
--   </pre>
--   
--   Additionally, notice that <a>runDiT'</a> itself is a <i>monad
--   morphism</i> from <tt><a>DiT</a> level path msg m</tt> to <tt>m</tt>
--   which doesn't perform any side effects of its own. Particularly, the
--   given <a>Di</a> remains unaffected. So you can use it as many times
--   you want.
--   
--   <pre>
--   forall f di x.
--      <a>runDiT'</a> f di (<a>lift</a> x)  ==  x
--   </pre>
--   
--   Please notice that <a>runDiT</a> doesn't perform a <a>flush</a> on the
--   given <a>Di</a> before returning. You are responsible for doing that
--   (or, more likely, <a>new</a> will do it for you).
runDiT' :: (forall x. STM x -> m x) -> Di level path msg -> DiT level path msg m a -> m a

-- | Lift a monad morphism from <tt>m</tt> to <tt>n</tt> to a monad
--   morphism from <tt><a>DiT</a> level path msg m</tt> to <tt><a>DiT</a>
--   level path msg n</tt>.
--   
--   Notice that <a>DiT</a> itself is not a functor in the category of
--   monads, so it can't be an instance of <a>MFunctor</a> from the
--   <a>mmorph</a> package. However, it becomes one if you pair it with a
--   natural transformation <tt><tt>nat</tt> :: forall x. n x -&gt; m
--   x</tt>. That is:
--   
--   <pre>
--   forall nat.  <i>such that <tt>nat</tt> is a natural transformation</i>
--      <a>hoistDiT</a> nat  ==  <a>hoist</a>
--   </pre>
--   
--   In practical terms, it means that most times you can “hoist” a
--   <a>DiT</a> anyway, just not through <a>hoist</a>.
hoistDiT :: (forall x. n x -> m x) -> (forall x. m x -> n x) -> DiT level path msg m a -> DiT level path msg n a

-- | Run a <a>DiT</a> with a modified <a>Di</a>:
--   
--   <pre>
--   <a>localDiT</a> (<a>const</a> x) <a>ask</a>  ==  <a>pure</a> x
--   </pre>
--   
--   Notice that, contrary to <a>local</a>, this allows changing the type
--   of <a>Di</a>, which means that you can use <a>localDiT</a> with
--   <a>contralevel</a>, <a>contrapath</a> or <a>contramsg</a> to change
--   the types of <tt>level</tt>, <tt>path</tt>, or <tt>message</tt> you
--   <a>DiT</a> works with.
--   
--   <pre>
--   <a>localDiT</a> (<a>contralevel</a> (f :: level -&gt; level'))
--       :: <a>DiT</a> level' path msg m a
--       -&gt; <a>DiT</a> level path msg m a
--   </pre>
--   
--   <pre>
--   <a>localDiT</a> (<a>contrapath</a> (f :: path -&gt; path'))
--       :: <a>DiT</a> level path' msg m a
--       -&gt; <a>DiT</a> level path msg m a
--   </pre>
--   
--   <pre>
--   <a>localDiT</a> (<a>contramsg</a> (f :: msg -&gt; msg'))
--       :: <a>DiT</a> level path msg' m a
--       -&gt; <a>DiT</a> level path msg m a
--   </pre>
--   
--   Identity law:
--   
--   <pre>
--   <a>localDiT</a> <a>id</a> x  ==  x
--   </pre>
--   
--   Distributive law:
--   
--   <pre>
--   <a>localDiT</a> f <a>.</a> <a>localDiT</a> g  ==  <a>localDiT</a> (f <a>.</a> g)
--   </pre>
--   
--   Idempotence law:
--   
--   <pre>
--   <a>localDiT</a> f (<a>pure</a> ()) <a>&gt;&gt;</a> x  ==  x
--   </pre>
localDiT :: (Di level path msg -> Di level' path' msg') -> DiT level' path' msg' m a -> DiT level path msg m a
instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Di.Monad.DiT level path msg m)
instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Di.Monad.DiT level path msg m)
instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (Di.Monad.DiT level path msg m)
instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Di.Monad.DiT level path msg m)
instance Control.Monad.Zip.MonadZip m => Control.Monad.Zip.MonadZip (Di.Monad.DiT level path msg m)
instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Di.Monad.DiT level path msg m)
instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Di.Monad.DiT level path msg m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Di.Monad.DiT level path msg m)
instance GHC.Base.Monad m => GHC.Base.Monad (Di.Monad.DiT level path msg m)
instance GHC.Base.Alternative m => GHC.Base.Alternative (Di.Monad.DiT level path msg m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Di.Monad.DiT level path msg m)
instance GHC.Base.Functor m => GHC.Base.Functor (Di.Monad.DiT level path msg m)
instance GHC.Base.Monad m => Di.Monad.MonadDi level path msg (Di.Monad.DiT level path msg m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Control.Monad.Trans.Reader.ReaderT r m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Control.Monad.Trans.State.Strict.StateT s m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Control.Monad.Trans.State.Lazy.StateT s m)
instance (GHC.Base.Monoid w, Di.Monad.MonadDi level path msg m) => Di.Monad.MonadDi level path msg (Control.Monad.Trans.Writer.Strict.WriterT w m)
instance (GHC.Base.Monoid w, Di.Monad.MonadDi level path msg m) => Di.Monad.MonadDi level path msg (Control.Monad.Trans.Writer.Lazy.WriterT w m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Control.Monad.Trans.Maybe.MaybeT m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Control.Monad.Trans.Except.ExceptT e m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Control.Monad.Trans.Identity.IdentityT m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Control.Monad.Trans.Cont.ContT r m)
instance (GHC.Base.Monoid w, Di.Monad.MonadDi level path msg m) => Di.Monad.MonadDi level path msg (Control.Monad.Trans.RWS.Strict.RWST r w s m)
instance (GHC.Base.Monoid w, Di.Monad.MonadDi level path msg m) => Di.Monad.MonadDi level path msg (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
instance (GHC.Base.Monoid w, Di.Monad.MonadDi level path msg m) => Di.Monad.MonadDi level path msg (Control.Monad.Trans.Accum.AccumT w m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Control.Monad.Trans.Select.SelectT r m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Pipes.Internal.Proxy a' a b' b m)
instance Di.Monad.MonadDi level path msg m => Di.Monad.MonadDi level path msg (Pipes.ListT m)
instance Control.Monad.Trans.Class.MonadTrans (Di.Monad.DiT level path msg)
instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Di.Monad.DiT level path msg m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Di.Monad.DiT level path msg m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Di.Monad.DiT level path msg m)
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Di.Monad.DiT level path msg m)
