Require
Import
Le.
Section
Lists.
Variable
A : Set.
Set Implicit
Arguments.
Inductive
list : Set :=
| nil : list
| cons : A -> list -> list.
Infix
"::" := cons (at level 60, right associativity) : list_scope.
Open Scope list_scope.
Discrimination |
Lemma
nil_cons : forall (a:A) (m:list), nil <> a :: m.
Proof
.
intros; discriminate.
Qed
.
Concatenation |
Fixpoint
app (l m:list) {struct l} : list :=
match l with
| nil => m
| a :: l1 => a :: app l1 m
end.
Infix
"++" := app (right associativity, at level 60) : list_scope.
Lemma
app_nil_end : forall l:list, l = l ++ nil.
Proof
.
induction l; simpl in |- *; auto.
rewrite <- IHl; auto.
Qed
.
Hint
Resolve app_nil_end.
Ltac
now_show c := change c in |- *.
Lemma
app_ass : forall l m n:list, (l ++ m) ++ n = l ++ m ++ n.
Proof
.
intros. induction l; simpl in |- *; auto.
now_show (a :: (l ++ m) ++ n = a :: l ++ m ++ n).
rewrite <- IHl; auto.
Qed
.
Hint
Resolve app_ass.
Lemma
ass_app : forall l m n:list, l ++ m ++ n = (l ++ m) ++ n.
Proof
.
auto.
Qed
.
Hint
Resolve ass_app.
Lemma
app_comm_cons : forall (x y:list) (a:A), a :: x ++ y = (a :: x) ++ y.
Proof
.
auto.
Qed
.
Lemma
app_eq_nil : forall x y:list, x ++ y = nil -> x = nil /\ y = nil.
Proof
.
destruct x as [| a l]; [ destruct y as [| a l] | destruct y as [| a0 l0] ];
simpl in |- *; auto.
intros H; discriminate H.
intros; discriminate H.
Qed
.
Lemma
app_cons_not_nil : forall (x y:list) (a:A), nil <> x ++ a :: y.
Proof
.
unfold not in |- *.
destruct x as [| a l]; simpl in |- *; intros.
discriminate H.
discriminate H.
Qed
.
Lemma
app_eq_unit :
forall (x y:list) (a:A),
x ++ y = a :: nil -> x = nil /\ y = a :: nil \/ x = a :: nil /\ y = nil.
Proof
.
destruct x as [| a l]; [ destruct y as [| a l] | destruct y as [| a0 l0] ];
simpl in |- *.
intros a H; discriminate H.
left; split; auto.
right; split; auto.
generalize H.
generalize (app_nil_end l); intros E.
rewrite <- E; auto.
intros.
injection H.
intro.
cut (nil = l ++ a0 :: l0); auto.
intro.
generalize (app_cons_not_nil _ _ _ H1); intro.
elim H2.
Qed
.
Lemma
app_inj_tail :
forall (x y:list) (a b:A), x ++ a :: nil = y ++ b :: nil -> x = y /\ a = b.
Proof
.
induction x as [| x l IHl];
[ destruct y as [| a l] | destruct y as [| a l0] ];
simpl in |- *; auto.
intros a b H.
injection H.
auto.
intros a0 b H.
injection H; intros.
generalize (app_cons_not_nil _ _ _ H0); destruct 1.
intros a b H.
injection H; intros.
cut (nil = l ++ a :: nil); auto.
intro.
generalize (app_cons_not_nil _ _ _ H2); destruct 1.
intros a0 b H.
injection H; intros.
destruct (IHl l0 a0 b H0).
split; auto.
rewrite <- H1; rewrite <- H2; reflexivity.
Qed
.
Head and tail |
Definition
head (l:list) :=
match l with
| nil => error
| x :: _ => value x
end.
Definition
tail (l:list) : list :=
match l with
| nil => nil
| a :: m => m
end.
Length of lists |
Fixpoint
length (l:list) : nat :=
match l with
| nil => 0
| _ :: m => S (length m)
end.
Length order of lists |
Section
length_order.
Definition
lel (l m:list) := length l <= length m.
Variables
a b : A.
Variables
l m n : list.
Lemma
lel_refl : lel l l.
Proof
.
unfold lel in |- *; auto with arith.
Qed
.
Lemma
lel_trans : lel l m -> lel m n -> lel l n.
Proof
.
unfold lel in |- *; intros.
now_show (length l <= length n).
apply le_trans with (length m); auto with arith.
Qed
.
Lemma
lel_cons_cons : lel l m -> lel (a :: l) (b :: m).
Proof
.
unfold lel in |- *; simpl in |- *; auto with arith.
Qed
.
Lemma
lel_cons : lel l m -> lel l (b :: m).
Proof
.
unfold lel in |- *; simpl in |- *; auto with arith.
Qed
.
Lemma
lel_tail : lel (a :: l) (b :: m) -> lel l m.
Proof
.
unfold lel in |- *; simpl in |- *; auto with arith.
Qed
.
Lemma
lel_nil : forall l':list, lel l' nil -> nil = l'.
Proof
.
intro l'; elim l'; auto with arith.
intros a' y H H0.
now_show (nil = a' :: y).
absurd (S (length y) <= 0); auto with arith.
Qed
.
End
length_order.
Hint
Resolve lel_refl lel_cons_cons lel_cons lel_nil lel_nil nil_cons.
The In predicate
|
Fixpoint
In (a:A) (l:list) {struct l} : Prop :=
match l with
| nil => False
| b :: m => b = a \/ In a m
end.
Lemma
in_eq : forall (a:A) (l:list), In a (a :: l).
Proof
.
simpl in |- *; auto.
Qed
.
Hint
Resolve in_eq.
Lemma
in_cons : forall (a b:A) (l:list), In b l -> In b (a :: l).
Proof
.
simpl in |- *; auto.
Qed
.
Hint
Resolve in_cons.
Lemma
in_nil : forall a:A, ~ In a nil.
Proof
.
unfold not in |- *; intros a H; inversion_clear H.
Qed
.
Lemma
in_inv : forall (a b:A) (l:list), In b (a :: l) -> a = b \/ In b l.
Proof
.
intros a b l H; inversion_clear H; auto.
Qed
.
Lemma
In_dec :
(forall x y:A, {x = y} + {x <> y}) ->
forall (a:A) (l:list), {In a l} + {~ In a l}.
Proof
.
induction l as [| a0 l IHl].
right; apply in_nil.
destruct (H a0 a); simpl in |- *; auto.
destruct IHl; simpl in |- *; auto.
right; unfold not in |- *; intros [Hc1| Hc2]; auto.
Qed
.
Lemma
in_app_or : forall (l m:list) (a:A), In a (l ++ m) -> In a l \/ In a m.
Proof
.
intros l m a.
elim l; simpl in |- *; auto.
intros a0 y H H0.
now_show ((a0 = a \/ In a y) \/ In a m).
elim H0; auto.
intro H1.
now_show ((a0 = a \/ In a y) \/ In a m).
elim (H H1); auto.
Qed
.
Hint
Immediate
in_app_or.
Lemma
in_or_app : forall (l m:list) (a:A), In a l \/ In a m -> In a (l ++ m).
Proof
.
intros l m a.
elim l; simpl in |- *; intro H.
now_show (In a m).
elim H; auto; intro H0.
now_show (In a m).
elim H0. intros y H0 H1.
now_show (H = a \/ In a (y ++ m)).
elim H1; auto 4.
intro H2.
now_show (H = a \/ In a (y ++ m)).
elim H2; auto.
Qed
.
Hint
Resolve in_or_app.
Set inclusion on list |
Definition
incl (l m:list) := forall a:A, In a l -> In a m.
Hint
Unfold incl.
Lemma
incl_refl : forall l:list, incl l l.
Proof
.
auto.
Qed
.
Hint
Resolve incl_refl.
Lemma
incl_tl : forall (a:A) (l m:list), incl l m -> incl l (a :: m).
Proof
.
auto.
Qed
.
Hint
Immediate
incl_tl.
Lemma
incl_tran : forall l m n:list, incl l m -> incl m n -> incl l n.
Proof
.
auto.
Qed
.
Lemma
incl_appl : forall l m n:list, incl l n -> incl l (n ++ m).
Proof
.
auto.
Qed
.
Hint
Immediate
incl_appl.
Lemma
incl_appr : forall l m n:list, incl l n -> incl l (m ++ n).
Proof
.
auto.
Qed
.
Hint
Immediate
incl_appr.
Lemma
incl_cons :
forall (a:A) (l m:list), In a m -> incl l m -> incl (a :: l) m.
Proof
.
unfold incl in |- *; simpl in |- *; intros a l m H H0 a0 H1.
now_show (In a0 m).
elim H1.
now_show (a = a0 -> In a0 m).
elim H1; auto; intro H2.
now_show (a = a0 -> In a0 m).
elim H2; auto. now_show (In a0 l -> In a0 m).
auto.
Qed
.
Hint
Resolve incl_cons.
Lemma
incl_app : forall l m n:list, incl l n -> incl m n -> incl (l ++ m) n.
Proof
.
unfold incl in |- *; simpl in |- *; intros l m n H H0 a H1.
now_show (In a n).
elim (in_app_or _ _ _ H1); auto.
Qed
.
Hint
Resolve incl_app.
Nth element of a list |
Fixpoint
nth (n:nat) (l:list) (default:A) {struct l} : A :=
match n, l with
| O, x :: l' => x
| O, other => default
| S m, nil => default
| S m, x :: t => nth m t default
end.
Fixpoint
nth_ok (n:nat) (l:list) (default:A) {struct l} : bool :=
match n, l with
| O, x :: l' => true
| O, other => false
| S m, nil => false
| S m, x :: t => nth_ok m t default
end.
Lemma
nth_in_or_default :
forall (n:nat) (l:list) (d:A), {In (nth n l d) l} + {nth n l d = d}.
Proof
.
intros n l d; generalize n; induction l; intro n0.
right; case n0; trivial.
case n0; simpl in |- *.
auto.
intro n1; elim (IHl n1); auto.
Qed
.
Lemma
nth_S_cons :
forall (n:nat) (l:list) (d a:A),
In (nth n l d) l -> In (nth (S n) (a :: l) d) (a :: l).
Proof
.
simpl in |- *; auto.
Qed
.
Fixpoint
nth_error (l:list) (n:nat) {struct n} : Exc A :=
match n, l with
| O, x :: _ => value x
| S n, _ :: l => nth_error l n
| _, _ => error
end.
Definition
nth_default (default:A) (l:list) (n:nat) : A :=
match nth_error l n with
| Some x => x
| None => default
end.
Lemma
nth_In :
forall (n:nat) (l:list) (d:A), n < length l -> In (nth n l d) l.
Proof
.
unfold lt in |- *; induction n as [| n hn]; simpl in |- *.
destruct l; simpl in |- *; [ inversion 2 | auto ].
destruct l as [| a l hl]; simpl in |- *.
inversion 2.
intros d ie; right; apply hn; auto with arith.
Qed
.
Decidable equality on lists |
Lemma
list_eq_dec :
(forall x y:A, {x = y} + {x <> y}) -> forall x y:list, {x = y} + {x <> y}.
Proof
.
induction x as [| a l IHl]; destruct y as [| a0 l0]; auto.
destruct (H a a0) as [e| e].
destruct (IHl l0) as [e'| e'].
left; rewrite e; rewrite e'; trivial.
right; red in |- *; intro.
apply e'; injection H0; trivial.
right; red in |- *; intro.
apply e; injection H0; trivial.
Qed
.
Reverse |
Fixpoint
rev (l:list) : list :=
match l with
| nil => nil
| x :: l' => rev l' ++ x :: nil
end.
Lemma
distr_rev : forall x y:list, rev (x ++ y) = rev y ++ rev x.
Proof
.
induction x as [| a l IHl].
destruct y as [| a l].
simpl in |- *.
auto.
simpl in |- *.
apply app_nil_end; auto.
intro y.
simpl in |- *.
rewrite (IHl y).
apply (app_ass (rev y) (rev l) (a :: nil)).
Qed
.
Remark
rev_unit : forall (l:list) (a:A), rev (l ++ a :: nil) = a :: rev l.
Proof
.
intros.
apply (distr_rev l (a :: nil)); simpl in |- *; auto.
Qed
.
Lemma
rev_involutive : forall l:list, rev (rev l) = l.
Proof
.
induction l as [| a l IHl].
simpl in |- *; auto.
simpl in |- *.
rewrite (rev_unit (rev l) a).
rewrite IHl; auto.
Qed
.
Reverse Induction Principle on Lists |
Section
Reverse_Induction.
Unset
Implicit
Arguments.
Remark
rev_list_ind :
forall P:list -> Prop,
P nil ->
(forall (a:A) (l:list), P (rev l) -> P (rev (a :: l))) ->
forall l:list, P (rev l).
Proof
.
induction l; auto.
Qed
.
Set Implicit
Arguments.
Lemma
rev_ind :
forall P:list -> Prop,
P nil ->
(forall (x:A) (l:list), P l -> P (l ++ x :: nil)) -> forall l:list, P l.
Proof
.
intros.
generalize (rev_involutive l).
intros E; rewrite <- E.
apply (rev_list_ind P).
auto.
simpl in |- *.
intros.
apply (H0 a (rev l0)).
auto.
Qed
.
End
Reverse_Induction.
End
Lists.
Implicit
Arguments nil [A].
Hint
Resolve nil_cons app_nil_end ass_app app_ass: datatypes v62.
Hint
Resolve app_comm_cons app_cons_not_nil: datatypes v62.
Hint
Immediate
app_eq_nil: datatypes v62.
Hint
Resolve app_eq_unit app_inj_tail: datatypes v62.
Hint
Resolve lel_refl lel_cons_cons lel_cons lel_nil lel_nil nil_cons:
datatypes v62.
Hint
Resolve in_eq in_cons in_inv in_nil in_app_or in_or_app: datatypes v62.
Hint
Resolve incl_refl incl_tl incl_tran incl_appl incl_appr incl_cons
incl_app: datatypes v62.
Section
Functions_on_lists.
Some generic functions on lists and basic functions of them |
Section
Map.
Variables
A B : Set.
Variable
f : A -> B.
Fixpoint
map (l:list A) : list B :=
match l with
| nil => nil
| cons a t => cons (f a) (map t)
end.
End
Map.
Lemma
in_map :
forall (A B:Set) (f:A -> B) (l:list A) (x:A), In x l -> In (f x) (map f l).
Proof
.
induction l as [| a l IHl]; simpl in |- *;
[ auto
| destruct 1; [ left; apply f_equal with (f:= f); assumption | auto ] ].
Qed
.
Fixpoint
flat_map (A B:Set) (f:A -> list B) (l:list A) {struct l} :
list B :=
match l with
| nil => nil
| cons x t => app (f x) (flat_map f t)
end.
Fixpoint
list_prod (A B:Set) (l:list A) (l':list B) {struct l} :
list (A * B) :=
match l with
| nil => nil
| cons x t => app (map (fun y:B => (x, y)) l') (list_prod t l')
end.
Lemma
in_prod_aux :
forall (A B:Set) (x:A) (y:B) (l:list B),
In y l -> In (x, y) (map (fun y0:B => (x, y0)) l).
Proof
.
induction l;
[ simpl in |- *; auto
| simpl in |- *; destruct 1 as [H1| ];
[ left; rewrite H1; trivial | right; auto ] ].
Qed
.
Lemma
in_prod :
forall (A B:Set) (l:list A) (l':list B) (x:A) (y:B),
In x l -> In y l' -> In (x, y) (list_prod l l').
Proof
.
induction l;
[ simpl in |- *; tauto
| simpl in |- *; intros; apply in_or_app; destruct H;
[ left; rewrite H; apply in_prod_aux; assumption | right; auto ] ].
Qed
.
(list_power x y) is y^x , or the set of sequences of elts of y
indexed by elts of x , sorted in lexicographic order.
|
Fixpoint
list_power (A B:Set) (l:list A) (l':list B) {struct l} :
list (list (A * B)) :=
match l with
| nil => cons nil nil
| cons x t =>
flat_map (fun f:list (A * B) => map (fun y:B => cons (x, y) f) l')
(list_power t l')
end.
Left-to-right iterator on lists |
Section
Fold_Left_Recursor.
Variables
A B : Set.
Variable
f : A -> B -> A.
Fixpoint
fold_left (l:list B) (a0:A) {struct l} : A :=
match l with
| nil => a0
| cons b t => fold_left t (f a0 b)
end.
End
Fold_Left_Recursor.
Right-to-left iterator on lists |
Section
Fold_Right_Recursor.
Variables
A B : Set.
Variable
f : B -> A -> A.
Variable
a0 : A.
Fixpoint
fold_right (l:list B) : A :=
match l with
| nil => a0
| cons b t => f b (fold_right t)
end.
End
Fold_Right_Recursor.
Theorem
fold_symmetric :
forall (A:Set) (f:A -> A -> A),
(forall x y z:A, f x (f y z) = f (f x y) z) ->
(forall x y:A, f x y = f y x) ->
forall (a0:A) (l:list A), fold_left f l a0 = fold_right f a0 l.
Proof
.
destruct l as [| a l].
reflexivity.
simpl in |- *.
rewrite <- H0.
generalize a0 a.
induction l as [| a3 l IHl]; simpl in |- *.
trivial.
intros.
rewrite H.
rewrite (H0 a2).
rewrite <- (H a1).
rewrite (H0 a1).
rewrite IHl.
reflexivity.
Qed
.
End
Functions_on_lists.
Exporting list notations |
Infix
"::" := cons (at level 60, right associativity) : list_scope.
Infix
"++" := app (right associativity, at level 60) : list_scope.
Open Scope list_scope.
Declare Scope list_scope with key list |
Delimit Scope list_scope with list.
Bind Scope list_scope with list.