Merge branch 'working'
[lambda.git] / code / reader2.hs
1 import Control.Monad.Reader
2 data Bound = Int Int | Fun (Reader Env Int -> Reader Env Int)
3 type Env = Char -> Bound
4
5
6 env0 = \var -> error "Not found"
7 insert var value e = \sought -> if sought == var then value else e sought
8
9 getint :: Char -> Reader Env Int
10 getint var = asks (\e -> let (Int x) = e var in x)
11
12 getfun :: Char -> Reader Env (Reader Env Int -> Reader Env Int)
13 getfun var = asks (\e -> let (Fun f) = e var in f)
14
15 -- monadic versions of `x` and `y` and `f`
16 getx = getint 'x'
17 gety = getint 'y'
18 getf = getfun 'f'
19
20 -- monadic version of `y + x`
21 expr1 :: Reader Env Int
22 expr1 = liftM2 (+) gety getx
23
24 -- monadic version of `\y -> y + x`
25 lambda1 :: Reader Env (Reader Env Int -> Reader Env Int)
26 lambda1 = return (\yy -> yy >>= \y -> local (insert 'y' (Int y)) expr1)
27
28 letx xx body = xx >>= \x -> local (insert 'x' (Int x)) body
29 letf ff body = ff >>= \f -> local (insert 'f' (Fun f)) body
30
31 -- monadic version of `let x = 2 in let f = \y -> y + x in f 3`
32 expr4 :: Reader Env Int
33 expr4 = letx (return 2) (letf lambda1 (getf >>= \f -> f (return 3)))
34
35 res = runReader expr4 env0 -- will be 5
36