iteratee-0.8.9.5: Iteratee-based I/O

Safe Haskell | Safe-Inferred
Language | Haskell2010

Data.Iteratee.Exception

Contents

- Exception types
  - Enumerator exceptions
  - Iteratee exceptions
- Functions

Description

Monadic and General Iteratees: Messaging and exception handling.

Iteratees use an internal exception handling mechanism that is parallel to that provided by `Exception`. This allows the iteratee framework to handle its own exceptions outside `IO`.

Iteratee exceptions are divided into two categories, `IterException` and `EnumException`. `IterExceptions` are exceptions within an iteratee, and `EnumExceptions` are exceptions within an enumerator.

Enumerators can be constructed to handle an `IterException` with `Data.Iteratee.Iteratee.enumFromCallbackCatch`. If the enumerator detects an `iteratee exception`, the enumerator calls the provided exception handler. The enumerator is then able to continue feeding data to the iteratee, provided the exception was successfully handled. If the handler could not handle the exception, the `IterException` is converted to an `EnumException` and processing aborts.

Exceptions can also be cleared by `Data.Iteratee.Iteratee.checkErr`, although in this case the iteratee continuation cannot be recovered.

When viewed as Resumable Exceptions, iteratee exceptions provide a means for iteratees to send control messages to enumerators. The `seek` implementation provides an example. `Data.Iteratee.Iteratee.seek` stores the current iteratee continuation and throws a `SeekException`, which inherits from `IterException`. `Data.Iteratee.IO.enumHandleRandom` is constructed with `enumFromCallbackCatch` and a handler that performs an `hSeek`. Upon receiving the `SeekException`, `enumHandleRandom` calls the handler, checks that it executed properly, and then continues with the stored continuation.

As the exception hierarchy is open, users can extend it with custom exceptions and exception handlers to implement sophisticated messaging systems based upon resumable exceptions.

Synopsis

- data IFException = forall e . Exception e => IFException e
- class (Typeable * e, Show e) => Exception e where
  - toException :: e -> SomeException
  - fromException :: SomeException -> Maybe e
- data EnumException = forall e . Exception e => EnumException e
- data DivergentException = DivergentException
- data EnumStringException = EnumStringException String
- data EnumUnhandledIterException = EnumUnhandledIterException IterException
- class Exception e => IException e where
  - toIterException :: e -> IterException
  - fromIterException :: IterException -> Maybe e
- data IterException = forall e . Exception e => IterException e
- data SeekException = SeekException FileOffset
- data EofException = EofException
- data IterStringException = IterStringException String
- enStrExc :: String -> EnumException
- iterStrExc :: String -> SomeException
- wrapIterExc :: IterException -> EnumException
- iterExceptionToException :: Exception e => e -> SomeException
- iterExceptionFromException :: Exception e => SomeException -> Maybe e

# Exception types

data IFException

Root of the Iteratee exception hierarchy. `IFException` derives from `Control.Exception.SomeException`. `EnumException`, `IterException`, and all inheritants are descendents of `IFException`.

Constructors

forall e . Exception e => IFException e |

Instances

Show IFException |
Exception IFException |
Typeable * IFException |

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

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

Minimal complete definition

Nothing

Methods

toException :: e -> SomeException

fromException :: SomeException -> Maybe e

Instances

Exception BlockedIndefinitelyOnMVar |
Exception BlockedIndefinitelyOnSTM |
Exception Deadlock |
Exception AssertionFailed |
Exception SomeAsyncException |
Exception AsyncException |
Exception ArrayException |
Exception ExitCode |
Exception IOException |
Exception ErrorCall |
Exception ArithException |
Exception SomeException |
Exception IterStringException |
Exception EofException |
Exception SeekException |
Exception IterException |
Exception EnumUnhandledIterException |
Exception EnumStringException |
Exception DivergentException |
Exception EnumException |
Exception IFException |

## Enumerator exceptions

data EnumException

Constructors

forall e . Exception e => EnumException e |

Instances

Show EnumException |
Exception EnumException |
Typeable * EnumException |

data DivergentException

The `iteratee` diverged upon receiving `EOF`.

Constructors

DivergentException |

Instances

Show DivergentException |
Exception DivergentException |
Typeable * DivergentException |

data EnumStringException

Create an enumerator exception from a `String`.

Constructors

EnumStringException String |

Instances

Show EnumStringException |
Exception EnumStringException |
Typeable * EnumStringException |

data EnumUnhandledIterException

The enumerator received an `IterException` it could not handle.

Constructors

EnumUnhandledIterException IterException |

Instances

Show EnumUnhandledIterException |
Exception EnumUnhandledIterException |
Typeable * EnumUnhandledIterException |

## Iteratee exceptions

class Exception e => IException e where

A class for `iteratee exceptions`. Only inheritants of `IterException` should be instances of this class.

Minimal complete definition

Nothing

Methods

toIterException :: e -> IterException

fromIterException :: IterException -> Maybe e

Instances

IException IterStringException |
IException EofException |
IException SeekException |
IException IterException |

data IterException

Root of iteratee exceptions.

Constructors

forall e . Exception e => IterException e |

Instances

Show IterException |
Exception IterException |
IException IterException |
Typeable * IterException |

data SeekException

A seek request within an `Iteratee`.

Constructors

SeekException FileOffset |

Instances

Show SeekException |
Exception SeekException |
IException SeekException |
Typeable * SeekException |

data EofException

The `Iteratee` needs more data but received `EOF`.

Constructors

EofException |

Instances

Show EofException |
Exception EofException |
IException EofException |
Typeable * EofException |

data IterStringException

An `Iteratee exception` specified by a `String`.

Constructors

IterStringException String |

Instances

Show IterStringException |
Exception IterStringException |
IException IterStringException |
Typeable * IterStringException |

# Functions

enStrExc :: String -> EnumException

Create an `EnumException` from a string.

iterStrExc :: String -> SomeException

Create an `iteratee exception` from a string. This convenience function wraps `IterStringException` and `toException`.

wrapIterExc :: IterException -> EnumException

Convert an `IterException` to an `EnumException`. Meant to be used within an `Enumerator` to signify that it could not handle the `IterException`.

iterExceptionToException :: Exception e => e -> SomeException

iterExceptionFromException :: Exception e => SomeException -> Maybe e