Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
From mathcomp Require Import all_ssreflect. (* Lambda calculator *) Module Lambda. Inductive expr : Set := | Var of nat | Abs of expr | App of expr & expr. Fixpoint shift k (e : expr) := match e with | Var n => if k <= n then Var n.+1 else Var n | Abs e1 => Abs (shift k.+1 e1) | App e1 e2 => App (shift k e1) (shift k e2) end. Fixpoint open_rec k u (e : expr) := match e with | Var n => if k == n then u else if leq k n then Var n.-1 else e | Abs e1 => Abs (open_rec k.+1 (shift 0 u) e1) | App e1 e2 => App (open_rec k u e1) (open_rec k u e2) end. Fixpoint reduce (e : expr) : option expr := match e with | App (Abs e1) e2 => Some (open_rec 0 e2 e1) | App e1 e2 => match reduce e1, reduce e2 with | Some e1', _ => Some (App e1' e2) | None, Some e2' => Some (App e1 e2') | None, None => None end | Abs e1 => if reduce e1 is Some e1' then Some (Abs e1') else None | _ => None end. Fixpoint eval (n : nat) e := if n is k.+1 then if reduce e is Some e' then eval k e' else e else e. Coercion Var : nat >-> expr. Definition church (n : nat) := Abs (Abs (iter n (App 1) 0)). Eval compute in church 3. Definition chadd := Abs (Abs (Abs (Abs (App (App 3 1) (App (App 2 1) 0))))). Eval compute in eval 6 (App (App chadd (church 3)) (church 2)). Fixpoint closed_expr n e := match e with | Var k => k < n | App e1 e2 => closed_expr n e1 && closed_expr n e2 | Abs e1 => closed_expr n.+1 e1 end. Lemma shift_closed n e : closed_expr n e -> shift n e = e. Proof. move: n; induction e => //= k Hc. + by rewrite leqNgt Hc. + by rewrite IHe. + move/andP: Hc => [Hc1 Hc2]. by rewrite IHe1 // IHe2. Qed. Lemma closed_iter_app n k e1 e2 : closed_expr k e1 -> closed_expr k e2 -> closed_expr k (iter n (App e1) e2). Proof. move=> He1. elim: n e2 => //= n IHn e2 He2. by rewrite He1 IHn. Qed. Lemma closed_church n : closed_expr 0 (church n). Proof. rewrite /church /=. by apply closed_iter_app. Qed. Lemma closed_expr_S n e : closed_expr n e -> closed_expr n.+1 e. Proof. move: n. induction e => //= k. + by apply ltnW. + by apply IHe. + move/andP => [He1 He2]. by rewrite IHe1 // IHe2. Qed. Hint Resolve closed_iter_app closed_church closed_expr_S. Lemma open_iter_app k n u e1 e2 : open_rec k u (iter n (App e1) e2) = iter n (App (open_rec k u e1)) (open_rec k u e2). Proof. elim: n e2 => //= n IHn e2. by rewrite IHn. Qed. Lemma eval_add m n e : eval (m+n) e = eval m (eval n e). Proof. elim: n e => //= [|n IHn] e. + by rewrite addn0. + rewrite addnS /=. case_eq (reduce e) => [e1|] He //. destruct m => //=. by rewrite He. Qed. Lemma iter_add {A} m n (f : A -> A) x : iter (m+n) f x = iter m f (iter n f x). Proof. elim: m x => [|m IHm] x //=. by rewrite -addnE IHm. Qed. Lemma reduce_iter_app n (k : nat) x : reduce (iter n (App k) x) = if reduce x is Some x' then Some (iter n (App k) x') else None. Proof. elim: n => [|n IHn] //=. by case: (reduce x). rewrite IHn /=. by case: (reduce x). Qed. Theorem chadd_ok m n : exists h, exists h', eval h (App (App chadd (church m)) (church n)) = eval h' (church (m+n)). Proof. elim: m n => [|m IHm] n. rewrite add0n. exists 6; exists 0 => /=. rewrite !shift_closed; auto. by rewrite !open_iter_app /=. move: {IHm}(IHm n.+1) => [h [h' IHm]]. exists (6+h); exists (6+h'). rewrite (addSnnS m) -(addn1 m). move: (f_equal (eval 6) IHm). rewrite -!eval_add => <-. simpl. rewrite !shift_closed /=; auto. rewrite !open_iter_app /=. rewrite !reduce_iter_app /=. rewrite !reduce_iter_app /=. by rewrite iter_add. Qed. Inductive reduces : expr -> expr -> Prop := | Rbeta : forall e1 e2, reduces (App (Abs e1) e2) (open_rec 0 e2 e1) | Rapp1 : forall e1 e2 e1', reduces e1 e1' -> reduces (App e1 e2) (App e1' e2) | Rapp2 : forall e1 e2 e2', reduces e2 e2' -> reduces (App e1 e2) (App e1 e2') | Rabs : forall e1 e1', reduces e1 e1' -> reduces (Abs e1) (Abs e1'). Hint Constructors reduces. Inductive RT_closure {A} (R : A -> A -> Prop) : A -> A -> Prop := | RTbase : forall a, RT_closure R a a | RTnext : forall a b c, R a b -> RT_closure R b c -> RT_closure R a c. Lemma reduces_iter n e1 e2 e2' : reduces e2 e2' -> reduces (iter n (App e1) e2) (iter n (App e1) e2'). Proof. elim: n => //=; auto. Qed. Lemma open_rec_closed n u e : closed_expr n e -> open_rec n u e = e. Proof. move: n u. induction e => //= k u Hc. + case: ifP => Hk1. by rewrite (eqP Hk1) ltnn in Hc. by rewrite leqNgt Hc. + by rewrite IHe. + move/andP: Hc => [Hc1 Hc2]. by rewrite IHe1 // IHe2. Qed. Theorem chadd_ok' m n : RT_closure reduces (App (App chadd (church m)) (church n)) (church (m+n)). Proof. eapply RTnext; repeat constructor. simpl. rewrite !shift_closed; auto. eapply RTnext; repeat constructor. simpl. rewrite !open_rec_closed; auto. rewrite !shift_closed; auto. eapply RTnext; repeat constructor. simpl. rewrite open_iter_app /=. eapply RTnext; repeat constructor. rewrite open_iter_app /=. eapply RTnext. constructor. constructor. apply reduces_iter. repeat constructor. rewrite /= open_iter_app /=. eapply RTnext. repeat constructor. apply reduces_iter. repeat constructor. rewrite open_iter_app /=. rewrite -iter_add. by constructor. Qed. Lemma reduce_ok e e' : reduce e = Some e' -> reduces e e'. Proof. move: e'. induction e => //= e'. by case_eq (reduce e) => // e1 He [] <-; auto. destruct e1. + by case_eq (reduce e2) => // e2' He2 [] <-; auto. + by move => [] <-; auto. + case_eq (reduce (App e1_1 e1_2)) => [e1'|] He1. by move => [] <-; auto. by case_eq (reduce e2) => // e2' He2 [] <-; auto. Qed. Lemma closed_expr_shift h k e : closed_expr h e -> closed_expr h.+1 (shift k e). Proof. move: h k. induction e => //= h k Hc. + case: ifP => Hk /=. by rewrite -(addn1 n) -(addn1 h) ltn_add2r. apply ltnW. by rewrite -(addn1 n) -(addn1 h) ltn_add2r. + by apply IHe. + move/andP: Hc => [Hc1 Hc2]. by rewrite IHe1 // IHe2. Qed. Lemma closed_expr_open n e1 e2 k e' : closed_expr n.+1 e1 -> k <= n -> closed_expr n e2 -> open_rec k e2 e1 = e' -> closed_expr n e'. Proof. move: n k e' e2. induction e1 => // h k e' e2 He1 Hk He2 <- //=. + case: ifP => Hk1 //. rewrite /= in He1. case: ifP => Hk2 //=. destruct n. by rewrite leqn0 Hk1 in Hk2. rewrite succnK. by rewrite -(ltn_add2r 1) !addn1. rewrite leqNgt in Hk2. by apply (leq_trans (negbFE Hk2)). + apply (IHe1 _ (k.+1) _ (shift 0 e2)) => //. by apply closed_expr_shift. + move: He1 => /= /andP [He11 He12]. rewrite (IHe1_1 _ k _ e2) //. by rewrite (IHe1_2 _ k _ e2). Qed. Lemma closed_inv n e e' : closed_expr n e -> reduce e = Some e' -> closed_expr n e'. Proof. move=> Hc Hr. apply reduce_ok in Hr. move: n Hc. induction Hr => //= n Hc. + move/andP: Hc => [Hc1 Hc2]. by apply (closed_expr_open n e1 e2 0). + move/andP: Hc => [Hc1 Hc2]. by rewrite IHHr. + move/andP: Hc => [Hc1 Hc2]. by rewrite Hc1 IHHr. + by apply IHHr. Qed. End Lambda.