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


-- | Safe, checked exceptions
--   
--   Machinery for throwing and catching both pure and impure synchronous
--   exceptions. Based on <a>Lightweight Checked Exceptions</a> by Edsko de
--   Vries and Adam Gundry.
@package safe-exceptions-checked
@version 0.1.0


-- | Lightweight checked exceptions, based on
--   <a>https://www.well-typed.com/blog/2015/07/checked-exceptions/</a>.
module Control.Exception.Safe.Checked

-- | A <tt><a>Throws</a> e</tt> constraint indicates a computation may
--   throw synchronous exception <tt>e</tt>. Introduce a constraint with
--   <a>throw</a>, and discharge it with <a>catch</a>.
--   
--   You may ignore the <tt>X</tt> superclass; it exists only to prevent
--   additional <a>Throws</a> instances from being created.
class X e => Throws e

-- | A <tt><a>ThrowsImpure</a> e</tt> constraint indicates a computation
--   may throw impure exception <tt>e</tt>. Introduce a constraint with
--   <a>impureThrow</a>, and discharge it with <a>catchDeep</a>.
--   
--   You may ignore the <tt>X</tt> superclass; it exists only to prevent
--   additional <a>ThrowsImpure</a> instances from being created.
class X e => ThrowsImpure e

-- | Like <a>throw</a>, but for checked exceptions.
throw :: (MonadThrow m, Exception e, Throws e) => e -> m a

-- | Like <a>impureThrow</a>, but for checked exceptions.
impureThrow :: (Exception e, ThrowsImpure e) => e -> a

-- | Like <a>catch</a>, but for checked exceptions.
catch :: (MonadCatch m, Exception e) => (Throws e => m a) -> (e -> m a) -> m a

-- | Like <a>catchDeep</a>, but for checked exceptions.
catchDeep :: (MonadCatch m, MonadIO m, Exception e, NFData a) => (ThrowsImpure e => m a) -> (e -> m a) -> m a

-- | Like <a>handle</a>, but for checked exceptions.
handle :: (MonadCatch m, Exception e) => (e -> m a) -> (Throws e => m a) -> m a

-- | Like <a>handleDeep</a>, but for checked exceptions.
handleDeep :: (MonadCatch m, MonadIO m, Exception e, NFData a) => (e -> m a) -> (ThrowsImpure e => m a) -> m a

-- | Like <a>try</a>, but for checked exceptions.
try :: (MonadCatch m, Exception e) => (Throws e => m a) -> m (Either e a)

-- | Like <a>tryDeep</a>, but for checked exceptions.
tryDeep :: (MonadCatch m, MonadIO m, Exception e, NFData a) => (ThrowsImpure e => m a) -> m (Either e a)

-- | Uncheck a checked exception.
--   
--   This is exported for completeness, but normally you should discharge a
--   <a>Throws</a> constraint with <a>catch</a>.
uncheck :: forall a e proxy. proxy e -> (Throws e => a) -> a

-- | Unchecked a checked, impure exception.
--   
--   This is exported for completeness, but normally you should discharge a
--   <a>ThrowsImpure</a> constraint with <a>catchDeep</a>.
uncheckImpure :: forall a e proxy. proxy e -> (ThrowsImpure e => a) -> a

-- | Any type that you wish to throw or catch as an exception must be an
--   instance of the <tt>Exception</tt> class. The simplest case is a new
--   exception type directly below the root:
--   
--   <pre>
--   data MyException = ThisException | ThatException
--       deriving (Show, Typeable)
--   
--   instance Exception MyException
--   </pre>
--   
--   The default method definitions in the <tt>Exception</tt> class do what
--   we need in this case. You can now throw and catch
--   <tt>ThisException</tt> and <tt>ThatException</tt> as exceptions:
--   
--   <pre>
--   *Main&gt; throw ThisException `catch` \e -&gt; putStrLn ("Caught " ++ show (e :: MyException))
--   Caught ThisException
--   </pre>
--   
--   In more complicated examples, you may wish to define a whole hierarchy
--   of exceptions:
--   
--   <pre>
--   ---------------------------------------------------------------------
--   -- Make the root exception type for all the exceptions in a compiler
--   
--   data SomeCompilerException = forall e . Exception e =&gt; SomeCompilerException e
--       deriving Typeable
--   
--   instance Show SomeCompilerException where
--       show (SomeCompilerException e) = show e
--   
--   instance Exception SomeCompilerException
--   
--   compilerExceptionToException :: Exception e =&gt; e -&gt; SomeException
--   compilerExceptionToException = toException . SomeCompilerException
--   
--   compilerExceptionFromException :: Exception e =&gt; SomeException -&gt; Maybe e
--   compilerExceptionFromException x = do
--       SomeCompilerException a &lt;- fromException x
--       cast a
--   
--   ---------------------------------------------------------------------
--   -- Make a subhierarchy for exceptions in the frontend of the compiler
--   
--   data SomeFrontendException = forall e . Exception e =&gt; SomeFrontendException e
--       deriving Typeable
--   
--   instance Show SomeFrontendException where
--       show (SomeFrontendException e) = show e
--   
--   instance Exception SomeFrontendException where
--       toException = compilerExceptionToException
--       fromException = compilerExceptionFromException
--   
--   frontendExceptionToException :: Exception e =&gt; e -&gt; SomeException
--   frontendExceptionToException = toException . SomeFrontendException
--   
--   frontendExceptionFromException :: Exception e =&gt; SomeException -&gt; Maybe e
--   frontendExceptionFromException x = do
--       SomeFrontendException a &lt;- fromException x
--       cast a
--   
--   ---------------------------------------------------------------------
--   -- Make an exception type for a particular frontend compiler exception
--   
--   data MismatchedParentheses = MismatchedParentheses
--       deriving (Typeable, Show)
--   
--   instance Exception MismatchedParentheses where
--       toException   = frontendExceptionToException
--       fromException = frontendExceptionFromException
--   </pre>
--   
--   We can now catch a <tt>MismatchedParentheses</tt> exception as
--   <tt>MismatchedParentheses</tt>, <tt>SomeFrontendException</tt> or
--   <tt>SomeCompilerException</tt>, but not other types, e.g.
--   <tt>IOException</tt>:
--   
--   <pre>
--   *Main&gt; throw MismatchedParentheses <tt>catch</tt> e -&gt; putStrLn ("Caught " ++ show (e :: MismatchedParentheses))
--   Caught MismatchedParentheses
--   *Main&gt; throw MismatchedParentheses <tt>catch</tt> e -&gt; putStrLn ("Caught " ++ show (e :: SomeFrontendException))
--   Caught MismatchedParentheses
--   *Main&gt; throw MismatchedParentheses <tt>catch</tt> e -&gt; putStrLn ("Caught " ++ show (e :: SomeCompilerException))
--   Caught MismatchedParentheses
--   *Main&gt; throw MismatchedParentheses <tt>catch</tt> e -&gt; putStrLn ("Caught " ++ show (e :: IOException))
--   *** Exception: MismatchedParentheses
--   </pre>
class (Typeable * e, Show e) => Exception e

-- | Monads in which <a>IO</a> computations may be embedded. Any monad
--   built by applying a sequence of monad transformers to the <a>IO</a>
--   monad will be an instance of this class.
--   
--   Instances should satisfy the following laws, which state that
--   <a>liftIO</a> is a transformer of monads:
--   
--   <ul>
--   <li><pre><a>liftIO</a> . <a>return</a> = <a>return</a></pre></li>
--   <li><pre><a>liftIO</a> (m &gt;&gt;= f) = <a>liftIO</a> m &gt;&gt;=
--   (<a>liftIO</a> . f)</pre></li>
--   </ul>
class Monad m => MonadIO (m :: * -> *)

-- | A class for monads which allow exceptions to be caught, in particular
--   exceptions which were thrown by <a>throwM</a>.
--   
--   Instances should obey the following law:
--   
--   <pre>
--   catch (throwM e) f = f e
--   </pre>
--   
--   Note that the ability to catch an exception does <i>not</i> guarantee
--   that we can deal with all possible exit points from a computation.
--   Some monads, such as continuation-based stacks, allow for more than
--   just a success/failure strategy, and therefore <tt>catch</tt>
--   <i>cannot</i> be used by those monads to properly implement a function
--   such as <tt>finally</tt>. For more information, see <a>MonadMask</a>.
class MonadThrow m => MonadCatch (m :: * -> *)

-- | A class for monads which provide for the ability to account for all
--   possible exit points from a computation, and to mask asynchronous
--   exceptions. Continuation-based monads, and stacks such as <tt>ErrorT e
--   IO</tt> which provide for multiple failure modes, are invalid
--   instances of this class.
--   
--   Note that this package <i>does</i> provide a <tt>MonadMask</tt>
--   instance for <tt>CatchT</tt>. This instance is <i>only</i> valid if
--   the base monad provides no ability to provide multiple exit. For
--   example, <tt>IO</tt> or <tt>Either</tt> would be invalid base monads,
--   but <tt>Reader</tt> or <tt>State</tt> would be acceptable.
--   
--   Instances should ensure that, in the following code:
--   
--   <pre>
--   f `finally` g
--   </pre>
--   
--   The action <tt>g</tt> is called regardless of what occurs within
--   <tt>f</tt>, including async exceptions.
class MonadCatch m => MonadMask (m :: * -> *)

-- | A class for monads in which exceptions may be thrown.
--   
--   Instances should obey the following law:
--   
--   <pre>
--   throwM e &gt;&gt; x = throwM e
--   </pre>
--   
--   In other words, throwing an exception short-circuits the rest of the
--   monadic computation.
class Monad m => MonadThrow (m :: * -> *)

-- | A class of types that can be fully evaluated.
class NFData a
instance Control.Exception.Safe.Checked.X (Control.Exception.Safe.Checked.Catch a)
instance Control.Exception.Safe.Checked.Throws (Control.Exception.Safe.Checked.Catch a)
instance Control.Exception.Safe.Checked.ThrowsImpure (Control.Exception.Safe.Checked.Catch a)
