@@ -48,6 +48,7 @@ module Control.Monad.Error.Class (
4848 tryError ,
4949 withError ,
5050 handleError ,
51+ onError ,
5152 mapError ,
5253 modifyError ,
5354 ) where
@@ -72,9 +73,9 @@ import qualified Control.Monad.Trans.RWS.CPS as CPSRWS
7273import qualified Control.Monad.Trans.Writer.CPS as CPSWriter
7374import Control.Monad.Trans.Class (lift )
7475import Control.Exception (IOException , catch , ioError )
75- import Control.Monad (Monad )
76+ import Control.Monad (Monad ( (>>=) , (>>) ) )
7677import Data.Monoid (Monoid )
77- import Prelude (Either (Left , Right ), Maybe (Nothing ), either , flip , (.) , IO , pure , (<$>) , (>>=) )
78+ import Prelude (Either (Left , Right ), Maybe (Nothing ), either , flip , (.) , IO , pure , (<$>) )
7879
7980{- |
8081The strategy of combining computations that can throw exceptions
@@ -227,6 +228,14 @@ withError f = handleError (throwError . f)
227228handleError :: MonadError e m => (e -> m a ) -> m a -> m a
228229handleError = flip catchError
229230
231+ -- | If an action throws an error, run a second action and rethrow the error.
232+ -- If the second action also throws an error, it takes precedence. Do not run
233+ -- the second action at all if the first succeeds.
234+ --
235+ -- @since 2.3.2
236+ onError :: MonadError e m => m a -> m b -> m a
237+ onError action1 action2 = action1 `catchError` \ e -> action2 >> throwError e
238+
230239-- | 'MonadError' analogue of the 'mapExceptT' function. The
231240-- computation is unwrapped, a function is applied to the @Either@, and
232241-- the result is lifted into the second 'MonadError' instance.
0 commit comments