Set Implicit Arguments.
Inductive list (A: Type) : Type :=
| nil : list A
| cons : A -> list A -> list A.
Fixpoint length (A: Type) (l: list A) : nat :=
match l with
| nil _ => O
| cons x xs => S (length xs)
end.
so far, Coq will not infer the type argument for nil:
Check (cons 1 nil). Error: The term "nil" has type "forall A : Type, list A" while it is expected to have type "list nat".
we can tell Coq to always try though
Arguments nil {A}.
Check (cons 1 nil).
Eval cbv in (length (cons 1 nil)).
Eval cbv in (length (cons 2 (cons 1 nil))).
Eval cbv in (length nil).
Fixpoint countdown (n: nat) :=
match n with
| O => cons n nil
| S m => cons n (countdown m)
end.
Eval cbv in (countdown 0).
Eval cbv in (countdown 3).
Eval cbv in (countdown 10).
Fixpoint map (A B: Type) (f: A -> B) (l: list A) : list B :=
match l with
| nil => nil
| cons x xs => cons (f x) (map f xs)
end.
Eval cbv in (map (plus 1) (countdown 3)).
Eval cbv in (map (fun _ => true) (countdown 3)).
Definition is_zero (n: nat) : bool :=
match n with
| O => true
| S m => false
end.
Eval cbv in (map is_zero (countdown 3)).
Fixpoint is_even (n: nat) : bool :=
match n with
| O => true
| S O => false
| S (S m) => is_even m
end.
Eval cbv in (map is_even (countdown 3)).
Lemma map_length:
forall (A B: Type) (f: A -> B) (l: list A),
length (map f l) = length l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite IHl. reflexivity.
Qed.
Check (cons 1 nil).
Eval cbv in (length (cons 1 nil)).
Eval cbv in (length (cons 2 (cons 1 nil))).
Eval cbv in (length nil).
Fixpoint countdown (n: nat) :=
match n with
| O => cons n nil
| S m => cons n (countdown m)
end.
Eval cbv in (countdown 0).
Eval cbv in (countdown 3).
Eval cbv in (countdown 10).
Fixpoint map (A B: Type) (f: A -> B) (l: list A) : list B :=
match l with
| nil => nil
| cons x xs => cons (f x) (map f xs)
end.
Eval cbv in (map (plus 1) (countdown 3)).
Eval cbv in (map (fun _ => true) (countdown 3)).
Definition is_zero (n: nat) : bool :=
match n with
| O => true
| S m => false
end.
Eval cbv in (map is_zero (countdown 3)).
Fixpoint is_even (n: nat) : bool :=
match n with
| O => true
| S O => false
| S (S m) => is_even m
end.
Eval cbv in (map is_even (countdown 3)).
Lemma map_length:
forall (A B: Type) (f: A -> B) (l: list A),
length (map f l) = length l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite IHl. reflexivity.
Qed.
discuss how does induction works
Definition compose (A B C: Type)
(f: B -> C)
(g: A -> B)
: A -> C :=
fun (x : A) => f (g x).
Lemma map_map_compose:
forall (A B C: Type)
(g: A -> B) (f: B -> C) (l: list A),
map f (map g l) = map (compose f g) l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+
simpl. rewrite IHl.
need to "unfold" compose to simpl
unfold compose. reflexivity.
Qed.
Fixpoint foldr (A B: Type) (f: A -> B -> B)
(l: list A) (b: B) : B :=
match l with
| nil => b
| cons x xs => f x (foldr f xs b)
end.
Qed.
Fixpoint foldr (A B: Type) (f: A -> B -> B)
(l: list A) (b: B) : B :=
match l with
| nil => b
| cons x xs => f x (foldr f xs b)
end.
foldr f (cons 1 (cons 2 (cons 3 nil))) x
>
f 1 (f 2 (f 3 x))
Check plus.
Print plus.
Eval cbv in (foldr plus (countdown 10) 0).
Fixpoint fact (n: nat) : nat :=
match n with
| O => 1
| S m => mult n (fact m)
end.
Eval cbv in (fact 0).
Eval cbv in (fact 1).
Eval cbv in (fact 2).
Eval cbv in (fact 3).
Eval cbv in (fact 4).
Definition fact' (n: nat) : nat :=
match n with
| O => 1
| S m => foldr mult (map (plus 1) (countdown m)) 1
end.
Eval cbv in (fact' 0).
Eval cbv in (fact' 1).
Eval cbv in (fact' 2).
Eval cbv in (fact' 3).
Eval cbv in (fact' 4).
Lemma fact_fact':
forall n,
fact n = fact' n.
Proof.
challenge problem
Admitted.
we can also define map using fold
Definition map' (A B: Type) (f: A -> B) (l: list A) : list B :=
foldr (fun x acc => cons (f x) acc) l nil.
Lemma map_map':
forall (A B: Type) (f: A -> B) (l: list A),
map f l = map' f l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite IHl.
foldr (fun x acc => cons (f x) acc) l nil.
Lemma map_map':
forall (A B: Type) (f: A -> B) (l: list A),
map f l = map' f l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite IHl.
again, need to unfold so simpl can work
note: very sensitive to order of rewrite and unroll!
Qed.
another flavor of fold
Fixpoint foldl (A B: Type) (f: A -> B -> B)
(l: list A) (b: B) : B :=
match l with
| nil => b
| cons x xs => foldl f xs (f x b)
end.
(l: list A) (b: B) : B :=
match l with
| nil => b
| cons x xs => foldl f xs (f x b)
end.
add one list to the end of another
Fixpoint app (A: Type) (l1: list A) (l2: list A) : list A :=
match l1 with
| nil => l2
| cons x xs => cons x (app xs l2)
end.
Eval cbv in (app (cons 1 (cons 2 nil)) (cons 3 nil)).
Theorem app_nil:
forall A (l: list A),
app l nil = l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite IHl. reflexivity.
Qed.
Theorem app_assoc:
forall A (l1 l2 l3: list A),
app (app l1 l2) l3 = app l1 (app l2 l3).
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl. rewrite IHl1. reflexivity.
Qed.
match l1 with
| nil => l2
| cons x xs => cons x (app xs l2)
end.
Eval cbv in (app (cons 1 (cons 2 nil)) (cons 3 nil)).
Theorem app_nil:
forall A (l: list A),
app l nil = l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite IHl. reflexivity.
Qed.
Theorem app_assoc:
forall A (l1 l2 l3: list A),
app (app l1 l2) l3 = app l1 (app l2 l3).
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl. rewrite IHl1. reflexivity.
Qed.
simple but inefficient way to reverse a list
Fixpoint rev (A: Type) (l: list A) : list A :=
match l with
| nil => nil
| cons x xs => app (rev xs) (cons x nil)
end.
Eval cbv in (countdown 5).
Eval cbv in (rev (countdown 5)).
match l with
| nil => nil
| cons x xs => app (rev xs) (cons x nil)
end.
Eval cbv in (countdown 5).
Eval cbv in (rev (countdown 5)).
tail recursion is faster, but more complicated
Fixpoint fast_rev_aux (A: Type) (l: list A) (acc: list A) : list A :=
match l with
| nil => acc
| cons x xs => fast_rev_aux xs (cons x acc)
end.
Definition fast_rev (A: Type) (l: list A) : list A :=
fast_rev_aux l nil.
match l with
| nil => acc
| cons x xs => fast_rev_aux xs (cons x acc)
end.
Definition fast_rev (A: Type) (l: list A) : list A :=
fast_rev_aux l nil.
let's make sure we got that right
reduces rev, but does nothing to rev_fast
unfold fast_rev.
unfold fast_rev to fast_rev_aux
simpl.
now we can simplify the term
reflexivity.
TIP: if simpl doesn't work, try unfolding!
this looks like it could be trouble...
simpl. rewrite <- IHl.
STUCK! need to know about the rev_aux accumulator (acc) TIP: if your IH seems weak, try proving something more general
Abort.
Lemma fast_rev_aux_ok:
forall A (l1 l2: list A),
fast_rev_aux l1 l2 = app (rev l1) l2.
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl.
Lemma fast_rev_aux_ok:
forall A (l1 l2: list A),
fast_rev_aux l1 l2 = app (rev l1) l2.
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl.
STUCK AGAIN! need to know for *any* l2 TIP: if your IH seems weak, only intro up to the induction variable
Abort.
Lemma fast_rev_aux_ok:
forall A (l1 l2: list A),
fast_rev_aux l1 l2 = app (rev l1) l2.
Proof.
intros A l1.
induction l1.
+ intros. simpl. reflexivity.
+ intros. simpl.
rename l2 into foo.
rewrite IHl1.
rewrite app_assoc.
simpl. reflexivity.
Qed.
Lemma fast_rev_aux_ok:
forall A (l1 l2: list A),
fast_rev_aux l1 l2 = app (rev l1) l2.
Proof.
intros A l1.
induction l1.
+ intros. simpl. reflexivity.
+ intros. simpl.
rename l2 into foo.
rewrite IHl1.
rewrite app_assoc.
simpl. reflexivity.
Qed.
now we can prove rev_ok as a special case of rev_aux_ok
Lemma fast_rev_ok:
forall A (l: list A),
fast_rev l = rev l.
Proof.
intros.
unfold fast_rev.
rewrite fast_rev_aux_ok.
rewrite app_nil.
reflexivity.
Qed.
forall A (l: list A),
fast_rev l = rev l.
Proof.
intros.
unfold fast_rev.
rewrite fast_rev_aux_ok.
rewrite app_nil.
reflexivity.
Qed.
~-. ,,,; ~-.~-.~- (.../ ~-.~-.~-.~-.~-. } o~`, ~-.~-.~-.~-.~-.~-. (/ \ ~-.~-.~-.~-.~-.~-.~-. ; \ ~-.~-.~-.~-.~-.~-.~-. ; {_.~-.~-.~-.~-.~-.~-.~ ;: .-~` ~-.~-.~-.~-.~-. ;.: :' ._ ~-.~-.~-.~-.~- ;::`-. '-._ ~-.~-.~-.~- ;::. `-. '-,~-.~-.~-. ';::::.`''-.-' ';::;;:,:' '||" / | ~` ~"'
Fixpoint snoc (A: Type) (l: list A) (x: A) : list A :=
match l with
| nil => cons x nil
| cons y ys => cons y (snoc ys x)
end.
Theorem snoc_app_singleton:
forall A (l: list A) (x: A),
snoc l x = app l (cons x nil).
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite IHl. reflexivity.
Qed.
Theorem app_snoc_l:
forall A (l1: list A) (l2: list A) (x: A),
app (snoc l1 x) l2 = app l1 (cons x l2).
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl. rewrite IHl1. reflexivity.
Qed.
Theorem app_snoc_r:
forall A (l1: list A) (l2: list A) (x: A),
app l1 (snoc l2 x) = snoc (app l1 l2) x.
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl. rewrite IHl1. reflexivity.
Qed.
match l with
| nil => cons x nil
| cons y ys => cons y (snoc ys x)
end.
Theorem snoc_app_singleton:
forall A (l: list A) (x: A),
snoc l x = app l (cons x nil).
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite IHl. reflexivity.
Qed.
Theorem app_snoc_l:
forall A (l1: list A) (l2: list A) (x: A),
app (snoc l1 x) l2 = app l1 (cons x l2).
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl. rewrite IHl1. reflexivity.
Qed.
Theorem app_snoc_r:
forall A (l1: list A) (l2: list A) (x: A),
app l1 (snoc l2 x) = snoc (app l1 l2) x.
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl. rewrite IHl1. reflexivity.
Qed.
simple but inefficient way to reverse a list
Fixpoint rev_snoc (A: Type) (l: list A) : list A :=
match l with
| nil => nil
| cons x xs => snoc (rev_snoc xs) x
end.
Lemma fast_rev_aux_ok_snoc:
forall A (l1 l2: list A),
fast_rev_aux l1 l2 = app (rev_snoc l1) l2.
Proof.
intros A l1.
induction l1.
+ intros. simpl. reflexivity.
+ intros. simpl.
rewrite IHl1.
rewrite app_snoc_l.
reflexivity.
Qed.
Lemma fast_rev_ok_snoc:
forall A (l: list A),
fast_rev l = rev_snoc l.
Proof.
intros.
unfold fast_rev.
rewrite fast_rev_aux_ok_snoc.
rewrite app_nil.
reflexivity.
Qed.
Lemma length_app:
forall A (l1 l2: list A),
length (app l1 l2) = plus (length l1) (length l2).
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl. rewrite IHl1. reflexivity.
Qed.
Lemma plus_1_S:
forall n,
plus n 1 = S n.
Proof.
intros.
induction n.
+ simpl. reflexivity.
+ simpl. rewrite IHn. reflexivity.
Qed.
Lemma rev_length:
forall A (l: list A),
length (rev l) = length l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite length_app.
simpl. rewrite plus_1_S.
rewrite IHl. reflexivity.
Qed.
Lemma rev_app:
forall A (l1 l2: list A),
rev (app l1 l2) = app (rev l2) (rev l1).
Proof.
intros.
induction l1.
+ simpl. rewrite app_nil. reflexivity.
+ simpl. rewrite IHl1. rewrite app_assoc.
reflexivity.
Qed.
Lemma rev_involutive:
forall A (l: list A),
rev (rev l) = l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite rev_app.
simpl. rewrite IHl. reflexivity.
Qed.
match l with
| nil => nil
| cons x xs => snoc (rev_snoc xs) x
end.
Lemma fast_rev_aux_ok_snoc:
forall A (l1 l2: list A),
fast_rev_aux l1 l2 = app (rev_snoc l1) l2.
Proof.
intros A l1.
induction l1.
+ intros. simpl. reflexivity.
+ intros. simpl.
rewrite IHl1.
rewrite app_snoc_l.
reflexivity.
Qed.
Lemma fast_rev_ok_snoc:
forall A (l: list A),
fast_rev l = rev_snoc l.
Proof.
intros.
unfold fast_rev.
rewrite fast_rev_aux_ok_snoc.
rewrite app_nil.
reflexivity.
Qed.
Lemma length_app:
forall A (l1 l2: list A),
length (app l1 l2) = plus (length l1) (length l2).
Proof.
intros.
induction l1.
+ simpl. reflexivity.
+ simpl. rewrite IHl1. reflexivity.
Qed.
Lemma plus_1_S:
forall n,
plus n 1 = S n.
Proof.
intros.
induction n.
+ simpl. reflexivity.
+ simpl. rewrite IHn. reflexivity.
Qed.
Lemma rev_length:
forall A (l: list A),
length (rev l) = length l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite length_app.
simpl. rewrite plus_1_S.
rewrite IHl. reflexivity.
Qed.
Lemma rev_app:
forall A (l1 l2: list A),
rev (app l1 l2) = app (rev l2) (rev l1).
Proof.
intros.
induction l1.
+ simpl. rewrite app_nil. reflexivity.
+ simpl. rewrite IHl1. rewrite app_assoc.
reflexivity.
Qed.
Lemma rev_involutive:
forall A (l: list A),
rev (rev l) = l.
Proof.
intros.
induction l.
+ simpl. reflexivity.
+ simpl. rewrite rev_app.
simpl. rewrite IHl. reflexivity.
Qed.
END LECTURE 02
E ::= N | V | E + E | E * E | E ? E
Inductive expr : Type :=
| Const : nat -> expr
| Var : string -> expr
| Add : expr -> expr -> expr
| Mul : expr -> expr -> expr
| Cmp : expr -> expr -> expr.
| Const : nat -> expr
| Var : string -> expr
| Add : expr -> expr -> expr
| Mul : expr -> expr -> expr
| Cmp : expr -> expr -> expr.
S ::= Skip | V <- E | S ;; S |
IF E THEN S ELSE S |
WHILE E S
Inductive stmt : Type :=
| Skip : stmt
| Asgn : string -> expr -> stmt
| Seq : stmt -> stmt -> stmt
| Cond : expr -> stmt -> stmt -> stmt
| While : expr -> stmt -> stmt.
| Skip : stmt
| Asgn : string -> expr -> stmt
| Seq : stmt -> stmt -> stmt
| Cond : expr -> stmt -> stmt -> stmt
| While : expr -> stmt -> stmt.
Programs are just elements of type stmt.
Definition prog_skip : stmt :=
Skip.
Definition prog_set_x : stmt :=
Asgn "x" (Const 1).
Definition prog_incr_x_forever : stmt :=
While (Const 1) (Asgn "x" (Const 1)).
Definition prog_xth_fib_in_y : stmt :=
Seq (Asgn "y" (Const 0)) (
Seq (Asgn "y0" (Const 1)) (
Seq (Asgn "y1" (Const 0)) (
Seq (Asgn "i" (Const 0)) (
While (Cmp (Var "i") (Var "x")) (
Seq (Asgn "y" (Add (Var "y0") (Var "y1"))) (
Seq (Asgn "y0" (Var "y1")) (
Seq (Asgn "y1" (Var "y")) (
(Asgn "i" (Add (Var "i") (Const 1)))
))))
)))).
but nobody wants to write programs like this,
so Coq provides a "Notation" mechanism
Notation "'C' X" := (Const X) (at level 80).
Notation "'V' X" := (Var X) (at level 81).
Notation "X <+> Y" := (Add X Y) (at level 83, left associativity).
Notation "X <*> Y" := (Mul X Y) (at level 82, left associativity).
Notation "X <?> Y" := (Cmp X Y) (at level 84).
Notation "X <- Y" := (Asgn X Y) (at level 86).
Notation "X ;; Y" := (Seq X Y) (at level 87, left associativity).
Notation "'IF' X 'THEN' Y 'ELSE' Z" := (Cond X Y Z) (at level 88).
Notation "'WHILE' X {{ Y }}" := (While X Y) (at level 89).
Definition prog_fib : stmt :=
"y" <- C 0;;
"y0" <- C 1;;
"y1" <- C 0;;
"i" <- C 0;;
WHILE (V"i" <?> V"x") {{
"y" <- V"y0" <+> V"y1";;
"y0" <- V"y1";;
"y1" <- V"y";;
"i" <- V"i" <+> C 1
}}.
Notation provides us with "concrete" syntax which
"desugars" to the underlying "abstract syntax tree".
Fixpoint nconsts (e: expr) : nat :=
match e with
| Const _ => 1
| Var _ => 0
| Add e1 e2 => plus (nconsts e1) (nconsts e2)
| Mul e1 e2 => plus (nconsts e1) (nconsts e2)
| Cmp e1 e2 => plus (nconsts e1) (nconsts e2)
end.
Lemma has_3_consts:
exists e, nconsts e = 3.
Proof.
exists (Add (Const 1) (Add (Const 2) (Const 3))).
simpl. reflexivity.
Qed.
Fixpoint expr_with_n_consts (n: nat) : expr :=
match n with
| O => Var "x"
| S m => Add (Const 0) (expr_with_n_consts m)
end.
Lemma has_n_consts:
forall n,
exists e, nconsts e = n.
Proof.
intros.
exists (expr_with_n_consts n).
induction n.
+ simpl. reflexivity.
+ simpl. rewrite IHn. reflexivity.
Qed.
Definition orb (b1 b2: bool) : bool :=
match b1 with
| true => true
| false => b2
end.
Fixpoint has_const (e: expr) : bool :=
match e with
| Const _ => true
| Var _ => false
| Add e1 e2 => orb (has_const e1) (has_const e2)
| Mul e1 e2 => orb (has_const e1) (has_const e2)
| Cmp e1 e2 => orb (has_const e1) (has_const e2)
end.
Fixpoint has_var (e: expr) : bool :=
match e with
| Const _ => false
| Var _ => true
| Add e1 e2 => orb (has_var e1) (has_var e2)
| Mul e1 e2 => orb (has_var e1) (has_var e2)
| Cmp e1 e2 => orb (has_var e1) (has_var e2)
end.
Lemma expr_bottoms_out:
forall e,
orb (has_const e) (has_var e) = true.
Proof.
intros.
induction e.
+
const
simpl. reflexivity.
+
+
var
simpl. reflexivity.
+
+
add
e1 has a const
simpl. reflexivity.
-
-
e1 does not have a const
e2 has a const
simpl. reflexivity.
*
*
e2 does not have a const
simpl.
we also want to simplify in the hypotheses
simpl in *.
and rewrite with the results
rewrite IHe1. rewrite IHe2.
simpl. reflexivity.
+
simpl. reflexivity.
+
mul
e1 has a const
simpl. reflexivity.
-
-
e1 does not have a const
e2 has a const
simpl. reflexivity.
*
*
e2 does not have a const
simpl.
we also want to simplify in the hypotheses
simpl in *.
and rewrite with the results
rewrite IHe1. rewrite IHe2.
simpl. reflexivity.
+
simpl. reflexivity.
+
cmp
e1 has a const
simpl. reflexivity.
-
-
e1 does not have a const
e2 has a const
simpl. reflexivity.
*
*
e2 does not have a const
simpl.
we also want to simplify in the hypotheses
simpl in *.
and rewrite with the results
rewrite IHe1. rewrite IHe2.
simpl. reflexivity.
Qed.
simpl. reflexivity.
Qed.
THE ABOVE PROOF IS VERY BAD. Make it better! Hint: think about how to rearrange the orbs.
Some interesting types
Inductive True : Prop :=
| I : True.
Inductive False : Prop :=
.
Lemma bogus:
False -> 1 = 2.
Proof.
intros.
inversion H.
Qed.
Lemma also_bogus:
1 = 2 -> False.
Proof.
intros.
discriminate.
Qed.
Inductive yo : Prop :=
| yolo : yo -> yo.
Lemma yoyo:
yo -> False.
Proof.
intros.
inversion H.
well, that didn't work
induction H.
assumption.
assumption.
but that did!
Qed.
This page has been generated by coqdoc