-- 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 Lightweight Checked Exceptions by Edsko de -- Vries and Adam Gundry. @package safe-exceptions-checked @version 0.1.0 -- | Lightweight checked exceptions, based on -- https://www.well-typed.com/blog/2015/07/checked-exceptions/. module Control.Exception.Safe.Checked -- | A Throws e constraint indicates a computation may -- throw synchronous exception e. Introduce a constraint with -- throw, and discharge it with catch. -- -- You may ignore the X superclass; it exists only to prevent -- additional Throws instances from being created. class X e => Throws e -- | A ThrowsImpure e constraint indicates a computation -- may throw impure exception e. Introduce a constraint with -- impureThrow, and discharge it with catchDeep. -- -- You may ignore the X superclass; it exists only to prevent -- additional ThrowsImpure instances from being created. class X e => ThrowsImpure e -- | Like throw, but for checked exceptions. throw :: (MonadThrow m, Exception e, Throws e) => e -> m a -- | Like impureThrow, but for checked exceptions. impureThrow :: (Exception e, ThrowsImpure e) => e -> a -- | Like catch, but for checked exceptions. catch :: (MonadCatch m, Exception e) => (Throws e => m a) -> (e -> m a) -> m a -- | Like catchDeep, but for checked exceptions. catchDeep :: (MonadCatch m, MonadIO m, Exception e, NFData a) => (ThrowsImpure e => m a) -> (e -> m a) -> m a -- | Like handle, but for checked exceptions. handle :: (MonadCatch m, Exception e) => (e -> m a) -> (Throws e => m a) -> m a -- | Like handleDeep, but for checked exceptions. handleDeep :: (MonadCatch m, MonadIO m, Exception e, NFData a) => (e -> m a) -> (ThrowsImpure e => m a) -> m a -- | Like try, but for checked exceptions. try :: (MonadCatch m, Exception e) => (Throws e => m a) -> m (Either e a) -- | Like tryDeep, 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 -- Throws constraint with catch. 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 -- ThrowsImpure constraint with catchDeep. 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 Exception class. The simplest case is a new -- exception type directly below the root: -- --
-- data MyException = ThisException | ThatException -- deriving (Show, Typeable) -- -- instance Exception MyException ---- -- The default method definitions in the Exception class do what -- we need in this case. You can now throw and catch -- ThisException and ThatException as exceptions: -- --
-- *Main> throw ThisException `catch` \e -> putStrLn ("Caught " ++ show (e :: MyException))
-- Caught ThisException
--
--
-- In more complicated examples, you may wish to define a whole hierarchy
-- of exceptions:
--
-- -- --------------------------------------------------------------------- -- -- Make the root exception type for all the exceptions in a compiler -- -- data SomeCompilerException = forall e . Exception e => SomeCompilerException e -- deriving Typeable -- -- instance Show SomeCompilerException where -- show (SomeCompilerException e) = show e -- -- instance Exception SomeCompilerException -- -- compilerExceptionToException :: Exception e => e -> SomeException -- compilerExceptionToException = toException . SomeCompilerException -- -- compilerExceptionFromException :: Exception e => SomeException -> Maybe e -- compilerExceptionFromException x = do -- SomeCompilerException a <- fromException x -- cast a -- -- --------------------------------------------------------------------- -- -- Make a subhierarchy for exceptions in the frontend of the compiler -- -- data SomeFrontendException = forall e . Exception e => SomeFrontendException e -- deriving Typeable -- -- instance Show SomeFrontendException where -- show (SomeFrontendException e) = show e -- -- instance Exception SomeFrontendException where -- toException = compilerExceptionToException -- fromException = compilerExceptionFromException -- -- frontendExceptionToException :: Exception e => e -> SomeException -- frontendExceptionToException = toException . SomeFrontendException -- -- frontendExceptionFromException :: Exception e => SomeException -> Maybe e -- frontendExceptionFromException x = do -- SomeFrontendException a <- 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 ---- -- We can now catch a MismatchedParentheses exception as -- MismatchedParentheses, SomeFrontendException or -- SomeCompilerException, but not other types, e.g. -- IOException: -- --
-- *Main> throw MismatchedParentheses catch e -> putStrLn ("Caught " ++ show (e :: MismatchedParentheses))
-- Caught MismatchedParentheses
-- *Main> throw MismatchedParentheses catch e -> putStrLn ("Caught " ++ show (e :: SomeFrontendException))
-- Caught MismatchedParentheses
-- *Main> throw MismatchedParentheses catch e -> putStrLn ("Caught " ++ show (e :: SomeCompilerException))
-- Caught MismatchedParentheses
-- *Main> throw MismatchedParentheses catch e -> putStrLn ("Caught " ++ show (e :: IOException))
-- *** Exception: MismatchedParentheses
--
class (Typeable * e, Show e) => Exception e
-- | Monads in which IO computations may be embedded. Any monad
-- built by applying a sequence of monad transformers to the IO
-- monad will be an instance of this class.
--
-- Instances should satisfy the following laws, which state that
-- liftIO is a transformer of monads:
--
--
class Monad m => MonadIO (m :: * -> *)
-- | A class for monads which allow exceptions to be caught, in particular
-- exceptions which were thrown by throwM.
--
-- Instances should obey the following law:
--
-- -- catch (throwM e) f = f e ---- -- Note that the ability to catch an exception does not 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 catch -- cannot be used by those monads to properly implement a function -- such as finally. For more information, see MonadMask. 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 ErrorT e -- IO which provide for multiple failure modes, are invalid -- instances of this class. -- -- Note that this package does provide a MonadMask -- instance for CatchT. This instance is only valid if -- the base monad provides no ability to provide multiple exit. For -- example, IO or Either would be invalid base monads, -- but Reader or State would be acceptable. -- -- Instances should ensure that, in the following code: -- --
-- f `finally` g ---- -- The action g is called regardless of what occurs within -- f, including async exceptions. class MonadCatch m => MonadMask (m :: * -> *) -- | A class for monads in which exceptions may be thrown. -- -- Instances should obey the following law: -- --
-- throwM e >> x = throwM e ---- -- 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)