Safe Haskell | Safe |
---|---|
Language | Haskell2010 |
The problem:
In Haskell it is usually simple to keep IOError bounded within a context, so that they can not interfere with the overall execution of a program. Since functional substitution is done in a hierarchical way, often a single try or catch statement is enough to treat all errors on an entire section of code.
Interruptible monad transformers turn this realitty upside down. Since the entire point of this type class is separating the hierarchical code organization from the monadic contexts, it becomes usefull to keep the exceptions information at the monadic context, instead of the default of carrying it in the code hierarchy.
That is, in the following example:
do let ct1 = createContext 1 ct2 = createContext 2 ct1' <- resume startClient ct1 ct2' <- resume startClient ct2 resume finishClient ct1' resume finishClient ct2'
It may be desirable to let any IO exception on startClient
with the ct1
context
influence only the execution of finishClient
with the ct1'
context, and not
affect any execution with the other contexts.
SafeIO was created to enforce this kind of behavior.
How to use:
- Idealy, do not import lift, liftIO, or anything similar at your module.
- Create an error type (let's call it
e
), and make it an instance of IOErrorDerivation. - Wrap your computation inside an
EitherT e
transformer (and keep the EitherT the top-level transformer). - Use the safe functions on this module instead of lift, liftIO, liftBase, etc.
Remember that the context of interruptible transformers are in the inverse order that the transformers appear on the stack, thus, at the end of execution if you want to retrieve the EitherT context, you'll have to peel all the other contexts from it first.
- class IOErrorDerivation e where
- safeIO :: (MonadIO m, IOErrorDerivation e) => IO a -> EitherT e m a
- safeCT :: (MonadBaseControl IO m, IOErrorDerivation e) => m a -> EitherT e m a
Documentation
class IOErrorDerivation e where Source #
Class for types that keep IOError information. Instantiate this for an error type for using the safe functions from this module.
coerceIOError :: IOError -> e Source #
Transforms an IOError on another error type
safeIO :: (MonadIO m, IOErrorDerivation e) => IO a -> EitherT e m a Source #
Safe alternative to liftIO
safeCT :: (MonadBaseControl IO m, IOErrorDerivation e) => m a -> EitherT e m a Source #
Safe alternative to lift for an stack that implements MonadBaseControl.