freer-simple-1.0.0.0: src/Control/Monad/Freer/Error.hs
-- |
-- 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 <lexi.lambda@gmail.com>
-- Stability: experimental
-- Portability: GHC specific language extensions.
--
-- Composable handler for Error effects. Communicates success\/failure via an
-- 'Either' type.
--
-- Using <http://okmij.org/ftp/Haskell/extensible/Eff1.hs> 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