    {-# LANGUAGE ExistentialQuantification #-}
    {-# LANGUAGE NoImplicitPrelude #-}
    {-# LANGUAGE Trustworthy #-}

    {-# OPTIONS_HADDOCK not-home #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GHC.Exception.Type
    -- Copyright   :  (c) The University of Glasgow, 1998-2002
    -- License     :  see libraries/base/LICENSE
    --
    -- Maintainer  :  cvs-ghc@haskell.org
    -- Stability   :  internal
    -- Portability :  non-portable (GHC extensions)
    --
    -- Exceptions and exception-handling functions.
    --
    -----------------------------------------------------------------------------

    module GHC.Exception.Type
           ( Exception(..)    -- Class
           , SomeException(..), ArithException(..)
           , divZeroException, overflowException, ratioZeroDenomException
           , underflowException
           ) where

    import Data.Maybe
    import Data.Typeable (Typeable, cast)
       -- loop: Data.Typeable -> GHC.Err -> GHC.Exception
    import GHC.Base
    import GHC.Show

    {- |
    The @SomeException@ type is the root of the exception type hierarchy.
    When an exception of type @e@ is thrown, behind the scenes it is
    encapsulated in a @SomeException@.
    -}
    data SomeException = forall e . Exception e => SomeException e

    -- | @since 3.0
    instance Show SomeException where
        showsPrec :: Int -> SomeException -> ShowS
    showsPrec Int
    p (SomeException e
    e) = Int -> e -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    p e
    e

    {- |
    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
    >
    > 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
    >
    > 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
    >
    > 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 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 where
        toException   :: e -> SomeException
        fromException :: SomeException -> Maybe e

        toException = e -> SomeException
    forall e. Exception e => e -> SomeException
    SomeException
        fromException (SomeException e
    e) = e -> Maybe e
    forall a b. (Typeable a, Typeable b) => a -> Maybe b
    cast e
    e

        -- | Render this exception value in a human-friendly manner.
        --
        -- Default implementation: @'show'@.
        --
        -- @since 4.8.0.0
        displayException :: e -> String
        displayException = e -> String
    forall a. Show a => a -> String
    show

    -- | @since 4.8.0.0
    instance Exception Void

    -- | @since 3.0
    instance Exception SomeException where
        toException :: SomeException -> SomeException
    toException SomeException
    se = SomeException
    se
        fromException :: SomeException -> Maybe SomeException
    fromException = SomeException -> Maybe SomeException
    forall a. a -> Maybe a
    Just
        displayException :: SomeException -> String
    displayException (SomeException e
    e) = e -> String
    forall e. Exception e => e -> String
    displayException e
    e

    -- |Arithmetic exceptions.
    data ArithException
      = Overflow
      | Underflow
      | LossOfPrecision
      | DivideByZero
      | Denormal
      | RatioZeroDenominator -- ^ @since 4.6.0.0
      deriving ( ArithException -> ArithException -> Bool
    (ArithException -> ArithException -> Bool)
    -> (ArithException -> ArithException -> Bool) -> Eq ArithException
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ArithException -> ArithException -> Bool
    == :: ArithException -> ArithException -> Bool
    $c/= :: ArithException -> ArithException -> Bool
    /= :: ArithException -> ArithException -> Bool
    Eq  -- ^ @since 3.0
               , Eq ArithException
    Eq ArithException =>
    (ArithException -> ArithException -> Ordering)
    -> (ArithException -> ArithException -> Bool)
    -> (ArithException -> ArithException -> Bool)
    -> (ArithException -> ArithException -> Bool)
    -> (ArithException -> ArithException -> Bool)
    -> (ArithException -> ArithException -> ArithException)
    -> (ArithException -> ArithException -> ArithException)
    -> Ord ArithException
    ArithException -> ArithException -> Bool
    ArithException -> ArithException -> Ordering
    ArithException -> ArithException -> ArithException
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ArithException -> ArithException -> Ordering
    compare :: ArithException -> ArithException -> Ordering
    $c< :: ArithException -> ArithException -> Bool
    < :: ArithException -> ArithException -> Bool
    $c<= :: ArithException -> ArithException -> Bool
    <= :: ArithException -> ArithException -> Bool
    $c> :: ArithException -> ArithException -> Bool
    > :: ArithException -> ArithException -> Bool
    $c>= :: ArithException -> ArithException -> Bool
    >= :: ArithException -> ArithException -> Bool
    $cmax :: ArithException -> ArithException -> ArithException
    max :: ArithException -> ArithException -> ArithException
    $cmin :: ArithException -> ArithException -> ArithException
    min :: ArithException -> ArithException -> ArithException
    Ord -- ^ @since 3.0
               )

    divZeroException, overflowException, ratioZeroDenomException, underflowException  :: SomeException
    divZeroException :: SomeException
    divZeroException        = ArithException -> SomeException
    forall e. Exception e => e -> SomeException
    toException ArithException
    DivideByZero
    overflowException :: SomeException
    overflowException       = ArithException -> SomeException
    forall e. Exception e => e -> SomeException
    toException ArithException
    Overflow
    ratioZeroDenomException :: SomeException
    ratioZeroDenomException = ArithException -> SomeException
    forall e. Exception e => e -> SomeException
    toException ArithException
    RatioZeroDenominator
    underflowException :: SomeException
    underflowException      = ArithException -> SomeException
    forall e. Exception e => e -> SomeException
    toException ArithException
    Underflow

    -- | @since 4.0.0.0
    instance Exception ArithException

    -- | @since 4.0.0.0
    instance Show ArithException where
      showsPrec :: Int -> ArithException -> ShowS
    showsPrec Int
    _ ArithException
    Overflow        = String -> ShowS
    showString String
    "arithmetic overflow"
      showsPrec Int
    _ ArithException
    Underflow       = String -> ShowS
    showString String
    "arithmetic underflow"
      showsPrec Int
    _ ArithException
    LossOfPrecision = String -> ShowS
    showString String
    "loss of precision"
      showsPrec Int
    _ ArithException
    DivideByZero    = String -> ShowS
    showString String
    "divide by zero"
      showsPrec Int
    _ ArithException
    Denormal        = String -> ShowS
    showString String
    "denormal"
      showsPrec Int
    _ ArithException
    RatioZeroDenominator = String -> ShowS
    showString String
    "Ratio has zero denominator"