module E = struct type bound = int type env = char -> bound end module R_E = Monad.Reader(E) module R = R_E.M let env0 = fun var -> raise Not_found let insert var value e = fun sought -> if sought = var then value else e sought let getint (var : char) : int R.t = R.asks (fun e -> let x = e var in x) (* monadic versions of `x` and `y` *) let getx = getint 'x' let gety = getint 'y' (* monadic version of `y + x` *) let (expr1 : int R.t) = R.(gety >>= fun y -> getx >>= fun x -> mid (y + x)) (* or *) let (expr1 : int R.t) = R.(map2 (+) gety getx) (* monadic version of `3 + x` *) let (expr2 : int R.t) = R.(map2 (+) (mid 3) getx) let letx xx body = R.(xx >>= fun x -> shift (insert 'x' x) body) (* monadic version of `let x = 2 in 3 + x` *) let (expr3 : int R.t) = R.(letx (mid 2) expr2) let res = R.run expr3 env0 (* will be 5 *)