-- | -- Module: Control.Monad.Freer.Error -- Description: An Error effect and handler. -- Copyright: (c) 2016 Allele Dev; 2017 Ixperta Solutions s.r.o.; 2017 Alexis King -- License: BSD3 -- Maintainer: Alexis King -- Stability: experimental -- Portability: GHC specific language extensions. -- -- Composable handler for Error effects. Communicates success\/failure via an -- 'Either' type. -- -- Using as a starting point. module Control.Monad.Freer.Error ( Error(..) , throwError , runError , catchError , handleError ) where import Control.Monad.Freer (Eff, Member, interposeWith, interpretWith, send) import Control.Monad.Freer.Internal (handleRelay) -- | Exceptions of the type @e :: *@ with no resumption. newtype Error e r where Error :: e -> Error e r -- | Throws an error carrying information of type @e :: *@. throwError :: forall e effs a. Member (Error e) effs => e -> Eff effs a throwError e = send (Error e) -- | Handler for exception effects. If there are no exceptions thrown, returns -- 'Right'. If exceptions are thrown and not handled, returns 'Left', while -- interrupting the execution of any other effect handlers. runError :: forall e effs a. Eff (Error e ': effs) a -> Eff effs (Either e a) runError = handleRelay (pure . Right) (\(Error e) _ -> pure (Left e)) -- | A catcher for Exceptions. Handlers are allowed to rethrow exceptions. catchError :: forall e effs a . Member (Error e) effs => Eff effs a -> (e -> Eff effs a) -> Eff effs a catchError m handle = interposeWith (\(Error e) _ -> handle e) m -- | A catcher for Exceptions. Handlers are /not/ allowed to rethrow exceptions. handleError :: forall e effs a . Eff (Error e ': effs) a -> (e -> Eff effs a) -> Eff effs a handleError m handle = interpretWith (\(Error e) _ -> handle e) m