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

Safe Haskell | None

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
- 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 => MonadException (StateT s m) |
MonadException m => MonadException (ReaderT r m) |
(MonadException m, Error e) => MonadException (ErrorT e 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

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

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 PatternMatchFail |
Exception RecSelError |
Exception RecConError |
Exception RecUpdError |
Exception NoMethodError |
Exception NonTermination |
Exception NestedAtomically |
Exception BlockedIndefinitelyOnMVar |
Exception BlockedIndefinitelyOnSTM |
Exception Deadlock |
Exception AssertionFailed |
Exception AsyncException |
Exception ArrayException |
Exception ExitCode |
Exception Dynamic |
Exception IOException |
Exception SomeException |
Exception ErrorCall |
Exception ArithException |
Exception SetupTermError |
Exception Interrupt |

data SomeException where

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 |
Typeable SomeException |
Exception SomeException |

data IOException

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 |
Typeable IOException |
Exception IOException |
Error IOException |