packages feed

bluefin-algae-0.1.0.2: src/Bluefin/Algae/Exception/DynExn.hs

{-# LANGUAGE
  BangPatterns,
  GADTs,
  RankNTypes,
  ScopedTypeVariables,
  StandaloneKindSignatures,
  TypeOperators #-}

-- | = Exceptions as an algebraic effect
--
-- Variant of "Bluefin.Algae.Exception" that uses dynamic exceptions to cancel
-- continuations.
module Bluefin.Algae.Exception.DynExn
  ( Exception(..)
  , throw
  , catch
  , try
  ) where

import Bluefin.Eff (Eff, type (:&), type (:>))
import Bluefin.Algae.DynExn
import Bluefin.Algae.Exception (Exception(..))
import Bluefin.Exception.Dynamic (DynExn)

-- | Catch an exception.
catch :: forall e a ex zz. ex :> zz =>
  DynExn ex ->
  (forall z. Handler ex (Exception e) z -> Eff (z :& zz) a) ->
  (e -> Eff zz a) ->
  Eff zz a
catch ex f h = handle ex exceptionHandler f
  where
    exceptionHandler :: HandlerBody ex (Exception e) zz a
    exceptionHandler (Throw e) k = cancel ex k *> h e

-- | Return 'Either' the exception or the result of the handled computation.
try :: forall e a ex zz. ex :> zz =>
  DynExn ex ->
  (forall z. Handler ex (Exception e) z -> Eff (z :& zz) a) ->
  Eff zz (Either e a)
try ex f = catch ex (fmap Right . f) (pure . Left)

-- | Throw an exception. Call the 'Throw' operation.
throw :: (ex :> zz, z :> zz) => Handler ex (Exception e) z -> e -> Eff zz a
throw h e = call h (Throw e)