--
import List(find) ----------------------------------------------- -- A simple functional language type Var = String data Term0 = Add0 Term0 Term0 | Const0 Int | Lambda0 Var Term0 | App0 Term0 Term0 | Var0 Var data Value0 = Int0 Int | Fun0 Var Term0 Env0 data Env0 = E0 [(Var,Value0)] ------------------------------------------------ -- A simple evaluator eval0 :: Env0 -> Term0 -> Value0 eval0 (e @ (E0 xs)) t = case t of Add0 x y -> plus (eval0 e x) (eval0 e y) Const0 n -> Int0 n Var0 s -> look xs s Lambda0 s t -> Fun0 s t e App0 f x -> apply (eval0 e f) (eval0 e x) where plus (Int0 x) (Int0 y) = Int0 (x+y) look ((x,v):xs) s = if s==x then v else look xs s apply (Fun0 v t e) x = eval0 (extend e v x) t extend (E0 xs) v x = (E0((v,x):xs)) ------------------------------------------------------------- -- Now let's try and make the environment abstract data Term1 = Add1 Term1 Term1 | Const1 Int | Lambda1 Var Term1 | App1 Term1 Term1 | Var1 Var data Value1 e = Int1 Int | Fun1 Var Term1 e ------------------------------------------------ -- A simple evaluator abstract on the environment type eval1 :: e -> (e -> Var -> Value1 e) -> (e -> Var -> Value1 e -> e) -> Term1 -> Value1 e eval1 e look extend t = case t of Add1 x y -> plus (eval e x) (eval e y) Const1 n -> Int1 n Var1 s -> look e s Lambda1 s t -> Fun1 s t e App1 f x -> apply (eval e f) (eval e x) where plus (Int1 x) (Int1 y) = Int1 (x+y) apply (Fun1 v t e) x = eval (extend e v x) t eval e x = eval1 e look extend x -------------------------------------------------------- -- Now supose we want to add pairs, or some other new type data Term2 = Add2 Term2 Term2 | Const2 Int | Lambda2 Var Term2 | App2 Term2 Term2 | Var2 Var | Pair2 Term2 Term2 -- (3, 4+5) | Let2 Pat Term2 Term2 -- let (x,y) = f x in x+y data Value2 e = Int2 Int | Fun2 Var Term2 e | Prod2 (Value2 e) (Value2 e) data Pat = Pat Var Var ----------------------------------------------------------- -- Now inorder to maintain the abstraction of enviroments -- the number of operators passed as parameters is getting -- out of hand eval2 :: e -> (e -> Var -> Value2 e) -> (e -> Var -> Value2 e -> e) -> (e -> Pat -> Value2 e -> e) -> Term2 -> Value2 e eval2 e look extend extpat t = case t of Add2 x y -> plus (eval e x) (eval e y) Const2 n -> Int2 n Var2 s -> look e s Lambda2 s t -> Fun2 s t e App2 f x -> apply (eval e f) (eval e x) Pair2 x y -> Prod2 (eval e x) (eval e y) Let2 p x y -> eval (extpat e p (eval e x)) y where plus (Int2 x) (Int2 y) = Int2 (x+y) apply (Fun2 v t e) x = eval (extend e v x) t eval e x = eval2 e look extend extpat x ----------------------------------------------------------- -- Lets capture the set of operators on the abstract environments -- as a type class class Environment e where look :: e -> Var -> Value2 e extend:: e -> Var -> Value2 e -> e extpat :: e -> Pat -> Value2 e -> e eval3 :: Environment e => e -> Term2 -> Value2 e eval3 e t = case t of Add2 x y -> plus (eval3 e x) (eval3 e y) Const2 n -> Int2 n Var2 s -> look e s Lambda2 s t -> Fun2 s t e App2 f x -> apply (eval3 e f) (eval3 e x) Pair2 x y -> Prod2 (eval3 e x) (eval3 e y) Let2 p x y -> eval3 (extpat e p (eval3 e x)) y where plus (Int2 x) (Int2 y) = Int2 (x+y) apply (Fun2 v t e) x = eval3 (extend e v x) t ------------------------------------------------------------- -- Lets try instantiating the Environment type class at -- several different types data Env3 = E3 [(Var,Value2 Env3)] instance Environment Env3 where look (E3((x,y):xs)) v = if x==v then y else look (E3 xs) v extend (E3 xs) v x = E3 ((v,x):xs) extpat (E3 xs) (Pat x y) (Prod2 a b) = E3 ((x,a):(y,b):xs) data Env4 = E4 (Var -> Value2 Env4) instance Environment Env4 where look (E4 f) v = f v extend (E4 f) v x = E4(\ y -> if y==v then x else f y) extpat (E4 f) (Pat x y) (Prod2 a b) = E4(\ z -> if x==z then a else if y==z then b else f z) -------------------------------------------------------------- -- let (f,g) = (\ x -> x+1, \ y -> y + 3) -- in f (g 5) prog = Let2 (Pat "f" "g") (Pair2 (Lambda2 "x" (Add2 (Var2 "x") (Const2 1))) (Lambda2 "y" (Add2 (Var2 "y") (Const2 3)))) (App2 (Var2 "f") (App2 (Var2 "g") (Const2 5))) ans = eval3 (E3 []) prog ans2 = eval3 (E4 (\ x -> error "no such name")) prog -------------------------------------------------------- data EnvironmentC e = EnvC {lookM :: e -> Var -> Value2 e, extendM :: e -> Var -> Value2 e -> e, extpatM :: e -> Pat -> Value2 e -> e } eval4 :: EnvironmentC a -> a -> Term2 -> Value2 a eval4 d e t = case t of Add2 x y -> plus (eval4 d e x) (eval4 d e y) Const2 n -> Int2 n Var2 s -> lookM d e s Lambda2 s t -> Fun2 s t e App2 f x -> apply (eval4 d e f) (eval4 d e x) Pair2 x y -> Prod2 (eval4 d e x) (eval4 d e y) Let2 p x y -> eval4 d (extpatM d e p (eval4 d e x)) y where plus (Int2 x) (Int2 y) = Int2 (x+y) apply (Fun2 v t e) x = eval4 d (extendM d e v x) t ----------------------------------------------------- e3Dict = EnvC { lookM = \ (E3((x,y):xs)) v -> if x==v then y else lookM e3Dict (E3 xs) v , extendM = \ (E3 xs) v x -> E3((v,x):xs) , extpatM = \ (E3 xs) (Pat x y) (Prod2 a b) -> E3((x,a):(y,b):xs) } e4Dict = EnvC { lookM = \ (E4 f) v -> f v , extendM = \ (E4 f) v x -> E4(\ y -> if y==v then x else f y) , extpatM = \ (E4 f) (Pat x y) (Prod2 a b) -> E4(\ z -> if x==z then a else if y==z then b else f z) } ans3 = eval4 e3Dict (E3 []) prog ans4 = eval4 e4Dict (E4 (\ x -> error "no such name")) prog --