mirror of
https://github.com/achlipala/frap.git
synced 2024-11-10 00:07:51 +00:00
Polymorphism: trees
This commit is contained in:
parent
b13baac51e
commit
0e32a409d7
1 changed files with 88 additions and 0 deletions
|
@ -127,6 +127,10 @@ Fixpoint rev {A} (ls : list A) : list A :=
|
||||||
| x :: ls' => rev ls' ++ [x]
|
| x :: ls' => rev ls' ++ [x]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Theorem length_app : forall A (ls1 ls2 : list A),
|
||||||
|
length (ls1 ++ ls2) = length ls1 + length ls2.
|
||||||
|
Admitted.
|
||||||
|
|
||||||
(* One of the classic gotchas in functional-programming class is how slow this
|
(* One of the classic gotchas in functional-programming class is how slow this
|
||||||
* naive [rev] is. Each [app] operation requires linear time, so running
|
* naive [rev] is. Each [app] operation requires linear time, so running
|
||||||
* linearly many [app]s brings us to quadratic time for [rev]. Using a helper
|
* linearly many [app]s brings us to quadratic time for [rev]. Using a helper
|
||||||
|
@ -326,3 +330,87 @@ Proof.
|
||||||
simplify.
|
simplify.
|
||||||
equality.
|
equality.
|
||||||
Qed.
|
Qed.
|
||||||
|
|
||||||
|
|
||||||
|
(** * Binary trees *)
|
||||||
|
|
||||||
|
(* Another classic datatype is binary trees, which we can define like so. *)
|
||||||
|
Inductive tree (A : Set) : Set :=
|
||||||
|
| Leaf
|
||||||
|
| Node (l : tree A) (d : A) (r : tree A).
|
||||||
|
|
||||||
|
Arguments Leaf [A].
|
||||||
|
|
||||||
|
Example tr1 : tree nat := Node (Node Leaf 7 Leaf) 8 (Node Leaf 9 (Node Leaf 10 Leaf)).
|
||||||
|
|
||||||
|
(* There is a natural notion of size of a tree. *)
|
||||||
|
Fixpoint size {A} (t : tree A) : nat :=
|
||||||
|
match t with
|
||||||
|
| Leaf => 0
|
||||||
|
| Node l _ r => 1 + size l + size r
|
||||||
|
end.
|
||||||
|
|
||||||
|
(* There is also a natural sense of reversing a tree, flipping it around its
|
||||||
|
* vertical axis. *)
|
||||||
|
Fixpoint reverse {A} (t : tree A) : tree A :=
|
||||||
|
match t with
|
||||||
|
| Leaf => Leaf
|
||||||
|
| Node l d r => Node (reverse r) d (reverse l)
|
||||||
|
end.
|
||||||
|
|
||||||
|
(* There is a natural relationship between the two. *)
|
||||||
|
Theorem size_reverse : forall A (t : tree A),
|
||||||
|
size (reverse t) = size t.
|
||||||
|
Proof.
|
||||||
|
induct t; simplify.
|
||||||
|
|
||||||
|
equality.
|
||||||
|
|
||||||
|
linear_arithmetic.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
(* Another classic tree operation is flattening into lists. *)
|
||||||
|
Fixpoint flatten {A} (t : tree A) : list A :=
|
||||||
|
match t with
|
||||||
|
| Leaf => []
|
||||||
|
| Node l d r => flatten l ++ d :: flatten r
|
||||||
|
end.
|
||||||
|
(* Note here that operators [++] and [::] are right-associative. *)
|
||||||
|
|
||||||
|
Theorem length_flatten : forall A (t : tree A),
|
||||||
|
length (flatten t) = size t.
|
||||||
|
Proof.
|
||||||
|
induct t; simplify.
|
||||||
|
|
||||||
|
equality.
|
||||||
|
|
||||||
|
rewrite length_app.
|
||||||
|
simplify.
|
||||||
|
linear_arithmetic.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma rev_app : forall A (ls1 ls2 : list A),
|
||||||
|
rev (ls1 ++ ls2) = rev ls2 ++ rev ls1.
|
||||||
|
Proof.
|
||||||
|
induct ls1; simplify.
|
||||||
|
|
||||||
|
rewrite app_nil.
|
||||||
|
equality.
|
||||||
|
|
||||||
|
rewrite IHls1.
|
||||||
|
apply app_assoc.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Theorem rev_flatten : forall A (t : tree A),
|
||||||
|
rev (flatten t) = flatten (reverse t).
|
||||||
|
Proof.
|
||||||
|
induct t; simplify.
|
||||||
|
|
||||||
|
equality.
|
||||||
|
|
||||||
|
rewrite rev_app.
|
||||||
|
simplify.
|
||||||
|
rewrite app_assoc.
|
||||||
|
simplify.
|
||||||
|
equality.
|
||||||
|
Qed.
|
||||||
|
|
Loading…
Reference in a new issue