module IxEnvMT (HasEnv(..), MT(..), at, Z, S, Top, Under, WithEnv, withEnv, mapEnv) where
import MT
import Control_Monad_Fix
import Monad(liftM,MonadPlus(..))
newtype WithEnv e m a = E { unE :: e -> m a }
withEnv :: e -> WithEnv e m a -> m a
withEnv e (E f) = f e
mapEnv :: Monad m => (e2 -> e1) -> WithEnv e1 m a -> WithEnv e2 m a
mapEnv f (E m) = E (\e -> m (f e))
--------------------------------------------------------------------------------
instance Monad m => Functor (WithEnv e m) where
fmap = liftM
instance Monad m => Monad (WithEnv e m) where
return = lift . return
E m >>= f = E (\e -> do x <- m e; unE (f x) e)
E m >> n = E (\e -> m e >> withEnv e n)
fail = lift . fail
instance MT (WithEnv e) where
lift = E . const
instance MonadPlus m => MonadPlus (WithEnv e m) where
mzero = lift mzero
E a `mplus` E b = E (\e -> a e `mplus` b e)
--------------------------------------------------------------------------------
-- Features --------------------------------------------------------------------
instance Monad m => HasEnv (WithEnv e m) Z e where
getEnv _ = E return
inModEnv _ = mapEnv
instance HasEnv m ix e => HasEnv (WithEnv e' m) (S ix) e where
getEnv (Next ix) = lift (getEnv ix)
inModEnv (Next ix) f m = E (\e -> inModEnv ix f (withEnv e m))
instance HasState m ix s => HasState (WithEnv e m) ix s where
updSt ix = lift . updSt ix
instance HasOutput m ix o => HasOutput (WithEnv e m) ix o where
outputTree ix = lift . outputTree ix
instance HasExcept m x => HasExcept (WithEnv e m) x where
raise = lift . raise
handle h (E m) = E (\e -> handle (withEnv e . h) (m e))
instance HasCont m => HasCont (WithEnv e m) where
callcc f = E (\e -> callcc (\k -> withEnv e $ f (lift . k)))
instance MonadFix m => MonadFix (WithEnv e m) where
mfix f = E (\e -> mfix (withEnv e . f))
instance HasBaseMonad m n => HasBaseMonad (WithEnv e m) n where
inBase = lift . inBase
instance HasRefs m r => HasRefs (WithEnv e m) r where
newRef = lift . newRef
readRef = lift . readRef
writeRef r = lift . writeRef r