{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
-- | Exception-producing and exception-handling effects
module Control.Eff.Exception( Exc(..)
, throwExc
, runExc
, catchExc
) where
import Data.Typeable
import Control.Eff
-- | These are exceptions of the type e. This is akin to the error monad.
newtype Exc e v = Exc e
deriving (Functor, Typeable)
-- | Throw an exception in an effectful computation.
throwExc :: (Typeable e, Member (Exc e) r) => e -> Eff r a
throwExc e = send (\_ -> inj $ Exc e)
-- | Run a computation that might produce an exception.
runExc :: Typeable e => Eff (Exc e :> r) a -> Eff r (Either e a)
runExc m = loop (admin m)
where
loop (Val x) = return (Right x)
loop (E u) = handleRelay u loop (\(Exc e) -> return (Left e))
-- | Run a computation that might produce exceptions,
-- and give it a way to deal with the exceptions that come up.
catchExc :: (Typeable e, Member (Exc e) r)
=> Eff r a
-> (e -> Eff r a)
-> Eff r a
catchExc m handle = loop (admin m)
where
loop (Val x) = return x
loop (E u) = interpose u loop (\(Exc e) -> handle e)