System.Console.Haskeline.MonadException

haskeline-0.7.2.1: A command-line interface for user input, written in Haskell.

Safe Haskell | None
Language | Haskell98

System.Console.Haskeline.MonadException

Contents

- The MonadException class
- Generalizations of Control.Exception
- Helpers for defining "wrapper" functions
- Internal implementation
- Extensible Exceptions

Description

This module redefines some of the functions in Control.Exception to work for more general monads built on top of `IO`.

Synopsis

- class MonadIO m => MonadException m where
  - controlIO :: (RunIO m -> IO (m a)) -> m a
- catch :: (MonadException m, Exception e) => m a -> (e -> m a) -> m a
- handle :: (MonadException m, Exception e) => (e -> m a) -> m a -> m a
- catches :: MonadException m => m a -> [Handler m a] -> m a
- data Handler m a = forall e . Exception e => Handler (e -> m a)
- finally :: MonadException m => m a -> m b -> m a
- throwIO :: (MonadIO m, Exception e) => e -> m a
- throwTo :: (MonadIO m, Exception e) => ThreadId -> e -> m ()
- bracket :: MonadException m => m a -> (a -> m b) -> (a -> m c) -> m c
- liftIOOp :: MonadException m => ((a -> IO (m b)) -> IO (m c)) -> (a -> m b) -> m c
- liftIOOp_ :: MonadException m => (IO (m a) -> IO (m a)) -> m a -> m a
- newtype RunIO m = RunIO (forall b. m b -> IO (m b))
- class (Typeable * e, Show e) => Exception e
- data SomeException :: * where
  - SomeException :: Exception e => e -> SomeException
- data IOException :: *

# The MonadException class

class MonadIO m => MonadException m where

An instance of `MonadException` is generally made up of monad transformers layered on top of the IO monad.

The `controlIO` method enables us to "lift" a function that manages IO actions (such as `bracket` or `catch`) into a function that wraps arbitrary monadic actions.

Methods

controlIO :: (RunIO m -> IO (m a)) -> m a

Instances

MonadException IO |
MonadException m => MonadException (MaybeT m) |
MonadException m => MonadException (ListT m) |
MonadException m => MonadException (InputT m) |
(Monoid w, MonadException m) => MonadException (WriterT w m) |
(MonadException m, Error e) => MonadException (ErrorT e m) |
MonadException m => MonadException (StateT s m) |
MonadException m => MonadException (ReaderT r m) |
(Monoid w, MonadException m) => MonadException (RWST r w s m) |

# Generalizations of Control.Exception

catch :: (MonadException m, Exception e) => m a -> (e -> m a) -> m a

handle :: (MonadException m, Exception e) => (e -> m a) -> m a -> m a

catches :: MonadException m => m a -> [Handler m a] -> m a

data Handler m a

Constructors

forall e . Exception e => Handler (e -> m a) |

finally :: MonadException m => m a -> m b -> m a

throwIO :: (MonadIO m, Exception e) => e -> m a

throwTo :: (MonadIO m, Exception e) => ThreadId -> e -> m ()

bracket :: MonadException m => m a -> (a -> m b) -> (a -> m c) -> m c

# Helpers for defining "wrapper" functions

liftIOOp :: MonadException m => ((a -> IO (m b)) -> IO (m c)) -> (a -> m b) -> m c

Lift a IO operation

    wrap :: (a -> IO b) -> IO b

to a more general monadic operation

    liftIOOp wrap :: MonadException m => (a -> m b) -> m b

For example:

     liftIOOp (withFile f m) :: MonadException m => (Handle -> m r) -> m r
     liftIOOp alloca :: (MonadException m, Storable a) => (Ptr a -> m b) -> m b
     liftIOOp (withForeignPtr fp) :: MonadException m => (Ptr a -> m b) -> m b

liftIOOp_ :: MonadException m => (IO (m a) -> IO (m a)) -> m a -> m a

Lift an IO operation

    wrap :: IO a -> IO a

to a more general monadic operation

    liftIOOp_ wrap :: MonadException m => m a -> m a

# Internal implementation

newtype RunIO m

A `RunIO` function takes a monadic action `m` as input, and outputs an IO action which performs the underlying impure part of `m` and returns the '`pure'` part of `m`.

Note that `(RunIO return)` is an incorrect implementation, since it does not separate the pure and impure parts of the monadic action. This module defines implementations for several common monad transformers.

Constructors

RunIO (forall b. m b -> IO (m b)) |

# Extensible Exceptions

class (Typeable * e, Show e) => Exception e Source

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

Instances

Exception Void |
Exception PatternMatchFail |
Exception RecSelError |
Exception RecConError |
Exception RecUpdError |
Exception NoMethodError |
Exception NonTermination |
Exception NestedAtomically |
Exception BlockedIndefinitelyOnMVar |
Exception BlockedIndefinitelyOnSTM |
Exception Deadlock |
Exception AllocationLimitExceeded |
Exception AssertionFailed |
Exception SomeAsyncException |
Exception AsyncException |
Exception ArrayException |
Exception ExitCode |
Exception Dynamic |
Exception IOException |
Exception ErrorCall |
Exception ArithException |
Exception SomeException |
Exception SetupTermError |
Exception Interrupt |

data SomeException :: * where Source

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`.

Constructors

SomeException :: Exception e => e -> SomeException |

Instances

Show SomeException |
Exception SomeException |

data IOException :: * Source

Exceptions that occur in the `IO` monad. An `IOException` records a more specific error type, a descriptive string and maybe the handle that was used when the error was flagged.

Instances

Eq IOException |
Show IOException |
Exception IOException |
Error IOException |