Safe Haskell | Trustworthy |
---|---|

Language | Haskell98 |

This module provides an orphan `MonadCatch`

instance for `Proxy`

of the
form:

instance (MonadCatch m, MonadIO m) => MonadCatch (Proxy a' a b' b m) where

... so you can throw and catch exceptions within pipes using all
`MonadCatch`

operations.

This module also provides generalized versions of some `MonadCatch`

operations so that you can also protect against premature termination of
connected components. For example, if you protect a `readFile`

computation
using `bracket`

from this module:

-- readFile.hs import Pipes import qualified Pipes.Prelude as P import Pipes.Safe import qualified System.IO as IO import Prelude hiding (readFile) readFile :: FilePath -> Producer' String (SafeT IO) () readFile file = bracket (do h <- IO.openFile file IO.ReadMode putStrLn $ "{" ++ file ++ " open}" return h ) (\h -> do IO.hClose h putStrLn $ "{" ++ file ++ " closed}" ) P.fromHandle

... then this generalized `bracket`

will guard against both exceptions and
premature termination of other pipes:

`>>>`

{readFile.hs open} -- readFile.hs import Pipes import qualified Pipes.Prelude as P import Pipes.Safe {readFile.hs closed}`runSafeT $ runEffect $ readFile "readFile.hs" >-> P.take 4 >-> P.stdoutLn`

Note that the `MonadCatch`

instance for `Proxy`

provides weaker versions of
`mask`

and `uninterruptibleMask`

that do not completely prevent asynchronous
exceptions. Instead, they provide a weaker guarantee that asynchronous
exceptions will only occur during `await`

s or `yield`

s and
nowhere else. For example, if you write:

mask_ $ do x <- await lift $ print x lift $ print x

... then you may receive an asynchronous exception during the `await`

,
but you will not receive an asynchronous exception during or in between the
two `print`

statements. This weaker guarantee suffices to provide
asynchronous exception safety.

- data SafeT m r
- runSafeT :: (MonadMask m, MonadIO m) => SafeT m r -> m r
- runSafeP :: (MonadMask m, MonadIO m) => Effect (SafeT m) r -> Effect' m r
- data ReleaseKey
- class (MonadCatch m, MonadMask m, MonadIO m, MonadIO (Base m)) => MonadSafe m where
- onException :: MonadSafe m => m a -> Base m b -> m a
- tryP :: (MonadSafe m, Exception e) => Proxy a' a b' b m r -> Proxy a' a b' b m (Either e r)
- catchP :: (MonadSafe m, Exception e) => Proxy a' a b' b m r -> (e -> Proxy a' a b' b m r) -> Proxy a' a b' b m r
- finally :: MonadSafe m => m a -> Base m b -> m a
- bracket :: MonadSafe m => Base m a -> (a -> Base m b) -> (a -> m c) -> m c
- bracket_ :: MonadSafe m => Base m a -> Base m b -> m c -> m c
- bracketOnError :: MonadSafe m => Base m a -> (a -> Base m b) -> (a -> m c) -> m c
- module Control.Monad.Catch
- module Control.Exception

# SafeT

`SafeT`

is a monad transformer that extends the base monad with the ability
to `register`

and `release`

finalizers.

All unreleased finalizers are called at the end of the `SafeT`

block, even
in the event of exceptions.

MonadTrans SafeT Source # | |

MonadBase b m => MonadBase b (SafeT m) Source # | |

MonadBaseControl b m => MonadBaseControl b (SafeT m) Source # | |

MonadWriter w m => MonadWriter w (SafeT m) Source # | |

MonadState s m => MonadState s (SafeT m) Source # | |

MonadError e m => MonadError e (SafeT m) Source # | |

Monad m => Monad (SafeT m) Source # | |

Functor m => Functor (SafeT m) Source # | |

MonadFix m => MonadFix (SafeT m) Source # | |

Applicative m => Applicative (SafeT m) Source # | |

MonadIO m => MonadIO (SafeT m) Source # | |

Alternative m => Alternative (SafeT m) Source # | |

MonadPlus m => MonadPlus (SafeT m) Source # | |

MonadThrow m => MonadThrow (SafeT m) Source # | |

MonadCatch m => MonadCatch (SafeT m) Source # | |

MonadMask m => MonadMask (SafeT m) Source # | |

MonadCont m => MonadCont (SafeT m) Source # | |

PrimMonad m => PrimMonad (SafeT m) Source # | |

(MonadIO m, MonadCatch m, MonadMask m) => MonadSafe (SafeT m) Source # | |

type PrimState (SafeT m) Source # | |

type Base (SafeT m) Source # | |

type StM (SafeT m) a Source # | |

runSafeT :: (MonadMask m, MonadIO m) => SafeT m r -> m r Source #

Run the `SafeT`

monad transformer, executing all unreleased finalizers at
the end of the computation

# MonadSafe

data ReleaseKey Source #

class (MonadCatch m, MonadMask m, MonadIO m, MonadIO (Base m)) => MonadSafe m where Source #

type Base (m :: * -> *) :: * -> * Source #

The monad used to run resource management actions, corresponding to the
monad directly beneath `SafeT`

liftBase :: Base m r -> m r Source #

Lift an action from the `Base`

monad

register :: Base m () -> m ReleaseKey Source #

`register`

a finalizer, ensuring that the finalizer gets called if the
finalizer is not `release`

d before the end of the surrounding `SafeT`

block.

release :: ReleaseKey -> m () Source #

`release`

a registered finalizer

You can safely call `release`

more than once on the same `ReleaseKey`

.
Every `release`

after the first one does nothing.

MonadSafe m => MonadSafe (CatchT m) Source # | |

(MonadIO m, MonadCatch m, MonadMask m) => MonadSafe (SafeT m) Source # | |

(MonadSafe m, Monoid w) => MonadSafe (WriterT w m) Source # | |

MonadSafe m => MonadSafe (StateT s m) Source # | |

MonadSafe m => MonadSafe (IdentityT * m) Source # | |

MonadSafe m => MonadSafe (StateT s m) Source # | |

(MonadSafe m, Monoid w) => MonadSafe (WriterT w m) Source # | |

MonadSafe m => MonadSafe (ReaderT * i m) Source # | |

(MonadSafe m, Monoid w) => MonadSafe (RWST i w s m) Source # | |

(MonadSafe m, Monoid w) => MonadSafe (RWST i w s m) Source # | |

MonadSafe m => MonadSafe (Proxy a' a b' b m) Source # | |

# Utilities

These utilities let you supply a finalizer that runs in the `Base`

monad
(i.e. the monad directly beneath `SafeT`

). If you don't need to use the
full power of the `Base`

monad and you only need to use to use `IO`

, then
just wrap the finalizer in `liftIO`

, like this:

myAction `finally` (liftIO myFinalizer)

This will lead to a simple inferred type with a single `MonadSafe`

constraint:

(MonadSafe m) => ...

For examples of this, see the utilities in Pipes.Safe.Prelude.

If you omit the `liftIO`

, the compiler will infer the following constraint
instead:

(MonadSafe m, Base m ~ IO) => ...

This means that this function would require `IO`

directly beneath the
`SafeT`

monad transformer, which might not be what you want.

onException :: MonadSafe m => m a -> Base m b -> m a Source #

Analogous to `onException`

from `Control.Monad.Catch`

, except this also
protects against premature termination

`(`onException` io)`

is a monad morphism.

tryP :: (MonadSafe m, Exception e) => Proxy a' a b' b m r -> Proxy a' a b' b m (Either e r) Source #

Transform a `Proxy`

into one that catches any exceptions caused by its
effects, and returns the resulting exception.

catchP :: (MonadSafe m, Exception e) => Proxy a' a b' b m r -> (e -> Proxy a' a b' b m r) -> Proxy a' a b' b m r Source #

Allows direct handling of exceptions raised by the effects in a `Proxy`

.

finally :: MonadSafe m => m a -> Base m b -> m a Source #

Analogous to `finally`

from `Control.Monad.Catch`

, except this also
protects against premature termination

bracket :: MonadSafe m => Base m a -> (a -> Base m b) -> (a -> m c) -> m c Source #

Analogous to `bracket`

from `Control.Monad.Catch`

, except this also
protects against premature termination

bracket_ :: MonadSafe m => Base m a -> Base m b -> m c -> m c Source #

Analogous to `bracket_`

from `Control.Monad.Catch`

, except this also
protects against premature termination

bracketOnError :: MonadSafe m => Base m a -> (a -> Base m b) -> (a -> m c) -> m c Source #

Analogous to `bracketOnError`

from `Control.Monad.Catch`

, except this also
protects against premature termination

# Re-exports

`Control.Monad.Catch`

re-exports all functions except for the ones that
conflict with the generalized versions provided here (i.e. `bracket`

,
`finally`

, etc.).

`Control.Exception`

re-exports `Exception`

and `SomeException`

.

module Control.Monad.Catch

module Control.Exception