open-witness-0.5: src/Data/OpenWitness/Exception.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# OPTIONS -fno-warn-unused-matches #-}
module Data.OpenWitness.Exception
( Exn
, declexn
, throw
, catch
) where
import qualified Control.Exception as CE (Exception, catch, throw)
import Data.Kind
import Data.OpenWitness
import Data.Typeable
import Data.Witness
import Language.Haskell.TH hiding (Type)
import Prelude
-- | A key to match exceptions. The type variable is the data the exception carries.
newtype Exn (e :: Type) =
MkExn (IOWitness e)
instance TestEquality Exn where
testEquality (MkExn a) (MkExn b) = testEquality a b
newtype ExnException =
MkExnException (AnyValue Exn)
deriving (Typeable)
-- | Template Haskell function to declare 'Exn' exception keys.
declexn :: TypeQ -> Q Exp
declexn te = [|MkExn $(iowitness te)|]
instance Show ExnException where
show _ = "ExnException"
instance CE.Exception ExnException
throw :: Exn e -> e -> a
throw exn e = CE.throw (MkExnException (MkAnyValue exn e))
catch :: IO a -> Exn e -> (e -> IO a) -> IO a
catch foo exn catcher =
CE.catch
foo
(\ex@(MkExnException cell) ->
case matchAnyValue exn cell of
Just e -> catcher e
_ -> CE.throw ex)