| Copyright | (c) Jamaal Malek <mjm540@york.ac.uk> 2014 |
|---|---|
| License | BSD3 |
| Maintainer | mjm540@york.ac.uk |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Control.Monad.Except.Backtracking
Description
- data BExceptT e m a
- bExceptT :: Monad m => m (Either e a) -> BExceptT e m a
- runBExceptT :: Monad m => BExceptT e m a -> m (Either e a)
- hoistEither :: Monad m => Either e a -> BExceptT e m a
- module Control.Monad.Error.Class
The BExceptT monad transformer
BExceptT is a monad transformer that adds backtracking
exception handling to its base monad.
Instances
| (Functor m, MonadRWS r w s m) => MonadRWS r w s (BExceptT e m) | |
| MonadState s m => MonadState s (BExceptT e m) | |
| MonadReader r m => MonadReader r (BExceptT e m) | |
| (Functor f, MonadFree f m) => MonadFree f (BExceptT e m) | |
| Monad m => MonadError e (BExceptT e m) | |
| (Functor m, MonadWriter w m) => MonadWriter w (BExceptT e m) | |
| MonadTrans (BExceptT e) | |
| (Monad m, Semigroup e, Monoid e) => Alternative (BExceptT e m) | |
| Monad (BExceptT e m) | |
| Functor (BExceptT e m) | |
| (Monad m, Semigroup e, Monoid e) => MonadPlus (BExceptT e m) | |
| Applicative (BExceptT e m) | |
| MonadIO m => MonadIO (BExceptT e m) | |
| (Monad m, Semigroup e, Monoid e) => Plus (BExceptT e m) | |
| (Monad m, Semigroup e) => Alt (BExceptT e m) | |
| Apply (BExceptT e m) |
runBExceptT :: Monad m => BExceptT e m a -> m (Either e a) Source
runBExceptT does the opposite of bExceptT
hoistEither :: Monad m => Either e a -> BExceptT e m a Source
hoistEither constructs a BExceptT from an Either value.
module Control.Monad.Error.Class
Usage example and explanation
The following example shows the basic operation of the BExceptT
monad.
example1 :: StateT Int (BExceptT String IO) ()
example1 = do
put 1
catchError (put 2) $ \e -> do
i <- get
liftIO $ do
putStrLn $ "caught an error: '" <|> e <|> "'"
putStrLn $ "setting i to 4, current value is " <|> show i
put 4
i <- get
when (i /= 4) $ put 3
liftIO $ putStrLn "reading i"
i <- get
when (i /= 4) $ throwError "i isnt 4"
runexample1 :: IO (Either String ((), Int))
runexample1 = runBExceptT $ flip runStateT 0 example1The output produced is:
reading i caught an error: 'i isnt 4' setting i to 4, current value is 1 reading i Right ((),4)
At first, the execution proceeds normally, setting the state to 1,
then 2, then 3. The final line throws an exception because the state
is 3, not 4. The execution then backtracks to before put 2 was
executed. The state has been restored to 1 at this stage. The exception
handler applied to put 2 is executed, and execution continues from
the line below.
Replacing when (i /= 4) $ put 3 with put 3 will not
create an infinite loop, after the failure of each exception handler
(in this case there is only one) execution will stop and return an
error.
Using instead of
BExceptT String (StateT Int IO) () means that the state
will not be restored after an error.StateT Int (BExceptT String IO) ()
The Alternative and MonadPlus instances of BExceptT can be used
like the instances in a nondeterminism monad, such as the list monad,
except only one successful result at most will be returned.