chap5: init
This commit is contained in:
+390
@@ -0,0 +1,390 @@
|
||||
Require Import Coq.Strings.String.
|
||||
Require Import Coq.Lists.List.
|
||||
Require Import Coq.Lists.ListSet.
|
||||
Require Import Coq.Arith.PeanoNat.
|
||||
Import ListNotations.
|
||||
|
||||
|
||||
Module Chap5.
|
||||
(* 5.1 *)
|
||||
Inductive term : Type :=
|
||||
| Var (name : string)
|
||||
| Lambda (var : string) (body : term)
|
||||
| App (t1 t2 : term).
|
||||
|
||||
Scheme Equality for term.
|
||||
|
||||
Fixpoint substitute (x : string) (s : term) (t : term) : term :=
|
||||
match t with
|
||||
| Var y => if String.eqb x y then s else t
|
||||
| Lambda y body => if String.eqb x y then t else Lambda y (substitute x s body)
|
||||
| App t1 t2 => App (substitute x s t1) (substitute x s t2)
|
||||
end.
|
||||
|
||||
Definition is_value (t : term) : bool :=
|
||||
match t with
|
||||
| Lambda _ _ => true
|
||||
| Var _ => true
|
||||
| App (Var _) _ => true
|
||||
| _ => false
|
||||
end.
|
||||
|
||||
Fixpoint single_step_eval (t : term) : term :=
|
||||
match t with
|
||||
| App (Lambda x body) arg =>
|
||||
if is_value arg
|
||||
then substitute x arg body
|
||||
else App (Lambda x body) (single_step_eval arg)
|
||||
|
||||
| App t1 t2 =>
|
||||
let t1' := single_step_eval t1 in
|
||||
if term_beq t1 t1'
|
||||
then App t1 (single_step_eval t2)
|
||||
else App t1' t2
|
||||
|
||||
| Lambda x body => Lambda x (single_step_eval body)
|
||||
|
||||
| _ => t
|
||||
end.
|
||||
|
||||
Fixpoint multi_step_eval (t : term) (i : nat) : term :=
|
||||
match i, (single_step_eval t) with
|
||||
| O, t' => t'
|
||||
| S i', t' => if (term_eq_dec t t') then t' else multi_step_eval t' i'
|
||||
end.
|
||||
|
||||
Lemma unwrap_multi_step_eval : forall (t : term), forall (i : nat),
|
||||
multi_step_eval t (S i) = multi_step_eval (single_step_eval t) i.
|
||||
Proof.
|
||||
intros t i. simpl. destruct (term_eq_dec t (single_step_eval t)) as [Heq | Hneq].
|
||||
- rewrite <- Heq.
|
||||
Admitted.
|
||||
|
||||
|
||||
(* Notation *)
|
||||
Declare Custom Entry ulc.
|
||||
Notation "<{ t }>" := (t) (t custom ulc at level 99).
|
||||
|
||||
Notation "( x )" := x
|
||||
(in custom ulc, x at level 99).
|
||||
|
||||
Notation "$ x" :=
|
||||
x
|
||||
(in custom ulc at level 0, x constr).
|
||||
|
||||
Notation "'λ' x , t" := (Lambda x t) (in custom ulc at level 90, x constr).
|
||||
|
||||
Notation "t1 . t2" := (App t1 t2) (in custom ulc at level 20, left associativity).
|
||||
|
||||
Notation "x" :=
|
||||
(Var x%string)
|
||||
(in custom ulc at level 0, x constr).
|
||||
|
||||
|
||||
Example single_step_eval_application :
|
||||
single_step_eval <{ (λ "x", "x") . "y" }> = <{ "y" }>.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Example multi_step_eval_application :
|
||||
multi_step_eval <{ (λ "x", "x") . (λ "x", "x") . "y" }> 2 = <{ "y" }>.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
(* Church Booleans *)
|
||||
Definition tru : term := <{ (λ "t", (λ "f", "t")) }>.
|
||||
Definition fls : term := <{ λ "t" , λ "f" , "f" }>.
|
||||
Definition test : term := <{ λ "l" , λ "m" , λ "n" , "l" . "m" . "n" }>.
|
||||
|
||||
Example test_tru:
|
||||
multi_step_eval <{ $test . $tru . "x" . "y" }> 100 = Var "x".
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
|
||||
Definition aand : term := <{ λ "b", λ "c", "b" . "c" . $fls }>.
|
||||
(* 5.2.1 *)
|
||||
Definition oor : term := <{ λ "b", λ "c", "b" . $tru . "c" }>.
|
||||
|
||||
(* Pairs *)
|
||||
Definition ppair : term := <{ λ "f", λ "s", λ "b", "b" . "f" . "s" }>.
|
||||
Definition fst : term := <{ λ "p", "p" . $tru }>.
|
||||
Definition snd : term := <{ λ "p", "p" . $fls }>.
|
||||
|
||||
Example test_pair:
|
||||
multi_step_eval <{ $fst . ($ppair . "v" . "w") }> 100 = Var "v".
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
(* Church numerals *)
|
||||
Definition zero : term := <{ λ "s", λ "z", "z" }>.
|
||||
|
||||
Fixpoint church_body (n : nat) : term :=
|
||||
match n with
|
||||
| O => Var "z"
|
||||
| S n' => <{ "s" . $church_body n' }>
|
||||
end.
|
||||
|
||||
Definition c (n : nat) : term :=
|
||||
<{ λ "s", λ "z", $church_body n }>.
|
||||
|
||||
Notation "# n" := (c n) (in custom ulc at level 0, n constr).
|
||||
|
||||
Fixpoint count_apps (s z : string) (t : term) : nat :=
|
||||
match t with
|
||||
| Var z' =>
|
||||
if String.eqb z z' then 0 else 0
|
||||
| App (Var s') t' =>
|
||||
if String.eqb s s'
|
||||
then S(count_apps s z t')
|
||||
else 0
|
||||
| _ => 0
|
||||
end.
|
||||
|
||||
Definition c_to_nat (t : term) : nat :=
|
||||
match t with
|
||||
| Lambda s (Lambda z body) => count_apps s z body
|
||||
| _ => 0
|
||||
end.
|
||||
|
||||
Lemma c_to_nat_0 : c_to_nat zero = 0.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Lemma c_to_nat_1 : c_to_nat (c 1) = 1.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Lemma c_to_nat_unwrap : forall n,
|
||||
c_to_nat <{ # S n }> = S (c_to_nat <{ # n }>).
|
||||
Proof.
|
||||
intros n. reflexivity.
|
||||
Qed.
|
||||
|
||||
Lemma c_to_nat_correct : forall n, c_to_nat (c n) = n.
|
||||
Proof.
|
||||
intros n. induction n as [| n' IH].
|
||||
- simpl. reflexivity.
|
||||
- simpl. rewrite <- IH.
|
||||
Admitted.
|
||||
|
||||
Definition scc : term := <{ λ "n", λ "s", λ "z", "s" . ("n" . "s" . "z") }>.
|
||||
|
||||
(* 5.2.2 *)
|
||||
Definition scc_2 : term := <{ λ "n", λ "s", λ "z", "s" . ("n" . "s" . "z") }>.
|
||||
|
||||
(* Lemma scc1_matches_scc2 : forall (i : nat),
|
||||
multi_step_eval <{ $scc . $c i }> 100 = multi_step_eval <{ $scc_2 . $c i }> 100.
|
||||
Proof.
|
||||
intros i. simpl. reflexivity.
|
||||
Qed. *)
|
||||
|
||||
Definition plus : term :=
|
||||
<{ λ "m", λ "n", λ "s", λ "z", "m" . "s" . ("n" . "s" . "z") }>.
|
||||
|
||||
Example test_plus:
|
||||
multi_step_eval <{ $plus . # 2 . # 3 }> 100 = <{ # 5 }>.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Definition times : term :=
|
||||
<{ λ "m", λ "n", "m" . ($plus . "n") . "z" }>.
|
||||
|
||||
Example test_times:
|
||||
multi_step_eval <{ $times . # 2 . # 3 }> 100 = <{ # 6 }>.
|
||||
Proof.
|
||||
simpl.
|
||||
Admitted.
|
||||
|
||||
(* 5.2.3 *)
|
||||
Definition times_2 : term :=
|
||||
<{ λ "m", λ "n", λ "s", λ "z", "m" . ("n" . "s") . "z" }>.
|
||||
|
||||
(* 5.2.4 *)
|
||||
Definition power : term :=
|
||||
<{ λ "m", λ "n", "m" . ($times . "n") . ($c 1) }>.
|
||||
|
||||
Definition power2 : term :=
|
||||
<{ λ "m", λ "n", "n" . "m" }>.
|
||||
|
||||
Definition iszro : term :=
|
||||
<{ λ "m", "m" . (λ "x", $fls) . $tru }>.
|
||||
|
||||
Example is_zro_test_0:
|
||||
multi_step_eval <{ $iszro . # 0 }> 100 = tru.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Example is_zro_test_1:
|
||||
multi_step_eval <{ $iszro . # 1 }> 100 = fls.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Example is_zro_test_expr:
|
||||
multi_step_eval <{ $iszro . ($times . # 0 . # 2) }> 100 = tru.
|
||||
Proof.
|
||||
simpl.
|
||||
Admitted.
|
||||
|
||||
Definition zz : term := <{ $ppair . # 0 . # 0 }>.
|
||||
Definition ss : term := <{ λ "p", $ppair . ($snd . "p") . ($scc . ($snd . "p")) }>.
|
||||
|
||||
(*
|
||||
"Apply ss to zz m times, take the first value of the result"
|
||||
(0,0) -> (0,1) -> (1,2) -> (2,3) -> ... -> (_m-1_,m)
|
||||
*)
|
||||
Definition prd : term := <{ λ "m", $fst . ("m" . $ss . $zz) }>.
|
||||
|
||||
(* 5.2.5 *)
|
||||
Definition sub : term :=
|
||||
<{ λ "m", λ "n", "n" . $prd . "m" }>.
|
||||
|
||||
(* Example sub_test_0:
|
||||
multi_step_eval <{ $sub . # 5 . # 3 }> 100 = <{ # 2 }>.
|
||||
Proof. simpl. reflexivity. Qed. *)
|
||||
|
||||
(* 5.2.6 *)
|
||||
(* It takes roughly O(n) steps to calculate prd C(n) *)
|
||||
|
||||
(* 5.2.7 *)
|
||||
Definition c_eq : term :=
|
||||
<{ λ "m", λ "n", ($aand . ($iszro . ($sub . "m" . "n")) . ($iszro . ($sub . "n" . "m"))) }>.
|
||||
|
||||
(* Example c_eq_test_0:
|
||||
multi_step_eval <{ $c_eq . # 0 . # 0 }> 100 = tru.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Example c_eq_test_1:
|
||||
multi_step_eval <{ $c_eq . # 0 . # 1 }> 100 = fls.
|
||||
Proof. reflexivity. Qed. *)
|
||||
|
||||
(* 5.2.8 *)
|
||||
|
||||
Definition l_nil : term := <{ λ "c", λ "n", "n" }>.
|
||||
Definition l_cons : term := <{ λ "h", λ "t", λ "c", λ "n", "c" . "h" . ("t" . "c" . "n") }>.
|
||||
Definition l_isnil : term := <{ λ "l", "l" . (λ "h", λ "t", $fls) . $tru }>.
|
||||
Definition l_head : term := <{ λ "l", "l" . (λ "h", λ "t", "h") . $l_nil }>.
|
||||
|
||||
Definition nn : term := <{ $ppair . $l_nil . $l_nil }>.
|
||||
Definition cc : term := <{ λ "e", λ "p", $ppair . ($snd . "p") . ($l_cons . "e" . ($snd . "p")) }>.
|
||||
Definition tail : term := <{ λ "l", $fst . ("l" . $cc . $nn) }>.
|
||||
|
||||
Definition omega : term := <{ (λ "x", "x" . "x") . (λ "x", "x" . "x") }>.
|
||||
|
||||
Lemma omega_idempotent : forall i, multi_step_eval omega i = omega.
|
||||
Proof.
|
||||
intros i. induction i as [| i' IH].
|
||||
- simpl. reflexivity.
|
||||
- rewrite unwrap_multi_step_eval. simpl. rewrite <- IH. reflexivity.
|
||||
Qed.
|
||||
|
||||
Definition ffix : term := <{ λ "f", (λ "x", "f" . ("x" . "x")) . (λ "x", "f" . ("x" . "x")) }>.
|
||||
|
||||
Definition g : term := <{ λ "fct", λ "n", ($iszro . "n") . ($c 1) . ($times . "n" . ("fct" . ($prd . "n"))) }>.
|
||||
Definition fact : term := <{ $ffix . $g }>.
|
||||
|
||||
(* Example fact_test_3:
|
||||
multi_step_eval <{ $fact . # 3 }> 100 = <{ # 6 }>.
|
||||
Proof. simpl. reflexivity. Qed. *)
|
||||
|
||||
(* 5.2.9 *)
|
||||
(* "test b v w" will eval v and w first due to call-by-value eval order
|
||||
so the naive factorial-in-terms-of-test would not terminate at n = 0.
|
||||
We can fix this by wrapping the v and w in closures that ignore their
|
||||
arguments, so-called "thunks", to force the evaluation order.
|
||||
*)
|
||||
Definition g2 : term := <{
|
||||
λ "fct", λ "n",
|
||||
($test
|
||||
. ($c_eq . "n" . # 0)
|
||||
. (λ "u", # 1)
|
||||
. (λ "u", $times . "n" . ("fct" . ($prd . "n")))
|
||||
) . # 0
|
||||
}>.
|
||||
Definition fact2 : term := <{ $ffix . $g2 }>.
|
||||
|
||||
(* 5.2.10 *)
|
||||
Definition churchnat : term := <{
|
||||
$ffix . (λ "cn", λ "n",
|
||||
($iszro . "n")
|
||||
. # 0
|
||||
. ($scc . ("cn" . ($prd . "n")))
|
||||
)
|
||||
}>.
|
||||
|
||||
(* 5.2.11 *)
|
||||
Definition sumlist : term := <{
|
||||
$ffix . (λ "f", λ "l",
|
||||
($l_isnil . "l")
|
||||
. # 0
|
||||
. ($plus . ($l_head . "l") . ("f" . ($tail . "l")))
|
||||
)
|
||||
}>.
|
||||
|
||||
(* 5.3.2 *)
|
||||
Fixpoint size (t : term) : nat :=
|
||||
match t with
|
||||
| Var _ => 1
|
||||
| Lambda _ body => 1 + size body
|
||||
| App t1 t2 => size t1 + size t2
|
||||
end.
|
||||
|
||||
Fixpoint free_vars (t : term) : set string :=
|
||||
match t with
|
||||
| Var x => [x]
|
||||
| Lambda x body => set_remove string_dec x (free_vars body)
|
||||
| App t1 t2 => set_union string_dec (free_vars t1) (free_vars t2)
|
||||
end.
|
||||
|
||||
(* 5.3.3 *)
|
||||
Lemma set_remove_length_le : forall (A : Type) (eq_dec : forall x y : A, {x = y} + {x <> y}) (x : A) (s : set A),
|
||||
length (set_remove eq_dec x s) <= length s.
|
||||
Proof.
|
||||
intros A eq_dec x s.
|
||||
induction s as [| y s' IH].
|
||||
- simpl. reflexivity.
|
||||
- simpl. destruct (eq_dec x y) as [Heq | Hneq].
|
||||
+ simpl. apply Nat.le_succ_diag_r.
|
||||
+ simpl. apply le_n_S. apply IH.
|
||||
Qed.
|
||||
|
||||
Lemma set_union_empty_l : forall (A : Type) (eq_dec : forall x y : A, {x = y} + {x <> y}) (s : set A),
|
||||
set_union eq_dec [] s = s.
|
||||
Proof.
|
||||
intros A eq_dec s.
|
||||
induction s as [| x s' IH].
|
||||
- simpl. reflexivity.
|
||||
- simpl.
|
||||
rewrite IH.
|
||||
Admitted.
|
||||
|
||||
Lemma set_union_length_le : forall (A : Type) (eq_dec : forall x y : A, {x = y} + {x <> y}) (s1 s2 : set A),
|
||||
length (set_union eq_dec s1 s2) <= length s1 + length s2.
|
||||
Proof.
|
||||
intros A eq_dec s1 s2.
|
||||
induction s1 as [| x s1' IH].
|
||||
- simpl. rewrite set_union_empty_l. reflexivity.
|
||||
- simpl. destruct (in_dec eq_dec x s2) as [Hin | Hnotin].
|
||||
+ simpl.
|
||||
Admitted.
|
||||
|
||||
Lemma le_sum : forall a b c d : nat, a <= b -> c <= d -> a + c <= b + d.
|
||||
Proof.
|
||||
intros a b c d H1 H2.
|
||||
apply Nat.add_le_mono; assumption.
|
||||
Qed.
|
||||
|
||||
Lemma fv_leq_size : forall t, length (free_vars t) <= size t.
|
||||
Proof.
|
||||
intros t.
|
||||
induction t as [x | x body IH | t1 IH1 t2 IH2].
|
||||
- simpl. reflexivity.
|
||||
- simpl.
|
||||
assert (H : length (set_remove string_dec x (free_vars body)) <= length (free_vars body)).
|
||||
{ apply set_remove_length_le. }
|
||||
rewrite H.
|
||||
assert (H2 : length (free_vars body) <= size body).
|
||||
{ apply IH. }
|
||||
rewrite H2.
|
||||
apply Nat.le_succ_diag_r.
|
||||
- simpl.
|
||||
assert (H1: length (set_union string_dec (free_vars t1) (free_vars t2)) <= length (free_vars t1) + length (free_vars t2)).
|
||||
{ apply set_union_length_le. }
|
||||
rewrite H1.
|
||||
apply le_sum.
|
||||
+ apply IH1.
|
||||
+ apply IH2.
|
||||
Qed.
|
||||
|
||||
End Chap5.
|
||||
Reference in New Issue
Block a user