module ExceptMT (HasExcept(..), MT(..), WithExcept, removeExcept, mapExcept) where import MT import Control_Monad_Fix import Monad(liftM,MonadPlus(..)) newtype WithExcept x m a = E { removeExcept :: m (Either x a) } iso f = E . f . removeExcept mapExcept :: Monad m => (x -> y) -> WithExcept x m a -> WithExcept y m a mapExcept f = iso (liftM (either (Left . f) Right)) -------------------------------------------------------------------------------- instance Monad m => Functor (WithExcept x m) where fmap = liftM instance Monad m => Monad (WithExcept x m) where return = lift . return E m >>= f = E $ do x <- m case x of Left x -> return (Left x) Right a -> removeExcept (f a) instance MT (WithExcept x) where lift m = E (m >>= return . Right) instance MonadPlus m => MonadPlus (WithExcept x m) where mzero = lift mzero E m1 `mplus` E m2 = E (m1 `mplus` m2) -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- instance HasEnv m ix e => HasEnv (WithExcept x m) ix e where getEnv ix = lift (getEnv ix) inModEnv ix f = iso (inModEnv ix f) instance HasState m ix s => HasState (WithExcept x m) ix s where updSt ix = lift . updSt ix instance HasOutput m ix o => HasOutput (WithExcept x m) ix o where outputTree ix = lift . outputTree ix instance Monad m => HasExcept (WithExcept x m) x where raise = E . return . Left handle h (E m) = E (m >>= either (removeExcept . h) (return . Right)) instance HasCont m => HasCont (WithExcept x m) where callcc f = E $ callcc $ \k -> removeExcept $ f $ E . k . Right instance HasBaseMonad m n => HasBaseMonad (WithExcept e m) n where inBase = lift . inBase instance HasRefs m r => HasRefs (WithExcept x m) r where newRef = lift . newRef readRef = lift . readRef writeRef r = lift . writeRef r instance MonadFix m => MonadFix (WithExcept x m) where mfix f = E $ mfix (removeExcept . f . either undefined id)