--
data Mon m = Mon (forall a . a -> m a) (forall a b . m a -> (a -> m b) -> m b) type Transformer s t = Mon s -> Mon t ------------------------------- -- Three Monads --Id data Id x = Id x --Env data Env e x = Env (e -> x) --State data State s x = State (s -> (x,s)) --------------------------------------------- --data Id x = Id x idMon = let bind x f = case x of {(Id y) -> f y } in Mon Id bind runId (Id x) = x --data Env e x = Env (e -> x) envMon = let unit x = Env(\ _ -> x) bind (Env g) f = Env(\ e -> case f(g e) of { Env h -> h e }) in Mon unit bind readEnv = Env(\ e -> e) inEnv e (Env f) = Env(\ e2 -> f e) --data State s x = State (s -> (x,s)) stateMon = let unit x = State(\ s -> (x,s)) bind (State g) f = State(\ s -> let (a,s') = g s State h = f a in h s') in Mon unit bind readSt = State(\ s -> (s,s)) writeSt x = State(\ s -> ((),x)) -------------------------------------------- data WithEnv env m a = WithEnv (env -> m a) data Fenv m = Fenv (forall a e . m a -> WithEnv e m a) (forall e . WithEnv e m e) (forall a e . e -> WithEnv e m a -> WithEnv e m a) ----------------------------------------------------- transEnv (Mon unitM bindM) = let unitEnv x = WithEnv(\ rho -> unitM x) bindEnv x f = WithEnv(\ rho -> let (WithEnv h) = x in bindM (h rho) (\ a -> let (WithEnv g) = f a in g rho)) lift2 x = WithEnv(\ rho -> x) rdEnv = WithEnv(\ rho -> unitM rho) inEnv rho (WithEnv x) = WithEnv(\ _ -> x rho) in (Mon unitEnv bindEnv,Fenv lift2 rdEnv inEnv) ------------------------------------------------------------ data WithStore s m a = WithStore (s -> m (a,s)) data Fstore m = Fstore (forall a s . m a -> WithStore s m a) (forall s . (s -> s) -> WithStore s m ()) (forall s . WithStore s m s) ------------------------------------------------------ transStore (Mon unitM bindM) = let unitStore x = WithStore(\sigma -> unitM(x,sigma)) bindStore x f = WithStore(\ sigma0 -> let (WithStore h) = x in bindM (h sigma0) (\ (a,sigma1) -> let (WithStore g) = f a in g sigma1 ) ) lift2 x = WithStore(\ sigma -> bindM x (\ y -> unitM(y,sigma))) update f = WithStore(\ sigma -> unitM((),f sigma)) get = WithStore(\sigma -> unitM(sigma,sigma)) in (Mon unitStore bindStore,Fstore lift2 update get) ---------------------------------------------------------- -- an example ex1 :: (Mon (WithStore a (WithEnv b Id)) ,Fenv Id ,Fstore (WithEnv c Id)) ex1 = let (mon1,funs1) = transEnv idMon (mon2,funs2) = transStore mon1 in (mon2,funs1,funs2) --