{-# options_haddock prune #-}

-- |Description: Critical effect
module Polysemy.Conc.Effect.Critical where

import Prelude hiding (catch)

-- |An effect that catches exceptions.
--
-- Provides the exact functionality of `Polysemy.Error.fromExceptionSem`, but pushes the dependency on @Final IO@ to the
-- interpreter, and makes it optional.
data Critical :: Effect where
  -- |Catch all exceptions of type @e@ in this computation.
  Catch :: Exception e => m a -> Critical m (Either e a)

makeSem ''Critical

-- |Catch exceptions of type @e@ and return a fallback value.
catchAs ::
   e a r .
  Exception e =>
  Member Critical r =>
  a ->
  Sem r a ->
  Sem r a
catchAs :: forall e a (r :: EffectRow).
(Exception e, Member Critical r) =>
a -> Sem r a -> Sem r a
catchAs a
a =
  (Either e a -> a) -> Sem r (Either e a) -> Sem r a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> Either e a -> a
forall b a. b -> Either a b -> b
fromRight a
a) (Sem r (Either e a) -> Sem r a)
-> (Sem r a -> Sem r (Either e a)) -> Sem r a -> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: EffectRow) e a.
(Member Critical r, Exception e) =>
Sem r a -> Sem r (Either e a)
catch @_ @e

-- |Convenience overload for 'SomeException'.
run ::
  Member Critical r =>
  Sem r a ->
  Sem r (Either SomeException a)
run :: forall (r :: EffectRow) a.
Member Critical r =>
Sem r a -> Sem r (Either SomeException a)
run =
  Sem r a -> Sem r (Either SomeException a)
forall (r :: EffectRow) e a.
(Member Critical r, Exception e) =>
Sem r a -> Sem r (Either e a)
catch

-- |Convenience overload for 'SomeException'.
runAs ::
  Member Critical r =>
  a ->
  Sem r a ->
  Sem r a
runAs :: forall (r :: EffectRow) a.
Member Critical r =>
a -> Sem r a -> Sem r a
runAs a
a =
  (Either SomeException a -> a)
-> Sem r (Either SomeException a) -> Sem r a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> Either SomeException a -> a
forall b a. b -> Either a b -> b
fromRight a
a) (Sem r (Either SomeException a) -> Sem r a)
-> (Sem r a -> Sem r (Either SomeException a))
-> Sem r a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem r a -> Sem r (Either SomeException a)
forall (r :: EffectRow) a.
Member Critical r =>
Sem r a -> Sem r (Either SomeException a)
run