-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmixev.ml
65 lines (47 loc) · 1.9 KB
/
mixev.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
(* $Id: mixev.ml,v 1.7 2002/01/10 09:46:44 garrigue Exp $ *)
(* Variables are common to lambda and expr *)
type var = [`Var of string]
let eval_var sub (`Var s as v : var) =
try List.assoc s sub with Not_found -> v
(* The lambda language: free variables, substitutions, and evaluation *)
type 'a lambda = [`Var of string | `Abs of string * 'a | `App of 'a * 'a]
let gensym = let n = ref 0 in fun () -> incr n; "_" ^ string_of_int !n
let eval_lambda eval_rec subst : 'a lambda -> [> 'a lambda] = function
#var as v -> eval_var subst v
| `App(l1, l2) ->
let l2' = eval_rec subst l2 in
begin match eval_rec subst l1 with
`Abs(s, body) ->
eval_rec [s,l2'] body
| l1' ->
`App (l1', l2')
end
| `Abs(s, l1) ->
let s' = gensym () in
`Abs(s', eval_rec ((s,`Var s')::subst) l1)
let rec eval1 subst = eval_lambda eval1 subst
(* The expr language of arithmetic expressions *)
type 'a expr =
[`Var of string | `Num of int | `Add of 'a * 'a | `Mult of 'a * 'a]
let map_expr f : 'a expr -> [> 'a expr] = function
#var | `Num _ as e -> e
| `Add(e1, e2) -> `Add (f e1, f e2)
| `Mult(e1, e2) -> `Mult (f e1, f e2)
let eval_expr eval_rec subst (e : 'a expr) : 'a =
match map_expr (eval_rec subst) e with
#var as v -> eval_var subst v
| `Add(`Num m, `Num n) -> `Num (m+n)
| `Mult(`Num m, `Num n) -> `Num (m*n)
| e -> e
let rec eval2 subst = eval_expr eval2 subst
(* The lexpr language, reunion of lambda and expr *)
type 'a lexpr = [ 'a lambda | 'a expr]
let eval_lexpr eval_rec subst : 'a lexpr -> [> 'a lexpr] = function
#lambda as x -> eval_lambda eval_rec subst x
| #expr as x -> eval_expr eval_rec subst x
let rec eval3 subst = eval_lexpr eval3 subst
(* A few examples:
eval1 [] (`App(`Abs("x",`Var"x"), `Var"y"));;
eval2 [] (`Add(`Mult(`Num 3, `Num 2), `Var"x"));;
eval3 [] (`Add(`App(`Abs("x",`Mult(`Var"x",`Var"x")),`Num 2), `Num 5));;
*)