pieuvre/lam.ml

119 lines
3.2 KiB
OCaml
Raw Permalink Normal View History

2024-04-09 11:09:33 +02:00
type id = string
2024-04-15 12:07:49 +02:00
type ty_annot = id * Types.ty
2024-04-09 11:09:33 +02:00
2024-04-16 10:07:09 +02:00
type lam =
Fun of ty_annot * lam
| App of lam * lam
2024-04-09 11:09:33 +02:00
| Var of id
2024-04-16 10:07:09 +02:00
| Exf of lam * Types.ty
2024-05-14 15:23:44 +02:00
| Pair of lam * lam
2024-05-17 08:10:26 +02:00
| Left of lam * Types.ty
| Right of lam * Types.ty
2024-04-16 10:23:44 +02:00
(** alpha renaming in a deterministic way
if readable is set to true, original variable's names are used to rename *)
let alpha_convert ?(readable=false) (e : lam) : lam =
2024-04-16 10:23:44 +02:00
let cpt_var = ref 0 in (* id cpt for variables *)
let generator (v : id) (cpt : int ref) : id = (* id generator *)
let start = if readable then v else "" in
let v = start ^ "__"^(string_of_int !cpt) in
incr cpt; v
2024-04-16 10:23:44 +02:00
in let get_ren_var (var : id) (g : (id * id) list): id = (* returns var if not found *)
2024-04-16 11:40:08 +02:00
match List.assoc_opt var g with
2024-04-16 10:23:44 +02:00
| Some var' -> var'
2024-04-16 10:40:50 +02:00
| None -> var
2024-04-16 11:40:08 +02:00
in let rec alpha_aux (e : lam) (g : (id * id) list): lam = match e with (* actual renaming *)
Fun ((v, t), e) ->
let v' = generator v cpt_var in
2024-04-16 11:40:08 +02:00
Fun ((v', t), alpha_aux e ((v, v')::g))
| App (e1, e2) -> App (alpha_aux e1 g, alpha_aux e2 g)
| Var v -> Var (get_ren_var v g)
| Exf (e, t) -> Exf (alpha_aux e g, t)
2024-05-14 15:23:44 +02:00
| Pair (e1, e2) -> Pair (alpha_aux e1 g, alpha_aux e2 g)
2024-05-17 08:10:26 +02:00
| Left (e, t) -> Left (alpha_aux e g, t)
| Right (e, t) -> Right (alpha_aux e g, t)
2024-04-16 11:40:08 +02:00
in alpha_aux e []
2024-04-16 10:23:44 +02:00
(** alpha equivalence *)
2024-04-16 10:30:10 +02:00
let (=~) (e1 : lam) (e2 : lam) : bool =
alpha_convert e1 = alpha_convert e2
2024-04-16 11:40:08 +02:00
(** beta-reduction *)
2024-04-16 12:05:13 +02:00
(* subst m n x substitutes x for n in m *)
let rec subst (m : lam) (n : lam) (x : id) : lam =
match m with
Fun ((y, t), e) ->
if x = y
then m
else Fun ((y, t), subst e n x)
| App (e1, e2) ->
let e1 = subst e1 n x in
let e2 = subst e2 n x in
App (e1, e2)
| Var y ->
if x = y then n else m
| Exf (e, t) ->
let e = subst e n x in
Exf (e, t)
2024-05-14 15:23:44 +02:00
| Pair (e1, e2) ->
let e1 = subst e1 n x in
let e2 = subst e2 n x in
Pair (e1, e2)
2024-05-17 08:10:26 +02:00
| Left (e, t) -> Left (subst e n x, t)
| Right (e, t) -> Right (subst e n x, t)
2024-04-16 12:05:13 +02:00
2024-04-25 04:20:12 +02:00
(* INVARIANT : e has already been alpha-converted *)
2024-04-16 12:05:13 +02:00
let rec betastep (e : lam) : lam option =
match e with
Fun ((x, t), e) ->
begin match betastep e with
None -> None
| Some e -> Some (Fun ((x, t), e))
end
| App (e1, e2) ->
2024-04-25 04:20:12 +02:00
(* reduce leftmost redex.
e1 e2 -> e1' e2 then
e1_nf e2 -> e1_nf e2 then
(fun x -> e_nf) e2_nf -> e_nf[e2/x] *)
2024-04-16 12:05:13 +02:00
begin match betastep e1 with
None ->
begin match betastep e2 with
2024-04-25 04:20:12 +02:00
None ->
begin match e1 with
Fun ((x, _), e) -> Some (subst e e2 x)
| _ -> None
end
2024-04-16 12:05:13 +02:00
| Some e2 -> Some (App (e1, e2))
end
| Some e1 -> Some (App (e1, e2))
end
2024-05-14 15:23:44 +02:00
| Pair (e1, e2) ->
begin match betastep e1 with
None ->
begin match betastep e2 with
None -> None
| Some e2 -> Some (Pair (e1, e2))
end
| Some e1 -> Some (Pair (e1, e2))
end
2024-05-17 08:10:26 +02:00
| Left (e, t) ->
2024-05-14 15:23:44 +02:00
begin match betastep e with
None -> None
2024-05-17 08:10:26 +02:00
| Some e -> Some (Left (e, t))
2024-05-14 15:23:44 +02:00
end
2024-05-17 08:10:26 +02:00
| Right (e, t) ->
2024-05-14 15:23:44 +02:00
begin match betastep e with
None -> None
2024-05-17 08:10:26 +02:00
| Some e -> Some (Right (e, t))
2024-05-14 15:23:44 +02:00
end
2024-04-16 12:05:13 +02:00
| Var _ -> None
| Exf (e, t) ->
begin match betastep e with
None -> None
| Some e -> Some (Exf (e, t))
end