3f1435dcb2c6546b7bc4707705508b5dfcf5ba18
[lambda.git] / code / lambda.ml
1 (* *)
2
3 module Private =  struct
4     type var_t = int*string
5     let var v = (0,v)
6     let string_of_var (i,v) = v ^ String.make i '\''
7     let equal_var (i1,v1) (i2,v2) = i1 == i2 && (String.compare v1 v2 == 0)
8
9     type lambda_t = [ `Var of var_t | `Lam of var_t * lambda_t | `App of lambda_t * lambda_t ]
10
11     type debruijn_t = [ `Var of var_t | `DVar of int | `DLam of debruijn_t | `DApp of debruijn_t*debruijn_t ]
12
13     let db_subst (expr : debruijn_t) (m : int) (repl : debruijn_t) =
14         let rec rename m i = function
15         | `Var _ as term -> term
16         | `DVar j as term when j < i -> term
17         | `DVar j -> `DVar (j + m - 1)
18         | `DApp(n1,n2) -> `DApp(rename m i n1, rename m i n2)
19         | `DLam n -> `DLam(rename m (i+1) n)
20         in let rec loop m = function
21         | `Var _ as term -> term
22         | `DVar n as term when n < m -> term
23         | `DVar n when n > m -> `DVar (n-1)
24         | `DVar n -> rename n 1 repl
25         | `DApp(m1,m2) -> `DApp(loop m m1, loop m m2)
26         | `DLam mterm -> `DLam(loop (m+1) mterm)
27         in loop m expr
28
29     let db (expr : lambda_t) : debruijn_t =
30         let pos seq (target : var_t) handler default =
31             let rec loop (i : int) = function
32             | [] -> default
33             | x::xs when equal_var x target -> handler i
34             | _::xs -> loop (i+1) xs
35             in loop 1 seq
36         in let rec loop seq = function
37         | `Var v as term -> pos seq v (fun i -> `DVar i) term
38         | `Lam (v,t) -> `DLam(loop (v::seq) t)
39         | `App (t1,t2) -> `DApp(loop seq t1, loop seq t2)
40         in loop [] expr
41
42     let rec db_equal (t1 : debruijn_t) (t2 : debruijn_t) = match (t1,t2) with
43     | (`Var v1,`Var v2) -> equal_var v1 v2
44     | (`DVar i1, `DVar i2) -> i1 == i2
45     | (`DApp(m1,m2),`DApp(n1,n2)) -> db_equal m1 n1 && db_equal m2 n2
46     | (`DLam(t1),`DLam(t2)) -> db_equal t1 t2
47     | _ -> false
48
49     let rec db_contains (t1 : debruijn_t) (t2 : debruijn_t) = match (t1,t2) with
50     | (`Var v1,`Var v2) -> equal_var v1 v2
51     | (`DVar i1, `DVar i2) -> i1 == i2
52     | (`DApp(m1,m2),`DApp(n1,n2)) when db_equal m1 n1 && db_equal m2 n2 -> true
53     | (`DApp(m1,m2), term) -> db_contains m1 term || db_contains m2 term
54     | (`DLam(t1),`DLam(t2)) when db_equal t1 t2 -> true
55     | (`DLam(t1), term) -> db_contains t1 term
56     | _ -> false
57
58     (* non-normalizing string_of_lambda *)
59     let string_of_lambda (expr : lambda_t) =
60         let rec top = function
61             | `Var v -> string_of_var v
62             | `Lam _ as t -> "fun " ^ funct t
63             | `App ((`App _ as t1),t2) -> top t1 ^ " " ^ atom t2
64             | `App (t1,t2) -> atom t1 ^ " " ^ atom t2
65         and atom = function
66             | `Var v -> string_of_var v
67             | `Lam _ as t -> "(fun " ^ funct t ^ ")"
68             | `App _ as t -> "(" ^ top t ^ ")"
69         and funct = function
70             | `Lam (v,(`Lam _ as t)) -> (string_of_var v) ^ " " ^ funct t
71             | `Lam (v,t) -> (string_of_var v) ^ " -> " ^ top t
72         in top expr
73
74
75     (* evaluator based on http://okmij.org/ftp/Haskell/Lambda_calc.lhs *)
76
77     (* if v occurs free_in term, returns Some v' where v' is the highest-tagged
78      * variable with the same name as v occurring (free or bound) in term *)
79
80     let free_in ((tag, name) as v) term =
81         let rec loop = function
82         | `Var((tag', name') as v') ->
83                 if name <> name' then false, v
84                 else if tag = tag' then true, v
85                 else false, v'
86         | `App(t1, t2) ->
87                 let b1, ((tag1, _) as v1) = loop t1 in
88                 let b2, ((tag2, _) as v2) = loop t2 in
89                 b1 || b2, if tag1 > tag2 then v1 else v2
90         | `Lam(x, _) when x = v -> (false, v)
91         | `Lam(_, body) -> loop body
92         in match loop term with
93         | false, _ -> None
94         | true, v -> Some v
95
96     let rec subst v st = function
97         | term when st = `Var v -> term
98         | `Var x when x = v -> st
99         | `Var _ as term -> term
100         | `App(t1,t2) -> `App(subst v st t1, subst v st t2)
101         | `Lam(x, _) as term when x = v -> term
102         (* if x is free in the inserted term st, a capture is possible
103          * we handle by ...
104          *)
105         | `Lam(x, body) ->
106                 (match free_in x st with
107                 (* x not free in st, can substitute st for v without any captures *)
108                 | None -> `Lam(x, subst v st body)
109                 (* x free in st, need to alpha-convert `Lam(x, body) *)
110                 | Some max_x ->  
111                     let bump_tag (tag, name) (tag', _) =
112                         (max tag tag') + 1, name in
113                     let bump_tag' ((_, name) as v1) ((_, name') as v2) =
114                         if name = name' then bump_tag v1 v2 else v1 in
115                     (* bump x > max_x from st, then check whether
116                      * it also needs to be bumped > v
117                      *)
118                     let uniq_x = bump_tag' (bump_tag x max_x) v in
119                     let uniq_x' = (match free_in uniq_x body with
120                         | None -> uniq_x
121                         (* bump uniq_x > max_x' from body *)
122                         | Some max_x' -> bump_tag uniq_x max_x'
123                     ) in
124                     (* alpha-convert body *)
125                     let body' = subst x (`Var uniq_x') body in
126                     (* now substitute st for v *)
127                     `Lam(uniq_x', subst v st body')
128                 )
129
130     let check_eta = function
131         | `Lam(v, `App(t, `Var u)) when v = u && free_in v t = None -> t
132         | (_ : lambda_t) as term -> term
133
134     exception Lambda_looping;;
135
136     let eval ?(eta=false) (expr : lambda_t) : lambda_t =
137         let rec looping (body : debruijn_t) = function
138         | [] -> false
139         | x::xs when db_equal body x -> true
140         | _::xs -> looping body xs
141         in let rec loop (stack : lambda_t list) (body : lambda_t) = 
142             match body with
143             | `Var v as term -> unwind term stack
144             | `App(t1, t2) as term -> loop (t2::stack) t1
145             | `Lam(v, body) -> (match stack with
146                 | [] ->
147                     let term = (`Lam(v, loop [] body)) in
148                         if eta then check_eta term else term
149                 | t::rest -> loop rest (subst v t body)
150             )
151         and unwind t1 = function
152         | [] -> t1
153         | t2::ts -> unwind (`App(t1, loop [] t2)) ts
154         in loop [] expr
155
156
157     (* (Oleg's version of) Ken's evaluator; doesn't seem to work -- requires laziness? *)
158
159     let eval' ?(eta=false) (expr : lambda_t) : lambda_t =
160         let rec loop = function
161         | `Var v as term -> term
162         | `Lam(v, body) ->
163                 let term = (`Lam(v, loop body)) in
164                     if eta then check_eta term else term
165         | `App(`App _ as t1, t2) ->
166             (match loop t1 with
167                 | `Lam _ as redux -> loop (`App(redux, t2))
168                 | nonred_head -> `App(nonred_head, loop t2)
169             )
170         | `App(t1, t2) -> `App(t1, loop t2)
171         in loop expr
172
173     let cbv ?(aggressive=true) (expr : lambda_t) : lambda_t =
174         let rec loop = function
175         | `Var x as term -> term
176         | `App(t1,t2) ->
177                 let t2' = loop t2 in
178                 (match loop t1 with
179                 | `Lam(x, t) -> loop (subst x t2' t)
180                 | _ as term -> `App(term, t2')
181                 )
182         | `Lam(x, t) as term ->
183                 if aggressive then `Lam(x, loop t)
184                 else term
185         in loop expr
186
187
188
189     (*
190         module Sorted = struct
191             let rec cons y = function
192                 | x :: _ as xs when x = y -> xs
193                 | x :: xs when x < y -> x :: cons y xs
194                 | xs [* [] or x > y *] -> y :: xs
195
196             let rec mem y = function
197                 | x :: _ when x = y -> true
198                 | x :: xs when x < y -> mem y xs
199                 | _ [* [] or x > y *] -> false
200
201             let rec remove y = function
202                 | x :: xs when x = y -> xs
203                 | x :: xs when x < y -> x :: remove y xs
204                 | xs [* [] or x > y *] -> xs
205
206             let rec merge x' y' = match x', y' with
207                 | [], ys -> ys
208                 | xs, [] -> xs
209                 | x::xs, y::ys ->
210                     if x < y then x :: merge xs y'
211                     else if x = y then x :: merge xs ys
212                     else [* x > y *] y :: merge x' ys
213         end
214
215         let free_vars (expr : lambda_t) : string list =
216             let rec loop = function
217                 | `Var x -> [x]
218                 | `Lam(x,t) -> Sorted.remove x (loop t)
219                 | `App(t1,t2) -> Sorted.merge (loop t1) (loop t2)
220             in loop expr
221
222         let free_in v (expr : lambda_t) =
223             Sorted.mem v (free_vars t)
224
225         let new_var =
226             let counter = ref 0 in
227             fun () -> (let z = !counter in incr counter; "_v"^(string_of_int z))
228
229         ...
230         | `Lam(x, body) as term when not (free_in v body) -> term
231         | `Lam(y, body) when not (free_in y st) -> `Lam(y, subst v st body)
232         | `Lam(y, body) ->
233             let z = new_var () in
234             subst v st (`Lam(z, subst y (`Var z) body))
235     *)
236
237
238
239     (*
240
241     let bound_vars (expr : lambda_t) : string list =
242         let rec loop = function
243             | `Var x -> []
244             | `Lam(x,t) -> Sorted.cons x (loop t)
245             | `App(t1,t2) -> Sorted.merge (loop t1) (loop t2)
246         in loop expr
247
248     let reduce_cbv ?(aggressive=true) (expr : lambda_t) : lambda_t =
249         let rec loop = function
250         | `Var x as term -> term
251         | `App(t1,t2) ->
252                 let t2' = loop t2 in
253                 (match loop t1 with
254                 | `Lam(x, t) -> loop (subst x t2' t)
255                 | _ as term -> `App(term, t2')
256                 )
257         | `Lam(x, t) as term ->
258                 if aggressive then `Lam(x, loop t)
259                 else term
260         in loop expr
261
262     let reduce_cbn (expr : lambda_t) : lambda_t =
263         let rec loop = function
264         | `Var x as term -> term
265         | `Lam(v, body) ->
266                 check_eta (`Lam(v, loop body))
267         | `App(t1,t2) ->
268                 (match loop t1 with
269                 | `Lam(x, t) -> loop (subst x t2 t)
270                 | _ as term -> `App(term, loop t2)
271                 )
272         in loop expr
273
274     *)
275
276
277     (*
278
279     type env_t = (string * lambda_t) list
280
281     let subst body x value =
282         ((fun env ->
283             let new_env = (x, value) :: env in
284             body new_env) : env_t -> lambda_t)
285
286     type strategy_t = By_value | By_name
287
288     let eval (strategy : strategy_t) (expr : lambda_t) : lambda_t =
289         in let rec inner = function
290             | `Var x as t ->
291                 (fun env ->
292                     try List.assoc x env with
293                     | Not_found -> t)
294             | `App(t1, value) -> 
295                 (fun env ->
296                     let value' =
297                         if strategy = By_value then inner value env else value in
298                     (match inner t1 env with
299                     | `Lam(x, body) ->
300                         let body' = (subst (inner body) x value' env) in
301                         if strategy = By_value then body' else inner body' env
302                     | (t1' : lambda_t) -> `App(t1', inner value env)
303                     )
304                 )
305             | `Lam(x, body) ->
306                 (fun env ->
307                     let v = new_var () in
308                     `Lam(v, inner body ((x,`Var v) :: env)))
309         in inner expr ([] : env_t)
310
311     let pp_env env =
312         let rec loop acc = function
313             | [] -> acc
314             | (x,term)::es -> loop ((x ^ "=" ^ string_of_lambda term) :: acc) es
315         in "[" ^ (String.concat ", " (loop [] (List.rev env))) ^ "]"
316
317     let eval (strategy : strategy_t) (expr : lambda_t) : lambda_t =
318         let new_var =
319             let counter = ref 0 in
320             fun () -> (let z = !counter in incr counter; "_v"^(string_of_int z))
321         in let rec inner term =
322             begin
323             Printf.printf "starting [ %s ]\n" (string_of_lambda term);
324             let res = match term with
325             | `Var x as t ->
326                 (fun env ->
327                     try List.assoc x env with
328                     | Not_found -> t)
329             | `App(t1, value) -> 
330                 (fun env ->
331                     let value' =
332                         if strategy = By_value then inner value env else value in
333                     (match inner t1 env with
334                     | `Lam(x, body) ->
335                         let body' = (subst (inner body) x value' env) in
336                         if strategy = By_value then body' else inner body' env
337                     | (t1' : lambda_t) -> `App(t1', inner value env)
338                     )
339                 )
340             | `Lam(x, body) ->
341                 (fun env ->
342                     let v = new_var () in
343                     `Lam(v, inner body ((x,`Var v) :: env)))
344             in
345             (fun env -> 
346                 (Printf.printf "%s with %s => %s\n" (string_of_lambda term) (pp_env env) (string_of_lambda (res env)); res env))
347             end
348         in inner expr ([] : env_t)
349
350     *)
351
352     let normal ?(eta=false) expr = eval ~eta expr
353
354     let normal_string_of_lambda ?(eta=false) (expr : lambda_t) =
355         string_of_lambda (normal ~eta expr)
356
357     let rec to_int expr = match expr with
358         | `Lam(s, `Lam(z, `Var z')) when z' = z -> 0
359         | `Lam(s, `Var s') when s = s' -> 1
360         | `Lam(s, `Lam(z, `App (`Var s', t))) when s' = s -> 1 + to_int (`Lam(s, `Lam(z, t)))
361         | _ -> failwith (normal_string_of_lambda expr ^ " is not a church numeral")
362
363     let int_of_lambda ?(eta=false) (expr : lambda_t) =
364         to_int (normal ~eta expr)
365
366 end
367
368 type lambda_t = Private.lambda_t
369 open Private
370 let var = var
371 let pp, pn, pi = string_of_lambda, normal_string_of_lambda, int_of_lambda
372 let pnv,piv= (fun expr -> string_of_lambda (cbv expr)), (fun expr -> to_int (cbv expr))
373 let db, db_equal, db_contains = db, db_equal, db_contains
374