module Data.OpenWitness.Exception
(
    Exn, declexn, throw, catch
) where
{
    import Data.Kind;
    import Data.OpenWitness;
    import Data.Witness;
    import Data.Maybe;
    import Data.Typeable;
    import Language.Haskell.TH;
    import qualified Control.Exception as CE (Exception,throw,catch);
    import Prelude(IO,Show(..));
    
    ;
    newtype Exn (e :: *) = MkExn (IOWitness e);
    instance TestEquality Exn where
    {
        testEquality (MkExn a) (MkExn b) = testEquality a b;
    };
    newtype ExnException = MkExnException (Any Exn) deriving Typeable;
    
    ;
    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 (MkAny exn e));
    catch :: IO a -> Exn e -> (e -> IO a) -> IO a;
    catch foo exn catcher = CE.catch foo (\ex@(MkExnException cell) -> case matchAny exn cell of
    {
        Just e -> catcher e;
        _ -> CE.throw ex;
    });
}