{-# LANGUAGE Trustworthy #-} {-# LANGUAGE NoImplicitPrelude , ExistentialQuantification , MagicHash , RecordWildCards , PatternSynonyms #-} {-# 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 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 ( Eq -- ^ @since 3.0 , 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"