summaryrefslogtreecommitdiff
path: root/theories/Lists/List.v
diff options
context:
space:
mode:
Diffstat (limited to 'theories/Lists/List.v')
-rw-r--r--theories/Lists/List.v2888
1 files changed, 1688 insertions, 1200 deletions
diff --git a/theories/Lists/List.v b/theories/Lists/List.v
index ad91a350..751bc3da 100644
--- a/theories/Lists/List.v
+++ b/theories/Lists/List.v
@@ -1,730 +1,83 @@
-(************************************************************************)
-(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(************************************************************************)
+ (************************************************************************)
+ (* v * The Coq Proof Assistant / The Coq Development Team *)
+ (* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+ (* \VV/ **************************************************************)
+ (* // * This file is distributed under the terms of the *)
+ (* * GNU Lesser General Public License Version 2.1 *)
+ (************************************************************************)
-(*i $Id: List.v 8686 2006-04-06 13:25:10Z letouzey $ i*)
+ (*i $Id: List.v 8866 2006-05-28 16:21:04Z herbelin $ i*)
-Require Import Le Minus Min Bool.
-
-Section Lists.
-
-Variable A : Set.
+Require Import Le Gt Minus Min Bool.
+Require Import Setoid.
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.
-
-Ltac now_show c := change c in |- *.
-
-(*************************)
-(** Discrimination *)
-(*************************)
-
-Lemma nil_cons : forall (a:A) (m:list), nil <> a :: m.
-Proof.
- intros; discriminate.
-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}.
+(******************************************************************)
+(** * Basics: definition of polymorphic lists and some operations *)
+(******************************************************************)
-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.
-Defined.
-
-(**************************)
-(** 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.
+(** ** Definitions *)
-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}.
-(* Realizer nth_ok. Program_all. *)
-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.
-
-Lemma nth_overflow : forall l n d, length l <= n -> nth n l d = d.
-Proof.
-induction l; destruct n; simpl; intros; auto.
-inversion H.
-apply IHl; auto with arith.
-Qed.
-
-Lemma nth_indep :
- forall l n d d', n < length l -> nth n l d = nth n l d'.
-Proof.
-induction l; simpl; intros; auto.
-inversion H.
-destruct n; simpl; auto with arith.
-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.
-
-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.
-
-Lemma app_length : forall l l', length (l++l') = length l + length l'.
-Proof.
-induction l; simpl; 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. (* subProof completed *)
- 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.
-
-Lemma app_nth1 :
- forall l l' d n, n < length l -> nth n (l++l') d = nth n l d.
-Proof.
-induction l.
-intros.
-inversion H.
-intros l' d n.
-case n; simpl; auto.
-intros; rewrite IHl; auto with arith.
-Qed.
-
-Lemma app_nth2 :
- forall l l' d n, n >= length l -> nth n (l++l') d = nth (n-length l) l' d.
-Proof.
-induction l.
-intros.
-simpl.
-destruct n; auto.
-intros l' d n.
-case n; simpl; auto.
-intros.
-inversion H.
-intros.
-rewrite IHl; auto with arith.
-Qed.
-
-
-(***************************)
-(** 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. (* solves subgoal *)
- 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.
-
-
-
-(********************************)
-(** 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.
-
-Lemma In_rev : forall l x, In x l <-> In x (rev l).
-Proof.
-induction l.
-simpl; intuition.
-intros.
-simpl.
-intuition.
-subst.
-apply in_or_app; right; simpl; auto.
-apply in_or_app; left; firstorder.
-destruct (in_app_or _ _ _ H); firstorder.
-Qed.
-
-Lemma rev_length : forall l, length (rev l) = length l.
-Proof.
-induction l;simpl; auto.
-rewrite app_length.
-rewrite IHl.
-simpl.
-elim (length l); simpl; auto.
-Qed.
-
-Lemma rev_nth : forall l d n, n < length l ->
- nth n (rev l) d = nth (length l - S n) l d.
-Proof.
-induction l.
-intros; inversion H.
-intros.
-simpl in H.
-simpl (rev (a :: l)).
-simpl (length (a :: l) - S n).
-inversion H.
-rewrite <- minus_n_n; simpl.
-rewrite <- rev_length.
-rewrite app_nth2; auto.
-rewrite <- minus_n_n; auto.
-rewrite app_nth1; auto.
-rewrite (minus_plus_simpl_l_reverse (length l) n 1).
-replace (1 + length l) with (S (length l)); auto with arith.
-rewrite <- minus_Sn_m; auto with arith; simpl.
-apply IHl; auto.
-rewrite rev_length; auto.
-Qed.
-
-(****************************************************)
-(** An alternative tail-recursive definition for reverse *)
-(****************************************************)
-
-Fixpoint rev_acc (l l': list) {struct l} : list :=
- match l with
- | nil => l'
- | a::l => rev_acc l (a::l')
- end.
-
-Lemma rev_acc_rev : forall l l', rev_acc l l' = rev l ++ l'.
-Proof.
-induction l; simpl; auto; intros.
-rewrite <- ass_app; firstorder.
-Qed.
-
-Lemma rev_alt : forall l, rev l = rev_acc l nil.
-Proof.
-intros; rewrite rev_acc_rev.
-apply app_nil_end.
-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.
-
-(***************************)
-(** Last elements of a list *)
-(***************************)
-
-(** [last l d] returns the last elements of the list [l],
- or the default value [d] if [l] is empty. *)
-
-Fixpoint last (l:list)(d:A) {struct l} : A :=
- match l with
- | nil => d
- | a :: nil => a
- | a :: l => last l d
- end.
-
-(** [removelast l] remove the last element of [l] *)
-
-Fixpoint removelast (l:list) {struct l} : list :=
- match l with
- | nil => nil
- | a :: nil => nil
- | a :: l => a :: removelast l
- end.
-
-Lemma app_removelast_last :
- forall l d, l<>nil -> l = removelast l ++ (last l d :: nil).
-Proof.
-induction l.
-destruct 1; auto.
-intros d _.
-destruct l; auto.
-pattern (a0::l) at 1; rewrite IHl with d; auto; discriminate.
-Qed.
-
-Lemma exists_last :
- forall l, l<>nil -> { l' : list & { a : A | l = l'++a::nil}}.
-Proof.
-induction l.
-destruct 1; auto.
-intros _.
-destruct l.
-exists nil; exists a; auto.
-destruct IHl as [l' (a',H)]; try discriminate.
-rewrite H.
-exists (a::l'); exists a'; auto.
-Qed.
-
-(********************************)
-(* Cutting a list at some position *)
-(********************************)
-
-Fixpoint firstn (n:nat)(l:list) {struct n} : list :=
- match n with
- | 0 => nil
- | S n => match l with
- | nil => nil
- | a::l => a::(firstn n l)
- end
- end.
-
-Fixpoint skipn (n:nat)(l:list) { struct n } : list :=
- match n with
- | 0 => l
- | S n => match l with
- | nil => nil
- | a::l => skipn n l
- end
- end.
-
-Lemma firstn_skipn : forall n l, firstn n l ++ skipn n l = l.
-Proof.
-induction n.
-simpl; auto.
-destruct l; simpl; auto.
-f_equal; auto.
-Qed.
-
-(**************)
-(** Remove *)
-(**************)
-
-Section Remove.
-
-Hypothesis eq_dec : forall x y : A, {x = y}+{x <> y}.
-
-Fixpoint remove (x : A) (l : list){struct l} : list :=
- match l with
- | nil => nil
- | y::tl => if (eq_dec x y) then remove x tl else y::(remove x tl)
- end.
-
-End Remove.
-
-(***************************)
-(** List without redundancy *)
-(***************************)
-
-Inductive NoDup : list -> Prop :=
- | NoDup_nil : NoDup nil
- | NoDup_cons : forall x l, ~ In x l -> NoDup l -> NoDup (x::l).
+Section Lists.
+ Variable A : Type.
+
+ Inductive list : Type :=
+ | nil : list
+ | cons : A -> list -> list.
+
+ Infix "::" := cons (at level 60, right associativity) : list_scope.
+
+ Open Scope list_scope.
+
+ (** 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.
+
+ (** 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.
+
+
+ (** Concatenation of two lists *)
+ 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.
+
End Lists.
-(** Exporting list notations and hints *)
+(** Exporting list notations and tactics *)
Implicit Arguments nil [A].
Infix "::" := cons (at level 60, right associativity) : list_scope.
Infix "++" := app (right associativity, at level 60) : list_scope.
+
+Ltac now_show c := change c in |- *.
Open Scope list_scope.
@@ -732,349 +85,1043 @@ Delimit Scope list_scope with list.
Bind Scope list_scope with list.
-Hint Resolve nil_cons app_nil_end ass_app app_ass: datatypes v62.
+
+(** ** Facts about lists *)
+
+Section Facts.
+
+ Variable A : Type.
+
+
+ (** *** Genereric facts *)
+
+ (** Discrimination *)
+ Theorem nil_cons : forall (x:A) (l:list A), nil <> x :: l.
+ Proof.
+ intros; discriminate.
+ Qed.
+
+
+ (** Destruction *)
+
+ Theorem destruct_list : forall l : list A, {x:A & {tl:list A | l = x::tl}}+{l = nil}.
+ Proof.
+ induction l as [|a tl].
+ right; reflexivity.
+ left; exists a; exists tl; reflexivity.
+ Qed.
+
+ (** *** Head and tail *)
+
+ Theorem head_nil : head (@nil A) = None.
+ Proof.
+ simpl; reflexivity.
+ Qed.
+
+ Theorem head_cons : forall (l : list A) (x : A), head (x::l) = Some x.
+ Proof.
+ intros; simpl; reflexivity.
+ Qed.
+
+
+ (************************)
+ (** *** Facts about [In] *)
+ (************************)
+
+
+ (** Characterization of [In] *)
+
+ Theorem in_eq : forall (a:A) (l:list A), In a (a :: l).
+ Proof.
+ simpl in |- *; auto.
+ Qed.
+ Hint Resolve in_eq.
+
+ Theorem in_cons : forall (a b:A) (l:list A), In b l -> In b (a :: l).
+ Proof.
+ simpl in |- *; auto.
+ Qed.
+ Hint Resolve in_cons.
+
+ Theorem in_nil : forall a:A, ~ In a nil.
+ Proof.
+ unfold not in |- *; intros a H; inversion_clear H.
+ Qed.
+
+ Lemma In_split : forall x (l:list A), In x l -> exists l1, exists l2, l = l1++x::l2.
+ Proof.
+ induction l; simpl; destruct 1.
+ subst a; auto.
+ exists (@nil A); exists l; auto.
+ destruct (IHl H) as (l1,(l2,H0)).
+ exists (a::l1); exists l2; simpl; f_equal; auto.
+ Qed.
+
+ (** Inversion *)
+ Theorem in_inv : forall (a b:A) (l:list A), In b (a :: l) -> a = b \/ In b l.
+ Proof.
+ intros a b l H; inversion_clear H; auto.
+ Qed.
+
+ (** Decidability of [In] *)
+ Theorem In_dec :
+ (forall x y:A, {x = y} + {x <> y}) ->
+ forall (a:A) (l:list A), {In a l} + {~ In a l}.
+ Proof.
+ intro H; 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.
+ Defined.
+
+
+ (*************************)
+ (** *** Facts about [app] *)
+ (*************************)
+
+ (** Discrimination *)
+ Theorem app_cons_not_nil : forall (x y:list A) (a:A), nil <> x ++ a :: y.
+ Proof.
+ unfold not in |- *.
+ destruct x as [| a l]; simpl in |- *; intros.
+ discriminate H.
+ discriminate H.
+ Qed.
+
+
+ (** Concat with [nil] *)
+
+ Theorem app_nil_end : forall l:list A, l = l ++ nil.
+ Proof.
+ induction l; simpl in |- *; auto.
+ rewrite <- IHl; auto.
+ Qed.
+ Hint Resolve app_nil_end.
+
+
+ (** [app] is associative *)
+ Theorem app_ass : forall l m n:list A, (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.
+
+ Theorem ass_app : forall l m n:list A, l ++ m ++ n = (l ++ m) ++ n.
+ Proof.
+ auto.
+ Qed.
+ Hint Resolve ass_app.
+
+ (** [app] commutes with [cons] *)
+ Theorem app_comm_cons : forall (x y:list A) (a:A), a :: (x ++ y) = (a :: x) ++ y.
+ Proof.
+ auto.
+ Qed.
+
+
+
+ (** Facts deduced from the result of a concatenation *)
+
+ Theorem app_eq_nil : forall l l':list A, l ++ l' = nil -> l = nil /\ l' = nil.
+ Proof.
+ destruct l as [| x l]; destruct l' as [| y l']; simpl in |- *; auto.
+ intro; discriminate.
+ intros H; discriminate H.
+ Qed.
+
+ Theorem app_eq_unit :
+ forall (x y:list A) (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) (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.
+
+
+ (** Compatibility wtih other operations *)
+
+ Lemma app_length : forall l l' : list A, length (l++l') = length l + length l'.
+ Proof.
+ induction l; simpl; auto.
+ Qed.
+
+ Lemma in_app_or : forall (l m:list A) (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: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. (* subProof completed *)
+ 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.
+
+
+End Facts.
+
+Hint Resolve 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 *)
-(****************************************************************)
-(*********)
-(** Map *)
-(*********)
+(*******************************************)
+(** * Operations on the elements of a list *)
+(*******************************************)
+
+Section Elts.
+
+ Variable A : Type.
+
+ (*****************************)
+ (** ** Nth element of a list *)
+ (*****************************)
+
+ Fixpoint nth (n:nat) (l:list A) (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 A) (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 A) (d:A), {In (nth n l d) l} + {nth n l d = d}.
+ (* Realizer nth_ok. Program_all. *)
+ 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 A) (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 A) (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 A) (n:nat) : A :=
+ match nth_error l n with
+ | Some x => x
+ | None => default
+ end.
+
+ Lemma nth_In :
+ forall (n:nat) (l:list A) (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.
+
+ Lemma nth_overflow : forall l n d, length l <= n -> nth n l d = d.
+ Proof.
+ induction l; destruct n; simpl; intros; auto.
+ inversion H.
+ apply IHl; auto with arith.
+ Qed.
+
+ Lemma nth_indep :
+ forall l n d d', n < length l -> nth n l d = nth n l d'.
+ Proof.
+ induction l; simpl; intros; auto.
+ inversion H.
+ destruct n; simpl; auto with arith.
+ Qed.
+
+ Lemma app_nth1 :
+ forall l l' d n, n < length l -> nth n (l++l') d = nth n l d.
+ Proof.
+ induction l.
+ intros.
+ inversion H.
+ intros l' d n.
+ case n; simpl; auto.
+ intros; rewrite IHl; auto with arith.
+ Qed.
+
+ Lemma app_nth2 :
+ forall l l' d n, n >= length l -> nth n (l++l') d = nth (n-length l) l' d.
+ Proof.
+ induction l.
+ intros.
+ simpl.
+ destruct n; auto.
+ intros l' d n.
+ case n; simpl; auto.
+ intros.
+ inversion H.
+ intros.
+ rewrite IHl; auto with arith.
+ Qed.
+
+
+
+
+ (*****************)
+ (** ** Remove *)
+ (*****************)
+
+ Section Remove.
+
+ Hypothesis eq_dec : forall x y : A, {x = y}+{x <> y}.
+
+ Fixpoint remove (x : A) (l : list A){struct l} : list A :=
+ match l with
+ | nil => nil
+ | y::tl => if (eq_dec x y) then remove x tl else y::(remove x tl)
+ end.
+
+ Theorem remove_In : forall (l : list A) (x : A), ~ In x (remove x l).
+ Proof.
+ induction l as [|x l]; auto.
+ intro y; simpl; destruct (eq_dec y x) as [yeqx | yneqx].
+ apply IHl.
+ unfold not; intro HF; simpl in HF; destruct HF; auto.
+ apply (IHl y); assumption.
+ Qed.
+
+ End Remove.
-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.
+(******************************)
+(** ** Last element of a list *)
+(******************************)
-Lemma in_map :
- forall (l:list A) (x:A), In x l -> In (f x) (map l).
-Proof.
- induction l as [| a l IHl]; simpl in |- *;
- [ auto
- | destruct 1; [ left; apply f_equal with (f := f); assumption | auto ] ].
-Qed.
+ (** [last l d] returns the last element of the list [l],
+ or the default value [d] if [l] is empty. *)
-Lemma in_map_iff : forall l y, In y (map l) <-> exists x, f x = y /\ In x l.
-Proof.
-induction l; firstorder (subst; auto).
-Qed.
+ Fixpoint last (l:list A) (d:A) {struct l} : A :=
+ match l with
+ | nil => d
+ | a :: nil => a
+ | a :: l => last l d
+ end.
-Lemma map_length : forall l, length (map l) = length l.
-Proof.
-induction l; simpl; auto.
-Qed.
+ (** [removelast l] remove the last element of [l] *)
+
+ Fixpoint removelast (l:list A) {struct l} : list A :=
+ match l with
+ | nil => nil
+ | a :: nil => nil
+ | a :: l => a :: removelast l
+ end.
+
+ Lemma app_removelast_last :
+ forall l d, l<>nil -> l = removelast l ++ (last l d :: nil).
+ Proof.
+ induction l.
+ destruct 1; auto.
+ intros d _.
+ destruct l; auto.
+ pattern (a0::l) at 1; rewrite IHl with d; auto; discriminate.
+ Qed.
+
+ Lemma exists_last :
+ forall l, l<>nil -> { l' : (list A) & { a : A | l = l'++a::nil}}.
+ Proof.
+ induction l.
+ destruct 1; auto.
+ intros _.
+ destruct l.
+ exists (@nil A); exists a; auto.
+ destruct IHl as [l' (a',H)]; try discriminate.
+ rewrite H.
+ exists (a::l'); exists a'; auto.
+ Qed.
+
+
+ (****************************************)
+ (** ** Counting occurences of a element *)
+ (****************************************)
+
+ Hypotheses eqA_dec : forall x y : A, {x = y}+{x <> y}.
+
+ Fixpoint count_occ (l : list A) (x : A){struct l} : nat :=
+ match l with
+ | nil => 0
+ | y :: tl =>
+ let n := count_occ tl x in
+ if eqA_dec y x then S n else n
+ end.
+
+ (** Compatibility of count_occ with operations on list *)
+ Theorem count_occ_In : forall (l : list A) (x : A), In x l <-> count_occ l x > 0.
+ Proof.
+ induction l as [|y l].
+ simpl; intros; split; [destruct 1 | apply gt_irrefl].
+ simpl. intro x; destruct (eqA_dec y x) as [Heq|Hneq].
+ rewrite Heq; intuition.
+ rewrite <- (IHl x).
+ tauto.
+ Qed.
+
+ Theorem count_occ_inv_nil : forall (l : list A), (forall x:A, count_occ l x = 0) <-> l = nil.
+ Proof.
+ split.
+ (* Case -> *)
+ induction l as [|x l].
+ trivial.
+ intro H.
+ elim (O_S (count_occ l x)).
+ apply sym_eq.
+ generalize (H x).
+ simpl. destruct (eqA_dec x x) as [|HF].
+ trivial.
+ elim HF; reflexivity.
+ (* Case <- *)
+ intro H; rewrite H; simpl; reflexivity.
+ Qed.
+
+ Lemma count_occ_nil : forall (x : A), count_occ nil x = 0.
+ Proof.
+ intro x; simpl; reflexivity.
+ Qed.
+
+ Lemma count_occ_cons_eq : forall (l : list A) (x y : A), x = y -> count_occ (x::l) y = S (count_occ l y).
+ Proof.
+ intros l x y H; simpl.
+ destruct (eqA_dec x y); [reflexivity | contradiction].
+ Qed.
+
+ Lemma count_occ_cons_neq : forall (l : list A) (x y : A), x <> y -> count_occ (x::l) y = count_occ l y.
+ Proof.
+ intros l x y H; simpl.
+ destruct (eqA_dec x y); [contradiction | reflexivity].
+ Qed.
+
+End Elts.
+
+
+
+(*******************************)
+(** * Manipulating whole lists *)
+(*******************************)
+
+Section ListOps.
+
+ Variable A : Type.
+
+ (*************************)
+ (** ** Reverse *)
+ (*************************)
+
+ Fixpoint rev (l:list A) : list A :=
+ match l with
+ | nil => nil
+ | x :: l' => rev l' ++ x :: nil
+ end.
+
+ Lemma distr_rev : forall x y:list A, 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: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 A, 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.
+
+
+ (** Compatibility with other operations *)
+
+ Lemma In_rev : forall l x, In x l <-> In x (rev l).
+ Proof.
+ induction l.
+ simpl; intuition.
+ intros.
+ simpl.
+ intuition.
+ subst.
+ apply in_or_app; right; simpl; auto.
+ apply in_or_app; left; firstorder.
+ destruct (in_app_or _ _ _ H); firstorder.
+ Qed.
+
+ Lemma rev_length : forall l, length (rev l) = length l.
+ Proof.
+ induction l;simpl; auto.
+ rewrite app_length.
+ rewrite IHl.
+ simpl.
+ elim (length l); simpl; auto.
+ Qed.
+
+ Lemma rev_nth : forall l d n, n < length l ->
+ nth n (rev l) d = nth (length l - S n) l d.
+ Proof.
+ induction l.
+ intros; inversion H.
+ intros.
+ simpl in H.
+ simpl (rev (a :: l)).
+ simpl (length (a :: l) - S n).
+ inversion H.
+ rewrite <- minus_n_n; simpl.
+ rewrite <- rev_length.
+ rewrite app_nth2; auto.
+ rewrite <- minus_n_n; auto.
+ rewrite app_nth1; auto.
+ rewrite (minus_plus_simpl_l_reverse (length l) n 1).
+ replace (1 + length l) with (S (length l)); auto with arith.
+ rewrite <- minus_Sn_m; auto with arith; simpl.
+ apply IHl; auto.
+ rewrite rev_length; auto.
+ Qed.
+
+
+ (** An alternative tail-recursive definition for reverse *)
+
+ Fixpoint rev_acc (l l': list A) {struct l} : list A :=
+ match l with
+ | nil => l'
+ | a::l => rev_acc l (a::l')
+ end.
+
+ Lemma rev_acc_rev : forall l l', rev_acc l l' = rev l ++ l'.
+ Proof.
+ induction l; simpl; auto; intros.
+ rewrite <- ass_app; firstorder.
+ Qed.
+
+ Lemma rev_alt : forall l, rev l = rev_acc l nil.
+ Proof.
+ intros; rewrite rev_acc_rev.
+ apply app_nil_end.
+ Qed.
-Lemma map_nth : forall l d n,
- nth n (map l) (f d) = f (nth n l d).
-Proof.
-induction l; simpl map; destruct n; firstorder.
-Qed.
-Lemma map_app : forall l l',
- map (l++l') = (map l)++(map l').
-Proof.
-induction l; simpl; auto.
-intros; rewrite IHl; auto.
-Qed.
+(*********************************************)
+(** Reverse Induction Principle on Lists *)
+(*********************************************)
+
+ Section Reverse_Induction.
+
+ Unset Implicit Arguments.
+
+ Lemma rev_list_ind :
+ forall P:list A-> Prop,
+ P nil ->
+ (forall (a:A) (l:list A), P (rev l) -> P (rev (a :: l))) ->
+ forall l:list A, P (rev l).
+ Proof.
+ induction l; auto.
+ Qed.
+ Set Implicit Arguments.
+
+ Theorem rev_ind :
+ forall P:list A -> Prop,
+ P nil ->
+ (forall (x:A) (l:list A), P l -> P (l ++ x :: nil)) -> forall l:list A, 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.
+
+
+
+ (***********************************)
+ (** ** Lists modulo permutation *)
+ (***********************************)
+
+ Section Permutation.
+
+ Inductive Permutation : list A -> list A -> Prop :=
+ | perm_nil: Permutation nil nil
+ | perm_skip: forall (x:A) (l l':list A), Permutation l l' -> Permutation (cons x l) (cons x l')
+ | perm_swap: forall (x y:A) (l:list A), Permutation (cons y (cons x l)) (cons x (cons y l))
+ | perm_trans: forall (l l' l'':list A), Permutation l l' -> Permutation l' l'' -> Permutation l l''.
+
+ Hint Constructors Permutation.
+
+ (** Some facts about [Permutation] *)
+
+ Theorem Permutation_nil : forall (l : list A), Permutation nil l -> l = nil.
+ Proof.
+ intros l HF.
+ set (m:=@nil A) in HF; assert (m = nil); [reflexivity|idtac]; clearbody m.
+ induction HF; try elim (nil_cons (sym_eq H)); auto.
+ Qed.
+
+ Theorem Permutation_nil_cons : forall (l : list A) (x : A), ~ Permutation nil (x::l).
+ Proof.
+ unfold not; intros l x HF.
+ elim (@nil_cons A x l). apply sym_eq. exact (Permutation_nil HF).
+ Qed.
+
+ (** Permutation over lists is a equivalence relation *)
+
+ Theorem Permutation_refl : forall l : list A, Permutation l l.
+ Proof.
+ induction l; constructor. exact IHl.
+ Qed.
+
+ Theorem Permutation_sym : forall l l' : list A, Permutation l l' -> Permutation l' l.
+ Proof.
+ intros l l' Hperm; induction Hperm; auto.
+ apply perm_trans with (l':=l'); assumption.
+ Qed.
+
+ Theorem Permutation_trans : forall l l' l'' : list A, Permutation l l' -> Permutation l' l'' -> Permutation l l''.
+ Proof.
+ exact perm_trans.
+ Qed.
+
+ Hint Resolve Permutation_refl Permutation_sym Permutation_trans.
+
+ (** Compatibility with others operations on lists *)
+
+ Theorem Permutation_in : forall (l l' : list A) (x : A), Permutation l l' -> In x l -> In x l'.
+ Proof.
+ intros l l' x Hperm; induction Hperm; simpl; tauto.
+ Qed.
+
+ Lemma Permutation_app_tail : forall (l l' tl : list A), Permutation l l' -> Permutation (l++tl) (l'++tl).
+ Proof.
+ intros l l' tl Hperm; induction Hperm as [|x l l'|x y l|l l' l'']; simpl; auto.
+ eapply Permutation_trans with (l':=l'++tl); trivial.
+ Qed.
+
+ Lemma Permutation_app_head : forall (l tl tl' : list A), Permutation tl tl' -> Permutation (l++tl) (l++tl').
+ Proof.
+ intros l tl tl' Hperm; induction l; [trivial | repeat rewrite <- app_comm_cons; constructor; assumption].
+ Qed.
+
+ Theorem Permutation_app : forall (l m l' m' : list A), Permutation l l' -> Permutation m m' -> Permutation (l++m) (l'++m').
+ Proof.
+ intros l m l' m' Hpermll' Hpermmm'; induction Hpermll' as [|x l l'|x y l|l l' l'']; repeat rewrite <- app_comm_cons; auto.
+ apply Permutation_trans with (l' := (x :: y :: l ++ m));
+ [idtac | repeat rewrite app_comm_cons; apply Permutation_app_head]; trivial.
+ apply Permutation_trans with (l' := (l' ++ m')); try assumption.
+ apply Permutation_app_tail; assumption.
+ Qed.
+
+ Theorem Permutation_app_swap : forall (l l' : list A), Permutation (l++l') (l'++l).
+ Proof.
+ induction l as [|x l].
+ simpl; intro l'; rewrite <- app_nil_end; trivial.
+ induction l' as [|y l'].
+ simpl; rewrite <- app_nil_end; trivial.
+ simpl; apply Permutation_trans with (l' := x :: y :: l' ++ l).
+ constructor; rewrite app_comm_cons; apply IHl.
+ apply Permutation_trans with (l' := y :: x :: l' ++ l); constructor.
+ apply Permutation_trans with (l' := x :: l ++ l'); auto.
+ Qed.
+
+ Theorem Permutation_cons_app : forall (l l1 l2:list A) a,
+ Permutation l (l1 ++ l2) -> Permutation (a :: l) (l1 ++ a :: l2).
+ Proof.
+ intros l l1; revert l.
+ induction l1.
+ simpl.
+ intros; apply perm_skip; auto.
+ simpl; intros.
+ apply perm_trans with (a0::a::l1++l2).
+ apply perm_skip; auto.
+ apply perm_trans with (a::a0::l1++l2).
+ apply perm_swap; auto.
+ apply perm_skip; auto.
+ Qed.
+ Hint Resolve Permutation_cons_app.
+
+ Theorem Permutation_length : forall (l l' : list A), Permutation l l' -> length l = length l'.
+ Proof.
+ intros l l' Hperm; induction Hperm; simpl; auto.
+ apply trans_eq with (y:= (length l')); trivial.
+ Qed.
+
+ Theorem Permutation_rev : forall (l : list A), Permutation l (rev l).
+ Proof.
+ induction l as [| x l]; simpl; trivial.
+ apply Permutation_trans with (l' := (x::nil)++rev l).
+ simpl; auto.
+ apply Permutation_app_swap.
+ Qed.
+
+ Theorem Permutation_ind_bis :
+ forall P : list A -> list A -> Prop,
+ P (@nil A) (@nil A) ->
+ (forall x l l', Permutation l l' -> P l l' -> P (x :: l) (x :: l')) ->
+ (forall x y l l', Permutation l l' -> P l l' -> P (y :: x :: l) (x :: y :: l')) ->
+ (forall l l' l'', Permutation l l' -> P l l' -> Permutation l' l'' -> P l' l'' -> P l l'') ->
+ forall l l', Permutation l l' -> P l l'.
+ Proof.
+ intros P Hnil Hskip Hswap Htrans.
+ induction 1; auto.
+ apply Htrans with (x::y::l); auto.
+ apply Hswap; auto.
+ induction l; auto.
+ apply Hskip; auto.
+ apply Hskip; auto.
+ induction l; auto.
+ eauto.
+ Qed.
+
+ Ltac break_list l x l' H :=
+ destruct l as [|x l']; simpl in *;
+ injection H; intros; subst; clear H.
+
+ Theorem Permutation_app_inv : forall (l1 l2 l3 l4:list A) a,
+ Permutation (l1++a::l2) (l3++a::l4) -> Permutation (l1++l2) (l3 ++ l4).
+ Proof.
+ set (P:=fun l l' =>
+ forall a l1 l2 l3 l4, l=l1++a::l2 -> l'=l3++a::l4 -> Permutation (l1++l2) (l3++l4)).
+ cut (forall l l', Permutation l l' -> P l l').
+ intros; apply (H _ _ H0 a); auto.
+ intros; apply (Permutation_ind_bis P); unfold P; clear P; try clear H l l'; simpl; auto.
+ (* nil *)
+ intros; destruct l1; simpl in *; discriminate.
+ (* skip *)
+ intros x l l' H IH; intros.
+ break_list l1 b l1' H0; break_list l3 c l3' H1.
+ auto.
+ apply perm_trans with (l3'++c::l4); auto.
+ apply perm_trans with (l1'++a::l2); auto.
+ apply perm_skip.
+ apply (IH a l1' l2 l3' l4); auto.
+ (* swap *)
+ intros x y l l' Hp IH; intros.
+ break_list l1 b l1' H; break_list l3 c l3' H0.
+ auto.
+ break_list l3' b l3'' H.
+ auto.
+ apply perm_trans with (c::l3''++b::l4); auto.
+ break_list l1' c l1'' H1.
+ auto.
+ apply perm_trans with (b::l1''++c::l2); auto.
+ break_list l3' d l3'' H; break_list l1' e l1'' H1.
+ auto.
+ apply perm_trans with (e::a::l1''++l2); auto.
+ apply perm_trans with (e::l1''++a::l2); auto.
+ apply perm_trans with (d::a::l3''++l4); auto.
+ apply perm_trans with (d::l3''++a::l4); auto.
+ apply perm_trans with (e::d::l1''++l2); auto.
+ apply perm_skip; apply perm_skip.
+ apply (IH a l1'' l2 l3'' l4); auto.
+ (*trans*)
+ intros.
+ destruct (In_split a l') as (l'1,(l'2,H6)).
+ apply (Permutation_in a H).
+ subst l.
+ apply in_or_app; right; red; auto.
+ apply perm_trans with (l'1++l'2).
+ apply (H0 _ _ _ _ _ H3 H6).
+ apply (H2 _ _ _ _ _ H6 H4).
+ Qed.
+
+ Theorem Permutation_cons_inv :
+ forall l l' a, Permutation (a::l) (a::l') -> Permutation l l'.
+ Proof.
+ intros; exact (Permutation_app_inv (@nil _) l (@nil _) l' a H).
+ Qed.
+
+ Theorem Permutation_cons_app_inv :
+ forall l l1 l2 a, Permutation (a :: l) (l1 ++ a :: l2) -> Permutation l (l1 ++ l2).
+ Proof.
+ intros; exact (Permutation_app_inv (@nil _) l l1 l2 a H).
+ Qed.
+
+ Theorem Permutation_app_inv_l :
+ forall l l1 l2, Permutation (l ++ l1) (l ++ l2) -> Permutation l1 l2.
+ Proof.
+ induction l; simpl; auto.
+ intros.
+ apply IHl.
+ apply Permutation_cons_inv with a; auto.
+ Qed.
+
+ Theorem Permutation_app_inv_r :
+ forall l l1 l2, Permutation (l1 ++ l) (l2 ++ l) -> Permutation l1 l2.
+ Proof.
+ induction l.
+ intros l1 l2; do 2 rewrite <- app_nil_end; auto.
+ intros.
+ apply IHl.
+ apply Permutation_app_inv with a; auto.
+ Qed.
+
+ End Permutation.
+
+
+ (***********************************)
+ (** ** Decidable equality on lists *)
+ (***********************************)
+
+ Hypotheses eqA_dec : forall (x y : A), {x = y}+{x <> y}.
+
+ Lemma list_eq_dec :
+ forall l l':list A, {l = l'} + {l <> l'}.
+ Proof.
+ induction l as [| x l IHl]; destruct l' as [| y l'].
+ left; trivial.
+ right; apply nil_cons.
+ right; unfold not; intro HF; apply (nil_cons (sym_eq HF)).
+ destruct (eqA_dec x y) as [xeqy|xneqy]; destruct (IHl l') as [leql'|lneql'];
+ try (right; unfold not; intro HF; injection HF; intros; contradiction).
+ rewrite xeqy; rewrite leql'; left; trivial.
+ Qed.
+
+
+End ListOps.
+
+
+(***************************************************)
+(** * Applying functions to the elements of a list *)
+(***************************************************)
+
+(************)
+(** ** Map *)
+(************)
-Lemma map_rev : forall l, map (rev l) = rev (map l).
-Proof.
-induction l; simpl; auto.
-rewrite map_app.
-rewrite IHl; auto.
-Qed.
+Section Map.
+ Variables A B : Type.
+ 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.
+
+ Lemma in_map :
+ forall (l:list A) (x:A), In x l -> In (f x) (map l).
+ Proof.
+ induction l as [| a l IHl]; simpl in |- *;
+ [ auto
+ | destruct 1; [ left; apply f_equal with (f := f); assumption | auto ] ].
+ Qed.
+
+ Lemma in_map_iff : forall l y, In y (map l) <-> exists x, f x = y /\ In x l.
+ Proof.
+ induction l; firstorder (subst; auto).
+ Qed.
+
+ Lemma map_length : forall l, length (map l) = length l.
+ Proof.
+ induction l; simpl; auto.
+ Qed.
+
+ Lemma map_nth : forall l d n,
+ nth n (map l) (f d) = f (nth n l d).
+ Proof.
+ induction l; simpl map; destruct n; firstorder.
+ Qed.
+
+ Lemma map_app : forall l l',
+ map (l++l') = (map l)++(map l').
+ Proof.
+ induction l; simpl; auto.
+ intros; rewrite IHl; auto.
+ Qed.
+
+ Lemma map_rev : forall l, map (rev l) = rev (map l).
+ Proof.
+ induction l; simpl; auto.
+ rewrite map_app.
+ rewrite IHl; auto.
+ Qed.
+
+ Hint Constructors Permutation.
+
+ Lemma Permutation_map :
+ forall l l', Permutation l l' -> Permutation (map l) (map l').
+ Proof.
+ induction 1; simpl; auto; eauto.
+ Qed.
+
+ (** [flat_map] *)
+
+ Fixpoint flat_map (f:A -> list B) (l:list A) {struct l} :
+ list B :=
+ match l with
+ | nil => nil
+ | cons x t => (f x)++(flat_map f t)
+ end.
+
+ Lemma in_flat_map : forall (f:A->list B)(l:list A)(y:B),
+ In y (flat_map f l) <-> exists x, In x l /\ In y (f x).
+ Proof.
+ induction l; simpl; split; intros.
+ contradiction.
+ destruct H as (x,(H,_)); contradiction.
+ destruct (in_app_or _ _ _ H).
+ exists a; auto.
+ destruct (IHl y) as (H1,_); destruct (H1 H0) as (x,(H2,H3)).
+ exists x; auto.
+ apply in_or_app.
+ destruct H as (x,(H0,H1)); destruct H0.
+ subst; auto.
+ right; destruct (IHl y) as (_,H2); apply H2.
+ exists x; auto.
+ Qed.
End Map.
-Lemma map_map : forall (A B C:Set)(f:A->B)(g:B->C) l,
+Lemma map_map : forall (A B C:Type)(f:A->B)(g:B->C) l,
map g (map f l) = map (fun x => g (f x)) l.
Proof.
-induction l; simpl; auto.
-rewrite IHl; auto.
+ induction l; simpl; auto.
+ rewrite IHl; auto.
Qed.
Lemma map_ext :
- forall (A B : Set)(f g:A->B), (forall a, f a = g a) -> forall l, map f l = map g l.
-Proof.
-induction l; simpl; auto.
-rewrite H; rewrite IHl; auto.
-Qed.
-
-(********************************************)
-(** Operations on lists of pairs or lists of lists *)
-(********************************************)
-
-Section ListPairs.
-Variable A B : Set.
-
-(** [split] derives two lists from a list of pairs *)
-
-Fixpoint split (l:list (A*B)) { struct l }: list A * list B :=
- match l with
- | nil => (nil, nil)
- | (x,y) :: tl => let (g,d) := split tl in (x::g, y::d)
- end.
-
-Lemma in_split_l : forall (l:list (A*B))(p:A*B),
- In p l -> In (fst p) (fst (split l)).
-Proof.
-induction l; simpl; intros; auto.
-destruct p; destruct a; destruct (split l); simpl in *.
-destruct H.
-injection H; auto.
-right; apply (IHl (a0,b) H).
-Qed.
-
-Lemma in_split_r : forall (l:list (A*B))(p:A*B),
- In p l -> In (snd p) (snd (split l)).
-Proof.
-induction l; simpl; intros; auto.
-destruct p; destruct a; destruct (split l); simpl in *.
-destruct H.
-injection H; auto.
-right; apply (IHl (a0,b) H).
-Qed.
-
-Lemma split_nth : forall (l:list (A*B))(n:nat)(d:A*B),
- nth n l d = (nth n (fst (split l)) (fst d), nth n (snd (split l)) (snd d)).
-Proof.
-induction l.
-destruct n; destruct d; simpl; auto.
-destruct n; destruct d; simpl; auto.
-destruct a; destruct (split l); simpl; auto.
-destruct a; destruct (split l); simpl in *; auto.
-rewrite IHl; simpl; auto.
-Qed.
-
-Lemma split_lenght_l : forall (l:list (A*B)),
- length (fst (split l)) = length l.
-Proof.
-induction l; simpl; auto.
-destruct a; destruct (split l); simpl; auto.
-Qed.
-
-Lemma split_lenght_r : forall (l:list (A*B)),
- length (snd (split l)) = length l.
-Proof.
-induction l; simpl; auto.
-destruct a; destruct (split l); simpl; auto.
-Qed.
-
-(** [combine] is the opposite of [split].
- Lists given to [combine] are meant to be of same length.
- If not, [combine] stops on the shorter list *)
-
-Fixpoint combine (l : list A) (l' : list B){struct l} : list (A*B) :=
- match l,l' with
- | x::tl, y::tl' => (x,y)::(combine tl tl')
- | _, _ => nil
- end.
-
-Lemma split_combine : forall (l: list (A*B)),
- let (l1,l2) := split l in combine l1 l2 = l.
-Proof.
-induction l.
-simpl; auto.
-destruct a; simpl.
-destruct (split l); simpl in *.
-f_equal; auto.
-Qed.
-
-Lemma combine_split : forall (l:list A)(l':list B), length l = length l' ->
- split (combine l l') = (l,l').
-Proof.
-induction l; destruct l'; simpl; intros; auto; try discriminate.
-injection H; clear H; intros.
-rewrite IHl; auto.
-Qed.
-
-Lemma in_combine_l : forall (l:list A)(l':list B)(x:A)(y:B),
- In (x,y) (combine l l') -> In x l.
-Proof.
-induction l.
-simpl; auto.
-destruct l'; simpl; auto; intros.
-contradiction.
-destruct H.
-injection H; auto.
-right; apply IHl with l' y; auto.
-Qed.
-
-Lemma in_combine_r : forall (l:list A)(l':list B)(x:A)(y:B),
- In (x,y) (combine l l') -> In y l'.
-Proof.
-induction l.
-simpl; intros; contradiction.
-destruct l'; simpl; auto; intros.
-destruct H.
-injection H; auto.
-right; apply IHl with x; auto.
-Qed.
-
-Lemma combine_length : forall (l:list A)(l':list B),
- length (combine l l') = min (length l) (length l').
-Proof.
-induction l.
-simpl; auto.
-destruct l'; simpl; auto.
-Qed.
-
-Lemma combine_nth : forall (l:list A)(l':list B)(n:nat)(x:A)(y:B),
- length l = length l' ->
- nth n (combine l l') (x,y) = (nth n l x, nth n l' y).
+ forall (A B : Type)(f g:A->B), (forall a, f a = g a) -> forall l, map f l = map g l.
Proof.
-induction l; destruct l'; intros; try discriminate.
-destruct n; simpl; auto.
-destruct n; simpl in *; auto.
+ induction l; simpl; auto.
+ rewrite H; rewrite IHl; auto.
Qed.
-(** [flat_map] *)
-
-Fixpoint flat_map (f:A -> list B) (l:list A) {struct l} :
- list B :=
- match l with
- | nil => nil
- | cons x t => (f x)++(flat_map f t)
- end.
-
-Lemma in_flat_map : forall (f:A->list B)(l:list A)(y:B),
- In y (flat_map f l) <-> exists x, In x l /\ In y (f x).
-Proof.
-induction l; simpl; split; intros.
-contradiction.
-destruct H as (x,(H,_)); contradiction.
-destruct (in_app_or _ _ _ H).
-exists a; auto.
-destruct (IHl y) as (H1,_); destruct (H1 H0) as (x,(H2,H3)).
-exists x; auto.
-apply in_or_app.
-destruct H as (x,(H0,H1)); destruct H0.
-subst; auto.
-right; destruct (IHl y) as (_,H2); apply H2.
-exists x; auto.
-Qed.
-
-(** [list_prod] has the same signature as [combine], but unlike
- [combine], it adds every possible pairs, not only those at the
- same position. *)
-
-Fixpoint list_prod (l:list A) (l':list B) {struct l} :
- list (A * B) :=
- match l with
- | nil => nil
- | cons x t => (map (fun y:B => (x, y)) l')++(list_prod t l')
- end.
-
-Lemma in_prod_aux :
- forall (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 (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.
-
-Lemma in_prod_iff :
- forall (l:list A)(l':list B)(x:A)(y:B),
- In (x,y) (list_prod l l') <-> In x l /\ In y l'.
-Proof.
-split; [ | intros; apply in_prod; intuition ].
-induction l; simpl; intros.
-intuition.
-destruct (in_app_or _ _ _ H); clear H.
-destruct (in_map_iff (fun y : B => (a, y)) l' (x,y)) as (H1,_).
-destruct (H1 H0) as (z,(H2,H3)); clear H0 H1.
-injection H2; clear H2; intros; subst; intuition.
-intuition.
-Qed.
-
-Lemma prod_length : forall (l:list A)(l':list B),
- length (list_prod l l') = (length l) * (length l').
-Proof.
-induction l; simpl; auto.
-intros.
-rewrite app_length.
-rewrite map_length.
-auto.
-Qed.
-
-End ListPairs.
-
-(** [(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.
-
-Lemma fold_left_app : forall (l l':list B)(i:A),
- fold_left (l++l') i = fold_left l' (fold_left l i).
-Proof.
-induction l.
-simpl; auto.
-intros.
-simpl.
-auto.
-Qed.
+ Variables A B : Type.
+ 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.
+
+ Lemma fold_left_app : forall (l l':list B)(i:A),
+ fold_left (l++l') i = fold_left l' (fold_left l i).
+ Proof.
+ induction l.
+ simpl; auto.
+ intros.
+ simpl.
+ auto.
+ Qed.
End Fold_Left_Recursor.
Lemma fold_left_length :
- forall (A:Set)(l:list A), fold_left (fun x _ => S x) l 0 = length l.
+ forall (A:Type)(l:list A), fold_left (fun x _ => S x) l 0 = length l.
Proof.
-intro A.
-cut (forall (l:list A) n, fold_left (fun x _ => S x) l n = n + length l).
-intros.
-exact (H l 0).
-induction l; simpl; auto.
-intros; rewrite IHl.
-simpl; auto with arith.
+ intro A.
+ cut (forall (l:list A) n, fold_left (fun x _ => S x) l n = n + length l).
+ intros.
+ exact (H l 0).
+ induction l; simpl; auto.
+ intros; rewrite IHl.
+ simpl; auto with arith.
Qed.
(************************************)
@@ -1082,210 +1129,651 @@ Qed.
(************************************)
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.
+ Variables A B : Type.
+ 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.
-Lemma fold_right_app : forall (A B:Set)(f:A->B->B) l l' i,
- fold_right f i (l++l') = fold_right f (fold_right f i l') l.
-Proof.
-induction l.
-simpl; auto.
-simpl; intros.
-f_equal; auto.
-Qed.
-
-Lemma fold_left_rev_right : forall (A B:Set)(f:A->B->B) l i,
- fold_right f i (rev l) = fold_left (fun x y => f y x) l i.
-Proof.
-induction l.
-simpl; auto.
-intros.
-simpl.
-rewrite fold_right_app; simpl; auto.
-Qed.
-
-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.
-
-(********************************)
-(** Boolean operations over lists *)
-(********************************)
-
-Section Bool.
-Variable A : Set.
-Variable f : A -> bool.
-
-(** find whether a boolean function can be satisfied by an
- elements of the list. *)
-
-Fixpoint existsb (l:list A) {struct l}: bool :=
- match l with
- | nil => false
- | a::l => f a || existsb l
- end.
-
-Lemma existsb_exists :
- forall l, existsb l = true <-> exists x, In x l /\ f x = true.
-Proof.
-induction l; simpl; intuition.
-inversion H.
-firstorder.
-destruct (orb_prop _ _ H1); firstorder.
-firstorder.
-subst.
-rewrite H2; auto.
-Qed.
-
-Lemma existsb_nth : forall l n d, n < length l ->
- existsb l = false -> f (nth n l d) = false.
-Proof.
-induction l.
-inversion 1.
-simpl; intros.
-destruct (orb_false_elim _ _ H0); clear H0; auto.
-destruct n ; auto.
-rewrite IHl; auto with arith.
-Qed.
-
-(** find whether a boolean function is satisfied by
- all the elements of a list. *)
-
-Fixpoint forallb (l:list A) {struct l} : bool :=
- match l with
- | nil => true
- | a::l => f a && forallb l
- end.
-
-Lemma forallb_forall :
- forall l, forallb l = true <-> (forall x, In x l -> f x = true).
-Proof.
-induction l; simpl; intuition.
-destruct (andb_prop _ _ H1).
-congruence.
-destruct (andb_prop _ _ H1); auto.
-assert (forallb l = true).
-apply H0; intuition.
-rewrite H1; auto.
-Qed.
-
-(** [filter] *)
-
-Fixpoint filter (l:list A) : list A :=
- match l with
- | nil => nil
- | x :: l => if f x then x::(filter l) else filter l
- end.
+ Lemma fold_right_app : forall (A B:Type)(f:A->B->B) l l' i,
+ fold_right f i (l++l') = fold_right f (fold_right f i l') l.
+ Proof.
+ induction l.
+ simpl; auto.
+ simpl; intros.
+ f_equal; auto.
+ Qed.
+
+ Lemma fold_left_rev_right : forall (A B:Type)(f:A->B->B) l i,
+ fold_right f i (rev l) = fold_left (fun x y => f y x) l i.
+ Proof.
+ induction l.
+ simpl; auto.
+ intros.
+ simpl.
+ rewrite fold_right_app; simpl; auto.
+ Qed.
+
+ Theorem fold_symmetric :
+ forall (A:Type) (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.
+
+
+
+ (** [(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:Type)(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.
+
+
+ (*************************************)
+ (** ** Boolean operations over lists *)
+ (*************************************)
+
+ Section Bool.
+ Variable A : Type.
+ Variable f : A -> bool.
+
+ (** find whether a boolean function can be satisfied by an
+ elements of the list. *)
+
+ Fixpoint existsb (l:list A) {struct l}: bool :=
+ match l with
+ | nil => false
+ | a::l => f a || existsb l
+ end.
+
+ Lemma existsb_exists :
+ forall l, existsb l = true <-> exists x, In x l /\ f x = true.
+ Proof.
+ induction l; simpl; intuition.
+ inversion H.
+ firstorder.
+ destruct (orb_prop _ _ H1); firstorder.
+ firstorder.
+ subst.
+ rewrite H2; auto.
+ Qed.
+
+ Lemma existsb_nth : forall l n d, n < length l ->
+ existsb l = false -> f (nth n l d) = false.
+ Proof.
+ induction l.
+ inversion 1.
+ simpl; intros.
+ destruct (orb_false_elim _ _ H0); clear H0; auto.
+ destruct n ; auto.
+ rewrite IHl; auto with arith.
+ Qed.
+
+ (** find whether a boolean function is satisfied by
+ all the elements of a list. *)
+
+ Fixpoint forallb (l:list A) {struct l} : bool :=
+ match l with
+ | nil => true
+ | a::l => f a && forallb l
+ end.
+
+ Lemma forallb_forall :
+ forall l, forallb l = true <-> (forall x, In x l -> f x = true).
+ Proof.
+ induction l; simpl; intuition.
+ destruct (andb_prop _ _ H1).
+ congruence.
+ destruct (andb_prop _ _ H1); auto.
+ assert (forallb l = true).
+ apply H0; intuition.
+ rewrite H1; auto.
+ Qed.
+
+ (** [filter] *)
+
+ Fixpoint filter (l:list A) : list A :=
+ match l with
+ | nil => nil
+ | x :: l => if f x then x::(filter l) else filter l
+ end.
+
+ Lemma filter_In : forall x l, In x (filter l) <-> In x l /\ f x = true.
+ Proof.
+ induction l; simpl.
+ intuition.
+ intros.
+ case_eq (f a); intros; simpl; intuition congruence.
+ Qed.
+
+ (** [find] *)
+
+ Fixpoint find (l:list A) : option A :=
+ match l with
+ | nil => None
+ | x :: tl => if f x then Some x else find tl
+ end.
+
+ (** [partition] *)
+
+ Fixpoint partition (l:list A) {struct l} : list A * list A :=
+ match l with
+ | nil => (nil, nil)
+ | x :: tl => let (g,d) := partition tl in
+ if f x then (x::g,d) else (g,x::d)
+ end.
+
+ End Bool.
+
+
+
+
+ (******************************************************)
+ (** ** Operations on lists of pairs or lists of lists *)
+ (******************************************************)
+
+ Section ListPairs.
+ Variables A B : Type.
+
+ (** [split] derives two lists from a list of pairs *)
+
+ Fixpoint split (l:list (A*B)) { struct l }: list A * list B :=
+ match l with
+ | nil => (nil, nil)
+ | (x,y) :: tl => let (g,d) := split tl in (x::g, y::d)
+ end.
+
+ Lemma in_split_l : forall (l:list (A*B))(p:A*B),
+ In p l -> In (fst p) (fst (split l)).
+ Proof.
+ induction l; simpl; intros; auto.
+ destruct p; destruct a; destruct (split l); simpl in *.
+ destruct H.
+ injection H; auto.
+ right; apply (IHl (a0,b) H).
+ Qed.
+
+ Lemma in_split_r : forall (l:list (A*B))(p:A*B),
+ In p l -> In (snd p) (snd (split l)).
+ Proof.
+ induction l; simpl; intros; auto.
+ destruct p; destruct a; destruct (split l); simpl in *.
+ destruct H.
+ injection H; auto.
+ right; apply (IHl (a0,b) H).
+ Qed.
+
+ Lemma split_nth : forall (l:list (A*B))(n:nat)(d:A*B),
+ nth n l d = (nth n (fst (split l)) (fst d), nth n (snd (split l)) (snd d)).
+ Proof.
+ induction l.
+ destruct n; destruct d; simpl; auto.
+ destruct n; destruct d; simpl; auto.
+ destruct a; destruct (split l); simpl; auto.
+ destruct a; destruct (split l); simpl in *; auto.
+ rewrite IHl; simpl; auto.
+ Qed.
+
+ Lemma split_lenght_l : forall (l:list (A*B)),
+ length (fst (split l)) = length l.
+ Proof.
+ induction l; simpl; auto.
+ destruct a; destruct (split l); simpl; auto.
+ Qed.
+
+ Lemma split_lenght_r : forall (l:list (A*B)),
+ length (snd (split l)) = length l.
+ Proof.
+ induction l; simpl; auto.
+ destruct a; destruct (split l); simpl; auto.
+ Qed.
+
+ (** [combine] is the opposite of [split].
+ Lists given to [combine] are meant to be of same length.
+ If not, [combine] stops on the shorter list *)
+
+ Fixpoint combine (l : list A) (l' : list B){struct l} : list (A*B) :=
+ match l,l' with
+ | x::tl, y::tl' => (x,y)::(combine tl tl')
+ | _, _ => nil
+ end.
+
+ Lemma split_combine : forall (l: list (A*B)),
+ let (l1,l2) := split l in combine l1 l2 = l.
+ Proof.
+ induction l.
+ simpl; auto.
+ destruct a; simpl.
+ destruct (split l); simpl in *.
+ f_equal; auto.
+ Qed.
+
+ Lemma combine_split : forall (l:list A)(l':list B), length l = length l' ->
+ split (combine l l') = (l,l').
+ Proof.
+ induction l; destruct l'; simpl; intros; auto; try discriminate.
+ injection H; clear H; intros.
+ rewrite IHl; auto.
+ Qed.
+
+ Lemma in_combine_l : forall (l:list A)(l':list B)(x:A)(y:B),
+ In (x,y) (combine l l') -> In x l.
+ Proof.
+ induction l.
+ simpl; auto.
+ destruct l'; simpl; auto; intros.
+ contradiction.
+ destruct H.
+ injection H; auto.
+ right; apply IHl with l' y; auto.
+ Qed.
+
+ Lemma in_combine_r : forall (l:list A)(l':list B)(x:A)(y:B),
+ In (x,y) (combine l l') -> In y l'.
+ Proof.
+ induction l.
+ simpl; intros; contradiction.
+ destruct l'; simpl; auto; intros.
+ destruct H.
+ injection H; auto.
+ right; apply IHl with x; auto.
+ Qed.
+
+ Lemma combine_length : forall (l:list A)(l':list B),
+ length (combine l l') = min (length l) (length l').
+ Proof.
+ induction l.
+ simpl; auto.
+ destruct l'; simpl; auto.
+ Qed.
+
+ Lemma combine_nth : forall (l:list A)(l':list B)(n:nat)(x:A)(y:B),
+ length l = length l' ->
+ nth n (combine l l') (x,y) = (nth n l x, nth n l' y).
+ Proof.
+ induction l; destruct l'; intros; try discriminate.
+ destruct n; simpl; auto.
+ destruct n; simpl in *; auto.
+ Qed.
+
+ (** [list_prod] has the same signature as [combine], but unlike
+ [combine], it adds every possible pairs, not only those at the
+ same position. *)
+
+ Fixpoint list_prod (l:list A) (l':list B) {struct l} :
+ list (A * B) :=
+ match l with
+ | nil => nil
+ | cons x t => (map (fun y:B => (x, y)) l')++(list_prod t l')
+ end.
+
+ Lemma in_prod_aux :
+ forall (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 (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.
+
+ Lemma in_prod_iff :
+ forall (l:list A)(l':list B)(x:A)(y:B),
+ In (x,y) (list_prod l l') <-> In x l /\ In y l'.
+ Proof.
+ split; [ | intros; apply in_prod; intuition ].
+ induction l; simpl; intros.
+ intuition.
+ destruct (in_app_or _ _ _ H); clear H.
+ destruct (in_map_iff (fun y : B => (a, y)) l' (x,y)) as (H1,_).
+ destruct (H1 H0) as (z,(H2,H3)); clear H0 H1.
+ injection H2; clear H2; intros; subst; intuition.
+ intuition.
+ Qed.
+
+ Lemma prod_length : forall (l:list A)(l':list B),
+ length (list_prod l l') = (length l) * (length l').
+ Proof.
+ induction l; simpl; auto.
+ intros.
+ rewrite app_length.
+ rewrite map_length.
+ auto.
+ Qed.
+
+ End ListPairs.
+
+
+
+
+(***************************************)
+(** * Miscelenous operations on lists *)
+(***************************************)
-Lemma filter_In : forall x l, In x (filter l) <-> In x l /\ f x = true.
-Proof.
-induction l; simpl.
-intuition.
-intros.
-case_eq (f a); intros; simpl; intuition congruence.
-Qed.
-(** [find] *)
-Fixpoint find (l:list A) : option A :=
- match l with
- | nil => None
- | x :: tl => if f x then Some x else find tl
- end.
+(******************************)
+(** ** Length order of lists *)
+(******************************)
-(** [partition] *)
+Section length_order.
+ Variable A : Type.
+
+ Definition lel (l m:list A) := length l <= length m.
+
+ Variables a b : A.
+ Variables l m n : list A.
+
+ 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 A, 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.
-Fixpoint partition (l:list A) {struct l} : list A * list A :=
- match l with
- | nil => (nil, nil)
- | x :: tl => let (g,d) := partition tl in
- if f x then (x::g,d) else (g,x::d)
- end.
+Hint Resolve lel_refl lel_cons_cons lel_cons lel_nil lel_nil nil_cons:
+ datatypes v62.
-End Bool.
+(******************************)
+(** ** Set inclusion on list *)
+(******************************)
-(*********************************)
-(** Sequence of natural numbers *)
-(*********************************)
+Section SetIncl.
+
+ Variable A : Type.
+
+ Definition incl (l m:list A) := forall a:A, In a l -> In a m.
+ Hint Unfold incl.
+
+ Lemma incl_refl : forall l:list A, incl l l.
+ Proof.
+ auto.
+ Qed.
+ Hint Resolve incl_refl.
+
+ Lemma incl_tl : forall (a:A) (l m:list A), incl l m -> incl l (a :: m).
+ Proof.
+ auto with datatypes.
+ Qed.
+ Hint Immediate incl_tl.
+
+ Lemma incl_tran : forall l m n:list A, incl l m -> incl m n -> incl l n.
+ Proof.
+ auto.
+ Qed.
+
+ Lemma incl_appl : forall l m n:list A, incl l n -> incl l (n ++ m).
+ Proof.
+ auto with datatypes.
+ Qed.
+ Hint Immediate incl_appl.
+
+ Lemma incl_appr : forall l m n:list A, incl l n -> incl l (m ++ n).
+ Proof.
+ auto with datatypes.
+ Qed.
+ Hint Immediate incl_appr.
+
+ Lemma incl_cons :
+ forall (a:A) (l m:list A), 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. (* solves subgoal *)
+ now_show (In a0 l -> In a0 m).
+ auto.
+ Qed.
+ Hint Resolve incl_cons.
+
+ Lemma incl_app : forall l m n:list A, 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.
+
+End SetIncl.
-(** [seq] computes the sequence of [len] contiguous integers
- that starts at [start]. For instance, [seq 2 3] is [2::3::4::nil]. *)
+Hint Resolve incl_refl incl_tl incl_tran incl_appl incl_appr incl_cons
+ incl_app: datatypes v62.
-Fixpoint seq (start len:nat) {struct len} : list nat :=
- match len with
- | 0 => nil
- | S len => start :: seq (S start) len
- end.
-Lemma seq_length : forall len start, length (seq start len) = len.
-Proof.
-induction len; simpl; auto.
-Qed.
+(**************************************)
+(* ** Cutting a list at some position *)
+(**************************************)
+
+Section Cutting.
+
+ Variable A : Type.
+
+ Fixpoint firstn (n:nat)(l:list A) {struct n} : list A :=
+ match n with
+ | 0 => nil
+ | S n => match l with
+ | nil => nil
+ | a::l => a::(firstn n l)
+ end
+ end.
+
+ Fixpoint skipn (n:nat)(l:list A) { struct n } : list A :=
+ match n with
+ | 0 => l
+ | S n => match l with
+ | nil => nil
+ | a::l => skipn n l
+ end
+ end.
+
+ Lemma firstn_skipn : forall n l, firstn n l ++ skipn n l = l.
+ Proof.
+ induction n.
+ simpl; auto.
+ destruct l; simpl; auto.
+ f_equal; auto.
+ Qed.
+
+End Cutting.
-Lemma seq_nth : forall len start n d,
- n < len -> nth n (seq start len) d = start+n.
-Proof.
-induction len; intros.
-inversion H.
-simpl seq.
-destruct n; simpl.
-auto with arith.
-rewrite IHlen;simpl; auto with arith.
-Qed.
-Lemma seq_shift : forall len start,
- map S (seq start len) = seq (S start) len.
-Proof.
-induction len; simpl; auto.
-intros.
-rewrite IHlen.
-auto with arith.
-Qed.
+(********************************)
+(** ** Lists without redundancy *)
+(********************************)
-End Functions_on_lists.
+Section ReDun.
+
+ Variable A : Type.
+
+ Inductive NoDup : list A -> Prop :=
+ | NoDup_nil : NoDup nil
+ | NoDup_cons : forall x l, ~ In x l -> NoDup l -> NoDup (x::l).
+
+ Lemma NoDup_remove_1 : forall l l' a, NoDup (l++a::l') -> NoDup (l++l').
+ Proof.
+ induction l; simpl.
+ inversion_clear 1; auto.
+ inversion_clear 1.
+ constructor.
+ swap H0.
+ apply in_or_app; destruct (in_app_or _ _ _ H); simpl; tauto.
+ apply IHl with a0; auto.
+ Qed.
+
+ Lemma NoDup_remove_2 : forall l l' a, NoDup (l++a::l') -> ~In a (l++l').
+ Proof.
+ induction l; simpl.
+ inversion_clear 1; auto.
+ inversion_clear 1.
+ swap H0.
+ destruct H.
+ subst a0.
+ apply in_or_app; right; red; auto.
+ destruct (IHl _ _ H1); auto.
+ Qed.
+
+ Lemma NoDup_Permutation : forall l l',
+ NoDup l -> NoDup l' -> (forall x, In x l <-> In x l') -> Permutation l l'.
+ Proof.
+ induction l.
+ destruct l'; simpl; intros.
+ apply perm_nil.
+ destruct (H1 a) as (_,H2); destruct H2; auto.
+ intros.
+ destruct (In_split a l') as (l'1,(l'2,H2)).
+ destruct (H1 a) as (H2,H3); simpl in *; auto.
+ subst l'.
+ apply Permutation_cons_app.
+ inversion_clear H.
+ apply IHl; auto.
+ apply NoDup_remove_1 with a; auto.
+ intro x; split; intros.
+ assert (In x (l'1++a::l'2)).
+ destruct (H1 x); simpl in *; auto.
+ apply in_or_app; destruct (in_app_or _ _ _ H4); auto.
+ destruct H5; auto.
+ subst x; destruct H2; auto.
+ assert (In x (l'1++a::l'2)).
+ apply in_or_app; destruct (in_app_or _ _ _ H); simpl; auto.
+ destruct (H1 x) as (_,H5); destruct H5; auto.
+ subst x.
+ destruct (NoDup_remove_2 _ _ _ H0 H).
+ Qed.
+
+End ReDun.
+
+
+(***********************************)
+(** ** Sequence of natural numbers *)
+(***********************************)
+
+Section NatSeq.
+
+ (** [seq] computes the sequence of [len] contiguous integers
+ that starts at [start]. For instance, [seq 2 3] is [2::3::4::nil]. *)
+
+ Fixpoint seq (start len:nat) {struct len} : list nat :=
+ match len with
+ | 0 => nil
+ | S len => start :: seq (S start) len
+ end.
+
+ Lemma seq_length : forall len start, length (seq start len) = len.
+ Proof.
+ induction len; simpl; auto.
+ Qed.
+
+ Lemma seq_nth : forall len start n d,
+ n < len -> nth n (seq start len) d = start+n.
+ Proof.
+ induction len; intros.
+ inversion H.
+ simpl seq.
+ destruct n; simpl.
+ auto with arith.
+ rewrite IHlen;simpl; auto with arith.
+ Qed.
+
+ Lemma seq_shift : forall len start,
+ map S (seq start len) = seq (S start) len.
+ Proof.
+ induction len; simpl; auto.
+ intros.
+ rewrite IHlen.
+ auto with arith.
+ Qed.
+
+End NatSeq.
+
+
+
+ (** * Exporting hints and tactics *)
Hint Rewrite
- rev_involutive (* rev (rev l) = l *)
- rev_unit (* rev (l ++ a :: nil) = a :: rev l *)
- map_nth (* nth n (map f l) (f d) = f (nth n l d) *)
- map_length (* length (map f l) = length l *)
- seq_length (* length (seq start len) = len *)
- app_length (* length (l ++ l') = length l + length l' *)
- rev_length (* length (rev l) = length l *)
- : list.
+ rev_involutive (* rev (rev l) = l *)
+ rev_unit (* rev (l ++ a :: nil) = a :: rev l *)
+ map_nth (* nth n (map f l) (f d) = f (nth n l d) *)
+ map_length (* length (map f l) = length l *)
+ seq_length (* length (seq start len) = len *)
+ app_length (* length (l ++ l') = length l + length l' *)
+ rev_length (* length (rev l) = length l *)
+ : list.
Hint Rewrite <-
- app_nil_end (* l = l ++ nil *)
- : list.
+ app_nil_end (* l = l ++ nil *)
+ : list.
Ltac simpl_list := autorewrite with list.
Ltac ssimpl_list := autorewrite with list using simpl.