effectful-0.0.0.0: src/Effectful/Error.hs
-- | Support for checked exceptions.
module Effectful.Error
( Error
, runError
, throwError
, catchError
, tryError
) where
import Control.Exception
import Data.Typeable
import GHC.Stack
import Effectful.Internal.Env
import Effectful.Internal.Has
import Effectful.Internal.Monad
import Effectful.Internal.Utils
type role Error nominal
data Error e = Error
runError
:: forall e es a. Exception e
=> Eff (Error e : es) a
-> Eff es (Either ([String], e) a)
runError (Eff m) = impureEff $ \es0 -> mask $ \release -> do
size <- sizeEnv es0
es <- unsafeConsEnv (Error @e) es0
try (release $ m es) >>= \case
Right a -> Right a <$ unsafeTrimEnv size es
Left (WrapE cs e) -> Left (cs, e) <$ unsafeTrimEnv size es
throwError
:: (HasCallStack, Exception e, Error e :> es)
=> e
-> Eff es a
throwError e = impureEff_ $ do
throwIO $ WrapE (ppCallStack <$> getCallStack callStack) e
catchError
:: (Exception e, Error e :> es)
=> Eff es a
-> ([String] -> e -> Eff es a)
-> Eff es a
catchError (Eff m) handler = impureEff $ \es -> do
size <- sizeEnv es
m es `catch` \(WrapE e cs) -> do
checkSizeEnv size es
unEff (handler e cs) es
tryError
:: (Exception e, Error e :> es)
=> Eff es a
-> Eff es (Either ([String], e) a)
tryError m = (Right <$> m) `catchError` \es e -> pure (Left (es, e))
----------------------------------------
-- WrapE
data WrapE e = WrapE [String] e
deriving Show
instance (Show e, Typeable e) => Exception (WrapE e)