mirror of
https://github.com/idris-lang/Idris2.git
synced 2024-12-19 09:12:34 +03:00
154 lines
5.4 KiB
Idris
154 lines
5.4 KiB
Idris
||| The Error monad (also called the Exception monad).
|
|
module Control.Monad.Error.Interface
|
|
|
|
-- module Control.Monad.Error.Class (
|
|
-- MonadError(..),
|
|
-- liftEither,
|
|
-- tryError,
|
|
-- withError,
|
|
-- handleError,
|
|
-- mapError,
|
|
-- ) where
|
|
--
|
|
||| The strategy of combining computations that can throw exceptions
|
|
||| by bypassing bound functions
|
|
||| from the point an exception is thrown to the point that it is handled.
|
|
||| Is parameterized over the type of error information and
|
|
||| the monad type constructor.
|
|
||| It is common to use `Either String` as the monad type constructor
|
|
||| for an error monad in which error descriptions take the form of strings.
|
|
||| In that case and many other common cases the resulting monad is already defined
|
|
||| as an instance of the 'MonadError' class.
|
|
public export
|
|
interface Monad m => MonadError e m | m where
|
|
||| Is used within a monadic computation to begin exception processing.
|
|
throwError : e -> m a
|
|
|
|
||| A handler function to handle previous errors and return to normal execution.
|
|
||| A common idiom is:
|
|
|||
|
|
||| ```idris example
|
|
||| do { action1; action2; action3 } `catchError` handler
|
|
||| ```
|
|
catchError : m a -> (e -> m a) -> m a
|
|
|
|
||| Lifts an `Either e` into any `MonadError e`.
|
|
public export
|
|
liftEither : MonadError e m => Either e a -> m a
|
|
liftEither = either throwError pure
|
|
|
|
||| Makes a success or failure of an action visible in
|
|
||| the return type.
|
|
public export
|
|
tryError : MonadError e m => m a -> m (Either e a)
|
|
tryError action = (map Right action) `catchError` (pure . Left)
|
|
|
|
||| `MonadError` analogue to the `withEitherT` function.
|
|
||| Modify the value (but not the type) of an error.
|
|
||| If you need to change the type of `e` use `mapError`.
|
|
public export
|
|
withError : MonadError e m => (e -> e) -> m a -> m a
|
|
withError f action = tryError action >>= either (throwError . f) pure
|
|
|
|
||| Flipped version of `catchError`.
|
|
public export
|
|
handleError : MonadError e m => (e -> m a) -> m a -> m a
|
|
handleError = flip catchError
|
|
|
|
||| `MonadError` analogue of the `mapEitherT` function. The
|
|
||| computation is unwrapped, a function is applied to the `Either`, and
|
|
||| the result is lifted into the second `MonadError` instance.
|
|
public export
|
|
mapError : (MonadError e m, MonadError e' n)
|
|
=> (m (Either e a) -> n (Either e' b)) -> m a -> n b
|
|
mapError f action = f (tryError action) >>= liftEither
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Implementations
|
|
--------------------------------------------------------------------------------
|
|
|
|
public export
|
|
MonadError () Maybe where
|
|
throwError () = Nothing
|
|
catchError Nothing f = f ()
|
|
catchError x _ = x
|
|
|
|
public export
|
|
MonadError e (Either e) where
|
|
throwError = Left
|
|
Left l `catchError` h = h l
|
|
Right r `catchError` _ = Right r
|
|
|
|
-- {- | @since 2.2 -}
|
|
-- instance Monad m => MonadError e (ExceptT e m) where
|
|
-- throwError = ExceptT.throwE
|
|
-- catchError = ExceptT.catchE
|
|
--
|
|
-- -- ---------------------------------------------------------------------------
|
|
-- -- Instances for other mtl transformers
|
|
-- --
|
|
-- -- All of these instances need UndecidableInstances,
|
|
-- -- because they do not satisfy the coverage condition.
|
|
--
|
|
-- instance MonadError e m => MonadError e (IdentityT m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = Identity.liftCatch catchError
|
|
--
|
|
-- instance MonadError e m => MonadError e (MaybeT m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = Maybe.liftCatch catchError
|
|
--
|
|
-- instance MonadError e m => MonadError e (ReaderT r m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = Reader.liftCatch catchError
|
|
--
|
|
-- instance (Monoid w, MonadError e m) => MonadError e (LazyRWS.RWST r w s m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = LazyRWS.liftCatch catchError
|
|
--
|
|
-- instance (Monoid w, MonadError e m) => MonadError e (StrictRWS.RWST r w s m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = StrictRWS.liftCatch catchError
|
|
--
|
|
-- instance MonadError e m => MonadError e (LazyState.StateT s m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = LazyState.liftCatch catchError
|
|
--
|
|
-- instance MonadError e m => MonadError e (StrictState.StateT s m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = StrictState.liftCatch catchError
|
|
--
|
|
-- instance (Monoid w, MonadError e m) => MonadError e (LazyWriter.WriterT w m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = LazyWriter.liftCatch catchError
|
|
--
|
|
-- instance (Monoid w, MonadError e m) => MonadError e (StrictWriter.WriterT w m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = StrictWriter.liftCatch catchError
|
|
--
|
|
-- #if MIN_VERSION_transformers(0,5,6)
|
|
-- -- | @since 2.3
|
|
-- instance (Monoid w, MonadError e m) => MonadError e (CPSRWS.RWST r w s m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = CPSRWS.liftCatch catchError
|
|
--
|
|
-- -- | @since 2.3
|
|
-- instance (Monoid w, MonadError e m) => MonadError e (CPSWriter.WriterT w m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = CPSWriter.liftCatch catchError
|
|
-- #endif
|
|
--
|
|
-- #if MIN_VERSION_transformers(0,5,3)
|
|
-- -- | @since 2.3
|
|
-- instance
|
|
-- ( Monoid w
|
|
-- , MonadError e m
|
|
-- #if !MIN_VERSION_base(4,8,0)
|
|
-- , Functor m
|
|
-- #endif
|
|
-- ) => MonadError e (AccumT w m) where
|
|
-- throwError = lift . throwError
|
|
-- catchError = Accum.liftCatch catchError
|
|
-- #endif
|
|
--
|