--
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)
--