1
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
3
-- | Basically a copy of the ErrorT monad transformer. It's handy to slap
4
-- onto TCM and still be a MonadTCM (which isn't possible with ErrorT).
6
module Agda.TypeChecking.Monad.Exception where
8
import Control.Applicative
9
import Control.Monad.Error
10
import Control.Monad.State
11
import Control.Monad.Reader
12
import Agda.TypeChecking.Monad.Base
14
newtype ExceptionT err m a = ExceptionT { runExceptionT :: m (Either err a) }
16
class Error err => MonadException err m | m -> err where
17
throwException :: err -> m a
18
catchException :: m a -> (err -> m a) -> m a
20
instance (Monad m, Error err) => Monad (ExceptionT err m) where
21
return = ExceptionT . return . Right
22
ExceptionT m >>= k = ExceptionT $ do
25
Left err -> return $ Left err
26
Right x -> runExceptionT $ k x
27
fail = ExceptionT . return . Left . strMsg
29
instance (Monad m, Error err) => MonadException err (ExceptionT err m) where
30
throwException = ExceptionT . return . Left
31
catchException m h = ExceptionT $ do
34
Left err -> runExceptionT $ h err
35
Right x -> return $ Right x
37
instance MonadTrans (ExceptionT err) where
38
lift = ExceptionT . liftM Right
40
instance Functor f => Functor (ExceptionT err f) where
41
fmap f = ExceptionT . fmap (either Left (Right . f)) . runExceptionT
43
instance (Error err, Applicative m, Monad m) => Applicative (ExceptionT err m) where
47
instance (Error err, MonadState s m) => MonadState s (ExceptionT err m) where
48
get = ExceptionT $ Right `liftM` get
49
put x = ExceptionT $ Right `liftM` put x
51
instance (Error err, MonadReader r m) => MonadReader r (ExceptionT err m) where
52
ask = ExceptionT $ Right `liftM` ask
53
local f = ExceptionT . local f . runExceptionT
55
instance (Error err, MonadError err' m) => MonadError err' (ExceptionT err m) where
56
throwError err = ExceptionT $ Right `liftM` throwError err
57
catchError m h = ExceptionT $ runExceptionT m `catchError` (runExceptionT . h)
59
instance (Error err, MonadIO m) => MonadIO (ExceptionT err m) where
60
liftIO m = ExceptionT $ Right `liftM` liftIO m
62
instance (Error err, MonadTCM tcm) => MonadTCM (ExceptionT err tcm) where
63
liftTCM m = ExceptionT $ Right `liftM` liftTCM m