{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}

module Bluefin.Internal.Capability.ThrowCatch
  ( ThrowCatch,
    module Bluefin.Internal.Capability.ThrowCatch,
  )
where

import Bluefin.Internal
  ( ThrowCatch (MkThrowCatch),
    Eff,
    throwCatchTry,
    throwCatchThrow,
    unsafeProvideIO,
    useImpl,
    withEffToIO_,
    (:&),
    type (<:),
  )
import Bluefin.Internal.Exception.Scoped qualified as Scoped

try ::
  (forall e. ThrowCatch ex e -> Eff (e :& es) a) ->
  -- | ͘
  Eff es (Either ex a)
try :: forall ex (es :: Effects) a.
(forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a)
-> Eff es (Either ex a)
try = (forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a)
-> Eff es (Either ex a)
forall ex (es :: Effects) a.
(forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a)
-> Eff es (Either ex a)
throwCatchTry

handle ::
  (ex -> Eff es a) ->
  (forall e. ThrowCatch ex e -> Eff (e :& es) a) ->
  -- | ͘
  Eff es a
handle :: forall ex (es :: Effects) a.
(ex -> Eff es a)
-> (forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a)
-> Eff es a
handle ex -> Eff es a
h forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a
f =
  (forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a)
-> Eff es (Either ex a)
forall ex (es :: Effects) a.
(forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a)
-> Eff es (Either ex a)
try ThrowCatch ex e -> Eff (e :& es) a
forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a
f Eff es (Either ex a) -> (Either ex a -> Eff es a) -> Eff es a
forall a b. Eff es a -> (a -> Eff es b) -> Eff es b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Left ex
ex -> ex -> Eff es a
h ex
ex
    Right a
a -> a -> Eff es a
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a

catch ::
  (forall e. ThrowCatch ex e -> Eff (e :& es) a) ->
  (ex -> Eff es a) ->
  -- | ͘
  Eff es a
catch :: forall ex (es :: Effects) a.
(forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a)
-> (ex -> Eff es a) -> Eff es a
catch forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a
f ex -> Eff es a
h = (ex -> Eff es a)
-> (forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a)
-> Eff es a
forall ex (es :: Effects) a.
(ex -> Eff es a)
-> (forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a)
-> Eff es a
handle ex -> Eff es a
h ThrowCatch ex e -> Eff (e :& es) a
forall (e :: Effects). ThrowCatch ex e -> Eff (e :& es) a
f

localCatch ::
  (e <: es) =>
  ThrowCatch ex e ->
  Eff es a ->
  (ex -> Eff es a) ->
  -- | ͘
  Eff es a
localCatch :: forall (e :: Effects) (es :: Effects) ex a.
(e <: es) =>
ThrowCatch ex e -> Eff es a -> (ex -> Eff es a) -> Eff es a
localCatch ThrowCatch ex e
h Eff es a
action ex -> Eff es a
handler =
  ThrowCatch ex e -> Eff es a -> Eff es (Either ex a)
forall (e :: Effects) (es :: Effects) ex a.
(e <: es) =>
ThrowCatch ex e -> Eff es a -> Eff es (Either ex a)
localTry ThrowCatch ex e
h Eff es a
action Eff es (Either ex a) -> (Either ex a -> Eff es a) -> Eff es a
forall a b. Eff es a -> (a -> Eff es b) -> Eff es b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Left ex
ex -> ex -> Eff es a
handler ex
ex
    Right a
a -> a -> Eff es a
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a

localHandle ::
  (e <: es) =>
  ThrowCatch ex e ->
  (ex -> Eff es a) ->
  Eff es a ->
  -- | ͘
  Eff es a
localHandle :: forall (e :: Effects) (es :: Effects) ex a.
(e <: es) =>
ThrowCatch ex e -> (ex -> Eff es a) -> Eff es a -> Eff es a
localHandle ThrowCatch ex e
h ex -> Eff es a
handler Eff es a
action = ThrowCatch ex e -> Eff es a -> (ex -> Eff es a) -> Eff es a
forall (e :: Effects) (es :: Effects) ex a.
(e <: es) =>
ThrowCatch ex e -> Eff es a -> (ex -> Eff es a) -> Eff es a
localCatch ThrowCatch ex e
h Eff es a
action ex -> Eff es a
handler

throw ::
  (e <: es) =>
  ThrowCatch ex e ->
  ex ->
  -- | ͘
  Eff es a
throw :: forall (e :: Effects) (es :: Effects) ex a.
(e <: es) =>
ThrowCatch ex e -> ex -> Eff es a
throw = ThrowCatch ex e -> ex -> Eff es a
forall (e :: Effects) (es :: Effects) ex a.
(e <: es) =>
ThrowCatch ex e -> ex -> Eff es a
throwCatchThrow

localTry ::
  (e <: es) =>
  ThrowCatch ex e ->
  Eff es a ->
  -- | ͘
  Eff es (Either ex a)
localTry :: forall (e :: Effects) (es :: Effects) ex a.
(e <: es) =>
ThrowCatch ex e -> Eff es a -> Eff es (Either ex a)
localTry ThrowCatch ex e
h Eff es a
action = case ThrowCatch ex e
h of
  MkThrowCatch Exception ex
ex ->
    (forall (e :: Effects). IOE e -> Eff (e :& es) (Either ex a))
-> Eff es (Either ex a)
forall (es :: Effects) a.
(forall (e :: Effects). IOE e -> Eff (e :& es) a) -> Eff es a
unsafeProvideIO ((forall (e :: Effects). IOE e -> Eff (e :& es) (Either ex a))
 -> Eff es (Either ex a))
-> (forall (e :: Effects). IOE e -> Eff (e :& es) (Either ex a))
-> Eff es (Either ex a)
forall a b. (a -> b) -> a -> b
$ \IOE e
io ->
      IOE e
-> ((forall {r}. Eff (e :& es) r -> IO r) -> IO (Either ex a))
-> Eff (e :& es) (Either ex a)
forall (e :: Effects) (es :: Effects) a.
(e <: es) =>
IOE e -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
withEffToIO_ IOE e
io (((forall {r}. Eff (e :& es) r -> IO r) -> IO (Either ex a))
 -> Eff (e :& es) (Either ex a))
-> ((forall {r}. Eff (e :& es) r -> IO r) -> IO (Either ex a))
-> Eff (e :& es) (Either ex a)
forall a b. (a -> b) -> a -> b
$ \forall {r}. Eff (e :& es) r -> IO r
runInIO ->
        Exception ex -> IO a -> IO (Either ex a)
forall e a. Exception e -> IO a -> IO (Either e a)
Scoped.localTry Exception ex
ex (Eff (e :& es) a -> IO a
forall {r}. Eff (e :& es) r -> IO r
runInIO (Eff es a -> Eff (e :& es) a
forall (e :: Effects) (es :: Effects) r.
(e <: es) =>
Eff e r -> Eff es r
useImpl Eff es a
action))