import Control.Monad.Reader type Bound = Int type Env = Char -> Bound env0 = \var -> error "Not found" insert var value e = \sought -> if sought == var then value else e sought getint :: Char -> Reader Env Int getint var = asks (\e -> let x = e var in x) -- monadic versions of `x` and `y` getx = getint 'x' gety = getint 'y' -- monadic version of `y + x` expr1 :: Reader Env Int expr1 = liftM2 (+) gety getx -- monadic version of `3 + x` expr2 :: Reader Env Int expr2 = liftM2 (+) (return 3) getx letx xx body = xx >>= \x -> local (insert 'x' x) body -- monadic version of `let x = 2 in 3 + x` expr3 :: Reader Env Int expr3 = letx (return 2) expr2 res = runReader expr3 env0 -- will be 5