Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* <O___,, * (see CREDITS file for the list of authors) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************) Require Setoid. Require Import PeanoNat Le Gt Minus Bool Lt. Set Implicit Arguments. (* Set Universe Polymorphism. *) (******************************************************************)
(******************************************************************)
The definition of list is now in Init/Datatypes,
as well as the definitions of length and app
Open Scope list_scope.
Standard notations for lists.
In a special module to avoid conflicts.
Module ListNotations. Notation "[ ]" := nil (format "[ ]") : list_scope. Notation "[ x ]" := (cons x nil) : list_scope. Notation "[ x ; y ; .. ; z ]" := (cons x (cons y .. (cons z nil) ..)) : list_scope. End ListNotations. Import ListNotations. Section Lists. Variable A : Type.
Head and tail
Definition hd (default:A) (l:list A) := match l with | [] => default | x :: _ => x end. Definition hd_error (l:list A) := match l with | [] => None | x :: _ => Some x end. Definition tl (l:list A) := match l with | [] => nil | a :: m => m end.
The In predicate
Fixpoint In (a:A) (l:list A) : Prop := match l with | [] => False | b :: m => b = a \/ In a m end. End Lists. Section Facts. Variable A : Type.
Discrimination
A:Typeforall (x : A) (l : list A), [] <> x :: lintros; discriminate. Qed.A:Typeforall (x : A) (l : list A), [] <> x :: l
Destruction
A:Typeforall l : list A, {x : A & {tl0 : list A | l = x :: tl0}} + {l = []}A:Typeforall l : list A, {x : A & {tl0 : list A | l = x :: tl0}} + {l = []}A:Type{x : A & {tl0 : list A | [] = x :: tl0}} + {[] = []}A:Typea:Atail:list AIHtail:{x : A & {tl0 : list A | tail = x :: tl0}} + {tail = []}{x : A & {tl0 : list A | a :: tail = x :: tl0}} + {a :: tail = []}left; exists a, tail; reflexivity. Qed.A:Typea:Atail:list AIHtail:{x : A & {tl0 : list A | tail = x :: tl0}} + {tail = []}{x : A & {tl0 : list A | a :: tail = x :: tl0}} + {a :: tail = []}A:Typeforall (l : list A) (a : A) (r : list A), hd_error l = Some a /\ tl l = r <-> l = a :: rA:Typeforall (l : list A) (a : A) (r : list A), hd_error l = Some a /\ tl l = r <-> l = a :: rA:Typeforall (a : A) (r : list A), hd_error [] = Some a /\ tl [] = r <-> [] = a :: rA:Typex:Axs:list Aforall (a : A) (r : list A), hd_error (x :: xs) = Some a /\ tl (x :: xs) = r <-> x :: xs = a :: rA:Typeforall (a : A) (r : list A), hd_error [] = Some a /\ tl [] = r <-> [] = a :: rsplit; firstorder discriminate.A:Typea:Ar:list ANone = Some a /\ [] = r <-> [] = a :: rA:Typex:Axs:list Aforall (a : A) (r : list A), hd_error (x :: xs) = Some a /\ tl (x :: xs) = r <-> x :: xs = a :: rA:Typex:Axs:list Aa:Ar:list Ahd_error (x :: xs) = Some a /\ tl (x :: xs) = r <-> x :: xs = a :: rA:Typex:Axs:list Aa:Ar:list ASome x = Some a /\ xs = r <-> x :: xs = a :: rA:Typex:Axs:list Aa:Ar:list ASome x = Some a /\ xs = r -> x :: xs = a :: rA:Typex:Axs:list Aa:Ar:list Ax :: xs = a :: r -> Some x = Some a /\ xs = rA:Typex:Axs:list Aa:Ar:list ASome x = Some a /\ xs = r -> x :: xs = a :: rA:Typex:Axs:list Aa:Ar:list AH1:Some x = Some aH2:xs = rx :: xs = a :: rA:Typex:Axs:list Aa:Ar:list AH1:Some x = Some aH2:xs = rH0:x = aa :: xs = a :: rreflexivity.A:Typex:Axs:list Aa:Ar:list AH1:Some x = Some aH2:xs = rH0:x = aa :: r = a :: rA:Typex:Axs:list Aa:Ar:list Ax :: xs = a :: r -> Some x = Some a /\ xs = rA:Typex:Axs:list Aa:Ar:list AH:x :: xs = a :: rH1:x = aH2:xs = rSome a = Some a /\ r = rauto. Qed.A:Typea:Ar:list AH:a :: r = a :: rSome a = Some a /\ r = rA:Typeforall (l : list A) (a : A), hd_error l = Some a -> l <> []A:Typeforall (l : list A) (a : A), hd_error l = Some a -> l <> []destruct l; now discriminate. Qed.A:Typeforall (l : list A) (a : A), match l with | [] => None | x :: _ => Some x end = Some a -> l <> []A:Typel:list Alength l = 0 <-> l = []split; [now destruct l | now intros ->]. Qed.A:Typel:list Alength l = 0 <-> l = []
A:Typehd_error [] = Nonesimpl; reflexivity. Qed.A:Typehd_error [] = NoneA:Typeforall (l : list A) (x : A), hd_error (x :: l) = Some xintros; simpl; reflexivity. Qed. (************************)A:Typeforall (l : list A) (x : A), hd_error (x :: l) = Some x
(************************)
Characterization of In
A:Typeforall (a : A) (l : list A), In a (a :: l)simpl; auto. Qed.A:Typeforall (a : A) (l : list A), In a (a :: l)A:Typeforall (a b : A) (l : list A), In b l -> In b (a :: l)simpl; auto. Qed.A:Typeforall (a b : A) (l : list A), In b l -> In b (a :: l)A:Typex, a:Al:list A~ In x (a :: l) <-> x <> a /\ ~ In x lA:Typex, a:Al:list A~ In x (a :: l) <-> x <> a /\ ~ In x lintuition. Qed.A:Typex, a:Al:list A~ (a = x \/ In x l) <-> x <> a /\ ~ In x lA:Typeforall a : A, ~ In a []unfold not; intros a H; inversion_clear H. Qed.A:Typeforall a : A, ~ In a []A:Typeforall (x : A) (l : list A), In x l -> exists l1 l2 : list A, l = l1 ++ x :: l2A:Typeforall (x : A) (l : list A), In x l -> exists l1 l2 : list A, l = l1 ++ x :: l2A:Typex, a:Al:list AIHl:In x l -> exists l1 l2 : list A, l = l1 ++ x :: l2H:a = xexists l1 l2 : list A, a :: l = l1 ++ x :: l2A:Typex, a:Al:list AIHl:In x l -> exists l1 l2 : list A, l = l1 ++ x :: l2H:In x lexists l1 l2 : list A, a :: l = l1 ++ x :: l2A:Typex:Al:list AIHl:In x l -> exists l1 l2 : list A, l = l1 ++ x :: l2exists l1 l2 : list A, x :: l = l1 ++ x :: l2A:Typex, a:Al:list AIHl:In x l -> exists l1 l2 : list A, l = l1 ++ x :: l2H:In x lexists l1 l2 : list A, a :: l = l1 ++ x :: l2A:Typex, a:Al:list AIHl:In x l -> exists l1 l2 : list A, l = l1 ++ x :: l2H:In x lexists l1 l2 : list A, a :: l = l1 ++ x :: l2A:Typex, a:Al:list AIHl:In x l -> exists l0 l3 : list A, l = l0 ++ x :: l3H:In x ll1, l2:list AH0:l = l1 ++ x :: l2exists l0 l3 : list A, a :: l = l0 ++ x :: l3A:Typex, a:Al:list AIHl:In x l -> exists l0 l3 : list A, l = l0 ++ x :: l3H:In x ll1, l2:list AH0:l = l1 ++ x :: l2a :: l = a :: l1 ++ x :: l2auto. Qed.A:Typex, a:Al:list AIHl:In x l -> exists l0 l3 : list A, l = l0 ++ x :: l3H:In x ll1, l2:list AH0:l = l1 ++ x :: l2l = l1 ++ x :: l2
Inversion
A:Typeforall (a b : A) (l : list A), In b (a :: l) -> a = b \/ In b lintros a b l H; inversion_clear H; auto. Qed.A:Typeforall (a b : A) (l : list A), In b (a :: l) -> a = b \/ In b l
Decidability of In
A:Type(forall x y : A, {x = y} + {x <> y}) -> forall (a : A) (l : list A), {In a l} + {~ In a l}A:Type(forall x y : A, {x = y} + {x <> y}) -> forall (a : A) (l : list A), {In a l} + {~ In a l}A:TypeH:forall x y : A, {x = y} + {x <> y}a:A{In a []} + {~ In a []}A:TypeH:forall x y : A, {x = y} + {x <> y}a, a0:Al:list AIHl:{In a l} + {~ In a l}{In a (a0 :: l)} + {~ In a (a0 :: l)}A:TypeH:forall x y : A, {x = y} + {x <> y}a, a0:Al:list AIHl:{In a l} + {~ In a l}{In a (a0 :: l)} + {~ In a (a0 :: l)}A:TypeH:forall x y : A, {x = y} + {x <> y}a, a0:Al:list AIHl:{In a l} + {~ In a l}n:a0 <> a{a0 = a \/ In a l} + {~ (a0 = a \/ In a l)}right; unfold not; intros [Hc1| Hc2]; auto. Defined. (**************************)A:TypeH:forall x y : A, {x = y} + {x <> y}a, a0:Al:list An0:~ In a ln:a0 <> a{a0 = a \/ In a l} + {~ (a0 = a \/ In a l)}
(**************************)
Discrimination
A:Typeforall (x y : list A) (a : A), [] <> x ++ a :: yA:Typeforall (x y : list A) (a : A), [] <> x ++ a :: yA:Typeforall (x y : list A) (a : A), [] = x ++ a :: y -> FalseA:Typey:list Aa:AH:[] = a :: yFalseA:Typea:Al, y:list Aa0:AH:[] = a :: l ++ a0 :: yFalsediscriminate H. Qed.A:Typea:Al, y:list Aa0:AH:[] = a :: l ++ a0 :: yFalse
Concat with nil
A:Typeforall l : list A, [] ++ l = lreflexivity. Qed.A:Typeforall l : list A, [] ++ l = lA:Typeforall l : list A, l ++ [] = linduction l; simpl; f_equal; auto. Qed. (* begin hide *) (* Deprecated *)A:Typeforall l : list A, l ++ [] = lA:Typeforall l : list A, l = l ++ []symmetry; apply app_nil_r. Qed. (* end hide *)A:Typeforall l : list A, l = l ++ []
app is associative
A:Typeforall l m n : list A, l ++ m ++ n = (l ++ m) ++ nintros l m n; induction l; simpl; f_equal; auto. Qed. (* begin hide *) (* Deprecated *)A:Typeforall l m n : list A, l ++ m ++ n = (l ++ m) ++ nA:Typeforall l m n : list A, (l ++ m) ++ n = l ++ m ++ nauto using app_assoc. Qed. Hint Resolve app_assoc_reverse : core. (* end hide *)A:Typeforall l m n : list A, (l ++ m) ++ n = l ++ m ++ n
app commutes with cons
A:Typeforall (x y : list A) (a : A), a :: x ++ y = (a :: x) ++ yauto. Qed.A:Typeforall (x y : list A) (a : A), a :: x ++ y = (a :: x) ++ y
Facts deduced from the result of a concatenation
A:Typeforall l l' : list A, l ++ l' = [] -> l = [] /\ l' = []A:Typeforall l l' : list A, l ++ l' = [] -> l = [] /\ l' = []A:Typex:Al:list Ax :: l ++ [] = [] -> x :: l = [] /\ [] = []A:Typex:Al:list Ay:Al':list Ax :: l ++ y :: l' = [] -> x :: l = [] /\ y :: l' = []intros H; discriminate H. Qed.A:Typex:Al:list Ay:Al':list Ax :: l ++ y :: l' = [] -> x :: l = [] /\ y :: l' = []A:Typeforall (x y : list A) (a : A), x ++ y = [a] -> x = [] /\ y = [a] \/ x = [a] /\ y = []A:Typeforall (x y : list A) (a : A), x ++ y = [a] -> x = [] /\ y = [a] \/ x = [a] /\ y = []A:Typeforall a : A, [] = [a] -> [] = [] /\ [] = [a] \/ [] = [a] /\ [] = []A:Typea:Al:list Aforall a0 : A, a :: l = [a0] -> [] = [] /\ a :: l = [a0] \/ [] = [a0] /\ a :: l = []A:Typea:Al:list Aforall a0 : A, a :: l ++ [] = [a0] -> a :: l = [] /\ [] = [a0] \/ a :: l = [a0] /\ [] = []A:Typea:Al:list Aa0:Al0:list Aforall a1 : A, a :: l ++ a0 :: l0 = [a1] -> a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []A:Typea:Al:list Aforall a0 : A, a :: l = [a0] -> [] = [] /\ a :: l = [a0] \/ [] = [a0] /\ a :: l = []A:Typea:Al:list Aforall a0 : A, a :: l ++ [] = [a0] -> a :: l = [] /\ [] = [a0] \/ a :: l = [a0] /\ [] = []A:Typea:Al:list Aa0:Al0:list Aforall a1 : A, a :: l ++ a0 :: l0 = [a1] -> a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []A:Typea:Al:list Aforall a0 : A, a :: l ++ [] = [a0] -> a :: l = [] /\ [] = [a0] \/ a :: l = [a0] /\ [] = []A:Typea:Al:list Aa0:Al0:list Aforall a1 : A, a :: l ++ a0 :: l0 = [a1] -> a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []A:Typea:Al:list Aa0:AH:a :: l ++ [] = [a0]a :: l = [a0]A:Typea:Al:list Aa0:Al0:list Aforall a1 : A, a :: l ++ a0 :: l0 = [a1] -> a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []A:Typea:Al:list Aa0:AH:a :: l ++ [] = [a0]a :: l ++ [] = [a0] -> a :: l = [a0]A:Typea:Al:list Aa0:Al0:list Aforall a1 : A, a :: l ++ a0 :: l0 = [a1] -> a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []A:Typea:Al:list Aa0:AH:a :: l ++ [] = [a0]E:l ++ [] = la :: l ++ [] = [a0] -> a :: l = [a0]A:Typea:Al:list Aa0:Al0:list Aforall a1 : A, a :: l ++ a0 :: l0 = [a1] -> a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []A:Typea:Al:list Aa0:Al0:list Aforall a1 : A, a :: l ++ a0 :: l0 = [a1] -> a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []A:Typea:Al:list Aa0:Al0:list Aa1:AH:a :: l ++ a0 :: l0 = [a1]a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []A:Typea:Al:list Aa0:Al0:list Aa1:AH:a = a1H0:l ++ a0 :: l0 = []a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []apply app_cons_not_nil in H1 as []. Qed.A:Typea:Al:list Aa0:Al0:list Aa1:AH:a = a1H0:l ++ a0 :: l0 = []H1:[] = l ++ a0 :: l0a :: l = [] /\ a0 :: l0 = [a1] \/ a :: l = [a1] /\ a0 :: l0 = []A:Typeforall (x y : list A) (a b : A), x ++ [a] = y ++ [b] -> x = y /\ a = bA:Typeforall (x y : list A) (a b : A), x ++ [a] = y ++ [b] -> x = y /\ a = bA:Typeforall a b : A, [a] = [b] -> [] = [] /\ a = bA:Typea:Al:list Aforall a0 b : A, [a0] = a :: l ++ [b] -> [] = a :: l /\ a0 = bA:Typex:Al:list AIHl:forall (y : list A) (a b : A), l ++ [a] = y ++ [b] -> l = y /\ a = bforall a b : A, x :: l ++ [a] = [b] -> x :: l = [] /\ a = bA:Typex:Al:list AIHl:forall (y : list A) (a0 b : A), l ++ [a0] = y ++ [b] -> l = y /\ a0 = ba:Al0:list Aforall a0 b : A, x :: l ++ [a0] = a :: l0 ++ [b] -> x :: l = a :: l0 /\ a0 = bA:Typeforall a b : A, [a] = [b] -> [] = [] /\ a = bA:Typea, b:AH:[a] = [b][] = [] /\ a = bauto.A:Typea, b:AH:[a] = [b]a = b -> [] = [] /\ a = bA:Typea:Al:list Aforall a0 b : A, [a0] = a :: l ++ [b] -> [] = a :: l /\ a0 = bA:Typea:Al:list Aa0, b:AH:[a0] = a :: l ++ [b][] = a :: l /\ a0 = bapply app_cons_not_nil in H0 as [].A:Typea:Al:list Aa0, b:AH1:a0 = aH0:[] = l ++ [b][] = a :: l /\ a0 = bA:Typex:Al:list AIHl:forall (y : list A) (a b : A), l ++ [a] = y ++ [b] -> l = y /\ a = bforall a b : A, x :: l ++ [a] = [b] -> x :: l = [] /\ a = bA:Typex:Al:list AIHl:forall (y : list A) (a0 b0 : A), l ++ [a0] = y ++ [b0] -> l = y /\ a0 = b0a, b:AH:x :: l ++ [a] = [b]x :: l = [] /\ a = bA:Typex:Al:list AIHl:forall (y : list A) (a0 b0 : A), l ++ [a0] = y ++ [b0] -> l = y /\ a0 = b0a, b:AH1:x = bH0:l ++ [a] = []x :: l = [] /\ a = bapply app_cons_not_nil in H as [].A:Typex:Al:list AIHl:forall (y : list A) (a0 b0 : A), l ++ [a0] = y ++ [b0] -> l = y /\ a0 = b0a, b:AH1:x = bH0:l ++ [a] = []H:[] = l ++ [a]x :: l = [] /\ a = bA:Typex:Al:list AIHl:forall (y : list A) (a0 b : A), l ++ [a0] = y ++ [b] -> l = y /\ a0 = ba:Al0:list Aforall a0 b : A, x :: l ++ [a0] = a :: l0 ++ [b] -> x :: l = a :: l0 /\ a0 = bA:Typex:Al:list AIHl:forall (y : list A) (a1 b0 : A), l ++ [a1] = y ++ [b0] -> l = y /\ a1 = b0a:Al0:list Aa0, b:AH:x :: l ++ [a0] = a :: l0 ++ [b]x :: l = a :: l0 /\ a0 = bA:Typex:Al:list AIHl:forall (y : list A) (a b0 : A), l ++ [a] = y ++ [b0] -> l = y /\ a = b0l0:list Aa0, b:AH0:l ++ [a0] = l0 ++ [b]x :: l = x :: l0 /\ a0 = bsplit; auto. Qed.A:Typex:Al:list AIHl:forall (y : list A) (a b : A), l ++ [a] = y ++ [b] -> l = y /\ a = ba0:AH0:l ++ [a0] = l ++ [a0]x :: l = x :: l /\ a0 = a0
Compatibility with other operations
A:Typeforall l l' : list A, length (l ++ l') = length l + length l'induction l; simpl; auto. Qed.A:Typeforall l l' : list A, length (l ++ l') = length l + length l'A:Typeforall (l m : list A) (a : A), In a (l ++ m) -> In a l \/ In a mA:Typeforall (l m : list A) (a : A), In a (l ++ m) -> In a l \/ In a mA:Typel, m:list Aa:AIn a (l ++ m) -> In a l \/ In a mA:Typel, m:list Aa:Aforall (a0 : A) (l0 : list A), (In a (l0 ++ m) -> In a l0 \/ In a m) -> a0 = a \/ In a (l0 ++ m) -> (a0 = a \/ In a l0) \/ In a mA:Typel, m:list Aa, a0:Ay:list AH:In a (y ++ m) -> In a y \/ In a mH0:a0 = a \/ In a (y ++ m)(a0 = a \/ In a y) \/ In a mA:Typel, m:list Aa, a0:Ay:list AH:In a (y ++ m) -> In a y \/ In a mH0:a0 = a \/ In a (y ++ m)(a0 = a \/ In a y) \/ In a mA:Typel, m:list Aa, a0:Ay:list AH:In a (y ++ m) -> In a y \/ In a mH0:a0 = a \/ In a (y ++ m)In a (y ++ m) -> (a0 = a \/ In a y) \/ In a mA:Typel, m:list Aa, a0:Ay:list AH:In a (y ++ m) -> In a y \/ In a mH0:a0 = a \/ In a (y ++ m)H1:In a (y ++ m)(a0 = a \/ In a y) \/ In a melim (H H1); auto. Qed.A:Typel, m:list Aa, a0:Ay:list AH:In a (y ++ m) -> In a y \/ In a mH0:a0 = a \/ In a (y ++ m)H1:In a (y ++ m)(a0 = a \/ In a y) \/ In a mA:Typeforall (l m : list A) (a : A), In a l \/ In a m -> In a (l ++ m)A:Typeforall (l m : list A) (a : A), In a l \/ In a m -> In a (l ++ m)A:Typel, m:list Aa:AIn a l \/ In a m -> In a (l ++ m)A:Typel, m:list Aa:AH:False \/ In a mIn a mA:Typel, m:list Aa, H:Aforall l0 : list A, (In a l0 \/ In a m -> In a (l0 ++ m)) -> (H = a \/ In a l0) \/ In a m -> H = a \/ In a (l0 ++ m)A:Typel, m:list Aa:AH:False \/ In a mIn a mA:Typel, m:list Aa, H:Aforall l0 : list A, (In a l0 \/ In a m -> In a (l0 ++ m)) -> (H = a \/ In a l0) \/ In a m -> H = a \/ In a (l0 ++ m)A:Typel, m:list Aa:AH:False \/ In a mH0:FalseIn a mA:Typel, m:list Aa, H:Aforall l0 : list A, (In a l0 \/ In a m -> In a (l0 ++ m)) -> (H = a \/ In a l0) \/ In a m -> H = a \/ In a (l0 ++ m)A:Typel, m:list Aa:AH:False \/ In a mH0:FalseIn a mA:Typel, m:list Aa, H:Aforall l0 : list A, (In a l0 \/ In a m -> In a (l0 ++ m)) -> (H = a \/ In a l0) \/ In a m -> H = a \/ In a (l0 ++ m)A:Typel, m:list Aa, H:Aforall l0 : list A, (In a l0 \/ In a m -> In a (l0 ++ m)) -> (H = a \/ In a l0) \/ In a m -> H = a \/ In a (l0 ++ m)A:Typel, m:list Aa, H:Ay:list AH0:In a y \/ In a m -> In a (y ++ m)H1:(H = a \/ In a y) \/ In a mH = a \/ In a (y ++ m)A:Typel, m:list Aa, H:Ay:list AH0:In a y \/ In a m -> In a (y ++ m)H1:(H = a \/ In a y) \/ In a mH = a \/ In a (y ++ m)A:Typel, m:list Aa, H:Ay:list AH0:In a y \/ In a m -> In a (y ++ m)H1:(H = a \/ In a y) \/ In a mH = a \/ In a y -> H = a \/ In a (y ++ m)A:Typel, m:list Aa, H:Ay:list AH0:In a y \/ In a m -> In a (y ++ m)H1:(H = a \/ In a y) \/ In a mH2:H = a \/ In a yH = a \/ In a (y ++ m)elim H2; auto. Qed.A:Typel, m:list Aa, H:Ay:list AH0:In a y \/ In a m -> In a (y ++ m)H1:(H = a \/ In a y) \/ In a mH2:H = a \/ In a yH = a \/ In a (y ++ m)A:Typeforall (l l' : list A) (a : A), In a (l ++ l') <-> In a l \/ In a l'split; auto using in_app_or, in_or_app. Qed.A:Typeforall (l l' : list A) (a : A), In a (l ++ l') <-> In a l \/ In a l'A:Typeforall l l1 l2 : list A, l ++ l1 = l ++ l2 -> l1 = l2induction l; simpl; auto; injection 1; auto. Qed.A:Typeforall l l1 l2 : list A, l ++ l1 = l ++ l2 -> l1 = l2A:Typeforall l l1 l2 : list A, l1 ++ l = l2 ++ l -> l1 = l2A:Typeforall l l1 l2 : list A, l1 ++ l = l2 ++ l -> l1 = l2A:Typeforall l1 l2 l : list A, l1 ++ l = l2 ++ l -> l1 = l2A:Typex2:Al2, l:list AH:l = x2 :: l2 ++ l[] = x2 :: l2A:Typex1:Al1:list AIHl1:forall l2 l0 : list A, l1 ++ l0 = l2 ++ l0 -> l1 = l2l:list AH:x1 :: l1 ++ l = lx1 :: l1 = []A:Typex1:Al1:list AIHl1:forall l0 l3 : list A, l1 ++ l3 = l0 ++ l3 -> l1 = l0x2:Al2, l:list AH:x1 :: l1 ++ l = x2 :: l2 ++ lx1 :: l1 = x2 :: l2A:Typex2:Al2, l:list AH:l = x2 :: l2 ++ l~ length (x2 :: l2 ++ l) <= length lA:Typex2:Al2, l:list AH:l = x2 :: l2 ++ llength (x2 :: l2 ++ l) <= length lA:Typex1:Al1:list AIHl1:forall l2 l0 : list A, l1 ++ l0 = l2 ++ l0 -> l1 = l2l:list AH:x1 :: l1 ++ l = lx1 :: l1 = []A:Typex1:Al1:list AIHl1:forall l0 l3 : list A, l1 ++ l3 = l0 ++ l3 -> l1 = l0x2:Al2, l:list AH:x1 :: l1 ++ l = x2 :: l2 ++ lx1 :: l1 = x2 :: l2A:Typex2:Al2, l:list AH:l = x2 :: l2 ++ llength (x2 :: l2 ++ l) <= length lA:Typex1:Al1:list AIHl1:forall l2 l0 : list A, l1 ++ l0 = l2 ++ l0 -> l1 = l2l:list AH:x1 :: l1 ++ l = lx1 :: l1 = []A:Typex1:Al1:list AIHl1:forall l0 l3 : list A, l1 ++ l3 = l0 ++ l3 -> l1 = l0x2:Al2, l:list AH:x1 :: l1 ++ l = x2 :: l2 ++ lx1 :: l1 = x2 :: l2A:Typex1:Al1:list AIHl1:forall l2 l0 : list A, l1 ++ l0 = l2 ++ l0 -> l1 = l2l:list AH:x1 :: l1 ++ l = lx1 :: l1 = []A:Typex1:Al1:list AIHl1:forall l0 l3 : list A, l1 ++ l3 = l0 ++ l3 -> l1 = l0x2:Al2, l:list AH:x1 :: l1 ++ l = x2 :: l2 ++ lx1 :: l1 = x2 :: l2A:Typex1:Al1:list AIHl1:forall l2 l0 : list A, l1 ++ l0 = l2 ++ l0 -> l1 = l2l:list AH:x1 :: l1 ++ l = l~ length (x1 :: l1 ++ l) <= length lA:Typex1:Al1:list AIHl1:forall l2 l0 : list A, l1 ++ l0 = l2 ++ l0 -> l1 = l2l:list AH:x1 :: l1 ++ l = llength (x1 :: l1 ++ l) <= length lA:Typex1:Al1:list AIHl1:forall l0 l3 : list A, l1 ++ l3 = l0 ++ l3 -> l1 = l0x2:Al2, l:list AH:x1 :: l1 ++ l = x2 :: l2 ++ lx1 :: l1 = x2 :: l2A:Typex1:Al1:list AIHl1:forall l2 l0 : list A, l1 ++ l0 = l2 ++ l0 -> l1 = l2l:list AH:x1 :: l1 ++ l = llength (x1 :: l1 ++ l) <= length lA:Typex1:Al1:list AIHl1:forall l0 l3 : list A, l1 ++ l3 = l0 ++ l3 -> l1 = l0x2:Al2, l:list AH:x1 :: l1 ++ l = x2 :: l2 ++ lx1 :: l1 = x2 :: l2injection H as H H0; f_equal; eauto. Qed. End Facts. Hint Resolve app_assoc app_assoc_reverse: datatypes. Hint Resolve app_comm_cons app_cons_not_nil: datatypes. Hint Immediate app_eq_nil: datatypes. Hint Resolve app_eq_unit app_inj_tail: datatypes. Hint Resolve in_eq in_cons in_inv in_nil in_app_or in_or_app: datatypes. (*******************************************)A:Typex1:Al1:list AIHl1:forall l0 l3 : list A, l1 ++ l3 = l0 ++ l3 -> l1 = l0x2:Al2, l:list AH:x1 :: l1 ++ l = x2 :: l2 ++ lx1 :: l1 = x2 :: l2
(*******************************************) Section Elts. Variable A : Type. (*****************************)
(*****************************) 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, [] => 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, [] => false | S m, x :: t => nth_ok m t default end.A:Typeforall (n : nat) (l : list A) (d : A), {In (nth n l d) l} + {nth n l d = d}A:Typeforall (n : nat) (l : list A) (d : A), {In (nth n l d) l} + {nth n l d = d}A:Typed:Aforall n : nat, {In (nth n [] d) []} + {nth n [] d = d}A:Typea:Al:list Ad:AIHl:forall n : nat, {In (nth n l d) l} + {nth n l d = d}forall n : nat, {In (nth n (a :: l) d) (a :: l)} + {nth n (a :: l) d = d}right; destruct n; trivial.A:Typed:Aforall n : nat, {In (nth n [] d) []} + {nth n [] d = d}A:Typea:Al:list Ad:AIHl:forall n : nat, {In (nth n l d) l} + {nth n l d = d}forall n : nat, {In (nth n (a :: l) d) (a :: l)} + {nth n (a :: l) d = d}A:Typea:Al:list Ad:AIHl:forall n : nat, {In (nth n l d) l} + {nth n l d = d}{a = a \/ In a l} + {a = d}A:Typea:Al:list Ad:AIHl:forall n0 : nat, {In (nth n0 l d) l} + {nth n0 l d = d}n:nat{a = nth n l d \/ In (nth n l d) l} + {nth n l d = d}left; auto.A:Typea:Al:list Ad:AIHl:forall n : nat, {In (nth n l d) l} + {nth n l d = d}{a = a \/ In a l} + {a = d}destruct (IHl n); auto. Qed.A:Typea:Al:list Ad:AIHl:forall n0 : nat, {In (nth n0 l d) l} + {nth n0 l d = d}n:nat{a = nth n l d \/ In (nth n l d) l} + {nth n l d = d}A:Typeforall (n : nat) (l : list A) (d a : A), In (nth n l d) l -> In (nth (S n) (a :: l) d) (a :: l)simpl; auto. Qed. Fixpoint nth_error (l:list A) (n:nat) {struct n} : option A := match n, l with | O, x :: _ => Some x | S n, _ :: l => nth_error l n | _, _ => None end. Definition nth_default (default:A) (l:list A) (n:nat) : A := match nth_error l n with | Some x => x | None => default end.A:Typeforall (n : nat) (l : list A) (d a : A), In (nth n l d) l -> In (nth (S n) (a :: l) d) (a :: l)A:Typeforall (n : nat) (l : list A) (d : A), nth_default d l n = nth n l dunfold nth_default; induction n; intros [ | ] ?; simpl; auto. Qed.A:Typeforall (n : nat) (l : list A) (d : A), nth_default d l n = nth n l d
Results about nth
A:Typeforall (n : nat) (l : list A) (d : A), n < length l -> In (nth n l d) lA:Typeforall (n : nat) (l : list A) (d : A), n < length l -> In (nth n l d) lA:Typeforall (l : list A) (d : A), 1 <= length l -> In (nth 0 l d) lA:Typen:nathn:forall (l : list A) (d : A), S n <= length l -> In (nth n l d) lforall (l : list A) (d : A), S (S n) <= length l -> In (nth (S n) l d) ldestruct l; simpl; [ inversion 2 | auto ].A:Typeforall (l : list A) (d : A), 1 <= length l -> In (nth 0 l d) lA:Typen:nathn:forall (l : list A) (d : A), S n <= length l -> In (nth n l d) lforall (l : list A) (d : A), S (S n) <= length l -> In (nth (S n) l d) lA:Typen:nathn:forall (l : list A) (d : A), S n <= length l -> In (nth n l d) lA -> S (S n) <= 0 -> FalseA:Typen:nathn:forall (l0 : list A) (d : A), S n <= length l0 -> In (nth n l0 d) l0a:Al:list Aforall d : A, S (S n) <= S (length l) -> a = nth n l d \/ In (nth n l d) linversion 2.A:Typen:nathn:forall (l : list A) (d : A), S n <= length l -> In (nth n l d) lA -> S (S n) <= 0 -> Falseintros d ie; right; apply hn; auto with arith. Qed.A:Typen:nathn:forall (l0 : list A) (d : A), S n <= length l0 -> In (nth n l0 d) l0a:Al:list Aforall d : A, S (S n) <= S (length l) -> a = nth n l d \/ In (nth n l d) lA:Typel:list Ax, d:AIn x l -> exists n : nat, n < length l /\ nth n l d = xA:Typel:list Ax, d:AIn x l -> exists n : nat, n < length l /\ nth n l d = xA:Typex, d:AIn x [] -> exists n : nat, n < length [] /\ nth n [] d = xA:Typea:Al:list Ax, d:AIH:In x l -> exists n : nat, n < length l /\ nth n l d = xIn x (a :: l) -> exists n : nat, n < length (a :: l) /\ nth n (a :: l) d = xeasy.A:Typex, d:AIn x [] -> exists n : nat, n < length [] /\ nth n [] d = xA:Typea:Al:list Ax, d:AIH:In x l -> exists n : nat, n < length l /\ nth n l d = xIn x (a :: l) -> exists n : nat, n < length (a :: l) /\ nth n (a :: l) d = xA:Typea:Al:list Ax, d:AIH:In x l -> exists n : nat, n < length l /\ nth n l d = xH:a = xexists n : nat, n < length (a :: l) /\ nth n (a :: l) d = xA:Typea:Al:list Ax, d:AIH:In x l -> exists n : nat, n < length l /\ nth n l d = xH:In x lexists n : nat, n < length (a :: l) /\ nth n (a :: l) d = xsubst; exists 0; simpl; auto with arith.A:Typea:Al:list Ax, d:AIH:In x l -> exists n : nat, n < length l /\ nth n l d = xH:a = xexists n : nat, n < length (a :: l) /\ nth n (a :: l) d = xA:Typea:Al:list Ax, d:AIH:In x l -> exists n : nat, n < length l /\ nth n l d = xH:In x lexists n : nat, n < length (a :: l) /\ nth n (a :: l) d = xexists (S n); simpl; auto with arith. Qed.A:Typea:Al:list Ax, d:AIH:In x l -> exists n0 : nat, n0 < length l /\ nth n0 l d = xH:In x ln:natHn:n < length lHn':nth n l d = xexists n0 : nat, n0 < length (a :: l) /\ nth n0 (a :: l) d = xA:Typeforall (l : list A) (n : nat) (d : A), length l <= n -> nth n l d = dA:Typeforall (l : list A) (n : nat) (d : A), length l <= n -> nth n l d = dA:Typea:Al:list AIHl:forall (n : nat) (d0 : A), length l <= n -> nth n l d0 = d0d:AH:S (length l) <= 0a = dA:Typea:Al:list AIHl:forall (n0 : nat) (d0 : A), length l <= n0 -> nth n0 l d0 = d0n:natd:AH:S (length l) <= S nnth n l d = dinversion H.A:Typea:Al:list AIHl:forall (n : nat) (d0 : A), length l <= n -> nth n l d0 = d0d:AH:S (length l) <= 0a = dapply IHl; auto with arith. Qed.A:Typea:Al:list AIHl:forall (n0 : nat) (d0 : A), length l <= n0 -> nth n0 l d0 = d0n:natd:AH:S (length l) <= S nnth n l d = dA:Typeforall (l : list A) (n : nat) (d d' : A), n < length l -> nth n l d = nth n l d'A:Typeforall (l : list A) (n : nat) (d d' : A), n < length l -> nth n l d = nth n l d'A:Typeforall (n : nat) (d d' : A), n < length [] -> nth n [] d = nth n [] d'A:Typea:Al:list AIHl:forall (n : nat) (d d' : A), n < length l -> nth n l d = nth n l d'forall (n : nat) (d d' : A), n < length (a :: l) -> nth n (a :: l) d = nth n (a :: l) d'inversion 1.A:Typeforall (n : nat) (d d' : A), n < length [] -> nth n [] d = nth n [] d'intros [|n] d d'; simpl; auto with arith. Qed.A:Typea:Al:list AIHl:forall (n : nat) (d d' : A), n < length l -> nth n l d = nth n l d'forall (n : nat) (d d' : A), n < length (a :: l) -> nth n (a :: l) d = nth n (a :: l) d'A:Typeforall (l l' : list A) (d : A) (n : nat), n < length l -> nth n (l ++ l') d = nth n l dA:Typeforall (l l' : list A) (d : A) (n : nat), n < length l -> nth n (l ++ l') d = nth n l dA:Typeforall (l' : list A) (d : A) (n : nat), n < length [] -> nth n ([] ++ l') d = nth n [] dA:Typea:Al:list AIHl:forall (l' : list A) (d : A) (n : nat), n < length l -> nth n (l ++ l') d = nth n l dforall (l' : list A) (d : A) (n : nat), n < length (a :: l) -> nth n ((a :: l) ++ l') d = nth n (a :: l) dinversion 1.A:Typeforall (l' : list A) (d : A) (n : nat), n < length [] -> nth n ([] ++ l') d = nth n [] dintros l' d [|n]; simpl; auto with arith. Qed.A:Typea:Al:list AIHl:forall (l' : list A) (d : A) (n : nat), n < length l -> nth n (l ++ l') d = nth n l dforall (l' : list A) (d : A) (n : nat), n < length (a :: l) -> nth n ((a :: l) ++ l') d = nth n (a :: l) dA:Typeforall (l l' : list A) (d : A) (n : nat), n >= length l -> nth n (l ++ l') d = nth (n - length l) l' dA:Typeforall (l l' : list A) (d : A) (n : nat), n >= length l -> nth n (l ++ l') d = nth (n - length l) l' dA:Typea:Al:list AIHl:forall (l'0 : list A) (d0 : A) (n : nat), n >= length l -> nth n (l ++ l'0) d0 = nth (n - length l) l'0 d0l':list Ad:A0 >= length (a :: l) -> nth 0 ((a :: l) ++ l') d = nth (0 - length (a :: l)) l' dA:Typea:Al:list AIHl:forall (l'0 : list A) (d0 : A) (n0 : nat), n0 >= length l -> nth n0 (l ++ l'0) d0 = nth (n0 - length l) l'0 d0l':list Ad:An:natS n >= length (a :: l) -> nth (S n) ((a :: l) ++ l') d = nth (S n - length (a :: l)) l' dinversion 1.A:Typea:Al:list AIHl:forall (l'0 : list A) (d0 : A) (n : nat), n >= length l -> nth n (l ++ l'0) d0 = nth (n - length l) l'0 d0l':list Ad:A0 >= length (a :: l) -> nth 0 ((a :: l) ++ l') d = nth (0 - length (a :: l)) l' dintros; simpl; rewrite IHl; auto with arith. Qed.A:Typea:Al:list AIHl:forall (l'0 : list A) (d0 : A) (n0 : nat), n0 >= length l -> nth n0 (l ++ l'0) d0 = nth (n0 - length l) l'0 d0l':list Ad:An:natS n >= length (a :: l) -> nth (S n) ((a :: l) ++ l') d = nth (S n - length (a :: l)) l' dA:Typen:natl:list Ad:An < length l -> exists l1 l2 : list A, l = l1 ++ nth n l d :: l2 /\ length l1 = nA:Typen:natl:list Ad:An < length l -> exists l1 l2 : list A, l = l1 ++ nth n l d :: l2 /\ length l1 = nA:Typen:natd:Aforall l : list A, n < length l -> exists l1 l2 : list A, l = l1 ++ nth n l d :: l2 /\ length l1 = nA:Typed, a:Al:list AH:0 < length (a :: l)exists l1 l2 : list A, a :: l = l1 ++ nth 0 (a :: l) d :: l2 /\ length l1 = 0A:Typen:natd:AIH:forall l0 : list A, n < length l0 -> exists l1 l2 : list A, l0 = l1 ++ nth n l0 d :: l2 /\ length l1 = na:Al:list AH:S n < length (a :: l)exists l1 l2 : list A, a :: l = l1 ++ nth (S n) (a :: l) d :: l2 /\ length l1 = S nexists nil; exists l; now simpl.A:Typed, a:Al:list AH:0 < length (a :: l)exists l1 l2 : list A, a :: l = l1 ++ nth 0 (a :: l) d :: l2 /\ length l1 = 0A:Typen:natd:AIH:forall l0 : list A, n < length l0 -> exists l1 l2 : list A, l0 = l1 ++ nth n l0 d :: l2 /\ length l1 = na:Al:list AH:S n < length (a :: l)exists l1 l2 : list A, a :: l = l1 ++ nth (S n) (a :: l) d :: l2 /\ length l1 = S nexists (a::l1); exists l2; simpl; split; now f_equal. Qed.A:Typen:natd:AIH:forall l0 : list A, n < length l0 -> exists l3 l4 : list A, l0 = l3 ++ nth n l0 d :: l4 /\ length l3 = na:Al:list AH:S n < length (a :: l)l1, l2:list AHl:l = l1 ++ nth n l d :: l2Hl1:length l1 = nexists l0 l3 : list A, a :: l = l0 ++ nth (S n) (a :: l) d :: l3 /\ length l0 = S n
Results about nth_error
A:Typel:list An:natx:Anth_error l n = Some x -> In x lA:Typel:list An:natx:Anth_error l n = Some x -> In x lA:Typel:list Ax:Aforall n : nat, nth_error l n = Some x -> In x lA:Typea:Al:list Ax:AIH:forall n : nat, nth_error l n = Some x -> In x lSome a = Some x -> a = x \/ In x lA:Typea:Al:list Ax:AIH:forall n0 : nat, nth_error l n0 = Some x -> In x ln:natnth_error l n = Some x -> a = x \/ In x linjection 1; auto.A:Typea:Al:list Ax:AIH:forall n : nat, nth_error l n = Some x -> In x lSome a = Some x -> a = x \/ In x leauto. Qed.A:Typea:Al:list Ax:AIH:forall n0 : nat, nth_error l n0 = Some x -> In x ln:natnth_error l n = Some x -> a = x \/ In x lA:Typel:list Ax:AIn x l -> exists n : nat, nth_error l n = Some xA:Typel:list Ax:AIn x l -> exists n : nat, nth_error l n = Some xA:Typex:AIn x [] -> exists n : nat, nth_error [] n = Some xA:Typea:Al:list Ax:AIH:In x l -> exists n : nat, nth_error l n = Some xIn x (a :: l) -> exists n : nat, nth_error (a :: l) n = Some xeasy.A:Typex:AIn x [] -> exists n : nat, nth_error [] n = Some xA:Typea:Al:list Ax:AIH:In x l -> exists n : nat, nth_error l n = Some xIn x (a :: l) -> exists n : nat, nth_error (a :: l) n = Some xA:Typea:Al:list Ax:AIH:In x l -> exists n : nat, nth_error l n = Some xH:a = xexists n : nat, nth_error (a :: l) n = Some xA:Typea:Al:list Ax:AIH:In x l -> exists n : nat, nth_error l n = Some xH:In x lexists n : nat, nth_error (a :: l) n = Some xsubst; exists 0; simpl; auto with arith.A:Typea:Al:list Ax:AIH:In x l -> exists n : nat, nth_error l n = Some xH:a = xexists n : nat, nth_error (a :: l) n = Some xA:Typea:Al:list Ax:AIH:In x l -> exists n : nat, nth_error l n = Some xH:In x lexists n : nat, nth_error (a :: l) n = Some xexists (S n); simpl; auto with arith. Qed.A:Typea:Al:list Ax:AIH:In x l -> exists n0 : nat, nth_error l n0 = Some xH:In x ln:natHn:nth_error l n = Some xexists n0 : nat, nth_error (a :: l) n0 = Some xA:Typel:list An:natnth_error l n = None <-> length l <= nA:Typel:list An:natnth_error l n = None <-> length l <= nA:Typel:list Aforall n : nat, nth_error l n = None <-> length l <= nA:TypeNone = None <-> 0 <= 0A:Typen:natNone = None <-> 0 <= S nA:Typea:Al:list AIHl:forall n : nat, nth_error l n = None <-> length l <= nSome a = None <-> S (length l) <= 0A:Typea:Al:list AIHl:forall n0 : nat, nth_error l n0 = None <-> length l <= n0n:natnth_error l n = None <-> S (length l) <= S nsplit; auto.A:TypeNone = None <-> 0 <= 0split; auto with arith.A:Typen:natNone = None <-> 0 <= S nsplit; now auto with arith.A:Typea:Al:list AIHl:forall n : nat, nth_error l n = None <-> length l <= nSome a = None <-> S (length l) <= 0rewrite IHl; split; auto with arith. Qed.A:Typea:Al:list AIHl:forall n0 : nat, nth_error l n0 = None <-> length l <= n0n:natnth_error l n = None <-> S (length l) <= S nA:Typel:list An:natnth_error l n <> None <-> n < length lA:Typel:list An:natnth_error l n <> None <-> n < length lA:Typel:list Aforall n : nat, nth_error l n <> None <-> n < length lA:TypeNone <> None <-> 0 < 0A:Typen:natNone <> None <-> S n < 0A:Typea:Al:list AIHl:forall n : nat, nth_error l n <> None <-> n < length lSome a <> None <-> 0 < S (length l)A:Typea:Al:list AIHl:forall n0 : nat, nth_error l n0 <> None <-> n0 < length ln:natnth_error l n <> None <-> S n < S (length l)split; [now destruct 1 | inversion 1].A:TypeNone <> None <-> 0 < 0split; [now destruct 1 | inversion 1].A:Typen:natNone <> None <-> S n < 0split; now auto with arith.A:Typea:Al:list AIHl:forall n : nat, nth_error l n <> None <-> n < length lSome a <> None <-> 0 < S (length l)rewrite IHl; split; auto with arith. Qed.A:Typea:Al:list AIHl:forall n0 : nat, nth_error l n0 <> None <-> n0 < length ln:natnth_error l n <> None <-> S n < S (length l)A:Typel:list An:nata:Anth_error l n = Some a -> exists l1 l2 : list A, l = l1 ++ a :: l2 /\ length l1 = nA:Typel:list An:nata:Anth_error l n = Some a -> exists l1 l2 : list A, l = l1 ++ a :: l2 /\ length l1 = nA:Typen:nata:Aforall l : list A, nth_error l n = Some a -> exists l1 l2 : list A, l = l1 ++ a :: l2 /\ length l1 = nA:Typea, x:Al:list AH:Some x = Some aexists l1 l2 : list A, x :: l = l1 ++ a :: l2 /\ length l1 = 0A:Typen:nata:AIH:forall l0 : list A, nth_error l0 n = Some a -> exists l1 l2 : list A, l0 = l1 ++ a :: l2 /\ length l1 = nx:Al:list AH:nth_error l n = Some aexists l1 l2 : list A, x :: l = l1 ++ a :: l2 /\ length l1 = S nA:Typea, x:Al:list AH:Some x = Some aexists l1 l2 : list A, x :: l = l1 ++ a :: l2 /\ length l1 = 0now injection H as ->.A:Typea, x:Al:list AH:Some x = Some ax :: l = [] ++ a :: l /\ length [] = 0A:Typen:nata:AIH:forall l0 : list A, nth_error l0 n = Some a -> exists l1 l2 : list A, l0 = l1 ++ a :: l2 /\ length l1 = nx:Al:list AH:nth_error l n = Some aexists l1 l2 : list A, x :: l = l1 ++ a :: l2 /\ length l1 = S nexists (x::l1); exists l2; simpl; split; now f_equal. Qed.A:Typen:nata:AIH:forall l0 : list A, nth_error l0 n = Some a -> exists l3 l4 : list A, l0 = l3 ++ a :: l4 /\ length l3 = nx:Al:list AH:nth_error l n = Some al1, l2:list AH1:l = l1 ++ a :: l2H2:length l1 = nexists l0 l3 : list A, x :: l = l0 ++ a :: l3 /\ length l0 = S nA:Typel, l':list An:natn < length l -> nth_error (l ++ l') n = nth_error l nA:Typel, l':list An:natn < length l -> nth_error (l ++ l') n = nth_error l nA:Typel':list An:natforall l : list A, n < length l -> nth_error (l ++ l') n = nth_error l nA:Typel':list An:natIHn:forall l0 : list A, n < length l0 -> nth_error (l0 ++ l') n = nth_error l0 na:Al:list AH:S n < length (a :: l)nth_error ((a :: l) ++ l') (S n) = nth_error (a :: l) (S n)A:Typel':list An:natIHn:forall l0 : list A, n < length l0 -> nth_error (l0 ++ l') n = nth_error l0 na:Al:list AH:S n < S (length l)nth_error (l ++ l') n = nth_error l nauto with arith. Qed.A:Typel':list An:natIHn:forall l0 : list A, n < length l0 -> nth_error (l0 ++ l') n = nth_error l0 na:Al:list AH:S n < S (length l)n < length lA:Typel, l':list An:natlength l <= n -> nth_error (l ++ l') n = nth_error l' (n - length l)A:Typel, l':list An:natlength l <= n -> nth_error (l ++ l') n = nth_error l' (n - length l)A:Typel':list An:natforall l : list A, length l <= n -> nth_error (l ++ l') n = nth_error l' (n - length l)A:Typel':list An:natIHn:forall l0 : list A, length l0 <= n -> nth_error (l0 ++ l') n = nth_error l' (n - length l0)a:Al:list AH:length (a :: l) <= S nnth_error ((a :: l) ++ l') (S n) = nth_error l' (S n - length (a :: l))A:Typel':list An:natIHn:forall l0 : list A, length l0 <= n -> nth_error (l0 ++ l') n = nth_error l' (n - length l0)a:Al:list AH:S (length l) <= S nnth_error (l ++ l') n = nth_error l' (n - length l)auto with arith. Qed. (*****************)A:Typel':list An:natIHn:forall l0 : list A, length l0 <= n -> nth_error (l0 ++ l') n = nth_error l' (n - length l0)a:Al:list AH:S (length l) <= S nlength l <= n
(*****************) Hypothesis eq_dec : forall x y : A, {x = y}+{x <> y}. Fixpoint remove (x : A) (l : list A) : list A := match l with | [] => [] | y::tl => if (eq_dec x y) then remove x tl else y::(remove x tl) end.A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall (l : list A) (x : A), ~ In x (remove x l)A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall (l : list A) (x : A), ~ In x (remove x l)A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}x:Al:list AIHl:forall x0 : A, ~ In x0 (remove x0 l)forall x0 : A, ~ In x0 (remove x0 (x :: l))A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}x:Al:list AIHl:forall x0 : A, ~ In x0 (remove x0 l)y:Ayeqx:y = x~ In y (remove y l)A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}x:Al:list AIHl:forall x0 : A, ~ In x0 (remove x0 l)y:Ayneqx:y <> x~ In y (x :: remove y l)A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}x:Al:list AIHl:forall x0 : A, ~ In x0 (remove x0 l)y:Ayneqx:y <> x~ In y (x :: remove y l)apply (IHl y); assumption. Qed. (******************************)A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}x:Al:list AIHl:forall x0 : A, ~ In x0 (remove x0 l)y:Ayneqx:y <> xH:In y (remove y l)False
(******************************)
last l d returns the last element of the list l,
or the default value d if l is empty.
Fixpoint last (l:list A) (d:A) : A := match l with | [] => d | [a] => a | a :: l => last l d end.
removelast l remove the last element of l
Fixpoint removelast (l:list A) : list A := match l with | [] => [] | [a] => [] | a :: l => a :: removelast l end.A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall (l : list A) (d : A), l <> [] -> l = removelast l ++ [last l d]A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall (l : list A) (d : A), l <> [] -> l = removelast l ++ [last l d]A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall d : A, [] <> [] -> [] = removelast [] ++ [last [] d]A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall d : A, l <> [] -> l = removelast l ++ [last l d]forall d : A, a :: l <> [] -> a :: l = removelast (a :: l) ++ [last (a :: l) d]A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall d : A, l <> [] -> l = removelast l ++ [last l d]forall d : A, a :: l <> [] -> a :: l = removelast (a :: l) ++ [last (a :: l) d]A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall d0 : A, l <> [] -> l = removelast l ++ [last l d0]d:Aa :: l = removelast (a :: l) ++ [last (a :: l) d]pattern (a0::l) at 1; rewrite IHl with d; auto; discriminate. Qed.A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a, a0:Al:list AIHl:forall d0 : A, a0 :: l <> [] -> a0 :: l = removelast (a0 :: l) ++ [last (a0 :: l) d0]d:Aa :: a0 :: l = removelast (a :: a0 :: l) ++ [last (a :: a0 :: l) d]A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall l : list A, l <> [] -> {l' : list A & {a : A | l = l' ++ [a]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall l : list A, l <> [] -> {l' : list A & {a : A | l = l' ++ [a]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}[] <> [] -> {l' : list A & {a : A | [] = l' ++ [a]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:l <> [] -> {l' : list A & {a0 : A | l = l' ++ [a0]}}a :: l <> [] -> {l' : list A & {a0 : A | a :: l = l' ++ [a0]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:l <> [] -> {l' : list A & {a0 : A | l = l' ++ [a0]}}a :: l <> [] -> {l' : list A & {a0 : A | a :: l = l' ++ [a0]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:l <> [] -> {l' : list A & {a0 : A | l = l' ++ [a0]}}{l' : list A & {a0 : A | a :: l = l' ++ [a0]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:AIHl:[] <> [] -> {l' : list A & {a0 : A | [] = l' ++ [a0]}}{l' : list A & {a0 : A | [a] = l' ++ [a0]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a, a0:Al:list AIHl:a0 :: l <> [] -> {l' : list A & {a1 : A | a0 :: l = l' ++ [a1]}}{l' : list A & {a1 : A | a :: a0 :: l = l' ++ [a1]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a, a0:Al:list AIHl:a0 :: l <> [] -> {l' : list A & {a1 : A | a0 :: l = l' ++ [a1]}}{l' : list A & {a1 : A | a :: a0 :: l = l' ++ [a1]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a, a0:Al, l':list Aa':AH:a0 :: l = l' ++ [a']{l'0 : list A & {a1 : A | a :: a0 :: l = l'0 ++ [a1]}}exists (a::l'), a'; auto. Qed.A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a, a0:Al, l':list Aa':AH:a0 :: l = l' ++ [a']{l'0 : list A & {a1 : A | a :: l' ++ [a'] = l'0 ++ [a1]}}A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall l l' : list A, l' <> [] -> removelast (l ++ l') = l ++ removelast l'A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall l l' : list A, l' <> [] -> removelast (l ++ l') = l ++ removelast l'A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall l' : list A, l' <> [] -> removelast ([] ++ l') = [] ++ removelast l'A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall l' : list A, l' <> [] -> removelast (l ++ l') = l ++ removelast l'forall l' : list A, l' <> [] -> removelast ((a :: l) ++ l') = (a :: l) ++ removelast l'A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall l' : list A, l' <> [] -> removelast (l ++ l') = l ++ removelast l'forall l' : list A, l' <> [] -> removelast ((a :: l) ++ l') = (a :: l) ++ removelast l'A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall l'0 : list A, l'0 <> [] -> removelast (l ++ l'0) = l ++ removelast l'0l':list AH:l' <> []match l ++ l' with | [] => [] | _ :: _ => a :: removelast (l ++ l') end = a :: l ++ removelast l'A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall l'0 : list A, l'0 <> [] -> removelast (l ++ l'0) = l ++ removelast l'0l':list AH:l' <> []l ++ l' <> []A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall l'0 : list A, l'0 <> [] -> removelast (l ++ l'0) = l ++ removelast l'0l':list AH:l' <> []H0:l ++ l' <> []match l ++ l' with | [] => [] | _ :: _ => a :: removelast (l ++ l') end = a :: l ++ removelast l'A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:AIHl:forall l'0 : list A, l'0 <> [] -> removelast ([] ++ l'0) = [] ++ removelast l'0l':list AH:l' <> [][] ++ l' <> []A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a, a0:Al:list AIHl:forall l'0 : list A, l'0 <> [] -> removelast ((a0 :: l) ++ l'0) = (a0 :: l) ++ removelast l'0l':list AH:l' <> [](a0 :: l) ++ l' <> []A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall l'0 : list A, l'0 <> [] -> removelast (l ++ l'0) = l ++ removelast l'0l':list AH:l' <> []H0:l ++ l' <> []match l ++ l' with | [] => [] | _ :: _ => a :: removelast (l ++ l') end = a :: l ++ removelast l'A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a, a0:Al:list AIHl:forall l'0 : list A, l'0 <> [] -> removelast ((a0 :: l) ++ l'0) = (a0 :: l) ++ removelast l'0l':list AH:l' <> [](a0 :: l) ++ l' <> []A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall l'0 : list A, l'0 <> [] -> removelast (l ++ l'0) = l ++ removelast l'0l':list AH:l' <> []H0:l ++ l' <> []match l ++ l' with | [] => [] | _ :: _ => a :: removelast (l ++ l') end = a :: l ++ removelast l'A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:forall l'0 : list A, l'0 <> [] -> removelast (l ++ l'0) = l ++ removelast l'0l':list AH:l' <> []H0:l ++ l' <> []match l ++ l' with | [] => [] | _ :: _ => a :: removelast (l ++ l') end = a :: l ++ removelast l'destruct (l++l'); [elim H0; auto|f_equal; auto]. Qed. (******************************************)A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}a:Al, l':list AIHl:removelast (l ++ l') = l ++ removelast l'H:l' <> []H0:l ++ l' <> []match l ++ l' with | [] => [] | _ :: _ => a :: removelast (l ++ l') end = a :: l ++ removelast l'
(******************************************) Fixpoint count_occ (l : list A) (x : A) : nat := match l with | [] => 0 | y :: tl => let n := count_occ tl x in if eq_dec y x then S n else n end.
Compatibility of count_occ with operations on list
A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:AIn x l <-> count_occ l x > 0A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:AIn x l <-> count_occ l x > 0A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}x:AFalse <-> 0 > 0A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}y:Al:list Ax:AIHl:In x l <-> count_occ l x > 0y = x \/ In x l <-> (if eq_dec y x then S (count_occ l x) else count_occ l x) > 0split; [destruct 1 | apply gt_irrefl].A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}x:AFalse <-> 0 > 0destruct eq_dec as [->|Hneq]; rewrite IHl; intuition. Qed.A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}y:Al:list Ax:AIHl:In x l <-> count_occ l x > 0y = x \/ In x l <-> (if eq_dec y x then S (count_occ l x) else count_occ l x) > 0A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:A~ In x l <-> count_occ l x = 0A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:A~ In x l <-> count_occ l x = 0A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:A~ count_occ l x > 0 <-> count_occ l x = 0now rewrite Nat.nlt_ge, Nat.le_0_r. Qed.A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:A~ 0 < count_occ l x <-> count_occ l x = 0A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}x:Acount_occ [] x = 0reflexivity. Qed.A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}x:Acount_occ [] x = 0A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}l:list A(forall x : A, count_occ l x = 0) <-> l = []A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}l:list A(forall x : A, count_occ l x = 0) <-> l = []A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}l:list A(forall x : A, count_occ l x = 0) -> l = []A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}l:list Al = [] -> forall x : A, count_occ l x = 0A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}l:list A(forall x : A, count_occ l x = 0) -> l = []A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}x:Al:list AIHl:(forall x0 : A, count_occ l x0 = 0) -> l = [](forall x0 : A, count_occ (x :: l) x0 = 0) -> x :: l = []A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}x:Al:list AIHl:(forall x0 : A, count_occ l x0 = 0) -> l = []H:forall x0 : A, count_occ (x :: l) x0 = 0x :: l = []A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}x:Al:list AIHl:(forall x0 : A, count_occ l x0 = 0) -> l = []H:count_occ (x :: l) x = 0x :: l = []destruct eq_dec as [_|NEQ]; [discriminate|now elim NEQ].A:Typeeq_dec:forall x0 y : A, {x0 = y} + {x0 <> y}x:Al:list AIHl:(forall x0 : A, count_occ l x0 = 0) -> l = []H:(if eq_dec x x then S (count_occ l x) else count_occ l x) = 0x :: l = []now intros ->. Qed.A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}l:list Al = [] -> forall x : A, count_occ l x = 0A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}l:list Ax, y:Ax = y -> count_occ (x :: l) y = S (count_occ l y)A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}l:list Ax, y:Ax = y -> count_occ (x :: l) y = S (count_occ l y)A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}l:list Ax, y:AH:x = ycount_occ (x :: l) y = S (count_occ l y)now destruct (eq_dec x y). Qed.A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}l:list Ax, y:AH:x = y(if eq_dec x y then S (count_occ l y) else count_occ l y) = S (count_occ l y)A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}l:list Ax, y:Ax <> y -> count_occ (x :: l) y = count_occ l yA:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}l:list Ax, y:Ax <> y -> count_occ (x :: l) y = count_occ l yA:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}l:list Ax, y:AH:x <> ycount_occ (x :: l) y = count_occ l ynow destruct (eq_dec x y). Qed. End Elts. (*******************************)A:Typeeq_dec:forall x0 y0 : A, {x0 = y0} + {x0 <> y0}l:list Ax, y:AH:x <> y(if eq_dec x y then S (count_occ l y) else count_occ l y) = count_occ l y
(*******************************) Section ListOps. Variable A : Type. (*************************)
(*************************) Fixpoint rev (l:list A) : list A := match l with | [] => [] | x :: l' => rev l' ++ [x] end.A:Typeforall x y : list A, rev (x ++ y) = rev y ++ rev xA:Typeforall x y : list A, rev (x ++ y) = rev y ++ rev xA:Typeforall y : list A, rev ([] ++ y) = rev y ++ rev []A:Typea:Al:list AIHl:forall y : list A, rev (l ++ y) = rev y ++ rev lforall y : list A, rev ((a :: l) ++ y) = rev y ++ rev (a :: l)A:Typerev ([] ++ []) = rev [] ++ rev []A:Typea:Al:list Arev ([] ++ a :: l) = rev (a :: l) ++ rev []A:Typea:Al:list AIHl:forall y : list A, rev (l ++ y) = rev y ++ rev lforall y : list A, rev ((a :: l) ++ y) = rev y ++ rev (a :: l)A:Type[] = []A:Typea:Al:list Arev ([] ++ a :: l) = rev (a :: l) ++ rev []A:Typea:Al:list AIHl:forall y : list A, rev (l ++ y) = rev y ++ rev lforall y : list A, rev ((a :: l) ++ y) = rev y ++ rev (a :: l)A:Typea:Al:list Arev ([] ++ a :: l) = rev (a :: l) ++ rev []A:Typea:Al:list AIHl:forall y : list A, rev (l ++ y) = rev y ++ rev lforall y : list A, rev ((a :: l) ++ y) = rev y ++ rev (a :: l)A:Typea:Al:list Arev l ++ [a] = (rev l ++ [a]) ++ []A:Typea:Al:list AIHl:forall y : list A, rev (l ++ y) = rev y ++ rev lforall y : list A, rev ((a :: l) ++ y) = rev y ++ rev (a :: l)A:Typea:Al:list AIHl:forall y : list A, rev (l ++ y) = rev y ++ rev lforall y : list A, rev ((a :: l) ++ y) = rev y ++ rev (a :: l)A:Typea:Al:list AIHl:forall y0 : list A, rev (l ++ y0) = rev y0 ++ rev ly:list Arev ((a :: l) ++ y) = rev y ++ rev (a :: l)A:Typea:Al:list AIHl:forall y0 : list A, rev (l ++ y0) = rev y0 ++ rev ly:list Arev (l ++ y) ++ [a] = rev y ++ rev l ++ [a]rewrite app_assoc; trivial. Qed.A:Typea:Al:list AIHl:forall y0 : list A, rev (l ++ y0) = rev y0 ++ rev ly:list A(rev y ++ rev l) ++ [a] = rev y ++ rev l ++ [a]A:Typeforall (l : list A) (a : A), rev (l ++ [a]) = a :: rev lA:Typeforall (l : list A) (a : A), rev (l ++ [a]) = a :: rev lapply (rev_app_distr l [a]); simpl; auto. Qed.A:Typel:list Aa:Arev (l ++ [a]) = a :: rev lA:Typeforall l : list A, rev (rev l) = lA:Typeforall l : list A, rev (rev l) = lA:Typerev (rev []) = []A:Typea:Al:list AIHl:rev (rev l) = lrev (rev (a :: l)) = a :: lA:Typea:Al:list AIHl:rev (rev l) = lrev (rev (a :: l)) = a :: lA:Typea:Al:list AIHl:rev (rev l) = lrev (rev l ++ [a]) = a :: lrewrite IHl; auto. Qed.A:Typea:Al:list AIHl:rev (rev l) = la :: rev (rev l) = a :: l
Compatibility with other operations
A:Typeforall (l : list A) (x : A), In x l <-> In x (rev l)A:Typeforall (l : list A) (x : A), In x l <-> In x (rev l)A:Typeforall x : A, In x [] <-> In x (rev [])A:Typea:Al:list AIHl:forall x : A, In x l <-> In x (rev l)forall x : A, In x (a :: l) <-> In x (rev (a :: l))A:Typea:Al:list AIHl:forall x : A, In x l <-> In x (rev l)forall x : A, In x (a :: l) <-> In x (rev (a :: l))A:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AIn x (a :: l) <-> In x (rev (a :: l))A:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:Aa = x \/ In x l <-> In x (rev l ++ [a])A:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AH0:a = xIn x (rev l ++ [a])A:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AH0:In x lIn x (rev l ++ [a])A:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AH:In x (rev l ++ [a])a = x \/ In x lA:Typel:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AIn x (rev l ++ [x])A:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AH0:In x lIn x (rev l ++ [a])A:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AH:In x (rev l ++ [a])a = x \/ In x lA:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AH0:In x lIn x (rev l ++ [a])A:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AH:In x (rev l ++ [a])a = x \/ In x ldestruct (in_app_or _ _ _ H); firstorder. Qed.A:Typea:Al:list AIHl:forall x0 : A, In x0 l <-> In x0 (rev l)x:AH:In x (rev l ++ [a])a = x \/ In x lA:Typeforall l : list A, length (rev l) = length lA:Typeforall l : list A, length (rev l) = length lA:Typea:Al:list AIHl:length (rev l) = length llength (rev l ++ [a]) = S (length l)A:Typea:Al:list AIHl:length (rev l) = length llength (rev l) + length [a] = S (length l)A:Typea:Al:list AIHl:length (rev l) = length llength l + length [a] = S (length l)elim (length l); simpl; auto. Qed.A:Typea:Al:list AIHl:length (rev l) = length llength l + 1 = S (length l)A:Typeforall (l : list A) (d : A) (n : nat), n < length l -> nth n (rev l) d = nth (length l - S n) l dA:Typeforall (l : list A) (d : A) (n : nat), n < length l -> nth n (rev l) d = nth (length l - S n) l dA:Typeforall (d : A) (n : nat), n < length [] -> nth n (rev []) d = nth (length [] - S n) [] dA:Typea:Al:list AIHl:forall (d : A) (n : nat), n < length l -> nth n (rev l) d = nth (length l - S n) l dforall (d : A) (n : nat), n < length (a :: l) -> nth n (rev (a :: l)) d = nth (length (a :: l) - S n) (a :: l) dA:Typea:Al:list AIHl:forall (d : A) (n : nat), n < length l -> nth n (rev l) d = nth (length l - S n) l dforall (d : A) (n : nat), n < length (a :: l) -> nth n (rev (a :: l)) d = nth (length (a :: l) - S n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < length (a :: l)nth n (rev (a :: l)) d = nth (length (a :: l) - S n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)nth n (rev (a :: l)) d = nth (length (a :: l) - S n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)nth n (rev l ++ [a]) d = nth (length (a :: l) - S n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)nth n (rev l ++ [a]) d = nth (length l - n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)H1:n = length lnth (length l) (rev l ++ [a]) d = nth (length l - length l) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length lnth n (rev l ++ [a]) d = nth (length l - n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)H1:n = length lnth (length l) (rev l ++ [a]) d = aA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length lnth n (rev l ++ [a]) d = nth (length l - n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)H1:n = length lnth (length (rev l)) (rev l ++ [a]) d = aA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length lnth n (rev l ++ [a]) d = nth (length l - n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)H1:n = length lnth (length (rev l) - length (rev l)) [a] d = aA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length lnth n (rev l ++ [a]) d = nth (length l - n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length lnth n (rev l ++ [a]) d = nth (length l - n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length lnth n (rev l) d = nth (length l - n) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length ln < length (rev l)A:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length lnth n (rev l) d = nth (1 + length l - (1 + n)) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length ln < length (rev l)A:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length lnth n (rev l) d = nth (S (length l) - (1 + n)) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length ln < length (rev l)A:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length lnth n (rev l) d = nth (S (length l - (1 + n))) (a :: l) dA:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length ln < length (rev l)rewrite rev_length; auto. Qed.A:Typea:Al:list AIHl:forall (d0 : A) (n0 : nat), n0 < length l -> nth n0 (rev l) d0 = nth (length l - S n0) l d0d:An:natH:n < S (length l)m:natH1:S n <= length lH0:m = length ln < length (rev l)
An alternative tail-recursive definition for reverse
Fixpoint rev_append (l l': list A) : list A := match l with | [] => l' | a::l => rev_append l (a::l') end. Definition rev' l : list A := rev_append l [].A:Typeforall l l' : list A, rev_append l l' = rev l ++ l'A:Typeforall l l' : list A, rev_append l l' = rev l ++ l'rewrite <- app_assoc; firstorder. Qed.A:Typea:Al:list AIHl:forall l'0 : list A, rev_append l l'0 = rev l ++ l'0l':list Arev_append l (a :: l') = (rev l ++ [a]) ++ l'A:Typeforall l : list A, rev l = rev_append l []A:Typeforall l : list A, rev l = rev_append l []rewrite app_nil_r; trivial. Qed. (*********************************************)A:Typel:list Arev l = rev l ++ []
Reverse Induction Principle on Lists
(*********************************************) Section Reverse_Induction.A:Typeforall P : list A -> Prop, P [] -> (forall (a : A) (l : list A), P (rev l) -> P (rev (a :: l))) -> forall l : list A, P (rev l)induction l; auto. Qed.A:Typeforall P : list A -> Prop, P [] -> (forall (a : A) (l : list A), P (rev l) -> P (rev (a :: l))) -> forall l : list A, P (rev l)A:Typeforall P : list A -> Prop, P [] -> (forall (x : A) (l : list A), P l -> P (l ++ [x])) -> forall l : list A, P lA:Typeforall P : list A -> Prop, P [] -> (forall (x : A) (l : list A), P l -> P (l ++ [x])) -> forall l : list A, P lA:TypeP:list A -> PropH:P []H0:forall (x : A) (l0 : list A), P l0 -> P (l0 ++ [x])l:list AP lA:TypeP:list A -> PropH:P []H0:forall (x : A) (l0 : list A), P l0 -> P (l0 ++ [x])l:list Arev (rev l) = l -> P lA:TypeP:list A -> PropH:P []H0:forall (x : A) (l0 : list A), P l0 -> P (l0 ++ [x])l:list AE:rev (rev l) = lP (rev (rev l))A:TypeP:list A -> PropH:P []H0:forall (x : A) (l0 : list A), P l0 -> P (l0 ++ [x])l:list AE:rev (rev l) = lP []A:TypeP:list A -> PropH:P []H0:forall (x : A) (l0 : list A), P l0 -> P (l0 ++ [x])l:list AE:rev (rev l) = lforall (a : A) (l0 : list A), P (rev l0) -> P (rev (a :: l0))A:TypeP:list A -> PropH:P []H0:forall (x : A) (l0 : list A), P l0 -> P (l0 ++ [x])l:list AE:rev (rev l) = lforall (a : A) (l0 : list A), P (rev l0) -> P (rev (a :: l0))A:TypeP:list A -> PropH:P []H0:forall (x : A) (l0 : list A), P l0 -> P (l0 ++ [x])l:list AE:rev (rev l) = lforall (a : A) (l0 : list A), P (rev l0) -> P (rev l0 ++ [a])A:TypeP:list A -> PropH:P []H0:forall (x : A) (l1 : list A), P l1 -> P (l1 ++ [x])l:list AE:rev (rev l) = la:Al0:list AH1:P (rev l0)P (rev l0 ++ [a])auto. Qed. End Reverse_Induction. (*************************)A:TypeP:list A -> PropH:P []H0:forall (x : A) (l1 : list A), P l1 -> P (l1 ++ [x])l:list AE:rev (rev l) = la:Al0:list AH1:P (rev l0)P (rev l0)
(*************************) Fixpoint concat (l : list (list A)) : list A := match l with | nil => nil | cons x l => x ++ concat l end.A:Typeconcat [] = []reflexivity. Qed.A:Typeconcat [] = []A:Typeforall (x : list A) (l : list (list A)), concat (x :: l) = x ++ concat lreflexivity. Qed.A:Typeforall (x : list A) (l : list (list A)), concat (x :: l) = x ++ concat lA:Typeforall l1 l2 : list (list A), concat (l1 ++ l2) = concat l1 ++ concat l2A:Typeforall l1 l2 : list (list A), concat (l1 ++ l2) = concat l1 ++ concat l2A:Typel2:list (list A)concat l2 = concat l2A:Typex:list Al1:list (list A)IH:forall l0 : list (list A), concat (l1 ++ l0) = concat l1 ++ concat l0l2:list (list A)x ++ concat (l1 ++ l2) = (x ++ concat l1) ++ concat l2reflexivity.A:Typel2:list (list A)concat l2 = concat l2rewrite IH; apply app_assoc. Qed. (***********************************)A:Typex:list Al1:list (list A)IH:forall l0 : list (list A), concat (l1 ++ l0) = concat l1 ++ concat l0l2:list (list A)x ++ concat (l1 ++ l2) = (x ++ concat l1) ++ concat l2
(***********************************) Hypothesis eq_dec : forall (x y : A), {x = y}+{x <> y}.A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall l l' : list A, {l = l'} + {l <> l'}decide equality. Defined. End ListOps. (***************************************************)A:Typeeq_dec:forall x y : A, {x = y} + {x <> y}forall l l' : list A, {l = l'} + {l <> l'}
(***************************************************)
(************)
(************) Section Map. Variables (A : Type) (B : Type). Variable f : A -> B. Fixpoint map (l:list A) : list B := match l with | [] => [] | a :: t => (f a) :: (map t) end.A, B:Typef:A -> Bx:Al:list Amap (x :: l) = f x :: map lreflexivity. Qed.A, B:Typef:A -> Bx:Al:list Amap (x :: l) = f x :: map lA, B:Typef:A -> Bforall (l : list A) (x : A), In x l -> In (f x) (map l)induction l; firstorder (subst; auto). Qed.A, B:Typef:A -> Bforall (l : list A) (x : A), In x l -> In (f x) (map l)A, B:Typef:A -> Bforall (l : list A) (y : B), In y (map l) <-> (exists x : A, f x = y /\ In x l)induction l; firstorder (subst; auto). Qed.A, B:Typef:A -> Bforall (l : list A) (y : B), In y (map l) <-> (exists x : A, f x = y /\ In x l)A, B:Typef:A -> Bforall l : list A, length (map l) = length linduction l; simpl; auto. Qed.A, B:Typef:A -> Bforall l : list A, length (map l) = length lA, B:Typef:A -> Bforall (l : list A) (d : A) (n : nat), nth n (map l) (f d) = f (nth n l d)induction l; simpl map; destruct n; firstorder. Qed.A, B:Typef:A -> Bforall (l : list A) (d : A) (n : nat), nth n (map l) (f d) = f (nth n l d)A, B:Typef:A -> Bforall (n : nat) (l : list A) (d : A), nth_error l n = Some d -> nth_error (map l) n = Some (f d)induction n; intros [ | ] ? Heq; simpl in *; inversion Heq; auto. Qed.A, B:Typef:A -> Bforall (n : nat) (l : list A) (d : A), nth_error l n = Some d -> nth_error (map l) n = Some (f d)A, B:Typef:A -> Bforall l l' : list A, map (l ++ l') = map l ++ map l'A, B:Typef:A -> Bforall l l' : list A, map (l ++ l') = map l ++ map l'intros; rewrite IHl; auto. Qed.A, B:Typef:A -> Ba:Al:list AIHl:forall l' : list A, map (l ++ l') = map l ++ map l'forall l' : list A, f a :: map (l ++ l') = f a :: map l ++ map l'A, B:Typef:A -> Bforall l : list A, map (rev l) = rev (map l)A, B:Typef:A -> Bforall l : list A, map (rev l) = rev (map l)A, B:Typef:A -> Ba:Al:list AIHl:map (rev l) = rev (map l)map (rev l ++ [a]) = rev (map l) ++ [f a]rewrite IHl; auto. Qed.A, B:Typef:A -> Ba:Al:list AIHl:map (rev l) = rev (map l)map (rev l) ++ map [a] = rev (map l) ++ [f a]A, B:Typef:A -> Bforall l : list A, map l = [] -> l = []destruct l; simpl; reflexivity || discriminate. Qed.A, B:Typef:A -> Bforall l : list A, map l = [] -> l = []
map and count of occurrences
Hypothesis decA: forall x1 x2 : A, {x1 = x2} + {x1 <> x2}. Hypothesis decB: forall y1 y2 : B, {y1 = y2} + {y1 <> y2}. Hypothesis Hfinjective: forall x1 x2: A, (f x1) = (f x2) -> x1 = x2.A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2x:Al:list Acount_occ decA l x = count_occ decB (map l) (f x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2x:Al:list Acount_occ decA l x = count_occ decB (map l) (f x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2l:list Aforall x : A, count_occ decA l x = count_occ decB (map l) (f x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2x:A0 = 0A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list AHrec:forall x0 : A, count_occ decA l' x0 = count_occ decB (map l') (f x0)x:A(if decA a x then S (count_occ decA l' x) else count_occ decA l' x) = (if decB (f a) (f x) then S (count_occ decB (map l') (f x)) else count_occ decB (map l') (f x))reflexivity.A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2x:A0 = 0A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list AHrec:forall x0 : A, count_occ decA l' x0 = count_occ decB (map l') (f x0)x:A(if decA a x then S (count_occ decA l' x) else count_occ decA l' x) = (if decB (f a) (f x) then S (count_occ decB (map l') (f x)) else count_occ decB (map l') (f x))A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)(if decA a x then S (count_occ decA l' x) else count_occ decA l' x) = (if decB (f a) (f x) then S (count_occ decB (map l') (f x)) else count_occ decB (map l') (f x))A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a = xH2:f a = f xS (count_occ decA l' x) = S (count_occ decB (map l') (f x))A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a = xH2:f a <> f xS (count_occ decA l' x) = count_occ decB (map l') (f x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a <> xH2:f a = f xcount_occ decA l' x = S (count_occ decB (map l') (f x))A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a <> xH2:f a <> f xcount_occ decA l' x = count_occ decB (map l') (f x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a = xH2:f a = f xS (count_occ decA l' x) = S (count_occ decB (map l') (f x))reflexivity.A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a = xH2:f a = f xS (count_occ decB (map l') (f x)) = S (count_occ decB (map l') (f x))A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a = xH2:f a <> f xS (count_occ decA l' x) = count_occ decB (map l') (f x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a = xH2:f a <> f xf a = f xreflexivity.A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a = xH2:f a <> f xf x = f xA, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a <> xH2:f a = f xcount_occ decA l' x = S (count_occ decB (map l') (f x))contradiction H1.A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}a, x:AHfinjective:a = xl':list AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a <> xH2:f a = f xcount_occ decA l' x = S (count_occ decB (map l') (f x))assumption. Qed.A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2a:Al':list Ax:AHrec:count_occ decA l' x = count_occ decB (map l') (f x)H1:a <> xH2:f a <> f xcount_occ decA l' x = count_occ decB (map l') (f x)
flat_map
Definition flat_map (f:A -> list B) := fix flat_map (l:list A) : list B := match l with | nil => nil | cons x t => (f x)++(flat_map t) end.A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2forall (f0 : A -> list B) (l : list A) (y : B), In y (flat_map f0 l) <-> (exists x : A, In x l /\ In y (f0 x))A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}Hfinjective:forall x1 x2 : A, f x1 = f x2 -> x1 = x2forall (f0 : A -> list B) (l : list A) (y : B), In y (flat_map f0 l) <-> (exists x : A, In x l /\ In y (f0 x))A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}forall (f0 : A -> list B) (l : list A) (y : B), In y (flat_map f0 l) <-> (exists x : A, In x l /\ In y (f0 x))A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list By:BH:Falseexists x : A, False /\ In y (f0 x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list By:BH:exists x : A, False /\ In y (f0 x)FalseA, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:In y (f0 a ++ flat_map f0 l)exists x : A, (a = x \/ In x l) /\ In y (f0 x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:exists x : A, (a = x \/ In x l) /\ In y (f0 x)In y (f0 a ++ flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list By:BH:exists x : A, False /\ In y (f0 x)FalseA, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:In y (f0 a ++ flat_map f0 l)exists x : A, (a = x \/ In x l) /\ In y (f0 x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:exists x : A, (a = x \/ In x l) /\ In y (f0 x)In y (f0 a ++ flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:In y (f0 a ++ flat_map f0 l)exists x : A, (a = x \/ In x l) /\ In y (f0 x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:exists x : A, (a = x \/ In x l) /\ In y (f0 x)In y (f0 a ++ flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:In y (f0 a ++ flat_map f0 l)H0:In y (f0 a)exists x : A, (a = x \/ In x l) /\ In y (f0 x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:In y (f0 a ++ flat_map f0 l)H0:In y (flat_map f0 l)exists x : A, (a = x \/ In x l) /\ In y (f0 x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:exists x : A, (a = x \/ In x l) /\ In y (f0 x)In y (f0 a ++ flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:In y (f0 a ++ flat_map f0 l)H0:In y (flat_map f0 l)exists x : A, (a = x \/ In x l) /\ In y (f0 x)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:exists x : A, (a = x \/ In x l) /\ In y (f0 x)In y (f0 a ++ flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x0 : A, In x0 l /\ In y0 (f0 x0))y:BH:In y (f0 a ++ flat_map f0 l)H0:In y (flat_map f0 l)H1:In y (flat_map f0 l) -> exists x0 : A, In x0 l /\ In y (f0 x0)x:AH2:In x lH3:In y (f0 x)exists x0 : A, (a = x0 \/ In x0 l) /\ In y (f0 x0)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:exists x : A, (a = x \/ In x l) /\ In y (f0 x)In y (f0 a ++ flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:exists x : A, (a = x \/ In x l) /\ In y (f0 x)In y (f0 a ++ flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x : A, In x l /\ In y0 (f0 x))y:BH:exists x : A, (a = x \/ In x l) /\ In y (f0 x)In y (f0 a) \/ In y (flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x0 : A, In x0 l /\ In y0 (f0 x0))y:Bx:AH:a = xH1:In y (f0 x)In y (f0 a) \/ In y (flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x0 : A, In x0 l /\ In y0 (f0 x0))y:Bx:AH:In x lH1:In y (f0 x)In y (f0 a) \/ In y (flat_map f0 l)A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x0 : A, In x0 l /\ In y0 (f0 x0))y:Bx:AH:In x lH1:In y (f0 x)In y (f0 a) \/ In y (flat_map f0 l)exists x; auto. Qed. End Map.A, B:Typef:A -> BdecA:forall x1 x2 : A, {x1 = x2} + {x1 <> x2}decB:forall y1 y2 : B, {y1 = y2} + {y1 <> y2}f0:A -> list Ba:Al:list AIHl:forall y0 : B, In y0 (flat_map f0 l) <-> (exists x0 : A, In x0 l /\ In y0 (f0 x0))y:Bx:AH:In x lH1:In y (f0 x)H2:(exists x0 : A, In x0 l /\ In y (f0 x0)) -> In y (flat_map f0 l)exists x0 : A, In x0 l /\ In y (f0 x0)forall (A B : Type) (f : A -> list B) (l : list A), flat_map f l = concat (map f l)forall (A B : Type) (f : A -> list B) (l : list A), flat_map f l = concat (map f l)A, B:Typef:A -> list B[] = []A, B:Typef:A -> list Bx:Al:list AIH:flat_map f l = concat (map f l)f x ++ flat_map f l = f x ++ concat (map f l)reflexivity.A, B:Typef:A -> list B[] = []rewrite IH; reflexivity. Qed.A, B:Typef:A -> list Bx:Al:list AIH:flat_map f l = concat (map f l)f x ++ flat_map f l = f x ++ concat (map f l)forall (A B : Type) (f : A -> B) (l : list (list A)), map f (concat l) = concat (map (map f) l)forall (A B : Type) (f : A -> B) (l : list (list A)), map f (concat l) = concat (map (map f) l)A, B:Typef:A -> B[] = []A, B:Typef:A -> Bx:list Al:list (list A)IH:map f (concat l) = concat (map (map f) l)map f (x ++ concat l) = map f x ++ concat (map (map f) l)reflexivity.A, B:Typef:A -> B[] = []rewrite map_app, IH; reflexivity. Qed.A, B:Typef:A -> Bx:list Al:list (list A)IH:map f (concat l) = concat (map (map f) l)map f (x ++ concat l) = map f x ++ concat (map (map f) l)forall (A : Type) (l : list A), map (fun x : A => x) l = linduction l; simpl; auto; rewrite IHl; auto. Qed.forall (A : Type) (l : list A), map (fun x : A => x) l = lforall (A B C : Type) (f : A -> B) (g : B -> C) (l : list A), map g (map f l) = map (fun x : A => g (f x)) lforall (A B C : Type) (f : A -> B) (g : B -> C) (l : list A), map g (map f l) = map (fun x : A => g (f x)) lrewrite IHl; auto. Qed.A, B, C:Typef:A -> Bg:B -> Ca:Al:list AIHl:map g (map f l) = map (fun x : A => g (f x)) lg (f a) :: map g (map f l) = g (f a) :: map (fun x : A => g (f x)) lforall (A B : Type) (f g : A -> B) (l : list A), (forall a : A, In a l -> f a = g a) -> map f l = map g lforall (A B : Type) (f g : A -> B) (l : list A), (forall a : A, In a l -> f a = g a) -> map f l = map g lintros; rewrite H by intuition; rewrite IHl; auto. Qed.A, B:Typef, g:A -> Ba:Al:list AIHl:(forall a0 : A, In a0 l -> f a0 = g a0) -> map f l = map g l(forall a0 : A, a = a0 \/ In a0 l -> f a0 = g a0) -> f a :: map f l = g a :: map g lforall (A B : Type) (f g : A -> B) (l : list A), map f l = map g l -> forall a : A, In a l -> f a = g ainduction l; intros [=] ? []; subst; auto. Qed. Arguments ext_in_map [A B f g l].forall (A B : Type) (f g : A -> B) (l : list A), map f l = map g l -> forall a : A, In a l -> f a = g aforall (A B : Type) (f g : A -> B) (l : list A), map f l = map g l <-> (forall a : A, In a l -> f a = g a)split; [apply ext_in_map | apply map_ext_in]. Qed. Arguments map_ext_in_iff {A B f g l}.forall (A B : Type) (f g : A -> B) (l : list A), map f l = map g l <-> (forall a : A, In a l -> f a = g a)forall (A B : Type) (f g : A -> B), (forall a : A, f a = g a) -> forall l : list A, map f l = map g lintros; apply map_ext_in; auto. Qed. (************************************)forall (A B : Type) (f g : A -> B), (forall a : A, f a = g a) -> forall l : list A, map f l = map g l
Left-to-right iterator on lists
(************************************) Section Fold_Left_Recursor. Variables (A : Type) (B : Type). Variable f : A -> B -> A. Fixpoint fold_left (l:list B) (a0:A) : A := match l with | nil => a0 | cons b t => fold_left t (f a0 b) end.A, B:Typef:A -> B -> Aforall (l l' : list B) (i : A), fold_left (l ++ l') i = fold_left l' (fold_left l i)A, B:Typef:A -> B -> Aforall (l l' : list B) (i : A), fold_left (l ++ l') i = fold_left l' (fold_left l i)A, B:Typef:A -> B -> Aforall (l' : list B) (i : A), fold_left ([] ++ l') i = fold_left l' (fold_left [] i)A, B:Typef:A -> B -> Aa:Bl:list BIHl:forall (l' : list B) (i : A), fold_left (l ++ l') i = fold_left l' (fold_left l i)forall (l' : list B) (i : A), fold_left ((a :: l) ++ l') i = fold_left l' (fold_left (a :: l) i)A, B:Typef:A -> B -> Aa:Bl:list BIHl:forall (l' : list B) (i : A), fold_left (l ++ l') i = fold_left l' (fold_left l i)forall (l' : list B) (i : A), fold_left ((a :: l) ++ l') i = fold_left l' (fold_left (a :: l) i)A, B:Typef:A -> B -> Aa:Bl:list BIHl:forall (l'0 : list B) (i0 : A), fold_left (l ++ l'0) i0 = fold_left l'0 (fold_left l i0)l':list Bi:Afold_left ((a :: l) ++ l') i = fold_left l' (fold_left (a :: l) i)auto. Qed. End Fold_Left_Recursor.A, B:Typef:A -> B -> Aa:Bl:list BIHl:forall (l'0 : list B) (i0 : A), fold_left (l ++ l'0) i0 = fold_left l'0 (fold_left l i0)l':list Bi:Afold_left (l ++ l') (f i a) = fold_left l' (fold_left l (f i a))forall (A : Type) (l : list A), fold_left (fun (x : nat) (_ : A) => S x) l 0 = length lforall (A : Type) (l : list A), fold_left (fun (x : nat) (_ : A) => S x) l 0 = length lA:Typel:list Afold_left (fun (x : nat) (_ : A) => S x) l 0 = length lA:Typel:list Aforall n : nat, fold_left (fun (x : nat) (_ : A) => S x) l n = n + length lA:Typea:Al:list AIHl:forall n : nat, fold_left (fun (x : nat) (_ : A) => S x) l n = n + length lforall n : nat, fold_left (fun (x : nat) (_ : A) => S x) l (S n) = n + S (length l)simpl; auto with arith. Qed. (************************************)A:Typea:Al:list AIHl:forall n0 : nat, fold_left (fun (x : nat) (_ : A) => S x) l n0 = n0 + length ln:natS n + length l = n + S (length l)
Right-to-left iterator on lists
(************************************) Section Fold_Right_Recursor. Variables (A : Type) (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.forall (A B : Type) (f : A -> B -> B) (l l' : list A) (i : B), fold_right f i (l ++ l') = fold_right f (fold_right f i l') lforall (A B : Type) (f : A -> B -> B) (l l' : list A) (i : B), fold_right f i (l ++ l') = fold_right f (fold_right f i l') lA, B:Typef:A -> B -> Bforall (l' : list A) (i : B), fold_right f i ([] ++ l') = fold_right f (fold_right f i l') []A, B:Typef:A -> B -> Ba:Al:list AIHl:forall (l' : list A) (i : B), fold_right f i (l ++ l') = fold_right f (fold_right f i l') lforall (l' : list A) (i : B), fold_right f i ((a :: l) ++ l') = fold_right f (fold_right f i l') (a :: l)A, B:Typef:A -> B -> Ba:Al:list AIHl:forall (l' : list A) (i : B), fold_right f i (l ++ l') = fold_right f (fold_right f i l') lforall (l' : list A) (i : B), fold_right f i ((a :: l) ++ l') = fold_right f (fold_right f i l') (a :: l)f_equal; auto. Qed.A, B:Typef:A -> B -> Ba:Al:list AIHl:forall (l'0 : list A) (i0 : B), fold_right f i0 (l ++ l'0) = fold_right f (fold_right f i0 l'0) ll':list Ai:Bf a (fold_right f i (l ++ l')) = f a (fold_right f (fold_right f i l') l)forall (A B : Type) (f : A -> B -> B) (l : list A) (i : B), fold_right f i (rev l) = fold_left (fun (x : B) (y : A) => f y x) l iforall (A B : Type) (f : A -> B -> B) (l : list A) (i : B), fold_right f i (rev l) = fold_left (fun (x : B) (y : A) => f y x) l iA, B:Typef:A -> B -> Bforall i : B, fold_right f i (rev []) = fold_left (fun (x : B) (y : A) => f y x) [] iA, B:Typef:A -> B -> Ba:Al:list AIHl:forall i : B, fold_right f i (rev l) = fold_left (fun (x : B) (y : A) => f y x) l iforall i : B, fold_right f i (rev (a :: l)) = fold_left (fun (x : B) (y : A) => f y x) (a :: l) iA, B:Typef:A -> B -> Ba:Al:list AIHl:forall i : B, fold_right f i (rev l) = fold_left (fun (x : B) (y : A) => f y x) l iforall i : B, fold_right f i (rev (a :: l)) = fold_left (fun (x : B) (y : A) => f y x) (a :: l) iA, B:Typef:A -> B -> Ba:Al:list AIHl:forall i0 : B, fold_right f i0 (rev l) = fold_left (fun (x : B) (y : A) => f y x) l i0i:Bfold_right f i (rev (a :: l)) = fold_left (fun (x : B) (y : A) => f y x) (a :: l) irewrite fold_right_app; simpl; auto. Qed.A, B:Typef:A -> B -> Ba:Al:list AIHl:forall i0 : B, fold_right f i0 (rev l) = fold_left (fun (x : B) (y : A) => f y x) l i0i:Bfold_right f i (rev l ++ [a]) = fold_left (fun (x : B) (y : A) => f y x) l (f a i)forall (A : Type) (f : A -> A -> A), (forall x y z : A, f x (f y z) = f (f x y) z) -> forall a0 : A, (forall y : A, f a0 y = f y a0) -> forall l : list A, fold_left f l a0 = fold_right f a0 lforall (A : Type) (f : A -> A -> A), (forall x y z : A, f x (f y z) = f (f x y) z) -> forall a0 : A, (forall y : A, f a0 y = f y a0) -> forall l : list A, fold_left f l a0 = fold_right f a0 lA:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0l:list Afold_left f l a0 = fold_right f a0 lA:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a1:Al:list AIHl:fold_left f l a0 = fold_right f a0 lfold_left f (a1 :: l) a0 = fold_right f a0 (a1 :: l)A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a1:Al:list AIHl:fold_left f l a0 = fold_right f a0 lfold_left f l (f a0 a1) = f a1 (fold_right f a0 l)A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a1:Al:list AIHl:fold_left f l a0 = fold_right f a0 lfold_left f l (f a0 a1) = f a1 (fold_left f l a0)A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a1:Al:list Afold_left f l (f a0 a1) = f a1 (fold_left f l a0)A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0l:list Aforall a1 : A, fold_left f l (f a0 a1) = f a1 (fold_left f l a0)A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a:Al:list AIHl:forall a1 : A, fold_left f l (f a0 a1) = f a1 (fold_left f l a0)forall a1 : A, fold_left f (a :: l) (f a0 a1) = f a1 (fold_left f (a :: l) a0)A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a:Al:list AIHl:forall a1 : A, fold_left f l (f a0 a1) = f a1 (fold_left f l a0)forall a1 : A, fold_left f l (f (f a0 a1) a) = f a1 (fold_left f l (f a0 a))A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a:Al:list AIHl:forall a2 : A, fold_left f l (f a0 a2) = f a2 (fold_left f l a0)a1:Afold_left f l (f (f a0 a1) a) = f a1 (fold_left f l (f a0 a))A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a:Al:list AIHl:forall a2 : A, fold_left f l (f a0 a2) = f a2 (fold_left f l a0)a1:Afold_left f l (f a0 (f a1 a)) = f a1 (fold_left f l (f a0 a))A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a:Al:list AIHl:forall a2 : A, fold_left f l (f a0 a2) = f a2 (fold_left f l a0)a1:Af (f a1 a) (fold_left f l a0) = f a1 (fold_left f l (f a0 a))auto. Qed.A:Typef:A -> A -> Aassoc:forall x y z : A, f x (f y z) = f (f x y) za0:Acomma0:forall y : A, f a0 y = f y a0a:Al:list AIHl:forall a2 : A, fold_left f l (f a0 a2) = f a2 (fold_left f l a0)a1:Af (f a1 a) (fold_left f l a0) = f a1 (f a (fold_left f l a0))
(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) : 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. (*************************************)
(*************************************) 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) : bool := match l with | nil => false | a::l => f a || existsb l end.A:Typef:A -> boolforall l : list A, existsb l = true <-> (exists x : A, In x l /\ f x = true)A:Typef:A -> boolforall l : list A, existsb l = true <-> (exists x : A, In x l /\ f x = true)A:Typef:A -> boolH:false = trueexists x : A, False /\ f x = trueA:Typef:A -> boolH:exists x : A, False /\ f x = truefalse = trueA:Typef:A -> boola:Al:list AH:existsb l = true -> exists x : A, In x l /\ f x = trueH0:(exists x : A, In x l /\ f x = true) -> existsb l = trueH1:f a || existsb l = trueexists x : A, (a = x \/ In x l) /\ f x = trueA:Typef:A -> boola:Al:list AH:existsb l = true -> exists x : A, In x l /\ f x = trueH0:(exists x : A, In x l /\ f x = true) -> existsb l = trueH1:exists x : A, (a = x \/ In x l) /\ f x = truef a || existsb l = trueA:Typef:A -> boolH:exists x : A, False /\ f x = truefalse = trueA:Typef:A -> boola:Al:list AH:existsb l = true -> exists x : A, In x l /\ f x = trueH0:(exists x : A, In x l /\ f x = true) -> existsb l = trueH1:f a || existsb l = trueexists x : A, (a = x \/ In x l) /\ f x = trueA:Typef:A -> boola:Al:list AH:existsb l = true -> exists x : A, In x l /\ f x = trueH0:(exists x : A, In x l /\ f x = true) -> existsb l = trueH1:exists x : A, (a = x \/ In x l) /\ f x = truef a || existsb l = trueA:Typef:A -> boola:Al:list AH:existsb l = true -> exists x : A, In x l /\ f x = trueH0:(exists x : A, In x l /\ f x = true) -> existsb l = trueH1:f a || existsb l = trueexists x : A, (a = x \/ In x l) /\ f x = trueA:Typef:A -> boola:Al:list AH:existsb l = true -> exists x : A, In x l /\ f x = trueH0:(exists x : A, In x l /\ f x = true) -> existsb l = trueH1:exists x : A, (a = x \/ In x l) /\ f x = truef a || existsb l = trueA:Typef:A -> boola:Al:list AH:existsb l = true -> exists x : A, In x l /\ f x = trueH0:(exists x : A, In x l /\ f x = true) -> existsb l = trueH1:exists x : A, (a = x \/ In x l) /\ f x = truef a || existsb l = trueA:Typef:A -> boola:Al:list AH:existsb l = true -> exists x0 : A, In x0 l /\ f x0 = truex:AH2:f x = trueH0:forall x0 : A, (fun x1 : A => In x1 l /\ f x1 = true) x0 -> existsb l = trueH1:a = xf a || existsb l = truerewrite H2; auto. Qed.A:Typef:A -> booll:list AH:existsb l = true -> exists x0 : A, In x0 l /\ f x0 = truex:AH2:f x = trueH0:forall x0 : A, (fun x1 : A => In x1 l /\ f x1 = true) x0 -> existsb l = truef x || existsb l = trueA:Typef:A -> boolforall (l : list A) (n : nat) (d : A), n < length l -> existsb l = false -> f (nth n l d) = falseA:Typef:A -> boolforall (l : list A) (n : nat) (d : A), n < length l -> existsb l = false -> f (nth n l d) = falseA:Typef:A -> boolforall (n : nat) (d : A), n < length [] -> existsb [] = false -> f (nth n [] d) = falseA:Typef:A -> boola:Al:list AIHl:forall (n : nat) (d : A), n < length l -> existsb l = false -> f (nth n l d) = falseforall (n : nat) (d : A), n < length (a :: l) -> existsb (a :: l) = false -> f (nth n (a :: l) d) = falseA:Typef:A -> boola:Al:list AIHl:forall (n : nat) (d : A), n < length l -> existsb l = false -> f (nth n l d) = falseforall (n : nat) (d : A), n < length (a :: l) -> existsb (a :: l) = false -> f (nth n (a :: l) d) = falseA:Typef:A -> boola:Al:list AIHl:forall (n0 : nat) (d0 : A), n0 < length l -> existsb l = false -> f (nth n0 l d0) = falsen:natd:AH:n < S (length l)H0:f a || existsb l = falsef match n with | 0 => a | S m => nth m l d end = falseA:Typef:A -> boola:Al:list AIHl:forall (n0 : nat) (d0 : A), n0 < length l -> existsb l = false -> f (nth n0 l d0) = falsen:natd:AH:n < S (length l)H1:f a = falseH2:existsb l = falsef match n with | 0 => a | S m => nth m l d end = falserewrite IHl; auto with arith. Qed.A:Typef:A -> boola:Al:list AIHl:forall (n0 : nat) (d0 : A), n0 < length l -> existsb l = false -> f (nth n0 l d0) = falsen:natd:AH:S n < S (length l)H1:f a = falseH2:existsb l = falsef (nth n l d) = falseA:Typef:A -> boolforall l1 l2 : list A, existsb (l1 ++ l2) = existsb l1 || existsb l2A:Typef:A -> boolforall l1 l2 : list A, existsb (l1 ++ l2) = existsb l1 || existsb l2A:Typef:A -> booll2:list Aexistsb l2 = existsb l2A:Typef:A -> boola:Al1:list AIHl1:forall l0 : list A, existsb (l1 ++ l0) = existsb l1 || existsb l0l2:list Af a || existsb (l1 ++ l2) = f a || existsb l1 || existsb l2case (f a); simpl; solve[auto]. Qed.A:Typef:A -> boola:Al1:list AIHl1:forall l0 : list A, existsb (l1 ++ l0) = existsb l1 || existsb l0l2:list Af a || existsb (l1 ++ l2) = f a || existsb l1 || existsb l2
find whether a boolean function is satisfied by
all the elements of a list.
Fixpoint forallb (l:list A) : bool := match l with | nil => true | a::l => f a && forallb l end.A:Typef:A -> boolforall l : list A, forallb l = true <-> (forall x : A, In x l -> f x = true)A:Typef:A -> boolforall l : list A, forallb l = true <-> (forall x : A, In x l -> f x = true)A:Typef:A -> boola:Al:list AH:forallb l = true -> forall x0 : A, In x0 l -> f x0 = trueH0:(forall x0 : A, In x0 l -> f x0 = true) -> forallb l = trueH1:f a && forallb l = truex:AH3:a = xf x = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x0 : A, In x0 l -> f x0 = trueH0:(forall x0 : A, In x0 l -> f x0 = true) -> forallb l = trueH1:f a && forallb l = truex:AH3:In x lf x = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x : A, In x l -> f x = trueH0:(forall x : A, In x l -> f x = true) -> forallb l = trueH1:forall x : A, a = x \/ In x l -> f x = truef a && forallb l = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x0 : A, In x0 l -> f x0 = trueH0:(forall x0 : A, In x0 l -> f x0 = true) -> forallb l = trueH1:f a && forallb l = truex:AH3:a = xH2:f a = trueH4:forallb l = truef x = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x0 : A, In x0 l -> f x0 = trueH0:(forall x0 : A, In x0 l -> f x0 = true) -> forallb l = trueH1:f a && forallb l = truex:AH3:In x lf x = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x : A, In x l -> f x = trueH0:(forall x : A, In x l -> f x = true) -> forallb l = trueH1:forall x : A, a = x \/ In x l -> f x = truef a && forallb l = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x0 : A, In x0 l -> f x0 = trueH0:(forall x0 : A, In x0 l -> f x0 = true) -> forallb l = trueH1:f a && forallb l = truex:AH3:In x lf x = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x : A, In x l -> f x = trueH0:(forall x : A, In x l -> f x = true) -> forallb l = trueH1:forall x : A, a = x \/ In x l -> f x = truef a && forallb l = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x : A, In x l -> f x = trueH0:(forall x : A, In x l -> f x = true) -> forallb l = trueH1:forall x : A, a = x \/ In x l -> f x = truef a && forallb l = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x : A, In x l -> f x = trueH0:(forall x : A, In x l -> f x = true) -> forallb l = trueH1:forall x : A, a = x \/ In x l -> f x = trueforallb l = trueA:Typef:A -> boola:Al:list AH:forallb l = true -> forall x : A, In x l -> f x = trueH0:(forall x : A, In x l -> f x = true) -> forallb l = trueH1:forall x : A, a = x \/ In x l -> f x = trueH2:forallb l = truef a && forallb l = truerewrite H1; auto. Qed.A:Typef:A -> boola:Al:list AH:forallb l = true -> forall x : A, In x l -> f x = trueH0:(forall x : A, In x l -> f x = true) -> forallb l = trueH1:forall x : A, a = x \/ In x l -> f x = trueH2:forallb l = truef a && forallb l = trueA:Typef:A -> boolforall l1 l2 : list A, forallb (l1 ++ l2) = forallb l1 && forallb l2A:Typef:A -> boolforall l1 l2 : list A, forallb (l1 ++ l2) = forallb l1 && forallb l2A:Typef:A -> boolforall l2 : list A, forallb l2 = forallb l2A:Typef:A -> boola:Al1:list AIHl1:forall l2 : list A, forallb (l1 ++ l2) = forallb l1 && forallb l2forall l2 : list A, f a && forallb (l1 ++ l2) = f a && forallb l1 && forallb l2case (f a); simpl; solve[auto]. Qed.A:Typef:A -> boola:Al1:list AIHl1:forall l2 : list A, forallb (l1 ++ l2) = forallb l1 && forallb l2forall l2 : list A, f a && forallb (l1 ++ l2) = f a && forallb l1 && forallb l2
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.A:Typef:A -> boolforall (x : A) (l : list A), In x (filter l) <-> In x l /\ f x = trueA:Typef:A -> boolforall (x : A) (l : list A), In x (filter l) <-> In x l /\ f x = trueA:Typef:A -> boolx:AFalse <-> False /\ f x = trueA:Typef:A -> boolx, a:Al:list AIHl:In x (filter l) <-> In x l /\ f x = trueIn x (if f a then a :: filter l else filter l) <-> (a = x \/ In x l) /\ f x = trueA:Typef:A -> boolx, a:Al:list AIHl:In x (filter l) <-> In x l /\ f x = trueIn x (if f a then a :: filter l else filter l) <-> (a = x \/ In x l) /\ f x = truecase_eq (f a); intros; simpl; intuition congruence. Qed.A:Typef:A -> boolx, a:Al:list AIHl:In x (filter l) <-> In x l /\ f x = trueIn x (if f a then a :: filter l else filter l) <-> (a = x \/ In x l) /\ f x = true
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.A:Typef:A -> booll:list Ax:Afind l = Some x -> In x l /\ f x = trueA:Typef:A -> booll:list Ax:Afind l = Some x -> In x l /\ f x = trueA:Typef:A -> boola:Al:list Ax:AIH:find l = Some x -> In x l /\ f x = true(if f a then Some a else find l) = Some x -> (a = x \/ In x l) /\ f x = trueA:Typef:A -> boola:Al:list Ax:AIH:find l = Some x -> In x l /\ f x = trueHa:f a = trueEq:Some a = Some x(a = x \/ In x l) /\ f x = trueA:Typef:A -> boola:Al:list Ax:AIH:find l = Some x -> In x l /\ f x = trueHa:f a = falseEq:find l = Some x(a = x \/ In x l) /\ f x = trueinjection Eq as ->; auto.A:Typef:A -> boola:Al:list Ax:AIH:find l = Some x -> In x l /\ f x = trueHa:f a = trueEq:Some a = Some x(a = x \/ In x l) /\ f x = truedestruct (IH Eq); auto. Qed.A:Typef:A -> boola:Al:list Ax:AIH:find l = Some x -> In x l /\ f x = trueHa:f a = falseEq:find l = Some x(a = x \/ In x l) /\ f x = trueA:Typef:A -> booll:list Afind l = None -> forall x : A, In x l -> f x = falseA:Typef:A -> booll:list Afind l = None -> forall x : A, In x l -> f x = falseA:Typef:A -> boola:Al:list AIH:find l = None -> forall x : A, In x l -> f x = false(if f a then Some a else find l) = None -> forall x : A, a = x \/ In x l -> f x = falsedestruct IN as [<-|IN]; auto. Qed.A:Typef:A -> boola:Al:list AIH:find l = None -> forall x0 : A, In x0 l -> f x0 = falseHa:f a = falseEq:find l = Nonex:AIN:a = x \/ In x lf x = false
partition
Fixpoint partition (l:list A) : 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.A:Typef:A -> boola:Al, l1, l2:list Apartition l = (l1, l2) -> f a = true -> partition (a :: l) = (a :: l1, l2)A:Typef:A -> boola:Al, l1, l2:list Apartition l = (l1, l2) -> f a = true -> partition (a :: l) = (a :: l1, l2)now intros -> ->. Qed.A:Typef:A -> boola:Al, l1, l2:list Apartition l = (l1, l2) -> f a = true -> (let (g, d) := partition l in if f a then (a :: g, d) else (g, a :: d)) = (a :: l1, l2)A:Typef:A -> boola:Al, l1, l2:list Apartition l = (l1, l2) -> f a = false -> partition (a :: l) = (l1, a :: l2)A:Typef:A -> boola:Al, l1, l2:list Apartition l = (l1, l2) -> f a = false -> partition (a :: l) = (l1, a :: l2)now intros -> ->. Qed.A:Typef:A -> boola:Al, l1, l2:list Apartition l = (l1, l2) -> f a = false -> (let (g, d) := partition l in if f a then (a :: g, d) else (g, a :: d)) = (l1, a :: l2)A:Typef:A -> booll, l1, l2:list Apartition l = (l1, l2) -> length l = length l1 + length l2A:Typef:A -> booll, l1, l2:list Apartition l = (l1, l2) -> length l = length l1 + length l2A:Typef:A -> booll:list Aforall l1 l2 : list A, partition l = (l1, l2) -> length l = length l1 + length l2A:Typef:A -> booll1, l2:list Apartition [] = (l1, l2) -> length [] = length l1 + length l2A:Typef:A -> boola:Al':list AHrec:forall l0 l3 : list A, partition l' = (l0, l3) -> length l' = length l0 + length l3l1, l2:list Apartition (a :: l') = (l1, l2) -> length (a :: l') = length l1 + length l2now intros [= <- <- ].A:Typef:A -> booll1, l2:list Apartition [] = (l1, l2) -> length [] = length l1 + length l2A:Typef:A -> boola:Al':list AHrec:forall l0 l3 : list A, partition l' = (l0, l3) -> length l' = length l0 + length l3l1, l2:list Apartition (a :: l') = (l1, l2) -> length (a :: l') = length l1 + length l2destruct (f a), (partition l') as (left, right); intros [= <- <- ]; simpl; rewrite (Hrec left right); auto. Qed.A:Typef:A -> boola:Al':list AHrec:forall l0 l3 : list A, partition l' = (l0, l3) -> length l' = length l0 + length l3l1, l2:list A(let (g, d) := partition l' in if f a then (a :: g, d) else (g, a :: d)) = (l1, l2) -> S (length l') = length l1 + length l2A:Typef:A -> booll:list Apartition l = ([], []) <-> l = []A:Typef:A -> booll:list Apartition l = ([], []) <-> l = []A:Typef:A -> booll:list Apartition l = ([], []) -> l = []A:Typef:A -> booll:list Al = [] -> partition l = ([], [])A:Typef:A -> booll:list Apartition l = ([], []) -> l = []A:Typef:A -> boolpartition [] = ([], []) -> [] = []A:Typef:A -> boola:Al':list Apartition (a :: l') = ([], []) -> a :: l' = []intuition.A:Typef:A -> boolpartition [] = ([], []) -> [] = []A:Typef:A -> boola:Al':list Apartition (a :: l') = ([], []) -> a :: l' = []destruct (f a), (partition l'); now intros [= -> ->].A:Typef:A -> boola:Al':list A(let (g, d) := partition l' in if f a then (a :: g, d) else (g, a :: d)) = ([], []) -> a :: l' = []now intros ->. Qed.A:Typef:A -> booll:list Al = [] -> partition l = ([], [])A:Typef:A -> booll, l1, l2:list Apartition l = (l1, l2) -> forall x : A, In x l <-> In x l1 \/ In x l2A:Typef:A -> booll, l1, l2:list Apartition l = (l1, l2) -> forall x : A, In x l <-> In x l1 \/ In x l2A:Typef:A -> booll:list Aforall l1 l2 : list A, partition l = (l1, l2) -> forall x : A, In x l <-> In x l1 \/ In x l2A:Typef:A -> booll1, l2:list AEq:([], []) = (l1, l2)x:AFalse <-> In x l1 \/ In x l2A:Typef:A -> boola:Al':list AHrec:forall l0 l3 : list A, partition l' = (l0, l3) -> forall x0 : A, In x0 l' <-> In x0 l0 \/ In x0 l3l1, l2:list AEq:(let (g, d) := partition l' in if f a then (a :: g, d) else (g, a :: d)) = (l1, l2)x:Aa = x \/ In x l' <-> In x l1 \/ In x l2A:Typef:A -> booll1, l2:list AEq:([], []) = (l1, l2)x:AFalse <-> In x l1 \/ In x l2tauto.A:Typef:A -> boolx:AFalse <-> In x [] \/ In x []A:Typef:A -> boola:Al':list AHrec:forall l0 l3 : list A, partition l' = (l0, l3) -> forall x0 : A, In x0 l' <-> In x0 l0 \/ In x0 l3l1, l2:list AEq:(let (g, d) := partition l' in if f a then (a :: g, d) else (g, a :: d)) = (l1, l2)x:Aa = x \/ In x l' <-> In x l1 \/ In x l2A:Typef:A -> boola:Al', left, right:list AHrec:forall l0 l3 : list A, (left, right) = (l0, l3) -> forall x0 : A, In x0 l' <-> In x0 l0 \/ In x0 l3l1, l2:list AEq:(if f a then (a :: left, right) else (left, a :: right)) = (l1, l2)x:Aa = x \/ In x l' <-> In x l1 \/ In x l2destruct (f a); injection Eq as <- <-; simpl; tauto. Qed. End Bool. (******************************************************)A:Typef:A -> boola:Al', left, right:list Ax:AHrec:In x l' <-> In x left \/ In x rightl1, l2:list AEq:(if f a then (a :: left, right) else (left, a :: right)) = (l1, l2)a = x \/ In x l' <-> In x l1 \/ In x l2
(******************************************************) Section ListPairs. Variables (A : Type) (B : Type).
split derives two lists from a list of pairs
Fixpoint split (l:list (A*B)) : list A * list B := match l with | [] => ([], []) | (x,y) :: tl => let (left,right) := split tl in (x::left, y::right) end.A, B:Typeforall (l : list (A * B)) (p : A * B), In p l -> In (fst p) (fst (split l))A, B:Typeforall (l : list (A * B)) (p : A * B), In p l -> In (fst p) (fst (split l))A, B:Typea:(A * B)%typel:list (A * B)IHl:forall p0 : A * B, In p0 l -> In (fst p0) (fst (split l))p:(A * B)%typeH:a = p \/ In p lIn (fst p) (fst (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right)))A, B:Typea:Ab0:Bl:list (A * B)l0:list Al1:list BIHl:forall p : A * B, In p l -> In (fst p) l0a0:Ab:BH:(a, b0) = (a0, b) \/ In (a0, b) la = a0 \/ In a0 l0A, B:Typea:Ab0:Bl:list (A * B)l0:list Al1:list BIHl:forall p : A * B, In p l -> In (fst p) l0a0:Ab:BH:(a, b0) = (a0, b)a = a0 \/ In a0 l0A, B:Typea:Ab0:Bl:list (A * B)l0:list Al1:list BIHl:forall p : A * B, In p l -> In (fst p) l0a0:Ab:BH:In (a0, b) la = a0 \/ In a0 l0right; apply (IHl (a0,b) H). Qed.A, B:Typea:Ab0:Bl:list (A * B)l0:list Al1:list BIHl:forall p : A * B, In p l -> In (fst p) l0a0:Ab:BH:In (a0, b) la = a0 \/ In a0 l0A, B:Typeforall (l : list (A * B)) (p : A * B), In p l -> In (snd p) (snd (split l))A, B:Typeforall (l : list (A * B)) (p : A * B), In p l -> In (snd p) (snd (split l))A, B:Typea:(A * B)%typel:list (A * B)IHl:forall p0 : A * B, In p0 l -> In (snd p0) (snd (split l))p:(A * B)%typeH:a = p \/ In p lIn (snd p) (snd (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right)))A, B:Typea:Ab0:Bl:list (A * B)l0:list Al1:list BIHl:forall p : A * B, In p l -> In (snd p) l1a0:Ab:BH:(a, b0) = (a0, b) \/ In (a0, b) lb0 = b \/ In b l1A, B:Typea:Ab0:Bl:list (A * B)l0:list Al1:list BIHl:forall p : A * B, In p l -> In (snd p) l1a0:Ab:BH:(a, b0) = (a0, b)b0 = b \/ In b l1A, B:Typea:Ab0:Bl:list (A * B)l0:list Al1:list BIHl:forall p : A * B, In p l -> In (snd p) l1a0:Ab:BH:In (a0, b) lb0 = b \/ In b l1right; apply (IHl (a0,b) H). Qed.A, B:Typea:Ab0:Bl:list (A * B)l0:list Al1:list BIHl:forall p : A * B, In p l -> In (snd p) l1a0:Ab:BH:In (a0, b) lb0 = b \/ In b l1A, B:Typeforall (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))A, B:Typeforall (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))A, B:Typeforall (n : nat) (d : A * B), nth n [] d = (nth n (fst (split [])) (fst d), nth n (snd (split [])) (snd d))A, B:Typea:(A * B)%typel:list (A * B)IHl:forall (n : nat) (d : A * B), nth n l d = (nth n (fst (split l)) (fst d), nth n (snd (split l)) (snd d))forall (n : nat) (d : A * B), nth n (a :: l) d = (nth n (fst (split (a :: l))) (fst d), nth n (snd (split (a :: l))) (snd d))A, B:Typea:(A * B)%typel:list (A * B)IHl:forall (n : nat) (d : A * B), nth n l d = (nth n (fst (split l)) (fst d), nth n (snd (split l)) (snd d))forall (n : nat) (d : A * B), nth n (a :: l) d = (nth n (fst (split (a :: l))) (fst d), nth n (snd (split (a :: l))) (snd d))A, B:Typea:(A * B)%typel:list (A * B)IHl:forall (n : nat) (d : A * B), nth n l d = (nth n (fst (split l)) (fst d), nth n (snd (split l)) (snd d))a0:Ab:Ba = (nth 0 (fst (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right))) a0, nth 0 (snd (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right))) b)A, B:Typea:(A * B)%typel:list (A * B)IHl:forall (n0 : nat) (d : A * B), nth n0 l d = (nth n0 (fst (split l)) (fst d), nth n0 (snd (split l)) (snd d))n:nata0:Ab:Bnth n l (a0, b) = (nth (S n) (fst (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right))) a0, nth (S n) (snd (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right))) b)A, B:Typea:(A * B)%typel:list (A * B)IHl:forall (n0 : nat) (d : A * B), nth n0 l d = (nth n0 (fst (split l)) (fst d), nth n0 (snd (split l)) (snd d))n:nata0:Ab:Bnth n l (a0, b) = (nth (S n) (fst (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right))) a0, nth (S n) (snd (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right))) b)apply IHl. Qed.A, B:Typea:Ab0:Bl:list (A * B)l0:list Al1:list BIHl:forall (n0 : nat) (d : A * B), nth n0 l d = (nth n0 l0 (fst d), nth n0 l1 (snd d))n:nata0:Ab:Bnth n l (a0, b) = (nth n l0 a0, nth n l1 b)A, B:Typeforall l : list (A * B), length (fst (split l)) = length lA, B:Typeforall l : list (A * B), length (fst (split l)) = length ldestruct a; destruct (split l); simpl; auto. Qed.A, B:Typea:(A * B)%typel:list (A * B)IHl:length (fst (split l)) = length llength (fst (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right))) = S (length l)A, B:Typeforall l : list (A * B), length (snd (split l)) = length lA, B:Typeforall l : list (A * B), length (snd (split l)) = length ldestruct a; destruct (split l); simpl; auto. Qed.A, B:Typea:(A * B)%typel:list (A * B)IHl:length (snd (split l)) = length llength (snd (let (x, y) := a in let (left, right) := split l in (x :: left, y :: right))) = S (length l)
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) : list (A*B) := match l,l' with | x::tl, y::tl' => (x,y)::(combine tl tl') | _, _ => nil end.A, B:Typeforall l : list (A * B), let (l1, l2) := split l in combine l1 l2 = lA, B:Typeforall l : list (A * B), let (l1, l2) := split l in combine l1 l2 = lA, B:Typelet (l1, l2) := split [] in combine l1 l2 = []A, B:Typea:(A * B)%typel:list (A * B)IHl:let (l1, l2) := split l in combine l1 l2 = llet (l1, l2) := split (a :: l) in combine l1 l2 = a :: lA, B:Typea:(A * B)%typel:list (A * B)IHl:let (l1, l2) := split l in combine l1 l2 = llet (l1, l2) := split (a :: l) in combine l1 l2 = a :: lA, B:Typea:Ab:Bl:list (A * B)IHl:let (l1, l2) := split l in combine l1 l2 = llet (l1, l2) := let (left, right) := split l in (a :: left, b :: right) in combine l1 l2 = (a, b) :: lf_equal; auto. Qed.A, B:Typea:Ab:Bl:list (A * B)l0:list Al1:list BIHl:combine l0 l1 = l(a, b) :: combine l0 l1 = (a, b) :: lA, B:Typeforall (l : list A) (l' : list B), length l = length l' -> split (combine l l') = (l, l')A, B:Typeforall (l : list A) (l' : list B), length l = length l' -> split (combine l l') = (l, l')now intros [= ->%IHl]. Qed.A, B:Typea:Al:list AIHl:forall l'0 : list B, length l = length l'0 -> split (combine l l'0) = (l, l'0)b:Bl':list BS (length l) = S (length l') -> (let (left, right) := split (combine l l') in (a :: left, b :: right)) = (a :: l, b :: l')A, B:Typeforall (l : list A) (l' : list B) (x : A) (y : B), In (x, y) (combine l l') -> In x lA, B:Typeforall (l : list A) (l' : list B) (x : A) (y : B), In (x, y) (combine l l') -> In x lA, B:Typeforall (l' : list B) (x : A) (y : B), In (x, y) (combine [] l') -> In x []A, B:Typea:Al:list AIHl:forall (l' : list B) (x : A) (y : B), In (x, y) (combine l l') -> In x lforall (l' : list B) (x : A) (y : B), In (x, y) (combine (a :: l) l') -> In x (a :: l)A, B:Typea:Al:list AIHl:forall (l' : list B) (x : A) (y : B), In (x, y) (combine l l') -> In x lforall (l' : list B) (x : A) (y : B), In (x, y) (combine (a :: l) l') -> In x (a :: l)A, B:Typea:Al:list AIHl:forall (l' : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l') -> In x0 lx:Ay:BH:Falsea = x \/ In x lA, B:Typea:Al:list AIHl:forall (l'0 : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l'0) -> In x0 lb:Bl':list Bx:Ay:BH:(a, b) = (x, y) \/ In (x, y) (combine l l')a = x \/ In x lA, B:Typea:Al:list AIHl:forall (l'0 : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l'0) -> In x0 lb:Bl':list Bx:Ay:BH:(a, b) = (x, y) \/ In (x, y) (combine l l')a = x \/ In x lA, B:Typea:Al:list AIHl:forall (l'0 : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l'0) -> In x0 lb:Bl':list Bx:Ay:BH:(a, b) = (x, y)a = x \/ In x lA, B:Typea:Al:list AIHl:forall (l'0 : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l'0) -> In x0 lb:Bl':list Bx:Ay:BH:In (x, y) (combine l l')a = x \/ In x lright; apply IHl with l' y; auto. Qed.A, B:Typea:Al:list AIHl:forall (l'0 : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l'0) -> In x0 lb:Bl':list Bx:Ay:BH:In (x, y) (combine l l')a = x \/ In x lA, B:Typeforall (l : list A) (l' : list B) (x : A) (y : B), In (x, y) (combine l l') -> In y l'A, B:Typeforall (l : list A) (l' : list B) (x : A) (y : B), In (x, y) (combine l l') -> In y l'A, B:Typeforall (l' : list B) (x : A) (y : B), In (x, y) (combine [] l') -> In y l'A, B:Typea:Al:list AIHl:forall (l' : list B) (x : A) (y : B), In (x, y) (combine l l') -> In y l'forall (l' : list B) (x : A) (y : B), In (x, y) (combine (a :: l) l') -> In y l'A, B:Typea:Al:list AIHl:forall (l' : list B) (x : A) (y : B), In (x, y) (combine l l') -> In y l'forall (l' : list B) (x : A) (y : B), In (x, y) (combine (a :: l) l') -> In y l'A, B:Typea:Al:list AIHl:forall (l'0 : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l'0) -> In y0 l'0b:Bl':list Bx:Ay:BH:(a, b) = (x, y) \/ In (x, y) (combine l l')b = y \/ In y l'A, B:Typea:Al:list AIHl:forall (l'0 : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l'0) -> In y0 l'0b:Bl':list Bx:Ay:BH:(a, b) = (x, y)b = y \/ In y l'A, B:Typea:Al:list AIHl:forall (l'0 : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l'0) -> In y0 l'0b:Bl':list Bx:Ay:BH:In (x, y) (combine l l')b = y \/ In y l'right; apply IHl with x; auto. Qed.A, B:Typea:Al:list AIHl:forall (l'0 : list B) (x0 : A) (y0 : B), In (x0, y0) (combine l l'0) -> In y0 l'0b:Bl':list Bx:Ay:BH:In (x, y) (combine l l')b = y \/ In y l'A, B:Typeforall (l : list A) (l' : list B), length (combine l l') = Init.Nat.min (length l) (length l')A, B:Typeforall (l : list A) (l' : list B), length (combine l l') = Init.Nat.min (length l) (length l')A, B:Typeforall l' : list B, length (combine [] l') = Init.Nat.min (length []) (length l')A, B:Typea:Al:list AIHl:forall l' : list B, length (combine l l') = Init.Nat.min (length l) (length l')forall l' : list B, length (combine (a :: l) l') = Init.Nat.min (length (a :: l)) (length l')destruct l'; simpl; auto. Qed.A, B:Typea:Al:list AIHl:forall l' : list B, length (combine l l') = Init.Nat.min (length l) (length l')forall l' : list B, length (combine (a :: l) l') = Init.Nat.min (length (a :: l)) (length l')A, B:Typeforall (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)A, B:Typeforall (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)A, B:Typen:natx:Ay:BH:length [] = length []nth n (combine [] []) (x, y) = (nth n [] x, nth n [] y)A, B:Typea:Al:list AIHl:forall (l'0 : list B) (n0 : nat) (x0 : A) (y0 : B), length l = length l'0 -> nth n0 (combine l l'0) (x0, y0) = (nth n0 l x0, nth n0 l'0 y0)b:Bl':list Bn:natx:Ay:BH:length (a :: l) = length (b :: l')nth n (combine (a :: l) (b :: l')) (x, y) = (nth n (a :: l) x, nth n (b :: l') y)destruct n; simpl in *; auto. Qed.A, B:Typea:Al:list AIHl:forall (l'0 : list B) (n0 : nat) (x0 : A) (y0 : B), length l = length l'0 -> nth n0 (combine l l'0) (x0, y0) = (nth n0 l x0, nth n0 l'0 y0)b:Bl':list Bn:natx:Ay:BH:length (a :: l) = length (b :: l')nth n (combine (a :: l) (b :: l')) (x, y) = (nth n (a :: l) x, nth n (b :: l') y)
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) : list (A * B) := match l with | nil => nil | cons x t => (map (fun y:B => (x, y)) l')++(list_prod t l') end.A, B:Typeforall (x : A) (y : B) (l : list B), In y l -> In (x, y) (map (fun y0 : B => (x, y0)) l)induction l; [ simpl; auto | simpl; destruct 1 as [H1| ]; [ left; rewrite H1; trivial | right; auto ] ]. Qed.A, B:Typeforall (x : A) (y : B) (l : list B), In y l -> In (x, y) (map (fun y0 : B => (x, y0)) l)A, B:Typeforall (l : list A) (l' : list B) (x : A) (y : B), In x l -> In y l' -> In (x, y) (list_prod l l')induction l; [ simpl; tauto | simpl; intros; apply in_or_app; destruct H; [ left; rewrite H; apply in_prod_aux; assumption | right; auto ] ]. Qed.A, B:Typeforall (l : list A) (l' : list B) (x : A) (y : B), In x l -> In y l' -> In (x, y) (list_prod l l')A, B:Typeforall (l : list A) (l' : list B) (x : A) (y : B), In (x, y) (list_prod l l') <-> In x l /\ In y l'A, B:Typeforall (l : list A) (l' : list B) (x : A) (y : B), In (x, y) (list_prod l l') <-> In x l /\ In y l'A, B:Typel:list Al':list Bx:Ay:BIn (x, y) (list_prod l l') -> In x l /\ In y l'A, B:Typel':list Bx:Ay:BH:FalseFalse /\ In y l'A, B:Typea:Al:list Al':list Bx:Ay:BIHl:In (x, y) (list_prod l l') -> In x l /\ In y l'H:In (x, y) (map (fun y0 : B => (a, y0)) l' ++ list_prod l l')(a = x \/ In x l) /\ In y l'A, B:Typea:Al:list Al':list Bx:Ay:BIHl:In (x, y) (list_prod l l') -> In x l /\ In y l'H:In (x, y) (map (fun y0 : B => (a, y0)) l' ++ list_prod l l')(a = x \/ In x l) /\ In y l'A, B:Typea:Al:list Al':list Bx:Ay:BIHl:In (x, y) (list_prod l l') -> In x l /\ In y l'H0:In (x, y) (map (fun y0 : B => (a, y0)) l')(a = x \/ In x l) /\ In y l'A, B:Typea:Al:list Al':list Bx:Ay:BIHl:In (x, y) (list_prod l l') -> In x l /\ In y l'H0:In (x, y) (list_prod l l')(a = x \/ In x l) /\ In y l'A, B:Typea:Al:list Al':list Bx:Ay:BIHl:In (x, y) (list_prod l l') -> In x l /\ In y l'H0:In (x, y) (map (fun y0 : B => (a, y0)) l')H1:In (x, y) (map (fun y0 : B => (a, y0)) l') -> exists x0 : B, (a, x0) = (x, y) /\ In x0 l'(a = x \/ In x l) /\ In y l'A, B:Typea:Al:list Al':list Bx:Ay:BIHl:In (x, y) (list_prod l l') -> In x l /\ In y l'H0:In (x, y) (list_prod l l')(a = x \/ In x l) /\ In y l'A, B:Typea:Al:list Al':list Bx:Ay:BIHl:In (x, y) (list_prod l l') -> In x l /\ In y l'z:BH2:(a, z) = (x, y)H3:In z l'(a = x \/ In x l) /\ In y l'A, B:Typea:Al:list Al':list Bx:Ay:BIHl:In (x, y) (list_prod l l') -> In x l /\ In y l'H0:In (x, y) (list_prod l l')(a = x \/ In x l) /\ In y l'intuition. Qed.A, B:Typea:Al:list Al':list Bx:Ay:BIHl:In (x, y) (list_prod l l') -> In x l /\ In y l'H0:In (x, y) (list_prod l l')(a = x \/ In x l) /\ In y l'A, B:Typeforall (l : list A) (l' : list B), length (list_prod l l') = length l * length l'A, B:Typeforall (l : list A) (l' : list B), length (list_prod l l') = length l * length l'A, B:Typea:Al:list AIHl:forall l' : list B, length (list_prod l l') = length l * length l'forall l' : list B, length (map (fun y : B => (a, y)) l' ++ list_prod l l') = length l' + length l * length l'A, B:Typea:Al:list AIHl:forall l'0 : list B, length (list_prod l l'0) = length l * length l'0l':list Blength (map (fun y : B => (a, y)) l' ++ list_prod l l') = length l' + length l * length l'A, B:Typea:Al:list AIHl:forall l'0 : list B, length (list_prod l l'0) = length l * length l'0l':list Blength (map (fun y : B => (a, y)) l') + length (list_prod l l') = length l' + length l * length l'auto. Qed. End ListPairs. (*****************************************)A, B:Typea:Al:list AIHl:forall l'0 : list B, length (list_prod l l'0) = length l * length l'0l':list Blength l' + length (list_prod l l') = length l' + length l * length l'
(*****************************************)
(******************************)
(******************************) 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.A:Typea, b:Al, m, n:list Alel l lunfold lel; auto with arith. Qed.A:Typea, b:Al, m, n:list Alel l lA:Typea, b:Al, m, n:list Alel l m -> lel m n -> lel l nA:Typea, b:Al, m, n:list Alel l m -> lel m n -> lel l nA:Typea, b:Al, m, n:list AH:length l <= length mH0:length m <= length nlength l <= length napply le_trans with (length m); auto with arith. Qed.A:Typea, b:Al, m, n:list AH:length l <= length mH0:length m <= length nlength l <= length nA:Typea, b:Al, m, n:list Alel l m -> lel (a :: l) (b :: m)unfold lel; simpl; auto with arith. Qed.A:Typea, b:Al, m, n:list Alel l m -> lel (a :: l) (b :: m)A:Typea, b:Al, m, n:list Alel l m -> lel l (b :: m)unfold lel; simpl; auto with arith. Qed.A:Typea, b:Al, m, n:list Alel l m -> lel l (b :: m)A:Typea, b:Al, m, n:list Alel (a :: l) (b :: m) -> lel l munfold lel; simpl; auto with arith. Qed.A:Typea, b:Al, m, n:list Alel (a :: l) (b :: m) -> lel l mA:Typea, b:Al, m, n:list Aforall l' : list A, lel l' [] -> [] = l'A:Typea, b:Al, m, n:list Aforall l' : list A, lel l' [] -> [] = l'A:Typea, b:Al, m, n, l':list Aforall (a0 : A) (l0 : list A), (lel l0 [] -> [] = l0) -> lel (a0 :: l0) [] -> [] = a0 :: l0A:Typea, b:Al, m, n, l':list Aa':Ay:list AH:lel y [] -> [] = yH0:lel (a' :: y) [][] = a' :: yabsurd (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: datatypes. (******************************)A:Typea, b:Al, m, n, l':list Aa':Ay:list AH:lel y [] -> [] = yH0:lel (a' :: y) [][] = a' :: y
(******************************) Section SetIncl. Variable A : Type. Definition incl (l m:list A) := forall a:A, In a l -> In a m. Hint Unfold incl : core.A:Typeforall l : list A, incl l lauto. Qed. Hint Resolve incl_refl : core.A:Typeforall l : list A, incl l lA:Typeforall (a : A) (l m : list A), incl l m -> incl l (a :: m)auto with datatypes. Qed. Hint Immediate incl_tl : core.A:Typeforall (a : A) (l m : list A), incl l m -> incl l (a :: m)A:Typeforall l m n : list A, incl l m -> incl m n -> incl l nauto. Qed.A:Typeforall l m n : list A, incl l m -> incl m n -> incl l nA:Typeforall l m n : list A, incl l n -> incl l (n ++ m)auto with datatypes. Qed. Hint Immediate incl_appl : core.A:Typeforall l m n : list A, incl l n -> incl l (n ++ m)A:Typeforall l m n : list A, incl l n -> incl l (m ++ n)auto with datatypes. Qed. Hint Immediate incl_appr : core.A:Typeforall l m n : list A, incl l n -> incl l (m ++ n)A:Typeforall (a : A) (l m : list A), In a m -> incl l m -> incl (a :: l) mA:Typeforall (a : A) (l m : list A), In a m -> incl l m -> incl (a :: l) mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lIn a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lIn a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 la = a0 -> In a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lIn a0 l -> In a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 la = a0 -> In a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lIn a0 l -> In a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lH2:a = a0a = a0 -> In a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lIn a0 l -> In a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lH2:a = a0a = a0 -> In a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lIn a0 l -> In a0 mA:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lIn a0 l -> In a0 mauto. Qed. Hint Resolve incl_cons : core.A:Typea:Al, m:list AH:In a mH0:forall a1 : A, In a1 l -> In a1 ma0:AH1:a = a0 \/ In a0 lIn a0 l -> In a0 mA:Typeforall l m n : list A, incl l n -> incl m n -> incl (l ++ m) nA:Typeforall l m n : list A, incl l n -> incl m n -> incl (l ++ m) nA:Typel, m, n:list AH:forall a0 : A, In a0 l -> In a0 nH0:forall a0 : A, In a0 m -> In a0 na:AH1:In a (l ++ m)In a nelim (in_app_or _ _ _ H1); auto. Qed. Hint Resolve incl_app : core. End SetIncl. Hint Resolve incl_refl incl_tl incl_tran incl_appl incl_appr incl_cons incl_app: datatypes. (**************************************)A:Typel, m, n:list AH:forall a0 : A, In a0 l -> In a0 nH0:forall a0 : A, In a0 m -> In a0 na:AH1:In a (l ++ m)In a n
(**************************************) Section Cutting. Variable A : Type. Fixpoint firstn (n:nat)(l:list A) : list A := match n with | 0 => nil | S n => match l with | nil => nil | a::l => a::(firstn n l) end end.A:Typen:natfirstn n [] = []induction n; now simpl. Qed.A:Typen:natfirstn n [] = []A:Typen:nata:Al:list Afirstn (S n) (a :: l) = a :: firstn n lnow simpl. Qed.A:Typen:nata:Al:list Afirstn (S n) (a :: l) = a :: firstn n lA:Typel:list Afirstn (length l) l = linduction l as [| ? ? H]; simpl; [reflexivity | now rewrite H]. Qed.A:Typel:list Afirstn (length l) l = lA:Typen:natforall l : list A, length l <= n -> firstn n l = lA:Typen:natforall l : list A, length l <= n -> firstn n l = lA:Typeforall l : list A, length l <= 0 -> firstn 0 l = lA:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = lforall l : list A, length l <= S k -> firstn (S k) l = lA:Typeforall l : list A, length l <= 0 -> firstn 0 l = lA:Typel:list Alength l <= 0 -> firstn 0 l = lA:Typel:list AH:length l <= 0H1:length l = 0firstn (length l) l = lA:Typel:list AH:length l <= 0H1:l = []firstn (length l) l = lnow simpl.A:TypeH:length [] <= 0firstn (length []) [] = []A:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = lforall l : list A, length l <= S k -> firstn (S k) l = lA:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = l0 <= S k -> [] = []A:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = lx:Axs:list AS (length xs) <= S k -> x :: firstn k xs = x :: xsnow reflexivity.A:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = l0 <= S k -> [] = []A:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = lx:Axs:list AS (length xs) <= S k -> x :: firstn k xs = x :: xsA:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = lx:Axs:list AS (length xs) <= S k -> x :: firstn k xs = x :: xsA:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = lx:Axs:list AH:S (length xs) <= S kx :: firstn k xs = x :: xsA:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = lx:Axs:list AH:length xs <= kx :: firstn k xs = x :: xsapply iHk, H. Qed.A:Typek:natiHk:forall l : list A, length l <= k -> firstn k l = lx:Axs:list AH:length xs <= kfirstn k xs = xsA:Typel:list Afirstn 0 l = []now simpl. Qed.A:Typel:list Afirstn 0 l = []A:Typen:natforall l : list A, length (firstn n l) <= nA:Typen:natforall l : list A, length (firstn n l) <= nA:Typek:natiHk:forall l : list A, length (firstn k l) <= k0 <= S kA:Typek:natiHk:forall l : list A, length (firstn k l) <= kx:Axs:list AS (length (firstn k xs)) <= S kauto with arith.A:Typek:natiHk:forall l : list A, length (firstn k l) <= k0 <= S kapply Peano.le_n_S, iHk. Qed.A:Typek:natiHk:forall l : list A, length (firstn k l) <= kx:Axs:list AS (length (firstn k xs)) <= S kA:Typeforall (l : list A) (n : nat), n <= length l -> length (firstn n l) = nA:Typeforall (l : list A) (n : nat), n <= length l -> length (firstn n l) = nA:Typeforall n : nat, n <= length [] -> length (firstn n []) = nA:Typex:Axs:list AHrec:forall n : nat, n <= length xs -> length (firstn n xs) = nforall n : nat, n <= length (x :: xs) -> length (firstn n (x :: xs)) = nA:Typeforall n : nat, n <= length [] -> length (firstn n []) = nA:Typeforall n : nat, n <= 0 -> length (firstn n []) = nA:Typen:natH:n <= 0length (firstn n []) = nA:Typen:natH:0 = nlength (firstn n []) = nnow simpl.A:Typen:natH:0 = nlength (firstn 0 []) = 0A:Typex:Axs:list AHrec:forall n : nat, n <= length xs -> length (firstn n xs) = nforall n : nat, n <= length (x :: xs) -> length (firstn n (x :: xs)) = nA:Typex:Axs:list AHrec:forall n : nat, n <= length xs -> length (firstn n xs) = n0 <= length (x :: xs) -> length (firstn 0 (x :: xs)) = 0A:Typex:Axs:list AHrec:forall n0 : nat, n0 <= length xs -> length (firstn n0 xs) = n0n:natS n <= length (x :: xs) -> length (firstn (S n) (x :: xs)) = S nnow simpl.A:Typex:Axs:list AHrec:forall n : nat, n <= length xs -> length (firstn n xs) = n0 <= length (x :: xs) -> length (firstn 0 (x :: xs)) = 0A:Typex:Axs:list AHrec:forall n0 : nat, n0 <= length xs -> length (firstn n0 xs) = n0n:natS n <= length (x :: xs) -> length (firstn (S n) (x :: xs)) = S nA:Typex:Axs:list AHrec:forall n0 : nat, n0 <= length xs -> length (firstn n0 xs) = n0n:natS n <= S (length xs) -> S (length (firstn n xs)) = S nA:Typex:Axs:list AHrec:forall n0 : nat, n0 <= length xs -> length (firstn n0 xs) = n0n:natH:S n <= S (length xs)S (length (firstn n xs)) = S nnow rewrite (Hrec n H). Qed.A:Typex:Axs:list AHrec:forall n0 : nat, n0 <= length xs -> length (firstn n0 xs) = n0n:natH:n <= length xsS (length (firstn n xs)) = S nA:Typen:natforall l1 l2 : list A, firstn n (l1 ++ l2) = firstn n l1 ++ firstn (n - length l1) l2A:Typen:natforall l1 l2 : list A, firstn n (l1 ++ l2) = firstn n l1 ++ firstn (n - length l1) l2A:Typel1, l2:list Afirstn 0 (l1 ++ l2) = firstn 0 l1 ++ firstn (0 - length l1) l2A:Typek:natiHk:forall l0 l3 : list A, firstn k (l0 ++ l3) = firstn k l0 ++ firstn (k - length l0) l3l1, l2:list Afirstn (S k) (l1 ++ l2) = firstn (S k) l1 ++ firstn (S k - length l1) l2now simpl.A:Typel1, l2:list Afirstn 0 (l1 ++ l2) = firstn 0 l1 ++ firstn (0 - length l1) l2A:Typek:natiHk:forall l0 l3 : list A, firstn k (l0 ++ l3) = firstn k l0 ++ firstn (k - length l0) l3l1, l2:list Afirstn (S k) (l1 ++ l2) = firstn (S k) l1 ++ firstn (S k - length l1) l2A:Typek:natiHk:forall l1 l0 : list A, firstn k (l1 ++ l0) = firstn k l1 ++ firstn (k - length l1) l0l2:list Afirstn (S k) ([] ++ l2) = firstn (S k) [] ++ firstn (S k - length []) l2A:Typek:natiHk:forall l1 l0 : list A, firstn k (l1 ++ l0) = firstn k l1 ++ firstn (k - length l1) l0x:Axs, l2:list Afirstn (S k) ((x :: xs) ++ l2) = firstn (S k) (x :: xs) ++ firstn (S k - length (x :: xs)) l2A:Typek:natiHk:forall l1 l0 : list A, firstn k (l1 ++ l0) = firstn k l1 ++ firstn (k - length l1) l0l2:list Afirstn (S k) ([] ++ l2) = firstn (S k) [] ++ firstn (S k - length []) l2now rewrite 2!app_nil_l, <- minus_n_O.A:Typek:natiHk:forall l1 l0 : list A, firstn k (l1 ++ l0) = firstn k l1 ++ firstn (k - length l1) l0l2:list Afirstn (S k) ([] ++ l2) = [] ++ firstn (S k - 0) l2A:Typek:natiHk:forall l1 l0 : list A, firstn k (l1 ++ l0) = firstn k l1 ++ firstn (k - length l1) l0x:Axs, l2:list Afirstn (S k) ((x :: xs) ++ l2) = firstn (S k) (x :: xs) ++ firstn (S k - length (x :: xs)) l2A:Typek:natiHk:forall l1 l0 : list A, firstn k (l1 ++ l0) = firstn k l1 ++ firstn (k - length l1) l0x:Axs, l2:list Afirstn (S k) (x :: xs ++ l2) = firstn (S k) (x :: xs) ++ firstn (S k - length (x :: xs)) l2A:Typek:natiHk:forall l1 l0 : list A, firstn k (l1 ++ l0) = firstn k l1 ++ firstn (k - length l1) l0x:Axs, l2:list Ax :: firstn k (xs ++ l2) = x :: firstn k xs ++ firstn (k - length xs) l2apply iHk. Qed.A:Typek:natiHk:forall l1 l0 : list A, firstn k (l1 ++ l0) = firstn k l1 ++ firstn (k - length l1) l0x:Axs, l2:list Afirstn k (xs ++ l2) = firstn k xs ++ firstn (k - length xs) l2A:Typen:natforall l1 l2 : list A, firstn (length l1 + n) (l1 ++ l2) = l1 ++ firstn n l2A:Typen:natforall l1 l2 : list A, firstn (length l1 + n) (l1 ++ l2) = l1 ++ firstn n l2A:Typel1, l2:list Afirstn (length l1 + 0) (l1 ++ l2) = l1 ++ firstn 0 l2A:Typek:natiHk:forall l0 l3 : list A, firstn (length l0 + k) (l0 ++ l3) = l0 ++ firstn k l3l1, l2:list Afirstn (length l1 + S k) (l1 ++ l2) = l1 ++ firstn (S k) l2A:Typel1, l2:list Afirstn (length l1 + 0) (l1 ++ l2) = l1 ++ firstn 0 l2A:Typel1, l2:list Afirstn (length l1 + 0) (l1 ++ l2) = l1 ++ []A:Typel1, l2:list Afirstn (length l1) (l1 ++ l2) = l1A:Typel1, l2:list Afirstn (length l1) l1 ++ firstn (length l1 - length l1) l2 = l1A:Typel1, l2:list Afirstn (length l1) l1 ++ firstn 0 l2 = l1A:Typel1, l2:list Afirstn (length l1) l1 ++ [] = l1apply firstn_all.A:Typel1, l2:list Afirstn (length l1) l1 = l1A:Typek:natiHk:forall l0 l3 : list A, firstn (length l0 + k) (l0 ++ l3) = l0 ++ firstn k l3l1, l2:list Afirstn (length l1 + S k) (l1 ++ l2) = l1 ++ firstn (S k) l2A:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Afirstn (length l1 + S k) (l1 ++ []) = l1 ++ firstn (S k) []A:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Ax:Axs:list Afirstn (length l1 + S k) (l1 ++ x :: xs) = l1 ++ firstn (S k) (x :: xs)A:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Afirstn (length l1 + S k) (l1 ++ []) = l1 ++ firstn (S k) []A:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Afirstn (length l1 + S k) (l1 ++ []) = l1 ++ []A:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Afirstn (length l1 + S k) l1 = l1auto with arith.A:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Alength l1 <= length l1 + S kA:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Ax:Axs:list Afirstn (length l1 + S k) (l1 ++ x :: xs) = l1 ++ firstn (S k) (x :: xs)A:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Ax:Axs:list Afirstn (length l1 + S k) l1 ++ firstn (length l1 + S k - length l1) (x :: xs) = l1 ++ firstn (S k) (x :: xs)A:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Ax:Axs:list Alength l1 + S k - length l1 = S kA:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Ax:Axs:list AH0:length l1 + S k - length l1 = S kfirstn (length l1 + S k) l1 ++ firstn (length l1 + S k - length l1) (x :: xs) = l1 ++ firstn (S k) (x :: xs)rewrite H0, firstn_all2; [reflexivity | auto with arith]. Qed.A:Typek:natiHk:forall l0 l2 : list A, firstn (length l0 + k) (l0 ++ l2) = l0 ++ firstn k l2l1:list Ax:Axs:list AH0:length l1 + S k - length l1 = S kfirstn (length l1 + S k) l1 ++ firstn (length l1 + S k - length l1) (x :: xs) = l1 ++ firstn (S k) (x :: xs)A:Typeforall (l : list A) (i j : nat), firstn i (firstn j l) = firstn (Init.Nat.min i j) lA:Typeforall (l : list A) (i j : nat), firstn i (firstn j l) = firstn (Init.Nat.min i j) lA:Typeforall i j : nat, firstn i (firstn j []) = firstn (Init.Nat.min i j) []A:Typex:Axs:list AHl:forall i j : nat, firstn i (firstn j xs) = firstn (Init.Nat.min i j) xsforall i j : nat, firstn i (firstn j (x :: xs)) = firstn (Init.Nat.min i j) (x :: xs)A:Typeforall i j : nat, firstn i (firstn j []) = firstn (Init.Nat.min i j) []A:Typei, j:natfirstn i (firstn j []) = firstn (Init.Nat.min i j) []now rewrite ?firstn_nil.A:Typei, j:natfirstn i (firstn j []) = firstn (Init.Nat.min i j) []A:Typex:Axs:list AHl:forall i j : nat, firstn i (firstn j xs) = firstn (Init.Nat.min i j) xsforall i j : nat, firstn i (firstn j (x :: xs)) = firstn (Init.Nat.min i j) (x :: xs)A:Typex:Axs:list AHl:forall i j : nat, firstn i (firstn j xs) = firstn (Init.Nat.min i j) xsforall j : nat, firstn 0 (firstn j (x :: xs)) = firstn (Init.Nat.min 0 j) (x :: xs)A:Typex:Axs:list AHl:forall i0 j : nat, firstn i0 (firstn j xs) = firstn (Init.Nat.min i0 j) xsi:natforall j : nat, firstn (S i) (firstn j (x :: xs)) = firstn (Init.Nat.min (S i) j) (x :: xs)A:Typex:Axs:list AHl:forall i j : nat, firstn i (firstn j xs) = firstn (Init.Nat.min i j) xsforall j : nat, firstn 0 (firstn j (x :: xs)) = firstn (Init.Nat.min 0 j) (x :: xs)now simpl.A:Typex:Axs:list AHl:forall i j0 : nat, firstn i (firstn j0 xs) = firstn (Init.Nat.min i j0) xsj:natfirstn 0 (firstn j (x :: xs)) = firstn (Init.Nat.min 0 j) (x :: xs)A:Typex:Axs:list AHl:forall i0 j : nat, firstn i0 (firstn j xs) = firstn (Init.Nat.min i0 j) xsi:natforall j : nat, firstn (S i) (firstn j (x :: xs)) = firstn (Init.Nat.min (S i) j) (x :: xs)A:Typex:Axs:list AHl:forall i0 j : nat, firstn i0 (firstn j xs) = firstn (Init.Nat.min i0 j) xsi:natfirstn (S i) (firstn 0 (x :: xs)) = firstn (Init.Nat.min (S i) 0) (x :: xs)A:Typex:Axs:list AHl:forall i0 j0 : nat, firstn i0 (firstn j0 xs) = firstn (Init.Nat.min i0 j0) xsi, j:natfirstn (S i) (firstn (S j) (x :: xs)) = firstn (Init.Nat.min (S i) (S j)) (x :: xs)now simpl.A:Typex:Axs:list AHl:forall i0 j : nat, firstn i0 (firstn j xs) = firstn (Init.Nat.min i0 j) xsi:natfirstn (S i) (firstn 0 (x :: xs)) = firstn (Init.Nat.min (S i) 0) (x :: xs)A:Typex:Axs:list AHl:forall i0 j0 : nat, firstn i0 (firstn j0 xs) = firstn (Init.Nat.min i0 j0) xsi, j:natfirstn (S i) (firstn (S j) (x :: xs)) = firstn (Init.Nat.min (S i) (S j)) (x :: xs)A:Typex:Axs:list AHl:forall i0 j0 : nat, firstn i0 (firstn j0 xs) = firstn (Init.Nat.min i0 j0) xsi, j:natx :: firstn i (firstn j xs) = x :: firstn (Init.Nat.min i j) xsapply Hl. Qed. Fixpoint skipn (n:nat)(l:list A) : list A := match n with | 0 => l | S n => match l with | nil => nil | a::l => skipn n l end end.A:Typex:Axs:list AHl:forall i0 j0 : nat, firstn i0 (firstn j0 xs) = firstn (Init.Nat.min i0 j0) xsi, j:natfirstn i (firstn j xs) = firstn (Init.Nat.min i j) xsA:Typeforall (m n : nat) (l : list A), firstn m (skipn n l) = skipn n (firstn (n + m) l)now intros m; induction n; intros []; simpl; destruct m. Qed.A:Typeforall (m n : nat) (l : list A), firstn m (skipn n l) = skipn n (firstn (n + m) l)A:Typeforall (m n : nat) (l : list A), skipn m (firstn n l) = firstn (n - m) (skipn m l)now induction m; intros [] []; simpl; rewrite ?firstn_nil. Qed.A:Typeforall (m n : nat) (l : list A), skipn m (firstn n l) = firstn (n - m) (skipn m l)A:Typeforall l : list A, skipn 0 l = lreflexivity. Qed.A:Typeforall l : list A, skipn 0 l = lA:Typeforall n : nat, skipn n ([] : list A) = []now intros []. Qed.A:Typeforall n : nat, skipn n ([] : list A) = []A:Typen:nata:Al:list Askipn (S n) (a :: l) = skipn n lreflexivity. Qed.A:Typen:nata:Al:list Askipn (S n) (a :: l) = skipn n lA:Typeforall l : list A, skipn (length l) l = []now induction l. Qed.A:Typeforall l : list A, skipn (length l) l = []A:Typen:natforall l : list A, length l <= n -> skipn n l = []A:Typen:natforall l : list A, length l <= n -> skipn n l = []now rewrite skipn_firstn_comm, L. Qed.A:Typen:natl:list AL:length l - n = 0skipn n (firstn (length l) l) = []A:Typeforall (n : nat) (l : list A), firstn n l ++ skipn n l = lA:Typeforall (n : nat) (l : list A), firstn n l ++ skipn n l = lA:Typeforall l : list A, firstn 0 l ++ skipn 0 l = lA:Typen:natIHn:forall l : list A, firstn n l ++ skipn n l = lforall l : list A, firstn (S n) l ++ skipn (S n) l = lA:Typen:natIHn:forall l : list A, firstn n l ++ skipn n l = lforall l : list A, firstn (S n) l ++ skipn (S n) l = lf_equal; auto. Qed.A:Typen:natIHn:forall l0 : list A, firstn n l0 ++ skipn n l0 = l0a:Al:list Aa :: firstn n l ++ skipn n l = a :: lA:Typeforall (n : nat) (l : list A), length (firstn n l) = Init.Nat.min n (length l)induction n; destruct l; simpl; auto. Qed.A:Typeforall (n : nat) (l : list A), length (firstn n l) = Init.Nat.min n (length l)A:Typen:natforall l : list A, length (skipn n l) = length l - nA:Typen:natforall l : list A, length (skipn n l) = length l - nA:Typeforall l : list A, length (skipn 0 l) = length l - 0A:Typen:natIHn:forall l : list A, length (skipn n l) = length l - nforall l : list A, length (skipn (S n) l) = length l - S nintros l; simpl; rewrite Nat.sub_0_r; reflexivity.A:Typeforall l : list A, length (skipn 0 l) = length l - 0destruct l; simpl; auto. Qed.A:Typen:natIHn:forall l : list A, length (skipn n l) = length l - nforall l : list A, length (skipn (S n) l) = length l - S nA:Typel:list Askipn (length l) l = []now induction l. Qed.A:Typel:list Askipn (length l) l = []A:Typen:natforall l1 l2 : list A, skipn n (l1 ++ l2) = skipn n l1 ++ skipn (n - length l1) l2induction n; auto; intros [|]; simpl; auto. Qed.A:Typen:natforall l1 l2 : list A, skipn n (l1 ++ l2) = skipn n l1 ++ skipn (n - length l1) l2A:Typeforall (x : nat) (l : list A), firstn x l = rev (skipn (length l - x) (rev l))A:Typeforall (x : nat) (l : list A), firstn x l = rev (skipn (length l - x) (rev l))A:Typex:natl:list Afirstn x l = rev (skipn (length l - x) (rev (firstn x l ++ skipn x l)))A:Typex:natl:list Afirstn x l = firstn x l ++ rev (skipn (length l - x) (rev (skipn x l)))repeat rewrite rev_length, skipn_length; apply Nat.sub_diag. Qed.A:Typex:natl:list Alength (rev (skipn (length l - x) (rev (skipn x l)))) = 0A:Typeforall (x : nat) (l : list A), firstn x (rev l) = rev (skipn (length l - x) l)now intros x l; rewrite firstn_skipn_rev, rev_involutive, rev_length. Qed.A:Typeforall (x : nat) (l : list A), firstn x (rev l) = rev (skipn (length l - x) l)A:Typeforall (x : nat) (l : list A), skipn x (rev l) = rev (firstn (length l - x) l)A:Typeforall (x : nat) (l : list A), skipn x (rev l) = rev (firstn (length l - x) l)A:Typex:natl:list Askipn x (rev l) = skipn (length (rev l) - (length (rev l) - x)) (rev l)A:Typex:natl:list AL:length (rev l) <= xskipn x (rev l) = skipn (length (rev l) - (length (rev l) - x)) (rev l)A:Typex:natl:list AL:x <= length (rev l)skipn x (rev l) = skipn (length (rev l) - (length (rev l) - x)) (rev l)A:Typex:natl:list AL:length (rev l) <= xskipn x (rev l) = skipn (length (rev l) - (length (rev l) - x)) (rev l)now rewrite L, Nat.sub_0_r, skipn_none.A:Typex:natl:list AL:length (rev l) - x = 0[] = skipn (length (rev l) - (length (rev l) - x)) (rev l)A:Typex:natl:list AL:x <= length (rev l)skipn x (rev l) = skipn (length (rev l) - (length (rev l) - x)) (rev l)A:Typex:natl:list AL:x <= length (rev l)skipn x (rev l) = skipn (length (rev l) + x - length (rev l)) (rev l)A:Typex:natl:list AL:x <= length (rev l)length (rev l) + x - length (rev l) = length (rev l) - (length (rev l) - x)A:Typex:natl:list AL:x <= length (rev l)skipn x (rev l) = skipn x (rev l)A:Typex:natl:list AL:x <= length (rev l)length (rev l) + x - length (rev l) = length (rev l) - (length (rev l) - x)A:Typex:natl:list AL:x <= length (rev l)length (rev l) + x - length (rev l) = length (rev l) - (length (rev l) - x)now rewrite <-!(Nat.add_comm x), <-minus_plus_simpl_l_reverse. Qed.A:Typex:natl:list AL:x <= length (rev l)length (rev l) + x - (length (rev l) - x + x) = length (rev l) - (length (rev l) - x)A:Typeforall (n : nat) (l : list A), n < length l -> removelast (firstn (S n) l) = firstn n lA:Typeforall (n : nat) (l : list A), n < length l -> removelast (firstn (S n) l) = firstn n lA:Type0 < length [] -> removelast (firstn 1 []) = firstn 0 []A:Typea:Al:list A0 < length (a :: l) -> removelast (firstn 1 (a :: l)) = firstn 0 (a :: l)A:Typen:natIHn:forall l : list A, n < length l -> removelast (firstn (S n) l) = firstn n lS n < length [] -> removelast (firstn (S (S n)) []) = firstn (S n) []A:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AS n < length (a :: l) -> removelast (firstn (S (S n)) (a :: l)) = firstn (S n) (a :: l)A:Typea:Al:list A0 < length (a :: l) -> removelast (firstn 1 (a :: l)) = firstn 0 (a :: l)A:Typen:natIHn:forall l : list A, n < length l -> removelast (firstn (S n) l) = firstn n lS n < length [] -> removelast (firstn (S (S n)) []) = firstn (S n) []A:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AS n < length (a :: l) -> removelast (firstn (S (S n)) (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l : list A, n < length l -> removelast (firstn (S n) l) = firstn n lS n < length [] -> removelast (firstn (S (S n)) []) = firstn (S n) []A:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AS n < length (a :: l) -> removelast (firstn (S (S n)) (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AS n < length (a :: l) -> removelast (firstn (S (S n)) (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AH:S n < length (a :: l)removelast (firstn (S (S n)) (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AH:S n < S (length l)removelast (firstn (S (S n)) (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AH:S n < S (length l)removelast ([a] ++ firstn (S n) l) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AH:S n < S (length l)removelast ([a] ++ firstn (S n) l) = a :: firstn n lA:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AH:S n < S (length l)[a] ++ removelast (firstn (S n) l) = a :: firstn n lA:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AH:S n < S (length l)firstn (S n) l <> []A:Typen:natIHn:forall l0 : list A, n < length l0 -> removelast (firstn (S n) l0) = firstn n l0a:Al:list AH:S n < S (length l)firstn (S n) l <> []A:Typen:nata:AH:S n < 1[] <> []inversion_clear H0. Qed.A:Typen:nata:AH0:S (S n) <= 0[] <> []A:Typeforall (n : nat) (l : list A), n < length l -> firstn n (removelast l) = firstn n lA:Typeforall (n : nat) (l : list A), n < length l -> firstn n (removelast l) = firstn n lA:Type0 < length [] -> firstn 0 (removelast []) = firstn 0 []A:Typea:Al:list A0 < length (a :: l) -> firstn 0 (removelast (a :: l)) = firstn 0 (a :: l)A:Typen:natIHn:forall l : list A, n < length l -> firstn n (removelast l) = firstn n lS n < length [] -> firstn (S n) (removelast []) = firstn (S n) []A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AS n < length (a :: l) -> firstn (S n) (removelast (a :: l)) = firstn (S n) (a :: l)A:Typea:Al:list A0 < length (a :: l) -> firstn 0 (removelast (a :: l)) = firstn 0 (a :: l)A:Typen:natIHn:forall l : list A, n < length l -> firstn n (removelast l) = firstn n lS n < length [] -> firstn (S n) (removelast []) = firstn (S n) []A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AS n < length (a :: l) -> firstn (S n) (removelast (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l : list A, n < length l -> firstn n (removelast l) = firstn n lS n < length [] -> firstn (S n) (removelast []) = firstn (S n) []A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AS n < length (a :: l) -> firstn (S n) (removelast (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AS n < length (a :: l) -> firstn (S n) (removelast (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AH:S n < length (a :: l)firstn (S n) (removelast (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AH:S n < S (length l)firstn (S n) (removelast (a :: l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AH:S n < S (length l)firstn (S n) (removelast ([a] ++ l)) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AH:S n < S (length l)firstn (S n) ([a] ++ removelast l) = firstn (S n) (a :: l)A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AH:S n < S (length l)l <> []intro H0; rewrite H0 in H; inversion_clear H; inversion_clear H1. Qed. End Cutting. (**********************************************************************)A:Typen:natIHn:forall l0 : list A, n < length l0 -> firstn n (removelast l0) = firstn n l0a:Al:list AH:S n < S (length l)l <> []
(**********************************************************************) Section Add. Variable A : Type. (* [Add a l l'] means that [l'] is exactly [l], with [a] added once somewhere *) Inductive Add (a:A) : list A -> list A -> Prop := | Add_head l : Add a l (a::l) | Add_cons x l l' : Add a l l' -> Add a (x::l) (x::l').A:Typea:Al1, l2:list AAdd a (l1 ++ l2) (l1 ++ a :: l2)induction l1; simpl; now constructor. Qed.A:Typea:Al1, l2:list AAdd a (l1 ++ l2) (l1 ++ a :: l2)A:Typea:Al, l':list AAdd a l l' -> exists l1 l2 : list A, l = l1 ++ l2 /\ l' = l1 ++ a :: l2A:Typea:Al, l':list AAdd a l l' -> exists l1 l2 : list A, l = l1 ++ l2 /\ l' = l1 ++ a :: l2A:Typea:Al:list Aexists l1 l2 : list A, l = l1 ++ l2 /\ a :: l = l1 ++ a :: l2A:Typea, x:Al, l':list AH:Add a l l'IHAdd:exists l1 l2 : list A, l = l1 ++ l2 /\ l' = l1 ++ a :: l2exists l1 l2 : list A, x :: l = l1 ++ l2 /\ x :: l' = l1 ++ a :: l2exists nil; exists l; split; trivial.A:Typea:Al:list Aexists l1 l2 : list A, l = l1 ++ l2 /\ a :: l = l1 ++ a :: l2A:Typea, x:Al, l':list AH:Add a l l'IHAdd:exists l1 l2 : list A, l = l1 ++ l2 /\ l' = l1 ++ a :: l2exists l1 l2 : list A, x :: l = l1 ++ l2 /\ x :: l' = l1 ++ a :: l2exists (x::l1); exists l2; split; simpl; f_equal; trivial. Qed.A:Typea, x:Al, l':list AH:Add a l l'l1, l2:list AHl:l = l1 ++ l2Hl':l' = l1 ++ a :: l2exists l0 l3 : list A, x :: l = l0 ++ l3 /\ x :: l' = l0 ++ a :: l3A:Typea:Al, l':list AAdd a l l' -> forall x : A, In x l' <-> In x (a :: l)induction 1; intros; simpl in *; rewrite ?IHAdd; tauto. Qed.A:Typea:Al, l':list AAdd a l l' -> forall x : A, In x l' <-> In x (a :: l)A:Typea:Al, l':list AAdd a l l' -> length l' = S (length l)induction 1; simpl; auto with arith. Qed.A:Typea:Al, l':list AAdd a l l' -> length l' = S (length l)A:Typea:Al:list AIn a l -> exists l' : list A, Add a l' lA:Typea:Al:list AIn a l -> exists l' : list A, Add a l' lA:Typea:Al:list AHa:In a lexists l' : list A, Add a l' lA:Typea:Al1, l2:list AHa:In a (l1 ++ a :: l2)exists l' : list A, Add a l' (l1 ++ a :: l2)apply Add_app. Qed.A:Typea:Al1, l2:list AHa:In a (l1 ++ a :: l2)Add a (l1 ++ l2) (l1 ++ a :: l2)A:Typea:Al, u, v:list A~ In a l -> incl (a :: l) v -> Add a u v -> incl l uA:Typea:Al, u, v:list A~ In a l -> incl (a :: l) v -> Add a u v -> incl l uA:Typea:Al, u, v:list AHa:~ In a lH:incl (a :: l) vAD:Add a u vy:AHy:In y lIn y uA:Typea:Al, u, v:list AHa:~ In a lH:incl (a :: l) vAD:Add a u vy:AHy:In y lIn y (a :: u)A:Typea:Al, u, v:list AHa:~ In a lH:incl (a :: l) vAD:Add a u vy:AHy:In y lHy':In y (a :: u)In y uA:Typea:Al, u, v:list AHa:~ In a lH:incl (a :: l) vAD:Add a u vy:AHy:In y lIn y (a :: u)apply H; simpl; auto.A:Typea:Al, u, v:list AHa:~ In a lH:incl (a :: l) vAD:Add a u vy:AHy:In y lIn y vdestruct Hy'; [ subst; now elim Ha | trivial ]. Qed. End Add. (********************************)A:Typea:Al, u, v:list AHa:~ In a lH:incl (a :: l) vAD:Add a u vy:AHy:In y lHy':In y (a :: u)In y u
(********************************) 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).A:Typea:Al, l':list AAdd a l l' -> NoDup l' <-> NoDup l /\ ~ In a lA:Typea:Al, l':list AAdd a l l' -> NoDup l' <-> NoDup l /\ ~ In a lA:Typea:Al:list ANoDup (a :: l) <-> NoDup l /\ ~ In a lA:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lNoDup (x :: l') <-> NoDup (x :: l) /\ ~ In a (x :: l)split; [ inversion_clear 1; now split | now constructor ].A:Typea:Al:list ANoDup (a :: l) <-> NoDup l /\ ~ In a lA:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lNoDup (x :: l') <-> NoDup (x :: l) /\ ~ In a (x :: l)A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lNoDup (x :: l') -> NoDup (x :: l) /\ ~ In a (x :: l)A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lNoDup (x :: l) /\ ~ In a (x :: l) -> NoDup (x :: l')A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lNoDup (x :: l') -> NoDup (x :: l) /\ ~ In a (x :: l)A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lH0:~ In x l'H1:NoDup l'NoDup (x :: l) /\ ~ In a (x :: l)A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lH0:~ In x l'H1:NoDup l /\ ~ In a lNoDup (x :: l) /\ ~ In a (x :: l)simpl in *; split; try constructor; intuition.A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lH0:~ In x (a :: l)H1:NoDup l /\ ~ In a lNoDup (x :: l) /\ ~ In a (x :: l)A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lNoDup (x :: l) /\ ~ In a (x :: l) -> NoDup (x :: l')A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lN:NoDup (x :: l)IN:~ In a (x :: l)NoDup (x :: l')A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lIN:~ In a (x :: l)H:~ In x lH0:NoDup lNoDup (x :: l')A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lIN:~ In a (x :: l)H:~ In x lH0:NoDup l~ In x l'A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lIN:~ In a (x :: l)H:~ In x lH0:NoDup lNoDup l'rewrite (Add_in AD); simpl in *; intuition.A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lIN:~ In a (x :: l)H:~ In x lH0:NoDup l~ In x l'A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lIN:~ In a (x :: l)H:~ In x lH0:NoDup lNoDup l'A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lIN:~ In a (x :: l)H:~ In x lH0:NoDup lNoDup l /\ ~ In a lsimpl in *; intuition. Qed.A:Typea, x:Al, l':list AAD:Add a l l'IH:NoDup l' <-> NoDup l /\ ~ In a lIN:~ In a (x :: l)H:~ In x lH0:NoDup l~ In a lA:Typel, l':list Aa:ANoDup (l ++ a :: l') -> NoDup (l ++ l') /\ ~ In a (l ++ l')A:Typel, l':list Aa:ANoDup (l ++ a :: l') -> NoDup (l ++ l') /\ ~ In a (l ++ l')apply Add_app. Qed.A:Typel, l':list Aa:AAdd a (l ++ l') (l ++ a :: l')A:Typel, l':list Aa:ANoDup (l ++ a :: l') -> NoDup (l ++ l')A:Typel, l':list Aa:ANoDup (l ++ a :: l') -> NoDup (l ++ l')now apply NoDup_remove with a. Qed.A:Typel, l':list Aa:AH:NoDup (l ++ a :: l')NoDup (l ++ l')A:Typel, l':list Aa:ANoDup (l ++ a :: l') -> ~ In a (l ++ l')A:Typel, l':list Aa:ANoDup (l ++ a :: l') -> ~ In a (l ++ l')now apply NoDup_remove. Qed.A:Typel, l':list Aa:AH:NoDup (l ++ a :: l')~ In a (l ++ l')A:Typea:Al:list ANoDup (a :: l) <-> ~ In a l /\ NoDup lA:Typea:Al:list ANoDup (a :: l) <-> ~ In a l /\ NoDup lA:Typea:Al:list ANoDup (a :: l) -> ~ In a l /\ NoDup lA:Typea:Al:list A~ In a l /\ NoDup l -> NoDup (a :: l)A:Typea:Al:list ANoDup (a :: l) -> ~ In a l /\ NoDup lnow split.A:Typea:Al:list AH0:~ In a lH1:NoDup l~ In a l /\ NoDup lnow constructor. Qed.A:Typea:Al:list A~ In a l /\ NoDup l -> NoDup (a :: l)
Effective computation of a list without duplicates
Hypothesis decA: forall x y : A, {x = y} + {x <> y}. Fixpoint nodup (l : list A) : list A := match l with | [] => [] | x::xs => if in_dec decA x xs then nodup xs else x::(nodup xs) end.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:AIn x (nodup l) <-> In x lA:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:AIn x (nodup l) <-> In x lA:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}x:AFalse <-> FalseA:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list Ax:AHrec:In x (nodup l') <-> In x l'In x (if in_dec decA a l' then nodup l' else a :: nodup l') <-> a = x \/ In x l'reflexivity.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}x:AFalse <-> FalseA:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list Ax:AHrec:In x (nodup l') <-> In x l'In x (if in_dec decA a l' then nodup l' else a :: nodup l') <-> a = x \/ In x l'A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list Ax:AHrec:In x (nodup l') <-> In x l'i:In a l'In x l' <-> a = x \/ In x l'A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list Ax:AHrec:In x (nodup l') <-> In x l'n:~ In a l'a = x \/ In x l' <-> a = x \/ In x l'intuition; now subst.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list Ax:AHrec:In x (nodup l') <-> In x l'i:In a l'In x l' <-> a = x \/ In x l'reflexivity. Qed.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list Ax:AHrec:In x (nodup l') <-> In x l'n:~ In a l'a = x \/ In x l' <-> a = x \/ In x l'A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup (nodup l)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup (nodup l)A:TypedecA:forall x y : A, {x = y} + {x <> y}NoDup []A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AHrec:NoDup (nodup l')NoDup (if in_dec decA a l' then nodup l' else a :: nodup l')constructor.A:TypedecA:forall x y : A, {x = y} + {x <> y}NoDup []A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AHrec:NoDup (nodup l')NoDup (if in_dec decA a l' then nodup l' else a :: nodup l')A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AHrec:NoDup (nodup l')i:In a l'NoDup (nodup l')A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AHrec:NoDup (nodup l')n:~ In a l'NoDup (a :: nodup l')assumption.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AHrec:NoDup (nodup l')i:In a l'NoDup (nodup l')constructor; [ now rewrite nodup_In | assumption]. Qed.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AHrec:NoDup (nodup l')n:~ In a l'NoDup (a :: nodup l')A:TypedecA:forall x y : A, {x = y} + {x <> y}k, l:list Aa:Anodup k = a :: l -> ~ In a lA:TypedecA:forall x y : A, {x = y} + {x <> y}k, l:list Aa:Anodup k = a :: l -> ~ In a lA:TypedecA:forall x y : A, {x = y} + {x <> y}k, l:list Aa:AH:nodup k = a :: l~ In a lA:TypedecA:forall x y : A, {x = y} + {x <> y}k, l:list Aa:AH:nodup k = a :: lNoDup (a :: l)A:TypedecA:forall x y : A, {x = y} + {x <> y}k, l:list Aa:AH:nodup k = a :: lH':NoDup (a :: l)~ In a lA:TypedecA:forall x y : A, {x = y} + {x <> y}k, l:list Aa:AH:nodup k = a :: lNoDup (a :: l)apply NoDup_nodup.A:TypedecA:forall x y : A, {x = y} + {x <> y}k, l:list Aa:AH:nodup k = a :: lNoDup (nodup k)now inversion_clear H'. Qed.A:TypedecA:forall x y : A, {x = y} + {x <> y}k, l:list Aa:AH:nodup k = a :: lH':NoDup (a :: l)~ In a lA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup l <-> (forall x : A, count_occ decA l x <= 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup l <-> (forall x : A, count_occ decA l x <= 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}NoDup [] <-> (forall x : A, count_occ decA [] x <= 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AHrec:NoDup l' <-> (forall x : A, count_occ decA l' x <= 1)NoDup (a :: l') <-> (forall x : A, count_occ decA (a :: l') x <= 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}NoDup [] <-> (forall x : A, count_occ decA [] x <= 1)constructor.A:TypedecA:forall x y : A, {x = y} + {x <> y}(A -> 0 <= 1) -> NoDup []A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AHrec:NoDup l' <-> (forall x : A, count_occ decA l' x <= 1)NoDup (a :: l') <-> (forall x : A, count_occ decA (a :: l') x <= 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AHrec:NoDup l' <-> (forall x : A, count_occ decA l' x <= 1)count_occ decA l' a = 0 /\ (forall x : A, count_occ decA l' x <= 1) <-> (forall x : A, count_occ decA (a :: l') x <= 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list Acount_occ decA l' a = 0 /\ (forall x : A, count_occ decA l' x <= 1) <-> (forall x : A, count_occ decA (a :: l') x <= 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list Acount_occ decA l' a = 0 /\ (forall x : A, count_occ decA l' x <= 1) -> forall x : A, count_occ decA (a :: l') x <= 1A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list A(forall x : A, count_occ decA (a :: l') x <= 1) -> count_occ decA l' a = 0 /\ (forall x : A, count_occ decA l' x <= 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list Acount_occ decA l' a = 0 /\ (forall x : A, count_occ decA l' x <= 1) -> forall x : A, count_occ decA (a :: l') x <= 1A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list AHa:count_occ decA l' a = 0H:forall x0 : A, count_occ decA l' x0 <= 1x:Acount_occ decA (a :: l') x <= 1A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list AHa:count_occ decA l' a = 0H:forall x0 : A, count_occ decA l' x0 <= 1x:A(if decA a x then S (count_occ decA l' x) else count_occ decA l' x) <= 1subst; now rewrite Ha.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list AHa:count_occ decA l' a = 0H:forall x0 : A, count_occ decA l' x0 <= 1x:Ae:a = xS (count_occ decA l' x) <= 1A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list A(forall x : A, count_occ decA (a :: l') x <= 1) -> count_occ decA l' a = 0 /\ (forall x : A, count_occ decA l' x <= 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AH:forall x : A, count_occ decA (a :: l') x <= 1count_occ decA l' a = 0A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AH:forall x : A, count_occ decA (a :: l') x <= 1forall x : A, count_occ decA l' x <= 1A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AH:forall x : A, count_occ decA (a :: l') x <= 1count_occ decA l' a = 0A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AH:count_occ decA (a :: l') a <= 1count_occ decA l' a = 0now inversion H.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AH:S (count_occ decA l' a) <= 1count_occ decA l' a = 0A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al':list AH:forall x : A, count_occ decA (a :: l') x <= 1forall x : A, count_occ decA l' x <= 1A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list AH:forall x0 : A, count_occ decA (a :: l') x0 <= 1x:Acount_occ decA l' x <= 1A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list Ax:AH:count_occ decA (a :: l') x <= 1count_occ decA l' x <= 1A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list Ax:AH:(if decA a x then S (count_occ decA l' x) else count_occ decA l' x) <= 1count_occ decA l' x <= 1now apply Nat.lt_le_incl. Qed.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al':list Ax:Ae:a = xH:S (count_occ decA l' x) <= 1count_occ decA l' x <= 1A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup l <-> (forall x : A, In x l -> count_occ decA l x = 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup l <-> (forall x : A, In x l -> count_occ decA l x = 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list A(forall x : A, count_occ decA l x <= 1) <-> (forall x : A, In x l -> count_occ decA l x = 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list A(forall x : A, count_occ decA l x <= 1) <-> (forall x : A, count_occ decA l x > 0 -> count_occ decA l x = 1)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list A(forall x : A, count_occ decA l x <= 1) <-> (forall x : A, 1 <= count_occ decA l x -> count_occ decA l x = 1)(* the rest would be solved by omega if we had it here... *)A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:An:natH:n <= 11 <= n -> n = 1A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:An:natH:1 <= n -> n = 1n <= 1now apply Nat.le_antisymm.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:An:natH:n <= 11 <= n -> n = 1A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:An:natH:1 <= n -> n = 1n <= 1A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:An:natH:1 <= n -> n = 1H0:1 <= nn <= 1A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:An:natH:1 <= n -> n = 1H0:n < 1n <= 1rewrite H; trivial.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:An:natH:1 <= n -> n = 1H0:1 <= nn <= 1now apply Nat.lt_le_incl. Qed.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}l:list Ax:An:natH:1 <= n -> n = 1H0:n < 1n <= 1
Alternative characterisations of being without duplicates,
thanks to nth_error and nth
A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup l <-> (forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup l <-> (forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup l -> forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = jA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list A(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list ANoDup l -> forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = jA:TypedecA:forall x y : A, {x = y} + {x <> y}i, j:natHi:i < length []E:nth_error [] i = nth_error [] ji = jA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> nth_error l i0 = nth_error l j0 -> i0 = j0i, j:natHi:i < length (a :: l)E:nth_error (a :: l) i = nth_error (a :: l) ji = jinversion Hi.A:TypedecA:forall x y : A, {x = y} + {x <> y}i, j:natHi:i < length []E:nth_error [] i = nth_error [] ji = jA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> nth_error l i0 = nth_error l j0 -> i0 = j0i, j:natHi:i < length (a :: l)E:nth_error (a :: l) i = nth_error (a :: l) ji = jA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i j0 : nat, i < length l -> nth_error l i = nth_error l j0 -> i = j0j:natHi:0 < S (length l)E:Some a = nth_error l j0 = S jA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j : nat, i0 < length l -> nth_error l i0 = nth_error l j -> i0 = ji:natHi:S i < S (length l)E:nth_error l i = Some aS i = 0A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> nth_error l i0 = nth_error l j0 -> i0 = j0i, j:natHi:S i < S (length l)E:nth_error l i = nth_error l jS i = S jA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i j0 : nat, i < length l -> nth_error l i = nth_error l j0 -> i = j0j:natHi:0 < S (length l)E:Some a = nth_error l j0 = S jeapply nth_error_In; eauto.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i j0 : nat, i < length l -> nth_error l i = nth_error l j0 -> i = j0j:natHi:0 < S (length l)E:Some a = nth_error l jIn a lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j : nat, i0 < length l -> nth_error l i0 = nth_error l j -> i0 = ji:natHi:S i < S (length l)E:nth_error l i = Some aS i = 0eapply nth_error_In; eauto.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j : nat, i0 < length l -> nth_error l i0 = nth_error l j -> i0 = ji:natHi:S i < S (length l)E:nth_error l i = Some aIn a lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> nth_error l i0 = nth_error l j0 -> i0 = j0i, j:natHi:S i < S (length l)E:nth_error l i = nth_error l jS i = S japply IH; auto with arith.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> nth_error l i0 = nth_error l j0 -> i0 = j0i, j:natHi:S i < S (length l)E:nth_error l i = nth_error l ji = jA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list A(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list A(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> nth_error (a :: l) i = nth_error (a :: l) j -> i = j~ In a lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> nth_error (a :: l) i = nth_error (a :: l) j -> i = jNoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> nth_error (a :: l) i = nth_error (a :: l) j -> i = j~ In a lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> nth_error (a :: l) i = nth_error (a :: l) j -> i = jHa:In a lFalseA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> nth_error (a :: l) i = nth_error (a :: l) j -> i = jHa:exists n : nat, nth_error l n = Some aFalseA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> nth_error (a :: l) i = nth_error (a :: l) j -> i = jn:natHn:nth_error l n = Some aFalseA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> nth_error (a :: l) i = nth_error (a :: l) j -> i = jn:natHn:nth_error l n = Some aH0:n < length lFalseA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup ln:natH:0 < length (a :: l) -> nth_error (a :: l) 0 = nth_error (a :: l) (S n) -> 0 = S nHn:nth_error l n = Some aH0:n < length lFalsediscriminate H; auto with arith.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup ln:natH:0 < S (length l) -> Some a = nth_error l n -> 0 = S nHn:nth_error l n = Some aH0:n < length lFalseA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> nth_error (a :: l) i = nth_error (a :: l) j -> i = jNoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> nth_error (a :: l) i = nth_error (a :: l) j -> i = jforall i j : nat, i < length l -> nth_error l i = nth_error l j -> i = japply eq_add_S, H; simpl; auto with arith. } Qed.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AIHl:(forall i0 j0 : nat, i0 < length l -> nth_error l i0 = nth_error l j0 -> i0 = j0) -> NoDup lH:forall i0 j0 : nat, i0 < length (a :: l) -> nth_error (a :: l) i0 = nth_error (a :: l) j0 -> i0 = j0i, j:natHi:i < length lE:nth_error l i = nth_error l ji = jA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list Ad:ANoDup l <-> (forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list Ad:ANoDup l <-> (forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j)A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list Ad:ANoDup l -> forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = jA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list Ad:A(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list Ad:ANoDup l -> forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = jA:TypedecA:forall x y : A, {x = y} + {x <> y}d:Ai, j:natHi:i < length []Hj:j < length []E:nth i [] d = nth j [] di = jA:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> j0 < length l -> nth i0 l d = nth j0 l d -> i0 = j0i, j:natHi:i < length (a :: l)Hj:j < length (a :: l)E:nth i (a :: l) d = nth j (a :: l) di = jinversion Hi.A:TypedecA:forall x y : A, {x = y} + {x <> y}d:Ai, j:natHi:i < length []Hj:j < length []E:nth i [] d = nth j [] di = jA:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> j0 < length l -> nth i0 l d = nth j0 l d -> i0 = j0i, j:natHi:i < length (a :: l)Hj:j < length (a :: l)E:nth i (a :: l) d = nth j (a :: l) di = jA:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i j0 : nat, i < length l -> j0 < length l -> nth i l d = nth j0 l d -> i = j0j:natHi:0 < S (length l)Hj:S j < S (length l)E:a = nth j l d0 = S jA:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j : nat, i0 < length l -> j < length l -> nth i0 l d = nth j l d -> i0 = ji:natHi:S i < S (length l)Hj:0 < S (length l)E:nth i l d = aS i = 0A:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> j0 < length l -> nth i0 l d = nth j0 l d -> i0 = j0i, j:natHi:S i < S (length l)Hj:S j < S (length l)E:nth i l d = nth j l dS i = S jA:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i j0 : nat, i < length l -> j0 < length l -> nth i l d = nth j0 l d -> i = j0j:natHi:0 < S (length l)Hj:S j < S (length l)E:a = nth j l d0 = S jA:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i j0 : nat, i < length l -> j0 < length l -> nth i l d = nth j0 l d -> i = j0j:natHi:0 < S (length l)Hj:S j < S (length l)E:a = nth j l dIn a lapply nth_In; auto with arith.A:TypedecA:forall x y : A, {x = y} + {x <> y}d:Al:list Aj:natHal:~ In (nth j l d) lHl:NoDup lIH:forall i j0 : nat, i < length l -> j0 < length l -> nth i l d = nth j0 l d -> i = j0Hi:0 < S (length l)Hj:S j < S (length l)In (nth j l d) lA:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j : nat, i0 < length l -> j < length l -> nth i0 l d = nth j l d -> i0 = ji:natHi:S i < S (length l)Hj:0 < S (length l)E:nth i l d = aS i = 0A:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j : nat, i0 < length l -> j < length l -> nth i0 l d = nth j l d -> i0 = ji:natHi:S i < S (length l)Hj:0 < S (length l)E:nth i l d = aIn a lapply nth_In; auto with arith.A:TypedecA:forall x y : A, {x = y} + {x <> y}d:Al:list Ai:natHal:~ In (nth i l d) lHl:NoDup lIH:forall i0 j : nat, i0 < length l -> j < length l -> nth i0 l d = nth j l d -> i0 = jHi:S i < S (length l)Hj:0 < S (length l)In (nth i l d) lA:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> j0 < length l -> nth i0 l d = nth j0 l d -> i0 = j0i, j:natHi:S i < S (length l)Hj:S j < S (length l)E:nth i l d = nth j l dS i = S japply IH; auto with arith.A:TypedecA:forall x y : A, {x = y} + {x <> y}d, a:Al:list AHal:~ In a lHl:NoDup lIH:forall i0 j0 : nat, i0 < length l -> j0 < length l -> nth i0 l d = nth j0 l d -> i0 = j0i, j:natHi:S i < S (length l)Hj:S j < S (length l)E:nth i l d = nth j l di = jA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list Ad:A(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list Ad:A(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> j < length (a :: l) -> nth i (a :: l) d = nth j (a :: l) d -> i = j~ In a lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> j < length (a :: l) -> nth i (a :: l) d = nth j (a :: l) d -> i = jNoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> j < length (a :: l) -> nth i (a :: l) d = nth j (a :: l) d -> i = j~ In a lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> j < length (a :: l) -> nth i (a :: l) d = nth j (a :: l) d -> i = jHa:In a lFalseA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> j < length (a :: l) -> nth i (a :: l) d = nth j (a :: l) d -> i = jHa:exists n : nat, n < length l /\ nth n l ?d = aFalseA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> j < length (a :: l) -> nth i (a :: l) d = nth j (a :: l) d -> i = jn:natHn:n < length lHn':nth n l ?d = aFalseA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup ln:natH:0 < length (a :: l) -> S n < length (a :: l) -> nth 0 (a :: l) d = nth (S n) (a :: l) d -> 0 = S nHn:n < length lHn':nth n l ?d = aFalsediscriminate H; eauto with arith.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup ln:natH:0 < S (length l) -> S n < S (length l) -> a = nth n l d -> 0 = S nHn:n < length lHn':nth n l ?d = aFalseA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> j < length (a :: l) -> nth i (a :: l) d = nth j (a :: l) d -> i = jNoDup lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = j) -> NoDup lH:forall i j : nat, i < length (a :: l) -> j < length (a :: l) -> nth i (a :: l) d = nth j (a :: l) d -> i = jforall i j : nat, i < length l -> j < length l -> nth i l d = nth j l d -> i = japply eq_add_S, H; simpl; auto with arith. } Qed.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list Ad:AIHl:(forall i0 j0 : nat, i0 < length l -> j0 < length l -> nth i0 l d = nth j0 l d -> i0 = j0) -> NoDup lH:forall i0 j0 : nat, i0 < length (a :: l) -> j0 < length (a :: l) -> nth i0 (a :: l) d = nth j0 (a :: l) d -> i0 = j0i, j:natHi:i < length lHj:j < length lE:nth i l d = nth j l di = j
Having NoDup hypotheses bring more precise facts about incl.
A:TypedecA:forall x y : A, {x = y} + {x <> y}l, l':list ANoDup l -> incl l l' -> length l <= length l'A:TypedecA:forall x y : A, {x = y} + {x <> y}l, l':list ANoDup l -> incl l l' -> length l <= length l'A:TypedecA:forall x y : A, {x = y} + {x <> y}l, l':list AN:NoDup lincl l l' -> length l <= length l'A:TypedecA:forall x y : A, {x = y} + {x <> y}l:list AN:NoDup lforall l' : list A, incl l l' -> length l <= length l'A:TypedecA:forall x y : A, {x = y} + {x <> y}forall l' : list A, incl [] l' -> 0 <= length l'A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l' : list A, incl l l' -> length l <= length l'forall l' : list A, incl (a :: l) l' -> S (length l) <= length l'auto with arith.A:TypedecA:forall x y : A, {x = y} + {x <> y}forall l' : list A, incl [] l' -> 0 <= length l'A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l' : list A, incl l l' -> length l <= length l'forall l' : list A, incl (a :: l) l' -> S (length l) <= length l'A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, incl l l'0 -> length l <= length l'0l':list AH:incl (a :: l) l'S (length l) <= length l'A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, incl l l'0 -> length l <= length l'0l':list AH:incl (a :: l) l'In a l'A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, incl l l'0 -> length l <= length l'0l':list AH:incl (a :: l) l'l'':list AAD:Add a l'' l'S (length l) <= length l'apply H; simpl; auto.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, incl l l'0 -> length l <= length l'0l':list AH:incl (a :: l) l'In a l'A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, incl l l'0 -> length l <= length l'0l':list AH:incl (a :: l) l'l'':list AAD:Add a l'' l'S (length l) <= length l'A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, incl l l'0 -> length l <= length l'0l':list AH:incl (a :: l) l'l'':list AAD:Add a l'' l'S (length l) <= S (length l'')A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, incl l l'0 -> length l <= length l'0l':list AH:incl (a :: l) l'l'':list AAD:Add a l'' l'length l <= length l''now apply incl_Add_inv with a l'. Qed.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, incl l l'0 -> length l <= length l'0l':list AH:incl (a :: l) l'l'':list AAD:Add a l'' l'incl l l''A:TypedecA:forall x y : A, {x = y} + {x <> y}l, l':list ANoDup l -> length l' <= length l -> incl l l' -> incl l' lA:TypedecA:forall x y : A, {x = y} + {x <> y}l, l':list ANoDup l -> length l' <= length l -> incl l l' -> incl l' lA:TypedecA:forall x y : A, {x = y} + {x <> y}l, l':list AN:NoDup llength l' <= length l -> incl l l' -> incl l' lA:TypedecA:forall x y : A, {x = y} + {x <> y}l:list AN:NoDup lforall l' : list A, length l' <= length l -> incl l l' -> incl l' lA:TypedecA:forall x y : A, {x = y} + {x <> y}forall l' : list A, length l' <= length [] -> incl [] l' -> incl l' []A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l' : list A, length l' <= length l -> incl l l' -> incl l' lforall l' : list A, length l' <= length (a :: l) -> incl (a :: l) l' -> incl l' (a :: l)destruct l'; easy.A:TypedecA:forall x y : A, {x = y} + {x <> y}forall l' : list A, length l' <= length [] -> incl [] l' -> incl l' []A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l' : list A, length l' <= length l -> incl l l' -> incl l' lforall l' : list A, length l' <= length (a :: l) -> incl (a :: l) l' -> incl l' (a :: l)A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'x:AHx:In x l'In x (a :: l)A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'x:AHx:In x l'In a l'A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'x:AHx:In x l'l'':list AAD:Add a l'' l'In x (a :: l)apply H; simpl; auto.A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'x:AHx:In x l'In a l'A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'x:AHx:In x l'l'':list AAD:Add a l'' l'In x (a :: l)A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'x:Al'':list AHx:In x (a :: l'')AD:Add a l'' l'In x (a :: l)A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'x:Al'':list AHx:a = x \/ In x l''AD:Add a l'' l'In x (a :: l)A:TypedecA:forall x0 y : A, {x0 = y} + {x0 <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'x:Al'':list AHx:In x l''AD:Add a l'' l'In x lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'l'':list AAD:Add a l'' l'forall x : A, In x l'' -> In x lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'l'':list AAD:Add a l'' l'length l'' <= length lA:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'l'':list AAD:Add a l'' l'incl l l''A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'l'':list AAD:Add a l'' l'length l'' <= length lnow rewrite <- (Add_length AD).A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'l'':list AAD:Add a l'' l'S (length l'') <= S (length l)now apply incl_Add_inv with a l'. Qed. End ReDun.A:TypedecA:forall x y : A, {x = y} + {x <> y}a:Al:list AHal:~ In a lN:NoDup lIH:forall l'0 : list A, length l'0 <= length l -> incl l l'0 -> incl l'0 ll':list AE:length l' <= length (a :: l)H:incl (a :: l) l'l'':list AAD:Add a l'' l'incl l l''
NoDup and map
NB: the reciprocal result holds only for injective functions,
see FinFun.v
A, B:Typef:A -> Bl:list ANoDup (map f l) -> NoDup lA, B:Typef:A -> Bl:list ANoDup (map f l) -> NoDup lA, B:Typef:A -> Ba:Al:list AIHl:NoDup (map f l) -> NoDup lH0:~ In (f a) (map f l)H1:NoDup (map f l)~ In a lnow apply (in_map f) in H. Qed. (***********************************)A, B:Typef:A -> Ba:Al:list AIHl:NoDup (map f l) -> NoDup lH0:~ In (f a) (map f l)H1:NoDup (map f l)H:In a lFalse
(***********************************) 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) : list nat := match len with | 0 => nil | S len => start :: seq (S start) len end.forall len start : nat, length (seq start len) = leninduction len; simpl; auto. Qed.forall len start : nat, length (seq start len) = lenforall len start n d : nat, n < len -> nth n (seq start len) d = start + nforall len start n d : nat, n < len -> nth n (seq start len) d = start + nstart, n, d:natH:n < 0nth n (seq start 0) d = start + nlen:natIHlen:forall start0 n0 d0 : nat, n0 < len -> nth n0 (seq start0 len) d0 = start0 + n0start, n, d:natH:n < S lennth n (seq start (S len)) d = start + nlen:natIHlen:forall start0 n0 d0 : nat, n0 < len -> nth n0 (seq start0 len) d0 = start0 + n0start, n, d:natH:n < S lennth n (seq start (S len)) d = start + nlen:natIHlen:forall start0 n0 d0 : nat, n0 < len -> nth n0 (seq start0 len) d0 = start0 + n0start, n, d:natH:n < S lennth n (start :: seq (S start) len) d = start + nlen:natIHlen:forall start0 n d0 : nat, n < len -> nth n (seq start0 len) d0 = start0 + nstart, d:natH:0 < S lenstart = start + 0len:natIHlen:forall start0 n0 d0 : nat, n0 < len -> nth n0 (seq start0 len) d0 = start0 + n0start, n, d:natH:S n < S lennth n (seq (S start) len) d = start + S nrewrite IHlen;simpl; auto with arith. Qed.len:natIHlen:forall start0 n0 d0 : nat, n0 < len -> nth n0 (seq start0 len) d0 = start0 + n0start, n, d:natH:S n < S lennth n (seq (S start) len) d = start + S nforall len start : nat, map S (seq start len) = seq (S start) lenforall len start : nat, map S (seq start len) = seq (S start) lenlen:natIHlen:forall start : nat, map S (seq start len) = seq (S start) lenforall start : nat, S start :: map S (seq (S start) len) = S start :: seq (S (S start)) lenlen:natIHlen:forall start0 : nat, map S (seq start0 len) = seq (S start0) lenstart:natS start :: map S (seq (S start) len) = S start :: seq (S (S start)) lenauto with arith. Qed.len:natIHlen:forall start0 : nat, map S (seq start0 len) = seq (S start0) lenstart:natS start :: seq (S (S start)) len = S start :: seq (S (S start)) lenlen, start, n:natIn n (seq start len) <-> start <= n < start + lenlen, start, n:natIn n (seq start len) <-> start <= n < start + lenlen, n:natforall start : nat, In n (seq start len) <-> start <= n < start + lenn, start:natFalse <-> start <= n < start + 0len, n:natIHlen:forall start0 : nat, In n (seq start0 len) <-> start0 <= n < start0 + lenstart:natstart = n \/ In n (seq (S start) len) <-> start <= n < start + S lenn, start:natFalse <-> start <= n < start + 0n, start:natFalse <-> start <= n < startn, start:natstart <= n < start -> Falseapply (Lt.lt_irrefl _ (Lt.le_lt_trans _ _ _ H H')).n, start:natH:start <= nH':n < startFalselen, n:natIHlen:forall start0 : nat, In n (seq start0 len) <-> start0 <= n < start0 + lenstart:natstart = n \/ In n (seq (S start) len) <-> start <= n < start + S lenlen, n:natIHlen:forall start0 : nat, In n (seq start0 len) <-> start0 <= n < start0 + lenstart:natstart = n \/ S start <= n < S (start + len) -> start <= n < S (start + len)len, n:natIHlen:forall start0 : nat, In n (seq start0 len) <-> start0 <= n < start0 + lenstart:natstart <= n < S (start + len) -> start = n \/ S start <= n < S (start + len)intros [H|H]; subst; intuition auto with arith.len, n:natIHlen:forall start0 : nat, In n (seq start0 len) <-> start0 <= n < start0 + lenstart:natstart = n \/ S start <= n < S (start + len) -> start <= n < S (start + len)len, n:natIHlen:forall start0 : nat, In n (seq start0 len) <-> start0 <= n < start0 + lenstart:natstart <= n < S (start + len) -> start = n \/ S start <= n < S (start + len)destruct (Lt.le_lt_or_eq _ _ H); intuition. Qed.len, n:natIHlen:forall start0 : nat, In n (seq start0 len) <-> start0 <= n < start0 + lenstart:natH:start <= nH':n < S (start + len)start = n \/ S start <= n < S (start + len)len, start:natNoDup (seq start len)len, start:natNoDup (seq start len)len:natIHlen:forall start0 : nat, NoDup (seq start0 len)start:nat~ In start (seq (S start) len)len:natIHlen:forall start0 : nat, NoDup (seq start0 len)start:nat~ S start <= start < S start + lenapply (Lt.lt_irrefl _ H). Qed.len:natIHlen:forall start0 : nat, NoDup (seq start0 len)start:natH:S start <= startFalseforall len1 len2 start : nat, seq start (len1 + len2) = seq start len1 ++ seq (start + len1) len2forall len1 len2 start : nat, seq start (len1 + len2) = seq start len1 ++ seq (start + len1) len2len2, start:natseq start len2 = seq (start + 0) len2len1':natIHlen:forall len0 start0 : nat, seq start0 (len1' + len0) = seq start0 len1' ++ seq (start0 + len1') len0len2, start:natstart :: seq (S start) (len1' + len2) = start :: seq (S start) len1' ++ seq (start + S len1') len2now rewrite Nat.add_0_r.len2, start:natseq start len2 = seq (start + 0) len2now rewrite Nat.add_succ_r, IHlen. Qed. End NatSeq. Section Exists_Forall.len1':natIHlen:forall len0 start0 : nat, seq start0 (len1' + len0) = seq start0 len1' ++ seq (start0 + len1') len0len2, start:natstart :: seq (S start) (len1' + len2) = start :: seq (S start) len1' ++ seq (start + S len1') len2
Variable A:Type. Section One_predicate. Variable P:A->Prop. Inductive Exists : list A -> Prop := | Exists_cons_hd : forall x l, P x -> Exists (x::l) | Exists_cons_tl : forall x l, Exists l -> Exists (x::l). Hint Constructors Exists : core.A:TypeP:A -> Propl:list AExists l <-> (exists x : A, In x l /\ P x)A:TypeP:A -> Propl:list AExists l <-> (exists x : A, In x l /\ P x)A:TypeP:A -> Propl:list AExists l -> exists x : A, In x l /\ P xA:TypeP:A -> Propl:list A(exists x : A, In x l /\ P x) -> Exists linduction 1; firstorder.A:TypeP:A -> Propl:list AExists l -> exists x : A, In x l /\ P xinduction l; firstorder; subst; auto. Qed.A:TypeP:A -> Propl:list A(exists x : A, In x l /\ P x) -> Exists lA:TypeP:A -> PropExists [] <-> Falsesplit; inversion 1. Qed.A:TypeP:A -> PropExists [] <-> FalseA:TypeP:A -> Propx:Al:list AExists (x :: l) <-> P x \/ Exists lsplit; inversion 1; auto. Qed.A:TypeP:A -> Propx:Al:list AExists (x :: l) <-> P x \/ Exists lA:TypeP:A -> Propl:list A(forall x : A, {P x} + {~ P x}) -> {Exists l} + {~ Exists l}A:TypeP:A -> Propl:list A(forall x : A, {P x} + {~ P x}) -> {Exists l} + {~ Exists l}A:TypeP:A -> Propl:list APdec:forall x : A, {P x} + {~ P x}{Exists l} + {~ Exists l}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}{Exists []} + {~ Exists []}A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hrec:{Exists l'} + {~ Exists l'}{Exists (a :: l')} + {~ Exists (a :: l')}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}{Exists []} + {~ Exists []}abstract now rewrite Exists_nil.A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}~ Exists []A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hrec:{Exists l'} + {~ Exists l'}{Exists (a :: l')} + {~ Exists (a :: l')}A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':Exists l'{Exists (a :: l')} + {~ Exists (a :: l')}A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':~ Exists l'{Exists (a :: l')} + {~ Exists (a :: l')}A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':Exists l'{Exists (a :: l')} + {~ Exists (a :: l')}now apply Exists_cons_tl.A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':Exists l'Exists (a :: l')A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':~ Exists l'{Exists (a :: l')} + {~ Exists (a :: l')}A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':~ Exists l'Ha:P a{Exists (a :: l')} + {~ Exists (a :: l')}A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':~ Exists l'Ha:~ P a{Exists (a :: l')} + {~ Exists (a :: l')}A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':~ Exists l'Ha:P a{Exists (a :: l')} + {~ Exists (a :: l')}now apply Exists_cons_hd.A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':~ Exists l'Ha:P aExists (a :: l')A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':~ Exists l'Ha:~ P a{Exists (a :: l')} + {~ Exists (a :: l')}abstract now inversion 1. Defined. Inductive Forall : list A -> Prop := | Forall_nil : Forall nil | Forall_cons : forall x l, P x -> Forall l -> Forall (x::l). Hint Constructors Forall : core.A:TypeP:A -> Propa:Al':list APdec:forall x : A, {P x} + {~ P x}Hl':~ Exists l'Ha:~ P a~ Exists (a :: l')A:TypeP:A -> Propl:list AForall l <-> (forall x : A, In x l -> P x)A:TypeP:A -> Propl:list AForall l <-> (forall x : A, In x l -> P x)A:TypeP:A -> Propl:list AForall l -> forall x : A, In x l -> P xA:TypeP:A -> Propl:list A(forall x : A, In x l -> P x) -> Forall linduction 1; firstorder; subst; auto.A:TypeP:A -> Propl:list AForall l -> forall x : A, In x l -> P xinduction l; firstorder. Qed.A:TypeP:A -> Propl:list A(forall x : A, In x l -> P x) -> Forall lA:TypeP:A -> Propforall (a : A) (l : list A), Forall (a :: l) -> P aintros; inversion H; trivial. Qed.A:TypeP:A -> Propforall (a : A) (l : list A), Forall (a :: l) -> P aA:TypeP:A -> Propforall Q : list A -> Type, Q [] -> (forall (b : A) (l : list A), P b -> Q (b :: l)) -> forall l : list A, Forall l -> Q lintros Q H H'; induction l; intro; [|eapply H', Forall_inv]; eassumption. Qed.A:TypeP:A -> Propforall Q : list A -> Type, Q [] -> (forall (b : A) (l : list A), P b -> Q (b :: l)) -> forall l : list A, Forall l -> Q lA:TypeP:A -> Prop(forall x : A, {P x} + {~ P x}) -> forall l : list A, {Forall l} + {~ Forall l}A:TypeP:A -> Prop(forall x : A, {P x} + {~ P x}) -> forall l : list A, {Forall l} + {~ Forall l}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}forall l : list A, {Forall l} + {~ Forall l}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}{Forall []} + {~ Forall []}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHrec:{Forall l'} + {~ Forall l'}{Forall (a :: l')} + {~ Forall (a :: l')}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}{Forall []} + {~ Forall []}apply Forall_nil.A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}Forall []A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHrec:{Forall l'} + {~ Forall l'}{Forall (a :: l')} + {~ Forall (a :: l')}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':Forall l'{Forall (a :: l')} + {~ Forall (a :: l')}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':~ Forall l'{Forall (a :: l')} + {~ Forall (a :: l')}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':Forall l'{Forall (a :: l')} + {~ Forall (a :: l')}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':Forall l'Ha:P a{Forall (a :: l')} + {~ Forall (a :: l')}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':Forall l'Ha:~ P a{Forall (a :: l')} + {~ Forall (a :: l')}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':Forall l'Ha:P a{Forall (a :: l')} + {~ Forall (a :: l')}now apply Forall_cons.A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':Forall l'Ha:P aForall (a :: l')A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':Forall l'Ha:~ P a{Forall (a :: l')} + {~ Forall (a :: l')}abstract now inversion 1.A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':Forall l'Ha:~ P a~ Forall (a :: l')A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':~ Forall l'{Forall (a :: l')} + {~ Forall (a :: l')}abstract now inversion 1. Defined. End One_predicate.A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}a:Al':list AHl':~ Forall l'~ Forall (a :: l')A:Typeforall (P : A -> Prop) (x0 : A) (xs : list A), Forall P (x0 :: xs) -> Forall P xsA:Typeforall (P : A -> Prop) (x0 : A) (xs : list A), Forall P (x0 :: xs) -> Forall P xsA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)Forall P xsA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)forall x : A, In x xs -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)forall x : A, In x (x0 :: xs) -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x : A, In x (x0 :: xs) -> P xforall x : A, In x xs -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)Forall P (x0 :: xs)A:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x : A, In x (x0 :: xs) -> P xforall x : A, In x xs -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x : A, In x (x0 :: xs) -> P xforall x : A, In x xs -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x : A, In x (x0 :: xs) -> P xforall x : A, In x xs -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x : A, In x (x0 :: xs) -> P xH1:forall x : A, In x xs -> P xforall x : A, In x xs -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x1 : A, In x1 (x0 :: xs) -> P x1x:AH2:In x xsP xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x : A, In x (x0 :: xs) -> P xH1:forall x : A, In x xs -> P xforall x : A, In x xs -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x1 : A, In x1 (x0 :: xs) -> P x1x:AH2:In x xsIn x (x0 :: xs)A:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x : A, In x (x0 :: xs) -> P xH1:forall x : A, In x xs -> P xforall x : A, In x xs -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x1 : A, In x1 (x0 :: xs) -> P x1x:AH2:In x xsIn x xsA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x : A, In x (x0 :: xs) -> P xH1:forall x : A, In x xs -> P xforall x : A, In x xs -> P xA:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x : A, In x (x0 :: xs) -> P xH1:forall x : A, In x xs -> P xforall x : A, In x xs -> P xapply (H1 x H2). Qed.A:TypeP:A -> Propx0:Axs:list AH:Forall P (x0 :: xs)H0:forall x1 : A, In x1 (x0 :: xs) -> P x1H1:forall x1 : A, In x1 xs -> P x1x:AH2:In x xsP xA:Typeforall P Q : A -> Prop, (forall x : A, P x -> Q x) -> forall xs : list A, Exists P xs -> Exists Q xsA:Typeforall P Q : A -> Prop, (forall x : A, P x -> Q x) -> forall xs : list A, Exists P xs -> Exists Q xsA:TypeP, Q:A -> PropH:forall x : A, P x -> Q xxs:list AH0:Exists P xsExists Q xsA:TypeP, Q:A -> PropH:forall x0 : A, P x0 -> Q x0x:Al:list AH0:P xExists Q (x :: l)A:TypeP, Q:A -> PropH:forall x0 : A, P x0 -> Q x0x:Al:list AH0:Exists P lIHExists:Exists Q lExists Q (x :: l)apply (Exists_cons_tl x IHExists). Qed.A:TypeP, Q:A -> PropH:forall x0 : A, P x0 -> Q x0x:Al:list AH0:Exists P lIHExists:Exists Q lExists Q (x :: l)A:TypeP:A -> Propl:list AForall (fun x : A => ~ P x) l <-> ~ Exists P lA:TypeP:A -> Propl:list AForall (fun x : A => ~ P x) l <-> ~ Exists P lfirstorder. Qed.A:TypeP:A -> Propl:list A(forall x : A, In x l -> ~ P x) <-> ~ (exists x : A, In x l /\ P x)A:TypeP:A -> Propl:list A(forall x : A, P x \/ ~ P x) -> Exists (fun x : A => ~ P x) l <-> ~ Forall P lA:TypeP:A -> Propl:list A(forall x : A, P x \/ ~ P x) -> Exists (fun x : A => ~ P x) l <-> ~ Forall P lA:TypeP:A -> Propl:list ADec:forall x : A, P x \/ ~ P xExists (fun x : A => ~ P x) l <-> ~ Forall P lA:TypeP:A -> Propl:list ADec:forall x : A, P x \/ ~ P xExists (fun x : A => ~ P x) l -> ~ Forall P lA:TypeP:A -> Propl:list ADec:forall x : A, P x \/ ~ P x~ Forall P l -> Exists (fun x : A => ~ P x) lrewrite Forall_forall, Exists_exists; firstorder.A:TypeP:A -> Propl:list ADec:forall x : A, P x \/ ~ P xExists (fun x : A => ~ P x) l -> ~ Forall P lA:TypeP:A -> Propl:list ADec:forall x : A, P x \/ ~ P x~ Forall P l -> Exists (fun x : A => ~ P x) lA:TypeP:A -> Propl:list ADec:forall x : A, P x \/ ~ P xNF:~ Forall P lExists (fun x : A => ~ P x) lA:TypeP:A -> PropDec:forall x : A, P x \/ ~ P xNF:~ Forall P []Exists (fun x : A => ~ P x) []A:TypeP:A -> Propa:Al:list ADec:forall x : A, P x \/ ~ P xNF:~ Forall P (a :: l)IH:~ Forall P l -> Exists (fun x : A => ~ P x) lExists (fun x : A => ~ P x) (a :: l)A:TypeP:A -> PropDec:forall x : A, P x \/ ~ P xNF:~ Forall P []Exists (fun x : A => ~ P x) []constructor.A:TypeP:A -> PropDec:forall x : A, P x \/ ~ P xForall P []A:TypeP:A -> Propa:Al:list ADec:forall x : A, P x \/ ~ P xNF:~ Forall P (a :: l)IH:~ Forall P l -> Exists (fun x : A => ~ P x) lExists (fun x : A => ~ P x) (a :: l)A:TypeP:A -> Propa:Al:list ADec:forall x : A, P x \/ ~ P xNF:~ Forall P (a :: l)IH:~ Forall P l -> Exists (fun x : A => ~ P x) lHa:P aExists (fun x : A => ~ P x) (a :: l)A:TypeP:A -> Propa:Al:list ADec:forall x : A, P x \/ ~ P xNF:~ Forall P (a :: l)IH:~ Forall P l -> Exists (fun x : A => ~ P x) lHa:~ P aExists (fun x : A => ~ P x) (a :: l)A:TypeP:A -> Propa:Al:list ADec:forall x : A, P x \/ ~ P xNF:~ Forall P (a :: l)IH:~ Forall P l -> Exists (fun x : A => ~ P x) lHa:P aExists (fun x : A => ~ P x) (a :: l)A:TypeP:A -> Propa:Al:list ADec:forall x : A, P x \/ ~ P xNF:~ Forall P (a :: l)IH:~ Forall P l -> Exists (fun x : A => ~ P x) lHa:P a~ Forall P lnow constructor.A:TypeP:A -> Propa:Al:list ADec:forall x : A, P x \/ ~ P xIH:~ Forall P l -> Exists (fun x : A => ~ P x) lHa:P aNF:Forall P lForall P (a :: l)now apply Exists_cons_hd. Qed.A:TypeP:A -> Propa:Al:list ADec:forall x : A, P x \/ ~ P xNF:~ Forall P (a :: l)IH:~ Forall P l -> Exists (fun x : A => ~ P x) lHa:~ P aExists (fun x : A => ~ P x) (a :: l)A:TypeP:A -> Propl:list A(forall x : A, {P x} + {~ P x}) -> ~ Forall P l -> Exists (fun x : A => ~ P x) lA:TypeP:A -> Propl:list A(forall x : A, {P x} + {~ P x}) -> ~ Forall P l -> Exists (fun x : A => ~ P x) lA:TypeP:A -> Propl:list ADec:forall x : A, {P x} + {~ P x}~ Forall P l -> Exists (fun x : A => ~ P x) ldestruct (Dec x); auto. Qed.A:TypeP:A -> Propl:list ADec:forall x0 : A, {P x0} + {~ P x0}x:AP x \/ ~ P xA:TypeP:A -> Prop(forall x : A, {P x} + {~ P x}) -> forall l : list A, {Forall P l} + {Exists (fun x : A => ~ P x) l}A:TypeP:A -> Prop(forall x : A, {P x} + {~ P x}) -> forall l : list A, {Forall P l} + {Exists (fun x : A => ~ P x) l}A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}l:list A{Forall P l} + {Exists (fun x : A => ~ P x) l}now apply neg_Forall_Exists_neg. Defined.A:TypeP:A -> PropPdec:forall x : A, {P x} + {~ P x}l:list An:~ Forall P lExists (fun x : A => ~ P x) lA:Typeforall P Q : A -> Prop, (forall a : A, P a -> Q a) -> forall l : list A, Forall P l -> Forall Q lA:Typeforall P Q : A -> Prop, (forall a : A, P a -> Q a) -> forall l : list A, Forall P l -> Forall Q lA:TypeP, Q:A -> PropH:forall a : A, P a -> Q al:list AForall P l -> Forall Q lfirstorder. Qed. End Exists_Forall. Hint Constructors Exists : core. Hint Constructors Forall : core. Section Forall2.A:TypeP, Q:A -> PropH:forall a : A, P a -> Q al:list A(forall x : A, In x l -> P x) -> forall x : A, In x l -> Q x
Forall2: stating that elements of two lists are pairwise related.
Variables A B : Type. Variable R : A -> B -> Prop. Inductive Forall2 : list A -> list B -> Prop := | Forall2_nil : Forall2 [] [] | Forall2_cons : forall x y l l', R x y -> Forall2 l l' -> Forall2 (x::l) (y::l'). Hint Constructors Forall2 : core.A, B:TypeR:A -> B -> PropForall2 [] []intros; apply Forall2_nil. Qed.A, B:TypeR:A -> B -> PropForall2 [] []A, B:TypeR:A -> B -> Propforall (l1 l2 : list A) (l' : list B), Forall2 (l1 ++ l2) l' -> exists l1' l2' : list B, Forall2 l1 l1' /\ Forall2 l2 l2' /\ l' = l1' ++ l2'A, B:TypeR:A -> B -> Propforall (l1 l2 : list A) (l' : list B), Forall2 (l1 ++ l2) l' -> exists l1' l2' : list B, Forall2 l1 l1' /\ Forall2 l2 l2' /\ l' = l1' ++ l2'A, B:TypeR:A -> B -> Propl2:list Al':list BH:Forall2 ([] ++ l2) l'exists l1' l2' : list B, Forall2 [] l1' /\ Forall2 l2 l2' /\ l' = l1' ++ l2'A, B:TypeR:A -> B -> Propa:Al1:list AIHl1:forall (l0 : list A) (l'0 : list B), Forall2 (l1 ++ l0) l'0 -> exists l1' l2' : list B, Forall2 l1 l1' /\ Forall2 l0 l2' /\ l'0 = l1' ++ l2'l2:list Al':list BH:Forall2 ((a :: l1) ++ l2) l'exists l1' l2' : list B, Forall2 (a :: l1) l1' /\ Forall2 l2 l2' /\ l' = l1' ++ l2'A, B:TypeR:A -> B -> Propa:Al1:list AIHl1:forall (l0 : list A) (l'0 : list B), Forall2 (l1 ++ l0) l'0 -> exists l1' l2' : list B, Forall2 l1 l1' /\ Forall2 l0 l2' /\ l'0 = l1' ++ l2'l2:list Al':list BH:Forall2 ((a :: l1) ++ l2) l'exists l1' l2' : list B, Forall2 (a :: l1) l1' /\ Forall2 l2 l2' /\ l' = l1' ++ l2'A, B:TypeR:A -> B -> Propa:Al1:list AIHl1:forall (l0 : list A) (l' : list B), Forall2 (l1 ++ l0) l' -> exists l1' l2' : list B, Forall2 l1 l1' /\ Forall2 l0 l2' /\ l' = l1' ++ l2'l2:list Ay:Bl'0:list BH2:R a yH4:Forall2 (l1 ++ l2) l'0exists l1' l2' : list B, Forall2 (a :: l1) l1' /\ Forall2 l2 l2' /\ y :: l'0 = l1' ++ l2'exists (y::l1'), l2'; simpl; auto. Qed.A, B:TypeR:A -> B -> Propa:Al1:list AIHl1:forall (l0 : list A) (l' : list B), Forall2 (l1 ++ l0) l' -> exists l1'0 l2'0 : list B, Forall2 l1 l1'0 /\ Forall2 l0 l2'0 /\ l' = l1'0 ++ l2'0l2:list Ay:BH2:R a yl1', l2':list BHl1:Forall2 l1 l1'Hl2:Forall2 l2 l2'exists l1'0 l2'0 : list B, Forall2 (a :: l1) l1'0 /\ Forall2 l2 l2'0 /\ y :: l1' ++ l2' = l1'0 ++ l2'0A, B:TypeR:A -> B -> Propforall (l1' l2' : list B) (l : list A), Forall2 l (l1' ++ l2') -> exists l1 l2 : list A, Forall2 l1 l1' /\ Forall2 l2 l2' /\ l = l1 ++ l2A, B:TypeR:A -> B -> Propforall (l1' l2' : list B) (l : list A), Forall2 l (l1' ++ l2') -> exists l1 l2 : list A, Forall2 l1 l1' /\ Forall2 l2 l2' /\ l = l1 ++ l2A, B:TypeR:A -> B -> Propl2':list Bl:list AH:Forall2 l ([] ++ l2')exists l1 l2 : list A, Forall2 l1 [] /\ Forall2 l2 l2' /\ l = l1 ++ l2A, B:TypeR:A -> B -> Propa:Bl1':list BIHl1':forall (l2'0 : list B) (l0 : list A), Forall2 l0 (l1' ++ l2'0) -> exists l1 l2 : list A, Forall2 l1 l1' /\ Forall2 l2 l2'0 /\ l0 = l1 ++ l2l2':list Bl:list AH:Forall2 l ((a :: l1') ++ l2')exists l1 l2 : list A, Forall2 l1 (a :: l1') /\ Forall2 l2 l2' /\ l = l1 ++ l2A, B:TypeR:A -> B -> Propa:Bl1':list BIHl1':forall (l2'0 : list B) (l0 : list A), Forall2 l0 (l1' ++ l2'0) -> exists l1 l2 : list A, Forall2 l1 l1' /\ Forall2 l2 l2'0 /\ l0 = l1 ++ l2l2':list Bl:list AH:Forall2 l ((a :: l1') ++ l2')exists l1 l2 : list A, Forall2 l1 (a :: l1') /\ Forall2 l2 l2' /\ l = l1 ++ l2A, B:TypeR:A -> B -> Propa:Bl1':list BIHl1':forall (l2'0 : list B) (l : list A), Forall2 l (l1' ++ l2'0) -> exists l1 l2 : list A, Forall2 l1 l1' /\ Forall2 l2 l2'0 /\ l = l1 ++ l2l2':list Bx:Al0:list AH3:R x aH4:Forall2 l0 (l1' ++ l2')exists l1 l2 : list A, Forall2 l1 (a :: l1') /\ Forall2 l2 l2' /\ x :: l0 = l1 ++ l2exists (x::l1), l2; simpl; auto. Qed.A, B:TypeR:A -> B -> Propa:Bl1':list BIHl1':forall (l2'0 : list B) (l : list A), Forall2 l (l1' ++ l2'0) -> exists l0 l3 : list A, Forall2 l0 l1' /\ Forall2 l3 l2'0 /\ l = l0 ++ l3l2':list Bx:AH3:R x al1, l2:list AHl1:Forall2 l1 l1'Hl2:Forall2 l2 l2'exists l0 l3 : list A, Forall2 l0 (a :: l1') /\ Forall2 l3 l2' /\ x :: l1 ++ l2 = l0 ++ l3A, B:TypeR:A -> B -> Propforall (l1 l2 : list A) (l1' l2' : list B), Forall2 l1 l1' -> Forall2 l2 l2' -> Forall2 (l1 ++ l2) (l1' ++ l2')A, B:TypeR:A -> B -> Propforall (l1 l2 : list A) (l1' l2' : list B), Forall2 l1 l1' -> Forall2 l2 l2' -> Forall2 (l1 ++ l2) (l1' ++ l2')induction l1 in l1', H, H0 |- *; inversion H; subst; simpl; auto. Qed. End Forall2. Hint Constructors Forall2 : core. Section ForallPairs.A, B:TypeR:A -> B -> Propl1, l2:list Al1', l2':list BH:Forall2 l1 l1'H0:Forall2 l2 l2'Forall2 (l1 ++ l2) (l1' ++ l2')
ForallPairs : specifies that a certain relation should
always hold when inspecting all possible pairs of elements of a list.
Variable A : Type. Variable R : A -> A -> Prop. Definition ForallPairs l := forall a b, In a l -> In b l -> R a b.
ForallOrdPairs : we still check a relation over all pairs
of elements of a list, but now the order of elements matters.
Inductive ForallOrdPairs : list A -> Prop := | FOP_nil : ForallOrdPairs nil | FOP_cons : forall a l, Forall (R a) l -> ForallOrdPairs l -> ForallOrdPairs (a::l). Hint Constructors ForallOrdPairs : core.A:TypeR:A -> A -> Propforall l : list A, ForallOrdPairs l -> forall x y : A, In x l -> In y l -> x = y \/ R x y \/ R y xA:TypeR:A -> A -> Propforall l : list A, ForallOrdPairs l -> forall x y : A, In x l -> In y l -> x = y \/ R x y \/ R y xA:TypeR:A -> A -> Propforall x y : A, In x [] -> In y [] -> x = y \/ R x y \/ R y xA:TypeR:A -> A -> Propa:Al:list AH:Forall (R a) lH0:ForallOrdPairs lIHForallOrdPairs:forall x y : A, In x l -> In y l -> x = y \/ R x y \/ R y xforall x y : A, In x (a :: l) -> In y (a :: l) -> x = y \/ R x y \/ R y xA:TypeR:A -> A -> Propa:Al:list AH:Forall (R a) lH0:ForallOrdPairs lIHForallOrdPairs:forall x y : A, In x l -> In y l -> x = y \/ R x y \/ R y xforall x y : A, In x (a :: l) -> In y (a :: l) -> x = y \/ R x y \/ R y xA:TypeR:A -> A -> Propl:list Ax:AH:Forall (R x) lH0:ForallOrdPairs lIHForallOrdPairs:forall x0 y0 : A, In x0 l -> In y0 l -> x0 = y0 \/ R x0 y0 \/ R y0 x0y:AH2:In y lx = y \/ R x y \/ R y xA:TypeR:A -> A -> Propl:list Ay:AH:Forall (R y) lH0:ForallOrdPairs lIHForallOrdPairs:forall x0 y0 : A, In x0 l -> In y0 l -> x0 = y0 \/ R x0 y0 \/ R y0 x0x:AH1:In x lx = y \/ R x y \/ R y xA:TypeR:A -> A -> Propl:list Ax:AH:Forall (R x) lH0:ForallOrdPairs lIHForallOrdPairs:forall x0 y0 : A, In x0 l -> In y0 l -> x0 = y0 \/ R x0 y0 \/ R y0 x0y:AH2:In y lR x yA:TypeR:A -> A -> Propl:list Ay:AH:Forall (R y) lH0:ForallOrdPairs lIHForallOrdPairs:forall x0 y0 : A, In x0 l -> In y0 l -> x0 = y0 \/ R x0 y0 \/ R y0 x0x:AH1:In x lx = y \/ R x y \/ R y xA:TypeR:A -> A -> Propl:list Ay:AH:Forall (R y) lH0:ForallOrdPairs lIHForallOrdPairs:forall x0 y0 : A, In x0 l -> In y0 l -> x0 = y0 \/ R x0 y0 \/ R y0 x0x:AH1:In x lx = y \/ R x y \/ R y xapply -> Forall_forall; eauto. Qed.A:TypeR:A -> A -> Propl:list Ay:AH:Forall (R y) lH0:ForallOrdPairs lIHForallOrdPairs:forall x0 y0 : A, In x0 l -> In y0 l -> x0 = y0 \/ R x0 y0 \/ R y0 x0x:AH1:In x lR y x
ForallPairs implies ForallOrdPairs. The reverse implication is true
only when R is symmetric and reflexive.
A:TypeR:A -> A -> Propl:list AForallPairs l -> ForallOrdPairs lA:TypeR:A -> A -> Propl:list AForallPairs l -> ForallOrdPairs lA:TypeR:A -> A -> Propa:Al:list AIHl:ForallPairs l -> ForallOrdPairs lForallPairs (a :: l) -> ForallOrdPairs (a :: l)A:TypeR:A -> A -> Propa:Al:list AIHl:ForallPairs l -> ForallOrdPairs lH:ForallPairs (a :: l)ForallOrdPairs (a :: l)A:TypeR:A -> A -> Propa:Al:list AIHl:ForallPairs l -> ForallOrdPairs lH:ForallPairs (a :: l)Forall (R a) lA:TypeR:A -> A -> Propa:Al:list AIHl:ForallPairs l -> ForallOrdPairs lH:ForallPairs (a :: l)ForallOrdPairs lA:TypeR:A -> A -> Propa:Al:list AIHl:ForallPairs l -> ForallOrdPairs lH:ForallPairs (a :: l)forall x : A, In x l -> R a xA:TypeR:A -> A -> Propa:Al:list AIHl:ForallPairs l -> ForallOrdPairs lH:ForallPairs (a :: l)ForallOrdPairs lA:TypeR:A -> A -> Propa:Al:list AIHl:ForallPairs l -> ForallOrdPairs lH:ForallPairs (a :: l)ForallOrdPairs lred; intros; apply H; simpl; auto. Qed.A:TypeR:A -> A -> Propa:Al:list AIHl:ForallPairs l -> ForallOrdPairs lH:ForallPairs (a :: l)ForallPairs lA:TypeR:A -> A -> Prop(forall x : A, R x x) -> (forall x y : A, R x y -> R y x) -> forall l : list A, ForallOrdPairs l -> ForallPairs lA:TypeR:A -> A -> Prop(forall x : A, R x x) -> (forall x y : A, R x y -> R y x) -> forall l : list A, ForallOrdPairs l -> ForallPairs ldestruct (ForallOrdPairs_In Hl _ _ Hx Hy); subst; intuition. Qed. End ForallPairs.A:TypeR:A -> A -> PropRefl:forall x0 : A, R x0 x0Sym:forall x0 y0 : A, R x0 y0 -> R y0 x0l:list AHl:ForallOrdPairs lx, y:AHx:In x lHy:In y lR x y
Ltac is_list_constr c := match c with | nil => idtac | (_::_) => idtac | _ => fail end. Ltac invlist f := match goal with | H:f ?l |- _ => is_list_constr l; inversion_clear H; invlist f | H:f _ ?l |- _ => is_list_constr l; inversion_clear H; invlist f | H:f _ _ ?l |- _ => is_list_constr l; inversion_clear H; invlist f | H:f _ _ _ ?l |- _ => is_list_constr l; inversion_clear H; invlist f | H:f _ _ _ _ ?l |- _ => is_list_constr l; inversion_clear H; invlist f | _ => idtac end.
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 *) app_nil_r (* l ++ nil = l *) : list. Ltac simpl_list := autorewrite with list. Ltac ssimpl_list := autorewrite with list using simpl. (* begin hide *) (* Compatibility notations after the migration of [list] to [Datatypes] *) Notation list := list (only parsing). Notation list_rect := list_rect (only parsing). Notation list_rec := list_rec (only parsing). Notation list_ind := list_ind (only parsing). Notation nil := nil (only parsing). Notation cons := cons (only parsing). Notation length := length (only parsing). Notation app := app (only parsing). (* Compatibility Names *) Notation tail := tl (only parsing). Notation head := hd_error (only parsing). Notation head_nil := hd_error_nil (only parsing). Notation head_cons := hd_error_cons (only parsing). Notation ass_app := app_assoc (only parsing). Notation app_ass := app_assoc_reverse (only parsing). Notation In_split := in_split (only parsing). Notation In_rev := in_rev (only parsing). Notation In_dec := in_dec (only parsing). Notation distr_rev := rev_app_distr (only parsing). Notation rev_acc := rev_append (only parsing). Notation rev_acc_rev := rev_append_rev (only parsing). Notation AllS := Forall (only parsing). (* was formerly in TheoryList *) Hint Resolve app_nil_end : datatypes. (* end hide *) Section Repeat. Variable A : Type. Fixpoint repeat (x : A) (n: nat ) := match n with | O => [] | S k => x::(repeat x k) end.A:Typex:An:natDatatypes.length (repeat x n) = ninduction n as [| k Hrec]; simpl; rewrite ?Hrec; reflexivity. Qed.A:Typex:An:natDatatypes.length (repeat x n) = nA:Typen:natx, y:AIn y (repeat x n) -> y = xinduction n as [|k Hrec]; simpl; destruct 1; auto. Qed. End Repeat. (* Unset Universe Polymorphism. *)A:Typen:natx, y:AIn y (repeat x n) -> y = x