From stdpp Require Import prelude finite. From Coq Require Import FinFun. From VLSM.Lib Require Import Preamble.
A list is either empty or it can be decomposed into an initial prefix
and the last element.
∀ (A : Type) (l : list A), {l' : list A & {a : A | l = l' ++ [a]}} + {l = []}∀ (A : Type) (l : list A), {l' : list A & {a : A | l = l' ++ [a]}} + {l = []}A: Type{l' : list A & {a : A | [] = l' ++ [a]}} + {[] = []}A: Type
a: A
l: list A{l' : list A & {a0 : A | a :: l = l' ++ [a0]}} + {a :: l = []}by right.A: Type{l' : list A & {a : A | [] = l' ++ [a]}} + {[] = []}by left; apply exists_last. Qed.A: Type
a: A
l: list A{l' : list A & {a0 : A | a :: l = l' ++ [a0]}} + {a :: l = []}
Decompose a list in into a prefix
l'
and the last element a
with an equation Heq
stating that l = l' ++ [a]
.
Ltac destruct_list_last l l' a Heq := destruct (has_last_or_null l) as [[l' [a Heq]] | Heq]; rewrite Heq in *; swap 1 2.∀ (A : Type) (l : list A) (a : A), l ++ [a] ≠ []by destruct l. Qed.∀ (A : Type) (l : list A) (a : A), l ++ [a] ≠ []
Return the last element of the list if it's present and None otherwise.
Definition last_error {A : Type} (l : list A) : option A := match l with | [] => None | a :: t => Some (List.last t a) end.∀ (A : Type) (random a b : A) (l : list A), List.last (a :: b :: l) random = List.last (b :: l) randomdone. Qed.∀ (A : Type) (random a b : A) (l : list A), List.last (a :: b :: l) random = List.last (b :: l) random∀ (A : Type) (random a b c : A) (l : list A), List.last (a :: b :: c :: l) random = List.last (b :: a :: c :: l) randomby induction l. Qed.∀ (A : Type) (random a b c : A) (l : list A), List.last (a :: b :: c :: l) random = List.last (b :: a :: c :: l) random∀ (A : Type) (hd1 hd2 d1 d2 : A) (tl : list A), List.last (hd1 :: hd2 :: tl) d1 = List.last (hd2 :: tl) d2∀ (A : Type) (hd1 hd2 d1 d2 : A) (tl : list A), List.last (hd1 :: hd2 :: tl) d1 = List.last (hd2 :: tl) d2by destruct tl. Qed.A: Type
hd1, hd2, d1, d2, a: A
tl: list A
IHtl: List.last (hd1 :: hd2 :: tl) d1 = List.last (hd2 :: tl) d2match tl with | [] => a | _ :: _ => List.last tl d1 end = match tl with | [] => a | _ :: _ => List.last tl d2 end∀ (A : Type) (random a : A) (l : list A), List.last (a :: l) random = List.last l a∀ (A : Type) (random a : A) (l : list A), List.last (a :: l) random = List.last l aby rewrite swap_head_last, unfold_last_hd, IHl, unfold_last_hd. Qed.A: Type
random, a, h, h': A
t: list A
IHl: List.last (a :: h' :: t) random = List.last (h' :: t) aList.last (a :: h :: h' :: t) random = List.last (h :: h' :: t) a∀ (A : Type) (l1 l2 : list A) (def : A), List.last (l1 ++ l2) def = List.last l2 (List.last l1 def)∀ (A : Type) (l1 l2 : list A) (def : A), List.last (l1 ++ l2) def = List.last l2 (List.last l1 def)by rewrite <- !app_comm_cons, !unroll_last. Qed.A: Type
a: A
l1: list A
IHl1: ∀ (l2 : list A) (def : A), List.last (l1 ++ l2) def = List.last l2 (List.last l1 def)
l2: list A
def: AList.last ((a :: l1) ++ l2) def = List.last l2 (List.last (a :: l1) def)∀ (A B : Type) (f : A → B) (t : list A) (h : A) (def : B), List.last (map f (h :: t)) def = f (List.last t h)∀ (A B : Type) (f : A → B) (t : list A) (h : A) (def : B), List.last (map f (h :: t)) def = f (List.last t h)by rewrite map_cons, !unroll_last. Qed.A, B: Type
f: A → B
a: A
t: list A
IHt: ∀ (h : A) (def : B), List.last (map f (h :: t)) def = f (List.last t h)
h: A
def: BList.last (map f (h :: a :: t)) def = f (List.last (a :: t) h)∀ (A : Type) (l : list A) (s random : A), last_error l = Some s → List.last l random = sby destruct l; [| inversion 1; apply unroll_last]. Qed.∀ (A : Type) (l : list A) (s random : A), last_error l = Some s → List.last l random = s∀ (A : Type) (l : list A) (a : A), l ⊆ [a] → ∀ b : A, b ∈ l → b = a∀ (A : Type) (l : list A) (a : A), l ⊆ [a] → ∀ b : A, b ∈ l → b = aby apply elem_of_list_singleton, Hsub. Qed.A: Type
l: list A
a: A
Hsub: l ⊆ [a]
b: A
Hin: b ∈ lb = a∀ (A : Type) (P : A → Prop), (∀ a : A, Decision (P a)) → ∀ l : list A, Exists P l → ∃ (prefix suffix : list A) (first : A), P first ∧ l = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefix∀ (A : Type) (P : A → Prop), (∀ a : A, Decision (P a)) → ∀ l : list A, Exists P l → ∃ (prefix suffix : list A) (first : A), P first ∧ l = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefixA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: Exists P t → ∃ (prefix suffix : list A) (first : A), P first ∧ t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefix
Hex: Exists P (h :: t)∃ (prefix suffix : list A) (first : A), P first ∧ h :: t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefixA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: Exists P t → ∃ (prefix suffix : list A) (first : A), P first ∧ t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefix
Hex: Exists P (h :: t)
p: P h∃ (prefix suffix : list A) (first : A), P first ∧ h :: t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefixA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: Exists P t → ∃ (prefix suffix : list A) (first : A), P first ∧ t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefix
Hex: Exists P (h :: t)
n: ¬ P h∃ (prefix suffix : list A) (first : A), P first ∧ h :: t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefixA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: Exists P t → ∃ (prefix suffix : list A) (first : A), P first ∧ t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefix
Hex: Exists P (h :: t)
p: P h∃ (prefix suffix : list A) (first : A), P first ∧ h :: t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefixA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: Exists P t → ∃ (prefix suffix : list A) (first : A), P first ∧ t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefix
Hex: Exists P (h :: t)
p: P hP h ∧ h :: t = [] ++ [h] ++ t ∧ ¬ Exists P []by itauto.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: Exists P t → ∃ (prefix suffix : list A) (first : A), P first ∧ t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefix
Hex: Exists P (h :: t)
p: P hP h ∧ h :: t = [] ++ [h] ++ t ∧ ¬ FalseA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: Exists P t → ∃ (prefix suffix : list A) (first : A), P first ∧ t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefix
Hex: Exists P (h :: t)
n: ¬ P h∃ (prefix suffix : list A) (first : A), P first ∧ h :: t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefixA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: Exists P t → ∃ (prefix suffix : list A) (first : A), P first ∧ t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefix
H: Exists P t
n: ¬ P h∃ (prefix suffix : list A) (first : A), P first ∧ h :: t = prefix ++ [first] ++ suffix ∧ ¬ Exists P prefixA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
prefix, suffix: list A
first: A
H: Exists P (prefix ++ [first] ++ suffix)
IHt: Exists P (prefix ++ [first] ++ suffix) → ∃ (prefix0 suffix0 : list A) (first0 : A), P first0 ∧ prefix ++ [first] ++ suffix = prefix0 ++ [first0] ++ suffix0 ∧ ¬ Exists P prefix0
n: ¬ P h
p: P first
Hnex: ¬ Exists P prefix∃ (prefix0 suffix0 : list A) (first0 : A), P first0 ∧ h :: prefix ++ [first] ++ suffix = prefix0 ++ [first0] ++ suffix0 ∧ ¬ Exists P prefix0A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
prefix, suffix: list A
first: A
H: Exists P (prefix ++ [first] ++ suffix)
IHt: Exists P (prefix ++ [first] ++ suffix) → ∃ (prefix0 suffix0 : list A) (first0 : A), P first0 ∧ prefix ++ [first] ++ suffix = prefix0 ++ [first0] ++ suffix0 ∧ ¬ Exists P prefix0
n: ¬ P h
p: P first
Hnex: ¬ Exists P prefixP first ∧ h :: prefix ++ [first] ++ suffix = (h :: prefix) ++ [first] ++ suffix ∧ ¬ Exists P (h :: prefix)by itauto. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
prefix, suffix: list A
first: A
H: Exists P (prefix ++ [first] ++ suffix)
IHt: Exists P (prefix ++ [first] ++ suffix) → ∃ (prefix0 suffix0 : list A) (first0 : A), P first0 ∧ prefix ++ [first] ++ suffix = prefix0 ++ [first0] ++ suffix0 ∧ ¬ Exists P prefix0
n: ¬ P h
p: P first
Hnex: ¬ Exists P prefixP first ∧ h :: prefix ++ [first] ++ suffix = (h :: prefix) ++ [first] ++ suffix ∧ ¬ (P h ∨ Exists P prefix)∀ (A B : Type) (f : A → B) (l1 l2 : list A), l1 ⊆ l2 → map f l1 ⊆ map f l2∀ (A B : Type) (f : A → B) (l1 l2 : list A), l1 ⊆ l2 → map f l1 ⊆ map f l2∀ (A B : Type) (f : A → B) (l1 l2 : list A), (∀ x : A, x ∈ l1 → x ∈ l2) → ∀ x : B, x ∈ map f l1 → x ∈ map f l2A, B: Type
f: A → B
l1, l2: list A
Hsub: ∀ x : A, x ∈ l1 → x ∈ l2
b: B
Hin: b ∈ map f l1b ∈ map f l2A, B: Type
f: A → B
l1, l2: list A
Hsub: ∀ x : A, x ∈ l1 → x ∈ l2
b: B
Hin: ∃ y : A, b = f y ∧ y ∈ l1∃ y : A, b = f y ∧ y ∈ l2A, B: Type
f: A → B
l1, l2: list A
Hsub: ∀ x : A, x ∈ l1 → x ∈ l2
x: A
Hin': x ∈ l1∃ y : A, f x = f y ∧ y ∈ l2by split; [| apply Hsub]. Qed.A, B: Type
f: A → B
l1, l2: list A
Hsub: ∀ x : A, x ∈ l1 → x ∈ l2
x: A
Hin': x ∈ l1f x = f x ∧ x ∈ l2A: Type∀ (a : A) (l : list A), [a] ++ l = a :: ldone. Qed.A: Type∀ (a : A) (l : list A), [a] ++ l = a :: lA: Type∀ (l : list A) (x : A), last_error (l ++ [x]) = Some xA: Type∀ (l : list A) (x : A), last_error (l ++ [x]) = Some xby rewrite last_app. Qed.A: Type
a: A
l: list A
x: ASome (List.last (l ++ [x]) a) = Some x∀ (A : Type) (n : nat) (l : list A), S n = length l → ∀ _last : A, nth_error l n = Some (List.last l _last)∀ (A : Type) (n : nat) (l : list A), S n = length l → ∀ _last : A, nth_error l n = Some (List.last l _last)A: Type
n: nat
l: list A
Hlast: S n = length l
_last: Anth_error l n = Some (List.last l _last)A: Type
n: nat
l, h: list A
t: A
Hlast: S n = length (h ++ [t])
_last: A
Heq: l = h ++ [t]nth_error (h ++ [t]) n = Some (List.last (h ++ [t]) _last)A: Type
n: nat
l, h: list A
t: A
Hlast: S n = length h + 1
_last: A
Heq: l = h ++ [t]nth_error (h ++ [t]) n = Some (List.last (h ++ [t]) _last)by replace (n - length h) with 0 by lia. Qed.A: Type
n: nat
l, h: list A
t: A
Hlast: S n = length h + 1
_last: A
Heq: l = h ++ [t]nth_error [t] (n - length h) = Some t∀ (A : Type) (l : list A) (n1 n2 : nat), n1 ≤ n2 → take n1 (take n2 l) = take n1 lby intros; rewrite take_take, min_l. Qed.∀ (A : Type) (l : list A) (n1 n2 : nat), n1 ≤ n2 → take n1 (take n2 l) = take n1 l∀ (A : Type) (l : list A) (n : nat), take n l `prefix_of` lby eexists; symmetry; apply take_drop. Qed.∀ (A : Type) (l : list A) (n : nat), take n l `prefix_of` l
Compute the sublist of list
l
which starts at index n1
and ends before index n2
.
For example, list_segment [0; 1; 2; 3; 4; 5] 2 4 = [2; 3]
.
Definition list_segment {A : Type} (l : list A) (n1 n2 : nat) : list A := drop n1 (take n2 l).∀ (A : Type) (l : list A) (n1 n2 : nat), n1 ≤ n2 → take n1 l ++ list_segment l n1 n2 ++ drop n2 l = l∀ (A : Type) (l : list A) (n1 n2 : nat), n1 ≤ n2 → take n1 l ++ list_segment l n1 n2 ++ drop n2 l = lA: Type
l: list A
n1, n2: nat
H: n1 ≤ n2take n1 l ++ list_segment l n1 n2 ++ drop n2 l = lA: Type
l: list A
n1, n2: nat
H: n1 ≤ n2take n1 l ++ drop n1 (take n2 l) ++ drop n2 l = lA: Type
l: list A
n1, n2: nat
H: n1 ≤ n2take n1 l ++ drop n1 (take n2 l) ++ drop n2 l = take n2 l ++ drop n2 lby rewrite <- app_assoc, take_prefix. Qed.A: Type
l: list A
n1, n2: nat
H: n1 ≤ n2take n1 l ++ drop n1 (take n2 l) ++ drop n2 l = (take n1 (take n2 l) ++ drop n1 (take n2 l)) ++ drop n2 l
Annotate each element of a list with the proof that it satisfies the
given decidable predicate.
Fixpoint list_annotate {A : Type} {P : A -> Prop} {Pdec : forall a, Decision (P a)} {l : list A} : Forall P l -> list (dsig P) := match l with | [] => fun _ => [] | h :: t => fun Hs => dexist h (Forall_inv Hs) :: list_annotate (Forall_inv_tail Hs) end. Section sec_list_annotate_props. Context {A : Type} {P : A -> Prop} `{Pdec : forall a, Decision (P a)} .A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs : Forall P l), length (list_annotate Hs) = length lby induction l; cbn; intros; [| rewrite IHl]. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs : Forall P l), length (list_annotate Hs) = length lA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs Hs' : Forall P l), list_annotate Hs = list_annotate Hs'A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs Hs' : Forall P l), list_annotate Hs = list_annotate Hs'by f_equal; [apply dsig_eq | apply IHl]. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l: list A
IHl: ∀ Hs Hs' : Forall P l, list_annotate Hs = list_annotate Hs'
Hs, Hs': Forall P (a :: l)dexist a (Forall_inv Hs) :: list_annotate (Forall_inv_tail Hs) = dexist a (Forall_inv Hs') :: list_annotate (Forall_inv_tail Hs')A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l1 l2 : list A) (Hl1 : Forall P l1) (Hl2 : Forall P l2), list_annotate Hl1 = list_annotate Hl2 ↔ l1 = l2A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l1 l2 : list A) (Hl1 : Forall P l1) (Hl2 : Forall P l2), list_annotate Hl1 = list_annotate Hl2 ↔ l1 = l2A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
l1, l2: list A
Hl1: Forall P l1
Hl2: Forall P l2list_annotate Hl1 = list_annotate Hl2 → l1 = l2A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
l1: list A∀ (l2 : list A) (Hl1 : Forall P l1) (Hl2 : Forall P l2), list_annotate Hl1 = list_annotate Hl2 → l1 = l2A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h1: A
t1: list A
IHt1: ∀ (l2 : list A) (Hl1 : Forall P t1) (Hl2 : Forall P l2), list_annotate Hl1 = list_annotate Hl2 → t1 = l2
h2: A
t2: list A
Hl1: Forall P (h1 :: t1)
Hl2: Forall P (h2 :: t2)
Heq: list_annotate Hl1 = list_annotate Hl2h1 :: t1 = h2 :: t2by apply IHt1 in H1 as ->. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
t1: list A
IHt1: ∀ (l2 : list A) (Hl1 : Forall P t1) (Hl2 : Forall P l2), list_annotate Hl1 = list_annotate Hl2 → t1 = l2
h2: A
t2: list A
Hl1: Forall P (h2 :: t1)
Hl2: Forall P (h2 :: t2)
Heq: list_annotate Hl1 = list_annotate Hl2
H1: list_annotate (Forall_inv_tail Hl1) = list_annotate (Forall_inv_tail Hl2)h2 :: t1 = h2 :: t2A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l1 l2 : list A) (Hs : Forall P (l1 ++ l2)), list_annotate Hs = list_annotate (proj1 (proj1 (Forall_app P l1 l2) Hs)) ++ list_annotate (proj2 (proj1 (Forall_app P l1 l2) Hs))A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l1 l2 : list A) (Hs : Forall P (l1 ++ l2)), list_annotate Hs = list_annotate (proj1 (proj1 (Forall_app P l1 l2) Hs)) ++ list_annotate (proj2 (proj1 (Forall_app P l1 l2) Hs))A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l1: list A
IHl1: ∀ (l2 : list A) (Hs : Forall P (l1 ++ l2)), list_annotate Hs = list_annotate (proj1 (proj1 (Forall_app P l1 l2) Hs)) ++ list_annotate (proj2 (proj1 (Forall_app P l1 l2) Hs))
l2: list A
Hs: Forall P (a :: l1 ++ l2)dexist a (Forall_inv Hs) :: list_annotate (Forall_inv_tail Hs) = dexist a (Forall_inv (proj1 (proj1 (Forall_app P (a :: l1) l2) Hs))) :: list_annotate (Forall_inv_tail (proj1 (proj1 (Forall_app P (a :: l1) l2) Hs))) ++ list_annotate (proj2 (proj1 (Forall_app P (a :: l1) l2) Hs))by rewrite IHl1; f_equal; apply list_annotate_pi. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l1: list A
IHl1: ∀ (l2 : list A) (Hs : Forall P (l1 ++ l2)), list_annotate Hs = list_annotate (proj1 (proj1 (Forall_app P l1 l2) Hs)) ++ list_annotate (proj2 (proj1 (Forall_app P l1 l2) Hs))
l2: list A
Hs: Forall P (a :: l1 ++ l2)list_annotate (Forall_inv_tail Hs) = list_annotate (Forall_inv_tail (proj1 (proj1 (Forall_app P (a :: l1) l2) Hs))) ++ list_annotate (proj2 (proj1 (Forall_app P (a :: l1) l2) Hs))A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (n : nat) (l : list A) (Hs : Forall P l), ∃ oa : option (dsig P), nth_error (list_annotate Hs) n = oa ∧ option_map proj1_sig oa = nth_error l nA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (n : nat) (l : list A) (Hs : Forall P l), ∃ oa : option (dsig P), nth_error (list_annotate Hs) n = oa ∧ option_map proj1_sig oa = nth_error l nA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
Hs: Forall P []∃ oa : option (dsig P), None = oa ∧ option_map proj1_sig oa = NoneA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
Hs: Forall P (h :: t)∃ oa : option (dsig P), Some (dexist h (Forall_inv Hs)) = oa ∧ option_map proj1_sig oa = Some hA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
n': nat
IHn': ∀ (l : list A) (Hs : Forall P l), ∃ oa : option (dsig P), nth_error (list_annotate Hs) n' = oa ∧ option_map proj1_sig oa = nth_error l n'
Hs: Forall P []∃ oa : option (dsig P), None = oa ∧ option_map proj1_sig oa = NoneA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
n': nat
IHn': ∀ (l : list A) (Hs : Forall P l), ∃ oa : option (dsig P), nth_error (list_annotate Hs) n' = oa ∧ option_map proj1_sig oa = nth_error l n'
h: A
t: list A
Hs: Forall P (h :: t)∃ oa : option (dsig P), nth_error (list_annotate (Forall_inv_tail Hs)) n' = oa ∧ option_map proj1_sig oa = nth_error t n'by exists None.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
Hs: Forall P []∃ oa : option (dsig P), None = oa ∧ option_map proj1_sig oa = NoneA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
Hs: Forall P (h :: t)∃ oa : option (dsig P), Some (dexist h (Forall_inv Hs)) = oa ∧ option_map proj1_sig oa = Some hby exists (Some (dexist h (Forall_inv Hs))).A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
Hs: Forall P (h :: t)
H1: P h
H2: Forall P t∃ oa : option (dsig P), Some (dexist h (Forall_inv Hs)) = oa ∧ option_map proj1_sig oa = Some hby exists None.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
n': nat
IHn': ∀ (l : list A) (Hs : Forall P l), ∃ oa : option (dsig P), nth_error (list_annotate Hs) n' = oa ∧ option_map proj1_sig oa = nth_error l n'
Hs: Forall P []∃ oa : option (dsig P), None = oa ∧ option_map proj1_sig oa = Noneby eauto. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
n': nat
IHn': ∀ (l : list A) (Hs : Forall P l), ∃ oa : option (dsig P), nth_error (list_annotate Hs) n' = oa ∧ option_map proj1_sig oa = nth_error l n'
h: A
t: list A
Hs: Forall P (h :: t)∃ oa : option (dsig P), nth_error (list_annotate (Forall_inv_tail Hs)) n' = oa ∧ option_map proj1_sig oa = nth_error t n'A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs : Forall P l) (a : {x : A | bool_decide (P x)}), a ∈ list_annotate Hs ↔ `a ∈ lA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs : Forall P l) (a : {x : A | bool_decide (P x)}), a ∈ list_annotate Hs ↔ `a ∈ lA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
Hs: Forall P []
a: {x : A | bool_decide (P x)}a ∈ [] ↔ `a ∈ []A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l: list A
IHl: ∀ (Hs : Forall P l) (a : {x : A | bool_decide (P x)}), a ∈ list_annotate Hs ↔ `a ∈ l
Hs: Forall P (a :: l)
a0: {x : A | bool_decide (P x)}a0 ∈ dexist a (Forall_inv Hs) :: list_annotate (Forall_inv_tail Hs) ↔ `a0 ∈ a :: lby rewrite !elem_of_nil.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
Hs: Forall P []
a: {x : A | bool_decide (P x)}a ∈ [] ↔ `a ∈ []by rewrite !elem_of_cons, IHl, (dsig_eq P a0); cbn. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l: list A
IHl: ∀ (Hs : Forall P l) (a : {x : A | bool_decide (P x)}), a ∈ list_annotate Hs ↔ `a ∈ l
Hs: Forall P (a :: l)
a0: {x : A | bool_decide (P x)}a0 ∈ dexist a (Forall_inv Hs) :: list_annotate (Forall_inv_tail Hs) ↔ `a0 ∈ a :: lA: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs : Forall P l), NoDup l → NoDup (list_annotate Hs)A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs : Forall P l), NoDup l → NoDup (list_annotate Hs)by rewrite elem_of_list_annotate. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
x: A
l: list A
Hs: Forall P (x :: l)
H: x ∉ l
H0: NoDup l
IHNoDup: ∀ Hs : Forall P l, NoDup (list_annotate Hs)dexist x (Forall_inv Hs) ∉ list_annotate (Forall_inv_tail Hs)A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs : Forall P l), map proj1_sig (list_annotate Hs) = lby induction l; cbn; intros; [| rewrite IHl]. Qed. End sec_list_annotate_props.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)∀ (l : list A) (Hs : Forall P l), map proj1_sig (list_annotate Hs) = l
Compute the index of the
n
-th element of the list that satisfies the
predicate P
.
Fixpoint nth_error_filter_index {A : Type} (P : A -> Prop) `{forall (x : A), Decision (P x)} (l : list A) (n : nat) : option nat := match l with | [] => None | h :: t => if decide (P h) then match n with | 0 => Some 0 | S n' => option_map S (nth_error_filter_index P t n') end else option_map S (nth_error_filter_index P t n) end.A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)∀ (l : list A) (n1 n2 in1 in2 : nat), n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)∀ (l : list A) (n1 n2 in1 in2 : nat), n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in1, in2: nat
Hle: n1 ≤ n2
Hin1: (if decide (P a) then match n1 with | 0 => Some 0 | S n' => option_map S (nth_error_filter_index P l n') end else option_map S (nth_error_filter_index P l n1)) = Some in1
Hin2: (if decide (P a) then match n2 with | 0 => Some 0 | S n' => option_map S (nth_error_filter_index P l n') end else option_map S (nth_error_filter_index P l n2)) = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in1, in2: nat
Hle: n1 ≤ n2
p: P a
Hin1: match n1 with | 0 => Some 0 | S n' => option_map S (nth_error_filter_index P l n') end = Some in1
Hin2: match n2 with | 0 => Some 0 | S n' => option_map S (nth_error_filter_index P l n') end = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in1, in2: nat
Hle: n1 ≤ n2
n: ¬ P a
Hin1: option_map S (nth_error_filter_index P l n1) = Some in1
Hin2: option_map S (nth_error_filter_index P l n2) = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in1, in2: nat
Hle: n1 ≤ n2
p: P a
Hin1: match n1 with | 0 => Some 0 | S n' => option_map S (nth_error_filter_index P l n') end = Some in1
Hin2: match n2 with | 0 => Some 0 | S n' => option_map S (nth_error_filter_index P l n') end = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
in1, in2: nat
Hle: 0 ≤ 0
p: P a
Hin1: Some 0 = Some in1
Hin2: Some 0 = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n2, in1, in2: nat
Hle: 0 ≤ S n2
p: P a
Hin1: Some 0 = Some in1
Hin2: option_map S (nth_error_filter_index P l n2) = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, in1, in2: nat
Hle: S n1 ≤ 0
p: P a
Hin1: option_map S (nth_error_filter_index P l n1) = Some in1
Hin2: Some 0 = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in1, in2: nat
Hle: S n1 ≤ S n2
p: P a
Hin1: option_map S (nth_error_filter_index P l n1) = Some in1
Hin2: option_map S (nth_error_filter_index P l n2) = Some in2in1 ≤ in2by congruence.A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
in1, in2: nat
Hle: 0 ≤ 0
p: P a
Hin1: Some 0 = Some in1
Hin2: Some 0 = Some in2in1 ≤ in2by inversion Hin1; lia.A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n2, in1, in2: nat
Hle: 0 ≤ S n2
p: P a
Hin1: Some 0 = Some in1
Hin2: option_map S (nth_error_filter_index P l n2) = Some in2in1 ≤ in2by lia.A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, in1, in2: nat
Hle: S n1 ≤ 0
p: P a
Hin1: option_map S (nth_error_filter_index P l n1) = Some in1
Hin2: Some 0 = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in1, in2: nat
Hle: S n1 ≤ S n2
p: P a
Hin1: option_map S (nth_error_filter_index P l n1) = Some in1
Hin2: option_map S (nth_error_filter_index P l n2) = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in1, in2: nat
Hle: S n1 ≤ S n2
p: P a
Hin1: match nth_error_filter_index P l n1 with | Some a => Some (S a) | None => None end = Some in1
Hin2: match nth_error_filter_index P l n2 with | Some a => Some (S a) | None => None end = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in2: nat
Hle: S n1 ≤ S n2
p: P a
n: nat
Hin1': nth_error_filter_index P l n1 = Some n
Hin2: match nth_error_filter_index P l n2 with | Some a => Some (S a) | None => None end = Some in2S n ≤ in2by eapply le_n_S, IHl; cycle 1; [done.. | lia].A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2: nat
Hle: S n1 ≤ S n2
p: P a
n: nat
Hin1': nth_error_filter_index P l n1 = Some n
n0: nat
Hin2': nth_error_filter_index P l n2 = Some n0S n ≤ S n0A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in1, in2: nat
Hle: n1 ≤ n2
n: ¬ P a
Hin1: option_map S (nth_error_filter_index P l n1) = Some in1
Hin2: option_map S (nth_error_filter_index P l n2) = Some in2in1 ≤ in2A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2, in2: nat
Hle: n1 ≤ n2
n: ¬ P a
n0: nat
Hin1': nth_error_filter_index P l n1 = Some n0
Hin2: option_map S (nth_error_filter_index P l n2) = Some in2S n0 ≤ in2by eapply le_n_S, IHl. Qed.A: Type
P: A → Prop
H: ∀ x : A, Decision (P x)
a: A
l: list A
IHl: ∀ n1 n2 in1 in2 : nat, n1 ≤ n2 → nth_error_filter_index P l n1 = Some in1 → nth_error_filter_index P l n2 = Some in2 → in1 ≤ in2
n1, n2: nat
Hle: n1 ≤ n2
n: ¬ P a
n0: nat
Hin1': nth_error_filter_index P l n1 = Some n0
n3: nat
Hin2': nth_error_filter_index P l n2 = Some n3S n0 ≤ S n3∀ (A : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (l : list A), Forall P (filter P l)∀ (A : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (l : list A), Forall P (filter P l)by case_decide; [constructor |]. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: Forall P (filter P t)Forall P (if decide (P h) then h :: filter P t else filter P t)
Compute the sublist of a list that contains only elements that satisfy the
given decidable predicate. Each element of the resulting list is paired with
the proof that it satisfies the predicate.
Fixpoint filter_annotate {A : Type} (P : A -> Prop) {Pdec : forall a : A, Decision (P a)} (l : list A) : list (dsig P) := match l with | [] => [] | h :: t => match decide (P h) with | left p => dexist h p :: filter_annotate P t | right _ => filter_annotate P t end end.∀ (A : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (l : list A), length (filter_annotate P l) = length (filter P l)∀ (A : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (l : list A), length (filter_annotate P l) = length (filter P l)A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: length (filter_annotate P t) = length (filter P t)length match decide (P h) with | left p => dexist h p :: filter_annotate P t | right _ => filter_annotate P t end = length (if decide (P h) then h :: filter P t else filter P t)by rewrite IHt. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
h: A
t: list A
IHt: length (filter_annotate P t) = length (filter P t)
H: P hS (length (filter_annotate P t)) = S (length (filter P t))∀ (A : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (a : A) (l : list A), filter_annotate P (a :: l) = (let fa := filter_annotate P l in match decide (P a) with | left pa => dexist a pa :: fa | right _ => fa end)done. Qed.∀ (A : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (a : A) (l : list A), filter_annotate P (a :: l) = (let fa := filter_annotate P l in match decide (P a) with | left pa => dexist a pa :: fa | right _ => fa end)∀ (A : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (l1 l2 : list A), filter_annotate P (l1 ++ l2) = filter_annotate P l1 ++ filter_annotate P l2∀ (A : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (l1 l2 : list A), filter_annotate P (l1 ++ l2) = filter_annotate P l1 ++ filter_annotate P l2A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l1: list A
IHl1: ∀ l2 : list A, filter_annotate P (l1 ++ l2) = filter_annotate P l1 ++ filter_annotate P l2
l2: list Amatch decide (P a) with | left p => dexist a p :: filter_annotate P (l1 ++ l2) | right _ => filter_annotate P (l1 ++ l2) end = match decide (P a) with | left p => dexist a p :: filter_annotate P l1 | right _ => filter_annotate P l1 end ++ filter_annotate P l2by rewrite IHl1. Qed.A: Type
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l1: list A
IHl1: ∀ l2 : list A, filter_annotate P (l1 ++ l2) = filter_annotate P l1 ++ filter_annotate P l2
l2: list A
H: P adexist a H :: filter_annotate P (l1 ++ l2) = dexist a H :: filter_annotate P l1 ++ filter_annotate P l2
Filters a list through a predicate, then transforms each element using a
function which depends on the fact that the predicate holds.
Definition list_filter_map {A B : Type} (P : A -> Prop) {Pdec : forall a, Decision (P a)} (f : dsig P -> B) (l : list A) : list B := map f (filter_annotate P l).∀ (A B : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (f : dsig P → B) (l1 l2 : list A), list_filter_map P f (l1 ++ l2) = list_filter_map P f l1 ++ list_filter_map P f l2by intros; unfold list_filter_map; rewrite filter_annotate_app, map_app. Qed.∀ (A B : Type) (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (f : dsig P → B) (l1 l2 : list A), list_filter_map P f (l1 ++ l2) = list_filter_map P f l1 ++ list_filter_map P f l2∀ (A : Type) (i n : nat) (s : list A), i < n → nth_error (take n s) i = nth_error s i∀ (A : Type) (i n : nat) (s : list A), i < n → nth_error (take n s) i = nth_error s iA: Type
i: nat
IHi: ∀ (n : nat) (s : list A), i < n → nth_error (take n s) i = nth_error s i
n: nat
h: A
t: list Anth_error (take (S i) t) i = nth_error t iA: Type
i: nat
IHi: ∀ (n : nat) (s : list A), i < n → nth_error (take n s) i = nth_error s i
n: nat
h: A
t: list A
m: nat
H: S (S i) ≤ mnth_error (take m t) i = nth_error t iby apply IHi; lia.A: Type
i: nat
IHi: ∀ (n : nat) (s : list A), i < n → nth_error (take n s) i = nth_error s i
n: nat
h: A
t: list Anth_error (take (S i) t) i = nth_error t iby apply IHi; lia. Qed.A: Type
i: nat
IHi: ∀ (n : nat) (s : list A), i < n → nth_error (take n s) i = nth_error s i
n: nat
h: A
t: list A
m: nat
H: S (S i) ≤ mnth_error (take m t) i = nth_error t i∀ (A : Type) (n : nat) (l : list A) (a : A), nth_error l n = Some a → S n ≤ length l∀ (A : Type) (n : nat) (l : list A) (a : A), nth_error l n = Some a → S n ≤ length lby eapply le_n_S, IHn'. Qed.A: Type
n': nat
IHn': ∀ (l : list A) (a : A), nth_error l n' = Some a → S n' ≤ length l
h: A
t: list A
a: A
H: nth_error (h :: t) (S n') = Some a
H1: nth_error t n' = Some aS (S n') ≤ S (length t)∀ (A : Type) (l : list A) (n : nat) (nth : A), nth_error l n = Some nth → ∀ _last : A, nth = List.last (take (S n) l) _last∀ (A : Type) (l : list A) (n : nat) (nth : A), nth_error l n = Some nth → ∀ _last : A, nth = List.last (take (S n) l) _lastA: Type
l: list A
n: nat
nth: A
Hnth: nth_error l n = Some nth
_last: Anth = List.last (take (S n) l) _lastA: Type
l: list A
n: nat
nth: A
Hnth: nth_error l n = Some nth
_last: ASome nth = Some (List.last (take (S n) l) _last)A: Type
l: list A
n: nat
nth: A
Hnth: nth_error l n = Some nth
_last: Anth_error l n = nth_error (take (S n) l) ?nA: Type
l: list A
n: nat
nth: A
Hnth: nth_error l n = Some nth
_last: AS ?n = length (take (S n) l)by rewrite take_nth; [done | lia].A: Type
l: list A
n: nat
nth: A
Hnth: nth_error l n = Some nth
_last: Anth_error l n = nth_error (take (S n) l) ?nA: Type
l: list A
n: nat
nth: A
Hnth: nth_error l n = Some nth
_last: AS n = length (take (S n) l)by apply nth_error_length in Hnth; lia. Qed.A: Type
l: list A
n: nat
nth: A
Hnth: nth_error l n = Some nth
_last: AS n = S n `min` length l∀ (A : Type) (l : list A) (n : nat), drop (S n) l = drop n (tail l)by intros A [] n; cbn; [rewrite drop_nil |]. Qed.∀ (A : Type) (l : list A) (n : nat), drop (S n) l = drop n (tail l)∀ (A : Type) (l : list A) (n : nat), drop n (tail l) = tail (drop n l)∀ (A : Type) (l : list A) (n : nat), drop n (tail l) = tail (drop n l)A: Type
l: list Adrop 0 (tail l) = tail (drop 0 l)A: Type
n: nat
IHn: ∀ l : list A, drop n (tail l) = tail (drop n l)
l: list Adrop (S n) (tail l) = tail (drop (S n) l)by rewrite !drop_0.A: Type
l: list Adrop 0 (tail l) = tail (drop 0 l)by rewrite !drop_S_tail, IHn. Qed.A: Type
n: nat
IHn: ∀ l : list A, drop n (tail l) = tail (drop n l)
l: list Adrop (S n) (tail l) = tail (drop (S n) l)∀ (A : Type) (s : list A) (n i : nat), n ≤ i → drop n s !! (i - n) = s !! i∀ (A : Type) (s : list A) (n i : nat), n ≤ i → drop n s !! (i - n) = s !! iA: Type
s: list A
n, i: nat
H: n ≤ idrop n s !! (i - n) = s !! iby replace (n + (i - n)) with i by lia. Qed.A: Type
s: list A
n, i: nat
H: n ≤ is !! (n + (i - n)) = s !! i∀ (A : Type) (i n : nat) (l : list A), n ≤ i → nth_error (drop n l) (i - n) = nth_error l i∀ (A : Type) (i n : nat) (l : list A), n ≤ i → nth_error (drop n l) (i - n) = nth_error l iA: Type
n': nat
h: A
t: list A
Hi: S n' ≤ 0match drop n' t with | [] => None | x :: _ => Some x end = Some hA: Type
i: nat
IHi: ∀ (n : nat) (l : list A), n ≤ i → nth_error (drop n l) (i - n) = nth_error l i
n': nat
Hi: S n' ≤ S inth_error [] (i - n') = NoneA: Type
i: nat
IHi: ∀ (n : nat) (l : list A), n ≤ i → nth_error (drop n l) (i - n) = nth_error l i
n': nat
h: A
t: list A
Hi: S n' ≤ S inth_error (drop n' t) (i - n') = nth_error t iby inversion Hi.A: Type
n': nat
h: A
t: list A
Hi: S n' ≤ 0match drop n' t with | [] => None | x :: _ => Some x end = Some hby apply nth_error_None; cbn; lia.A: Type
i: nat
IHi: ∀ (n : nat) (l : list A), n ≤ i → nth_error (drop n l) (i - n) = nth_error l i
n': nat
Hi: S n' ≤ S inth_error [] (i - n') = Noneby apply IHi; lia. Qed.A: Type
i: nat
IHi: ∀ (n : nat) (l : list A), n ≤ i → nth_error (drop n l) (i - n) = nth_error l i
n': nat
h: A
t: list A
Hi: S n' ≤ S inth_error (drop n' t) (i - n') = nth_error t i∀ (A : Type) (i : nat) (l : list A) (_default : A), i < length l → List.last (drop i l) _default = List.last l _default∀ (A : Type) (i : nat) (l : list A) (_default : A), i < length l → List.last (drop i l) _default = List.last l _defaultA: Type
i: nat
IHi: ∀ (l : list A) (_default : A), i < length l → List.last (drop i l) _default = List.last l _default
h: A
t: list A
_default: A
Hlt: S i < S (length t)List.last (drop i t) _default = match t with | [] => h | _ :: _ => List.last t _default endA: Type
i: nat
IHi: ∀ (l : list A) (_default : A), i < length l → List.last (drop i l) _default = List.last l _default
h: A
t: list A
_default: A
Hlt: S i < S (length t)List.last t _default = match t with | [] => h | _ :: _ => List.last t _default endby inversion Hlt; lia. Qed.A: Type
i: nat
IHi: ∀ (l : list A) (_default : A), i < length l → List.last (drop i l) _default = List.last l _default
h, _default: A
Hlt: S i < S (length [])List.last [] _default = h∀ (A : Type) (l : list A) (n1 n2 i : nat), n1 ≤ n2 → n1 ≤ i → i < n2 → nth_error (list_segment l n1 n2) (i - n1) = nth_error l i∀ (A : Type) (l : list A) (n1 n2 i : nat), n1 ≤ n2 → n1 ≤ i → i < n2 → nth_error (list_segment l n1 n2) (i - n1) = nth_error l iA: Type
l: list A
n1, n2, i: nat
H: n1 ≤ n2
H0: n1 ≤ i
H1: i < n2nth_error (list_segment l n1 n2) (i - n1) = nth_error l iA: Type
l: list A
n1, n2, i: nat
H: n1 ≤ n2
H0: n1 ≤ i
H1: i < n2nth_error (drop n1 (take n2 l)) (i - n1) = nth_error l iby apply take_nth. Qed.A: Type
l: list A
n1, n2, i: nat
H: n1 ≤ n2
H0: n1 ≤ i
H1: i < n2nth_error (take n2 l) i = nth_error l i∀ (A : Type) (l : list A) (n1 n2 n3 : nat), n1 ≤ n2 → n2 ≤ n3 → list_segment l n1 n2 ++ list_segment l n2 n3 = list_segment l n1 n3∀ (A : Type) (l : list A) (n1 n2 n3 : nat), n1 ≤ n2 → n2 ≤ n3 → list_segment l n1 n2 ++ list_segment l n2 n3 = list_segment l n1 n3A: Type
l: list A
n1, n2, n3: nat
H: n1 ≤ n2
H0: n2 ≤ n3list_segment l n1 n2 ++ list_segment l n2 n3 = list_segment l n1 n3A: Type
l: list A
n1, n2, n3: nat
H: n1 ≤ n2
H0: n2 ≤ n3drop n1 (take n2 l) ++ drop n2 (take n3 l) = drop n1 (take n3 l)A: Type
l: list A
n1, n2, n3: nat
H: n1 ≤ n2
H0: n2 ≤ n3
Hle: n1 ≤ n3drop n1 (take n2 l) ++ drop n2 (take n3 l) = drop n1 (take n3 l)A: Type
l: list A
n1, n2, n3: nat
H: n1 ≤ n2
H0: n2 ≤ n3
Hle: n1 ≤ n3
Hl1: take n1 l ++ list_segment l n1 n3 ++ drop n3 l = ldrop n1 (take n2 l) ++ drop n2 (take n3 l) = drop n1 (take n3 l)A: Type
l: list A
n1, n2, n3: nat
H: n1 ≤ n2
H0: n2 ≤ n3
Hle: n1 ≤ n3
Hl1: take n1 l ++ list_segment l n1 n3 ++ drop n3 l = take n2 l ++ list_segment l n2 n3 ++ drop n3 ldrop n1 (take n2 l) ++ drop n2 (take n3 l) = drop n1 (take n3 l)A: Type
l: list A
n1, n2, n3: nat
H: n1 ≤ n2
H0: n2 ≤ n3
Hle: n1 ≤ n3
Hl1: (take n1 l ++ list_segment l n1 n3) ++ drop n3 l = (take n2 l ++ list_segment l n2 n3) ++ drop n3 ldrop n1 (take n2 l) ++ drop n2 (take n3 l) = drop n1 (take n3 l)A: Type
l: list A
n1, n2, n3: nat
H: n1 ≤ n2
H0: n2 ≤ n3
Hle: n1 ≤ n3
Hl1: take n1 l ++ list_segment l n1 n3 = take n2 l ++ list_segment l n2 n3drop n1 (take n2 l) ++ drop n2 (take n3 l) = drop n1 (take n3 l)by apply app_inv_head in Hl1. Qed.A: Type
l: list A
n1, n2, n3: nat
H: n1 ≤ n2
H0: n2 ≤ n3
Hle: n1 ≤ n3
Hl1: take n1 l ++ list_segment l n1 n3 = take n1 l ++ drop n1 (take n2 l) ++ list_segment l n2 n3drop n1 (take n2 l) ++ drop n2 (take n3 l) = drop n1 (take n3 l)∀ (A : Type) (l : list A) (n : nat) (a : A), nth_error l n = Some a → list_segment l n (S n) = [a]∀ (A : Type) (l : list A) (n : nat) (a : A), nth_error l n = Some a → list_segment l n (S n) = [a]A: Type
l: list A
n: nat
a: A
Hnth: nth_error l n = Some alist_segment l n (S n) = [a]A: Type
a: A
l1, l2: list Alist_segment (l1 ++ a :: l2) (length l1) (S (length l1)) = [a]A: Type
a: A
l1, l2: list Adrop (length l1) (take (S (length l1)) (l1 ++ a :: l2)) = [a]by rewrite app_length; cbn; lia. Qed.A: Type
a: A
l1, l2: list AS (length l1) = length (l1 ++ [a])∀ (A B : Type) (f : A → B) (l : list A) (n : nat), nth_error (map f l) n = option_map f (nth_error l n)by induction l; intros [| n]; cbn; [.. | apply IHl]. Qed.∀ (A B : Type) (f : A → B) (l : list A) (n : nat), nth_error (map f l) n = option_map f (nth_error l n)∀ (A B : Type) (f : A → option B) (l : list A) (l1' l2' : list B), omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'∀ (A B : Type) (f : A → option B) (l : list A) (l1' l2' : list B), omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'A, B: Type
f: A → option B
l1', l2': list B
Happ_rev: omap f [] = l1' ++ l2'∃ l1 l2 : list A, [] = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'A, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
l1', l2': list B
Happ_rev: omap f (a :: l) = l1' ++ l2'∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'A, B: Type
f: A → option B
l1', l2': list B
Happ_rev: omap f [] = l1' ++ l2'∃ l1 l2 : list A, [] = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'A, B: Type
f: A → option B
l1', l2': list B
Happ_rev: l1' ++ l2' = omap f []∃ l1 l2 : list A, [] = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'by exists [], [].A, B: Type
f: A → option B∃ l1 l2 : list A, [] = l1 ++ l2 ∧ omap f l1 = [] ∧ omap f l2 = []A, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
l1', l2': list B
Happ_rev: omap f (a :: l) = l1' ++ l2'∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'A, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
l1', l2': list B
Happ_rev: match f a with | Some y => y :: omap f l | None => omap f l end = l1' ++ l2'∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'A, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
l1', l2': list B
Hfa: f a = None
Happ_rev: omap f l = l1' ++ l2'∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'A, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
l1', l2': list B
b: B
Hfa: f a = Some b
Happ_rev: b :: omap f l = l1' ++ l2'∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'A, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
l1', l2': list B
Hfa: f a = None
Happ_rev: omap f l = l1' ++ l2'∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'by exists (a :: _l1), l2; cbn; rewrite Hfa.A, B: Type
f: A → option B
a: A
_l1, l2: list A
IHl: ∀ l1' l2' : list B, omap f (_l1 ++ l2) = l1' ++ l2' → ∃ l1 l3 : list A, _l1 ++ l2 = l1 ++ l3 ∧ omap f l1 = l1' ∧ omap f l3 = l2'
Hfa: f a = None
Happ_rev: omap f (_l1 ++ l2) = omap f _l1 ++ omap f l2∃ l1 l3 : list A, a :: _l1 ++ l2 = l1 ++ l3 ∧ omap f l1 = omap f _l1 ∧ omap f l3 = omap f l2A, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
l1', l2': list B
b: B
Hfa: f a = Some b
Happ_rev: b :: omap f l = l1' ++ l2'∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'A, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
b: B
Hfa: f a = Some b
H: b :: omap f l = b :: omap f l∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = [] ∧ omap f l2 = b :: omap f lA, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
_b: B
l1', l2': list B
Happ_rev: _b :: omap f l = _b :: l1' ++ l2'
Hfa: f a = Some _b
H1: omap f l = l1' ++ l2'∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = _b :: l1' ∧ omap f l2 = l2'by exists [], (a :: l); cbn; rewrite Hfa.A, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
b: B
Hfa: f a = Some b
H: b :: omap f l = b :: omap f l∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = [] ∧ omap f l2 = b :: omap f lA, B: Type
f: A → option B
a: A
l: list A
IHl: ∀ l1' l2' : list B, omap f l = l1' ++ l2' → ∃ l1 l2 : list A, l = l1 ++ l2 ∧ omap f l1 = l1' ∧ omap f l2 = l2'
_b: B
l1', l2': list B
Happ_rev: _b :: omap f l = _b :: l1' ++ l2'
Hfa: f a = Some _b
H1: omap f l = l1' ++ l2'∃ l1 l2 : list A, a :: l = l1 ++ l2 ∧ omap f l1 = _b :: l1' ∧ omap f l2 = l2'by exists (a :: _l1), l2; cbn; rewrite Hfa. Qed.A, B: Type
f: A → option B
a: A
_l1, l2: list A
IHl: ∀ l1' l2' : list B, omap f (_l1 ++ l2) = l1' ++ l2' → ∃ l1 l3 : list A, _l1 ++ l2 = l1 ++ l3 ∧ omap f l1 = l1' ∧ omap f l3 = l2'
_b: B
Happ_rev: _b :: omap f (_l1 ++ l2) = _b :: omap f _l1 ++ omap f l2
Hfa: f a = Some _b
H1: omap f (_l1 ++ l2) = omap f _l1 ++ omap f l2∃ l1 l3 : list A, a :: _l1 ++ l2 = l1 ++ l3 ∧ omap f l1 = _b :: omap f _l1 ∧ omap f l3 = omap f l2∀ (A B : Type) (f : A → option B) (l : list A), Forall (λ a : A, f a ≠ None) l → length (omap f l) = length l∀ (A B : Type) (f : A → option B) (l : list A), Forall (λ a : A, f a ≠ None) l → length (omap f l) = length lby case_match; cbn; congruence. Qed.A, B: Type
f: A → option B
x: A
l: list A
H: f x ≠ None
H0: Forall (λ a : A, f a ≠ None) l
IHForall: length (omap f l) = length llength match f x with | Some y => y :: omap f l | None => omap f l end = S (length l)∀ (A B : Type) (f : A → option B) (l : list A) (i : nat) (dummya : A) (dummyb : B), Forall (λ a : A, f a ≠ None) l → i < length l → Some (nth i (omap f l) dummyb) = f (nth i l dummya)∀ (A B : Type) (f : A → option B) (l : list A) (i : nat) (dummya : A) (dummyb : B), Forall (λ a : A, f a ≠ None) l → i < length l → Some (nth i (omap f l) dummyb) = f (nth i l dummya)A, B: Type
f: A → option B
l: list A
dummya: A
dummyb: B
Hall: Forall (λ a : A, f a ≠ None) l∀ i : nat, i < length l → Some (nth i (omap f l) dummyb) = f (nth i l dummya)A, B: Type
f: A → option B
dummya: A
dummyb: B
x: A
l: list A
H: f x ≠ None
Hall: Forall (λ a : A, f a ≠ None) l
IHHall: ∀ i : nat, i < length l → Some (nth i (omap f l) dummyb) = f (nth i l dummya)
i: nat
H0: i < S (length l)Some (nth i match f x with | Some y => y :: omap f l | None => omap f l end dummyb) = f match i with | 0 => x | S m => nth m l dummya endby apply IHHall; lia. Qed.A, B: Type
f: A → option B
dummya: A
dummyb: B
x: A
l: list A
b: B
H: Some b ≠ None
Hall: Forall (λ a : A, f a ≠ None) l
IHHall: ∀ i : nat, i < length l → Some (nth i (omap f l) dummyb) = f (nth i l dummya)
i: nat
H0: S i < S (length l)Some (nth i (omap f l) dummyb) = f (nth i l dummya)
omap can be expressed as a list_filter_map.
∀ (A B : Type) (f : A → option B) (l : list A), omap f l = list_filter_map (is_Some ∘ f) (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) l∀ (A B : Type) (f : A → option B) (l : list A), omap f l = list_filter_map (is_Some ∘ f) (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) lA, B: Type
f: A → option B
a: A
l: list A
IHl: omap f l = list_filter_map (is_Some ∘ f) (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) lmatch f a with | Some y => y :: omap f l | None => omap f l end = map (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) match decide (is_Some (f a)) with | left p => dexist a p :: filter_annotate (is_Some ∘ f) l | right _ => filter_annotate (is_Some ∘ f) l endA, B: Type
f: A → option B
a: A
l: list A
IHl: omap f l = list_filter_map (is_Some ∘ f) (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) l
H: is_Some (f a)match f a with | Some y => y :: omap f l | None => omap f l end = is_Some_proj (proj2_dsig (dexist a H)) :: map (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) (filter_annotate (is_Some ∘ f) l)A, B: Type
f: A → option B
a: A
l: list A
IHl: omap f l = list_filter_map (is_Some ∘ f) (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) l
H: ¬ is_Some (f a)match f a with | Some y => y :: omap f l | None => omap f l end = map (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) (filter_annotate (is_Some ∘ f) l)by rewrite IHl; cbv; destruct H as [? ->].A, B: Type
f: A → option B
a: A
l: list A
IHl: omap f l = list_filter_map (is_Some ∘ f) (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) l
H: is_Some (f a)match f a with | Some y => y :: omap f l | None => omap f l end = is_Some_proj (proj2_dsig (dexist a H)) :: map (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) (filter_annotate (is_Some ∘ f) l)by destruct (f a); [contradict H |]. Qed.A, B: Type
f: A → option B
a: A
l: list A
IHl: omap f l = list_filter_map (is_Some ∘ f) (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) l
H: ¬ is_Some (f a)match f a with | Some y => y :: omap f l | None => omap f l end = map (λ x : dsig (is_Some ∘ f), is_Some_proj (proj2_dsig x)) (filter_annotate (is_Some ∘ f) l)∀ (A B : Type) (f : A → option B) (l : list A), Forall (λ x : A, ¬ is_Some (f x)) l → omap f l = []∀ (A B : Type) (f : A → option B) (l : list A), Forall (λ x : A, ¬ is_Some (f x)) l → omap f l = []by case_match; [contradict H |]. Qed.A, B: Type
f: A → option B
x: A
l: list A
H: ¬ is_Some (f x)
H0: Forall (λ x : A, ¬ is_Some (f x)) l
IHForall: omap f l = []match f x with | Some y => y :: omap f l | None => omap f l end = []∀ (A B : Type) (f : A → option B) (l : list A), (∀ a1 a2 : A, is_Some (f a1) → is_Some (f a2) → f a1 = f a2 → a1 = a2) → NoDup l → NoDup (omap f l)∀ (A B : Type) (f : A → option B) (l : list A), (∀ a1 a2 : A, is_Some (f a1) → is_Some (f a2) → f a1 = f a2 → a1 = a2) → NoDup l → NoDup (omap f l)A, B: Type
f: A → option B
l: list A
Hinj: ∀ a1 a2 : A, is_Some (f a1) → is_Some (f a2) → f a1 = f a2 → a1 = a2
Hnd: NoDup lNoDup (omap f l)A, B: Type
f: A → option B
Hinj: ∀ a1 a2 : A, is_Some (f a1) → is_Some (f a2) → f a1 = f a2 → a1 = a2
h: A
t: list A
Hnin: h ∉ t
Hnd: NoDup t
IH: NoDup (omap f t)NoDup match f h with | Some y => y :: omap f t | None => omap f t endA, B: Type
f: A → option B
Hinj: ∀ a1 a2 : A, is_Some (f a1) → is_Some (f a2) → f a1 = f a2 → a1 = a2
h: A
t: list A
Hnin: h ∉ t
Hnd: NoDup t
IH: NoDup (omap f t)
b: B
Heq: f h = Some bNoDup (b :: omap f t)A, B: Type
f: A → option B
Hinj: ∀ a1 a2 : A, is_Some (f a1) → is_Some (f a2) → f a1 = f a2 → a1 = a2
h: A
t: list A
Hnin: h ∉ t
Hnd: NoDup t
IH: NoDup (omap f t)
b: B
Heq: f h = Some bb ∉ omap f tA, B: Type
f: A → option B
Hinj: ∀ a1 a2 : A, is_Some (f a1) → is_Some (f a2) → f a1 = f a2 → a1 = a2
h: A
t: list A
Hnin: h ∉ t
Hnd: NoDup t
IH: NoDup (omap f t)
b: B
Heq: f h = Some b
x: A
Hinx: x ∈ t
Hfx: f x = Some bFalseby congruence. Qed.A, B: Type
f: A → option B
Hinj: ∀ a1 a2 : A, is_Some (f a1) → is_Some (f a2) → f a1 = f a2 → a1 = a2
h: A
t: list A
Hnin: h ∉ t
Hnd: NoDup t
IH: NoDup (omap f t)
b: B
Heq: f h = Some b
x: A
Hinx: x ∈ t
Hfx: f x = Some b
H: x = hFalse
Unpack list of option A into list of A.
Definition cat_option {A : Type} : list (option A) -> list A := omap id.∀ (A : Type) (l : list (option A)), Forall (λ a : option A, a ≠ None) l → length (cat_option l) = length lby intros; apply omap_length. Qed.∀ (A : Type) (l : list (option A)), Forall (λ a : option A, a ≠ None) l → length (cat_option l) = length l∀ (A : Type) (l : list (option A)), length (cat_option l) ≤ length lby induction l as [| []]; cbn; [| lia..]. Qed.∀ (A : Type) (l : list (option A)), length (cat_option l) ≤ length l∀ (A : Type) (l1 l2 : list (option A)), cat_option (l1 ++ l2) = cat_option l1 ++ cat_option l2by unfold cat_option; intros; rewrite omap_app. Qed.∀ (A : Type) (l1 l2 : list (option A)), cat_option (l1 ++ l2) = cat_option l1 ++ cat_option l2∀ (A : Type) (l : list (option A)) (i : nat) (dummya : A), Forall (λ a : option A, a ≠ None) l → i < length l → Some (nth i (cat_option l) dummya) = nth i l (Some dummya)by unfold cat_option; intros; erewrite omap_nth. Qed.∀ (A : Type) (l : list (option A)) (i : nat) (dummya : A), Forall (λ a : option A, a ≠ None) l → i < length l → Some (nth i (cat_option l) dummya) = nth i l (Some dummya)∀ (A : Type) (l1 l2 : list A), (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2∀ (A : Type) (l1 l2 : list A), (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2A: Type
a2: A
l2: list A
Hnth: ∀ n : nat, nth_error [] n = nth_error (a2 :: l2) n[] = a2 :: l2A: Type
a: A
l1: list A
IHl1: ∀ l2 : list A, (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2
Hnth: ∀ n : nat, nth_error (a :: l1) n = nth_error [] na :: l1 = []A: Type
a: A
l1: list A
IHl1: ∀ l2 : list A, (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2
a2: A
l2: list A
Hnth: ∀ n : nat, nth_error (a :: l1) n = nth_error (a2 :: l2) na :: l1 = a2 :: l2by specialize (Hnth 0); inversion Hnth.A: Type
a2: A
l2: list A
Hnth: ∀ n : nat, nth_error [] n = nth_error (a2 :: l2) n[] = a2 :: l2by specialize (Hnth 0); inversion Hnth.A: Type
a: A
l1: list A
IHl1: ∀ l2 : list A, (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2
Hnth: ∀ n : nat, nth_error (a :: l1) n = nth_error [] na :: l1 = []A: Type
a: A
l1: list A
IHl1: ∀ l2 : list A, (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2
a2: A
l2: list A
Hnth: ∀ n : nat, nth_error (a :: l1) n = nth_error (a2 :: l2) na :: l1 = a2 :: l2A: Type
a: A
l1: list A
IHl1: ∀ l2 : list A, (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2
a2: A
l2: list A
Hnth: ∀ n : nat, nth_error (a :: l1) n = nth_error (a2 :: l2) na = a2A: Type
a: A
l1: list A
IHl1: ∀ l2 : list A, (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2
a2: A
l2: list A
Hnth: ∀ n : nat, nth_error (a :: l1) n = nth_error (a2 :: l2) nl1 = l2by specialize (Hnth 0); cbn in Hnth; congruence.A: Type
a: A
l1: list A
IHl1: ∀ l2 : list A, (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2
a2: A
l2: list A
Hnth: ∀ n : nat, nth_error (a :: l1) n = nth_error (a2 :: l2) na = a2A: Type
a: A
l1: list A
IHl1: ∀ l2 : list A, (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2
a2: A
l2: list A
Hnth: ∀ n : nat, nth_error (a :: l1) n = nth_error (a2 :: l2) nl1 = l2by specialize (Hnth (S n)); cbn in Hnth. Qed.A: Type
a: A
l1: list A
IHl1: ∀ l2 : list A, (∀ n : nat, nth_error l1 n = nth_error l2 n) → l1 = l2
a2: A
l2: list A
Hnth: ∀ n : nat, nth_error (a :: l1) n = nth_error (a2 :: l2) n
n: natnth_error l1 n = nth_error l2 n
Compute the list of all decompositions of the given list
l
into
triples (l1, x, l2)
such that l = l1 ++ x :: l2
.
Fixpoint one_element_decompositions {A : Type} (l : list A) : list (list A * A * list A) := match l with | [] => [] | a :: l' => ([], a, l') :: map (fun t => match t with (l1, b, l2) => (a :: l1, b, l2) end) (one_element_decompositions l') end.∀ (A : Type) (l pre suf : list A) (x : A), (pre, x, suf) ∈ one_element_decompositions l ↔ pre ++ [x] ++ suf = l∀ (A : Type) (l pre suf : list A) (x : A), (pre, x, suf) ∈ one_element_decompositions l ↔ pre ++ [x] ++ suf = lA: Type
pre, suf: list A
x: A
Hin: (pre, x, suf) ∈ []pre ++ x :: suf = []A: Type
pre, suf: list A
x: A
Hin: pre ++ x :: suf = [](pre, x, suf) ∈ []A: Type
a: A
l: list A
IHl: ∀ (pre suf : list A) (x : A), (pre, x, suf) ∈ one_element_decompositions l ↔ pre ++ [x] ++ suf = l
pre, suf: list A
x: A
Hin: (pre, x, suf) ∈ ([], a, l) :: map (λ t : list A * A * list A, let (y, l2) := t in let (l1, b) := y in (a :: l1, b, l2)) (one_element_decompositions l)pre ++ x :: suf = a :: lA: Type
a: A
l: list A
IHl: ∀ (pre suf : list A) (x : A), (pre, x, suf) ∈ one_element_decompositions l ↔ pre ++ [x] ++ suf = l
pre, suf: list A
x: A
Hin: pre ++ x :: suf = a :: l(pre, x, suf) ∈ ([], a, l) :: map (λ t : list A * A * list A, let (y, l2) := t in let (l1, b) := y in (a :: l1, b, l2)) (one_element_decompositions l)by inversion Hin.A: Type
pre, suf: list A
x: A
Hin: (pre, x, suf) ∈ []pre ++ x :: suf = []by destruct pre; inversion Hin.A: Type
pre, suf: list A
x: A
Hin: pre ++ x :: suf = [](pre, x, suf) ∈ []A: Type
a: A
l: list A
IHl: ∀ (pre suf : list A) (x : A), (pre, x, suf) ∈ one_element_decompositions l ↔ pre ++ [x] ++ suf = l
pre, suf: list A
x: A
Hin: (pre, x, suf) ∈ ([], a, l) :: map (λ t : list A * A * list A, let (y, l2) := t in let (l1, b) := y in (a :: l1, b, l2)) (one_element_decompositions l)pre ++ x :: suf = a :: lA: Type
a: A
l: list A
IHl: ∀ (pre suf : list A) (x : A), (pre, x, suf) ∈ one_element_decompositions l ↔ pre ++ [x] ++ suf = l
pre, suf: list A
x: A
Hin: (pre, x, suf) = ([], a, l) ∨ (∃ y : list A * A * list A, (pre, x, suf) = (let (y0, l2) := y in let (l1, b) := y0 in (a :: l1, b, l2)) ∧ y ∈ one_element_decompositions l)pre ++ x :: suf = a :: lby apply (IHl pre' suf' x') in Hin; subst.A: Type
a: A
l: list A
IHl: ∀ (pre suf : list A) (x : A), (pre, x, suf) ∈ one_element_decompositions l ↔ pre ++ [x] ++ suf = l
pre': list A
x': A
suf': list A
Hin: (pre', x', suf') ∈ one_element_decompositions l(a :: pre') ++ x' :: suf' = a :: lA: Type
a: A
l: list A
IHl: ∀ (pre suf : list A) (x : A), (pre, x, suf) ∈ one_element_decompositions l ↔ pre ++ [x] ++ suf = l
pre, suf: list A
x: A
Hin: pre ++ x :: suf = a :: l(pre, x, suf) ∈ ([], a, l) :: map (λ t : list A * A * list A, let (y, l2) := t in let (l1, b) := y in (a :: l1, b, l2)) (one_element_decompositions l)A: Type
a: A
pre, suf: list A
x: A
IHl: ∀ (pre0 suf0 : list A) (x0 : A), (pre0, x0, suf0) ∈ one_element_decompositions (pre ++ x :: suf) ↔ pre0 ++ [x0] ++ suf0 = pre ++ x :: suf(a :: pre, x, suf) ∈ ([], a, pre ++ x :: suf) :: map (λ t : list A * A * list A, let (y, l2) := t in let (l1, b) := y in (a :: l1, b, l2)) (one_element_decompositions (pre ++ x :: suf))A: Type
a: A
pre, suf: list A
x: A
IHl: ∀ (pre0 suf0 : list A) (x0 : A), (pre0, x0, suf0) ∈ one_element_decompositions (pre ++ x :: suf) ↔ pre0 ++ [x0] ++ suf0 = pre ++ x :: suf(a :: pre, x, suf) ∈ map (λ t : list A * A * list A, let (y, l2) := t in let (l1, b) := y in (a :: l1, b, l2)) (one_element_decompositions (pre ++ x :: suf))A: Type
a: A
pre, suf: list A
x: A
IHl: ∀ (pre0 suf0 : list A) (x0 : A), (pre0, x0, suf0) ∈ one_element_decompositions (pre ++ x :: suf) ↔ pre0 ++ [x0] ++ suf0 = pre ++ x :: suf∃ y : list A * A * list A, (a :: pre, x, suf) = (let (y0, l2) := y in let (l1, b) := y0 in (a :: l1, b, l2)) ∧ y ∈ one_element_decompositions (pre ++ x :: suf)by rewrite IHl. Qed.A: Type
a: A
pre, suf: list A
x: A
IHl: ∀ (pre0 suf0 : list A) (x0 : A), (pre0, x0, suf0) ∈ one_element_decompositions (pre ++ x :: suf) ↔ pre0 ++ [x0] ++ suf0 = pre ++ x :: suf(a :: pre, x, suf) = (a :: pre, x, suf) ∧ (pre, x, suf) ∈ one_element_decompositions (pre ++ x :: suf)
Compute the list of all decompositions of the given list
l
into
tuples (l1, x, l2, y, l3)
such that l = l1 ++ x :: l2 ++ y :: l3
.
Definition two_element_decompositions {A : Type} (l : list A) : list (list A * A * list A * A * list A) := flat_map (fun t => match t with (l1, e1, l2) => map (fun t => match t with (l2', e2, l3) => (l1, e1, l2', e2, l3) end) (one_element_decompositions l2) end) (one_element_decompositions l).∀ (A : Type) (l pre mid suf : list A) (x y : A), (pre, x, mid, y, suf) ∈ two_element_decompositions l ↔ pre ++ [x] ++ mid ++ [y] ++ suf = l∀ (A : Type) (l pre mid suf : list A) (x y : A), (pre, x, mid, y, suf) ∈ two_element_decompositions l ↔ pre ++ [x] ++ mid ++ [y] ++ suf = lA: Type
l, pre, mid, suf: list A
x, y: A(pre, x, mid, y, suf) ∈ two_element_decompositions l ↔ pre ++ [x] ++ mid ++ [y] ++ suf = lA: Type
l, pre, mid, suf: list A
x, y: A(pre, x, mid, y, suf) ∈ flat_map (λ t : list A * A * list A, let (y, l2) := t in let (l1, e1) := y in map (λ t0 : list A * A * list A, let (y0, l3) := t0 in let (l2', e2) := y0 in (l1, e1, l2', e2, l3)) (one_element_decompositions l2)) (one_element_decompositions l) ↔ pre ++ [x] ++ mid ++ [y] ++ suf = lA: Type
l, pre, mid, suf: list A
x, y: A(∃ x0 : list A * A * list A, x0 ∈ one_element_decompositions l ∧ (pre, x, mid, y, suf) ∈ (let (y, l2) := x0 in let (l1, e1) := y in map (λ t : list A * A * list A, let (y0, l3) := t in let (l2', e2) := y0 in (l1, e1, l2', e2, l3)) (one_element_decompositions l2))) ↔ pre ++ [x] ++ mid ++ [y] ++ suf = lA: Type
l, pre, mid, suf: list A
x, y: A(∃ x0 : list A * A * list A, x0 ∈ one_element_decompositions l ∧ (pre, x, mid, y, suf) ∈ (let (y, l2) := x0 in let (l1, e1) := y in map (λ t : list A * A * list A, let (y0, l3) := t in let (l2', e2) := y0 in (l1, e1, l2', e2, l3)) (one_element_decompositions l2))) → pre ++ [x] ++ mid ++ [y] ++ suf = lA: Type
l, pre, mid, suf: list A
x, y: Apre ++ [x] ++ mid ++ [y] ++ suf = l → ∃ x0 : list A * A * list A, x0 ∈ one_element_decompositions l ∧ (pre, x, mid, y, suf) ∈ (let (y, l2) := x0 in let (l1, e1) := y in map (λ t : list A * A * list A, let (y0, l3) := t in let (l2', e2) := y0 in (l1, e1, l2', e2, l3)) (one_element_decompositions l2))A: Type
l, pre, mid, suf: list A
x, y: A(∃ x0 : list A * A * list A, x0 ∈ one_element_decompositions l ∧ (pre, x, mid, y, suf) ∈ (let (y, l2) := x0 in let (l1, e1) := y in map (λ t : list A * A * list A, let (y0, l3) := t in let (l2', e2) := y0 in (l1, e1, l2', e2, l3)) (one_element_decompositions l2))) → pre ++ [x] ++ mid ++ [y] ++ suf = lA: Type
l, pre, mid, suf: list A
x, y: A
pre': list A
x': A
sufx: list A
Hdecx: (pre', x', sufx) ∈ one_element_decompositions l
Hin: (pre, x, mid, y, suf) ∈ map (λ t : list A * A * list A, let (y, l3) := t in let (l2', e2) := y in (pre', x', l2', e2, l3)) (one_element_decompositions sufx)pre ++ [x] ++ mid ++ [y] ++ suf = lby apply elem_of_one_element_decompositions in Hdecx as <-, Hin as <-.A: Type
l, pre': list A
x': A
sufx: list A
Hdecx: (pre', x', sufx) ∈ one_element_decompositions l
mid': list A
y': A
suf': list A
Hin: (mid', y', suf') ∈ one_element_decompositions sufxpre' ++ [x'] ++ mid' ++ [y'] ++ suf' = lA: Type
l, pre, mid, suf: list A
x, y: Apre ++ [x] ++ mid ++ [y] ++ suf = l → ∃ x0 : list A * A * list A, x0 ∈ one_element_decompositions l ∧ (pre, x, mid, y, suf) ∈ (let (y, l2) := x0 in let (l1, e1) := y in map (λ t : list A * A * list A, let (y0, l3) := t in let (l2', e2) := y0 in (l1, e1, l2', e2, l3)) (one_element_decompositions l2))A: Type
l, pre, mid, suf: list A
x, y: A
H: pre ++ [x] ++ mid ++ [y] ++ suf = l∃ x0 : list A * A * list A, x0 ∈ one_element_decompositions l ∧ (pre, x, mid, y, suf) ∈ (let (y, l2) := x0 in let (l1, e1) := y in map (λ t : list A * A * list A, let (y0, l3) := t in let (l2', e2) := y0 in (l1, e1, l2', e2, l3)) (one_element_decompositions l2))A: Type
l, pre, mid, suf: list A
x, y: A
H: (pre, x, mid ++ [y] ++ suf) ∈ one_element_decompositions l∃ x0 : list A * A * list A, x0 ∈ one_element_decompositions l ∧ (pre, x, mid, y, suf) ∈ (let (y, l2) := x0 in let (l1, e1) := y in map (λ t : list A * A * list A, let (y0, l3) := t in let (l2', e2) := y0 in (l1, e1, l2', e2, l3)) (one_element_decompositions l2))A: Type
l, pre, mid, suf: list A
x, y: A
H: (pre, x, mid ++ [y] ++ suf) ∈ one_element_decompositions l(pre, x, mid ++ [y] ++ suf) ∈ one_element_decompositions l ∧ (pre, x, mid, y, suf) ∈ map (λ t : list A * A * list A, let (y, l3) := t in let (l2', e2) := y in (pre, x, l2', e2, l3)) (one_element_decompositions (mid ++ [y] ++ suf))A: Type
l, pre, mid, suf: list A
x, y: A
H: (pre, x, mid ++ [y] ++ suf) ∈ one_element_decompositions l(pre, x, mid, y, suf) ∈ map (λ t : list A * A * list A, let (y, l3) := t in let (l2', e2) := y in (pre, x, l2', e2, l3)) (one_element_decompositions (mid ++ [y] ++ suf))A: Type
l, pre, mid, suf: list A
x, y: A
H: (pre, x, mid ++ [y] ++ suf) ∈ one_element_decompositions l∃ y0 : list A * A * list A, (pre, x, mid, y, suf) = (let (y, l3) := y0 in let (l2', e2) := y in (pre, x, l2', e2, l3)) ∧ y0 ∈ one_element_decompositions (mid ++ [y] ++ suf)by rewrite elem_of_one_element_decompositions. Qed.A: Type
l, pre, mid, suf: list A
x, y: A
H: (pre, x, mid ++ [y] ++ suf) ∈ one_element_decompositions l(pre, x, mid, y, suf) = (pre, x, mid, y, suf) ∧ (mid, y, suf) ∈ one_element_decompositions (mid ++ [y] ++ suf)∀ (A : Type) (pre1 suf1 pre2 suf2 : list A), pre1 ++ suf1 = pre2 ++ suf2 → pre1 = pre2 ∨ (∃ suf1' : list A, pre1 = pre2 ++ suf1') ∨ (∃ suf2' : list A, pre2 = pre1 ++ suf2')∀ (A : Type) (pre1 suf1 pre2 suf2 : list A), pre1 ++ suf1 = pre2 ++ suf2 → pre1 = pre2 ∨ (∃ suf1' : list A, pre1 = pre2 ++ suf1') ∨ (∃ suf2' : list A, pre2 = pre1 ++ suf2')A: Type
a: A
pre1: list A
IHpre1: ∀ suf1 pre2 suf2 : list A, pre1 ++ suf1 = pre2 ++ suf2 → pre1 = pre2 ∨ (∃ suf1' : list A, pre1 = pre2 ++ suf1') ∨ (∃ suf2' : list A, pre2 = pre1 ++ suf2')
suf1: list A
a0: A
pre2: list A∀ suf2 : list A, a :: pre1 ++ suf1 = a0 :: pre2 ++ suf2 → a :: pre1 = a0 :: pre2 ∨ (∃ suf1' : list A, a :: pre1 = a0 :: pre2 ++ suf1') ∨ (∃ suf2' : list A, a0 :: pre2 = a :: pre1 ++ suf2')by edestruct IHpre1 as [| [[] | []]]; [done | subst; eauto..]. Qed.A: Type
pre1: list A
IHpre1: ∀ suf1 pre2 suf2 : list A, pre1 ++ suf1 = pre2 ++ suf2 → pre1 = pre2 ∨ (∃ suf1' : list A, pre1 = pre2 ++ suf1') ∨ (∃ suf2' : list A, pre2 = pre1 ++ suf2')
suf1: list A
a0: A
pre2, suf2: list A
H: a0 :: pre1 ++ suf1 = a0 :: pre2 ++ suf2
H2: pre1 ++ suf1 = pre2 ++ suf2a0 :: pre1 = a0 :: pre2 ∨ (∃ suf1' : list A, a0 :: pre1 = a0 :: pre2 ++ suf1') ∨ (∃ suf2' : list A, a0 :: pre2 = a0 :: pre1 ++ suf2')∀ l : list nat, l ≠ [] → list_max l ∈ l∀ l : list nat, l ≠ [] → list_max l ∈ lh: nat
t: list nat
IHt: t ≠ [] → list_max t ∈ t
H: h :: t ≠ []h `max` foldr Init.Nat.max 0 t ∈ h :: th: nat
t: list nat
IHt: t ≠ [] → list_max t ∈ t
H: h :: t ≠ []
Hlt: h < foldr Init.Nat.max 0 tfoldr Init.Nat.max 0 t ∈ h :: tby destruct t; [cbn in Hlt; lia |]. Qed.h: nat
t: list nat
IHt: t ≠ [] → list_max t ∈ t
H: h :: t ≠ []
Hlt: h < foldr Init.Nat.max 0 tt ≠ []
Returns all values which occur with maximum frequency in the given list.
Note that these values are returned with their original multiplicity.
Definition mode `{EqDecision A} (l : list A) : list A := let mode_value := list_max (List.map (count_occ decide_eq l) l) in filter (fun a => (count_occ decide_eq l a) = mode_value) l.mode [1; 1; 2; 3; 3] = [1; 1; 3; 3]by itauto. Qed.mode [1; 1; 2; 3; 3] = [1; 1; 3; 3]
Computes the list
suff
which satisfies pref ++ suff = l
or
reports that no such list exists.
Fixpoint complete_prefix `{EqDecision A} (l pref : list A) : option (list A) := match l, pref with | l , [] => Some l | [], b :: pref' => None | a :: l', b :: pref' => if decide (a = b) then complete_prefix l' pref' else None end.complete_prefix [1; 2; 3; 4] [1; 2] = Some [3; 4]by itauto. Qed.complete_prefix [1; 2; 3; 4] [1; 2] = Some [3; 4]complete_prefix [1; 2; 3; 4] [1; 3] = Noneby itauto. Qed.complete_prefix [1; 2; 3; 4] [1; 3] = NoneA: Type
EqDecision0: EqDecision A∀ l : list A, complete_prefix l [] = Some lby induction l. Qed.A: Type
EqDecision0: EqDecision A∀ l : list A, complete_prefix l [] = Some lA: Type
EqDecision0: EqDecision A∀ l pref suff : list A, l = pref ++ suff ↔ complete_prefix l pref = Some suffA: Type
EqDecision0: EqDecision A∀ l pref suff : list A, l = pref ++ suff ↔ complete_prefix l pref = Some suffA: Type
EqDecision0: EqDecision A
a: A
l: list A
IHl: ∀ pref suff : list A, l = pref ++ suff ↔ complete_prefix l pref = Some suff
a0: A
l0, suff: list Aa :: l = a0 :: l0 ++ suff ↔ (if decide (a = a0) then complete_prefix l l0 else None) = Some suffby rewrite <- IHl; itauto congruence. Qed.A: Type
EqDecision0: EqDecision A
a: A
l: list A
IHl: ∀ pref suff : list A, l = pref ++ suff ↔ complete_prefix l pref = Some suff
a0: A
l0, suff: list A
H: a = a0a :: l = a0 :: l0 ++ suff ↔ complete_prefix l l0 = Some suff
Computes the list
pref
which satisfies pref ++ suff = l
or
reports that no such list exists.
Definition complete_suffix `{EqDecision A} (l suff : list A) : option (list A) := match complete_prefix (rev l) (rev suff) with | None => None | Some ls => Some (rev ls) end.complete_suffix [1; 2; 3; 4] [3; 4] = Some [1; 2]by itauto. Qed.complete_suffix [1; 2; 3; 4] [3; 4] = Some [1; 2]A: Type
EqDecision0: EqDecision A∀ l pref suff : list A, l = pref ++ suff ↔ complete_suffix l suff = Some prefA: Type
EqDecision0: EqDecision A∀ l pref suff : list A, l = pref ++ suff ↔ complete_suffix l suff = Some prefA: Type
EqDecision0: EqDecision A
l, pref, suff: list Al = pref ++ suff → match complete_prefix (rev l) (rev suff) with | Some ls => Some (rev ls) | None => None end = Some prefA: Type
EqDecision0: EqDecision A
l, pref, suff: list Amatch complete_prefix (rev l) (rev suff) with | Some ls => Some (rev ls) | None => None end = Some pref → l = pref ++ suffA: Type
EqDecision0: EqDecision A
l, pref, suff: list Al = pref ++ suff → match complete_prefix (rev l) (rev suff) with | Some ls => Some (rev ls) | None => None end = Some prefA: Type
EqDecision0: EqDecision A
pref, suff: list Amatch complete_prefix (rev (pref ++ suff)) (rev suff) with | Some ls => Some (rev ls) | None => None end = Some prefA: Type
EqDecision0: EqDecision A
pref, suff: list ASome (rev (rev pref)) = Some prefA: Type
EqDecision0: EqDecision A
pref, suff: list ASome (rev pref) = complete_prefix (rev (pref ++ suff)) (rev suff)by rewrite rev_involutive.A: Type
EqDecision0: EqDecision A
pref, suff: list ASome (rev (rev pref)) = Some prefA: Type
EqDecision0: EqDecision A
pref, suff: list ASome (rev pref) = complete_prefix (rev (pref ++ suff)) (rev suff)by rewrite rev_app_distr.A: Type
EqDecision0: EqDecision A
pref, suff: list Arev (pref ++ suff) = rev suff ++ rev prefA: Type
EqDecision0: EqDecision A
l, pref, suff: list Amatch complete_prefix (rev l) (rev suff) with | Some ls => Some (rev ls) | None => None end = Some pref → l = pref ++ suffA: Type
EqDecision0: EqDecision A
l, suff, l0: list A
Heq: complete_prefix (rev l) (rev suff) = Some l0l = rev l0 ++ suffA: Type
EqDecision0: EqDecision A
l, suff, l0: list A
Heq: rev l = rev suff ++ l0l = rev l0 ++ suffby rewrite rev_involutive in Heq. Qed.A: Type
EqDecision0: EqDecision A
l, suff, l0: list A
Heq: l = rev l0 ++ rev (rev suff)l = rev l0 ++ suffA: Type
EqDecision0: EqDecision A∀ l : list A, complete_suffix l [] = Some lA: Type
EqDecision0: EqDecision A∀ l : list A, complete_suffix l [] = Some lby rewrite complete_prefix_empty, rev_involutive. Qed.A: Type
EqDecision0: EqDecision A
l: list Amatch complete_prefix (rev l) [] with | Some ls => Some (rev ls) | None => None end = Some l
Keep elements which are inl but throw away those that are inr.
Definition list_sum_project_left {A B : Type} (x : list (A + B)) : list A :=
omap sum_project_left x.
Keep elements which are inr but throw away those that are inl.
Definition list_sum_project_right {A B : Type} (x : list (A + B)) : list B := omap sum_project_right x.∀ l : list bool, foldr andb false l = false∀ l : list bool, foldr andb false l = falseby rewrite IHl, andb_false_r. Qed.a: bool
l: list bool
IHl: foldr andb false l = falsea && foldr andb false l = false∀ (A : Type) (P Q : A → Prop), (∀ x : A, {P x} + {Q x}) → ∀ l : list A, {Forall P l} + {Exists Q l}∀ (A : Type) (P Q : A → Prop), (∀ x : A, {P x} + {Q x}) → ∀ l : list A, {Forall P l} + {Exists Q l}A: Type
P, Q: A → Prop
Hdec: ∀ x : A, {P x} + {Q x}∀ l : list A, {Forall P l} + {Exists Q l}A: Type
P, Q: A → Prop
Hdec: ∀ x : A, {P x} + {Q x}
a: A
l: list A
IHl: {Forall P l} + {Exists Q l}{Forall P (a :: l)} + {Exists Q (a :: l)}by destruct IHl; [left | right]; constructor. Qed.A: Type
P, Q: A → Prop
Hdec: ∀ x : A, {P x} + {Q x}
a: A
l: list A
IHl: {Forall P l} + {Exists Q l}
p: P a{Forall P (a :: l)} + {Exists Q (a :: l)}∀ (A : Type) (f g : A → nat) (l : list A), (∀ x : A, x ∈ l → f x ≤ g x) → list_sum (map f l) ≤ list_sum (map g l)∀ (A : Type) (f g : A → nat) (l : list A), (∀ x : A, x ∈ l → f x ≤ g x) → list_sum (map f l) ≤ list_sum (map g l)A: Type
f, g: A → nat
h: A
t: list A
IHt: (∀ x : A, x ∈ t → f x ≤ g x) → list_sum (map f t) ≤ list_sum (map g t)
Hle: ∀ x : A, x ∈ h :: t → f x ≤ g xf h + foldr Init.Nat.add 0 (map f t) ≤ g h + foldr Init.Nat.add 0 (map g t)A: Type
f, g: A → nat
h: A
t: list A
IHt: (∀ x : A, x ∈ t → f x ≤ g x) → list_sum (map f t) ≤ list_sum (map g t)
Hle: ∀ x : A, x ∈ h :: t → f x ≤ g xf h ≤ g hA: Type
f, g: A → nat
h: A
t: list A
IHt: (∀ x : A, x ∈ t → f x ≤ g x) → list_sum (map f t) ≤ list_sum (map g t)
Hle: ∀ x : A, x ∈ h :: t → f x ≤ g xfoldr Init.Nat.add 0 (map f t) ≤ foldr Init.Nat.add 0 (map g t)by apply Hle; left.A: Type
f, g: A → nat
h: A
t: list A
IHt: (∀ x : A, x ∈ t → f x ≤ g x) → list_sum (map f t) ≤ list_sum (map g t)
Hle: ∀ x : A, x ∈ h :: t → f x ≤ g xf h ≤ g hA: Type
f, g: A → nat
h: A
t: list A
IHt: (∀ x : A, x ∈ t → f x ≤ g x) → list_sum (map f t) ≤ list_sum (map g t)
Hle: ∀ x : A, x ∈ h :: t → f x ≤ g xfoldr Init.Nat.add 0 (map f t) ≤ foldr Init.Nat.add 0 (map g t)by apply Hle; right. Qed.A: Type
f, g: A → nat
h: A
t: list A
IHt: (∀ x : A, x ∈ t → f x ≤ g x) → list_sum (map f t) ≤ list_sum (map g t)
Hle: ∀ x : A, x ∈ h :: t → f x ≤ g x
x: A
Hin: x ∈ tf x ≤ g x∀ (A : Type) (f g : A → nat) (l : list A), (∀ a : A, a ∈ l → f a ≤ g a) → Exists (λ a : A, f a < g a) l → list_sum (map f l) < list_sum (map g l)∀ (A : Type) (f g : A → nat) (l : list A), (∀ a : A, a ∈ l → f a ≤ g a) → Exists (λ a : A, f a < g a) l → list_sum (map f l) < list_sum (map g l)A: Type
f, g: A → nat
l: list A
Hall: ∀ a : A, a ∈ l → f a ≤ g a
Hex: Exists (λ a : A, f a < g a) llist_sum (map f l) < list_sum (map g l)A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
H: f x < g xf x + foldr Init.Nat.add 0 (map f l) < g x + foldr Init.Nat.add 0 (map g l)A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
Hex: Exists (λ a : A, f a < g a) l
IHHex: (∀ a : A, a ∈ l → f a ≤ g a) → list_sum (map f l) < list_sum (map g l)f x + foldr Init.Nat.add 0 (map f l) < g x + foldr Init.Nat.add 0 (map g l)A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
H: f x < g xf x + foldr Init.Nat.add 0 (map f l) < g x + foldr Init.Nat.add 0 (map g l)A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
H: f x < g xfoldr Init.Nat.add 0 (map f l) ≤ foldr Init.Nat.add 0 (map g l)A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
H: f x < g x∀ x : A, x ∈ l → f x ≤ g xby apply Hall; right.A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
H: f x < g x
a': A
Hin: a' ∈ lf a' ≤ g a'A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
Hex: Exists (λ a : A, f a < g a) l
IHHex: (∀ a : A, a ∈ l → f a ≤ g a) → list_sum (map f l) < list_sum (map g l)f x + foldr Init.Nat.add 0 (map f l) < g x + foldr Init.Nat.add 0 (map g l)A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
Hex: Exists (λ a : A, f a < g a) l
IHHex: (∀ a : A, a ∈ l → f a ≤ g a) → list_sum (map f l) < list_sum (map g l)foldr Init.Nat.add 0 (map f l) < foldr Init.Nat.add 0 (map g l)A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
Hex: Exists (λ a : A, f a < g a) l
IHHex: (∀ a : A, a ∈ l → f a ≤ g a) → list_sum (map f l) < list_sum (map g l)∀ a : A, a ∈ l → f a ≤ g aby apply Hall; right. Qed.A: Type
f, g: A → nat
x: A
l: list A
Hall: ∀ a : A, a ∈ x :: l → f a ≤ g a
Hex: Exists (λ a : A, f a < g a) l
IHHex: (∀ a : A, a ∈ l → f a ≤ g a) → list_sum (map f l) < list_sum (map g l)
a: A
Hin: a ∈ lf a ≤ g a
Nearly the natural induction principle for fold_left.
Useful if you can think of fold_left f as transforming
a list into a B → B function, and can describe the
effect with a P : list A → relation B.
The assumption Hstep could be weakened by replacing r
with fold_left f l (f x a), but that isn't useful in
natural examples.
∀ (A B : Type) (f : B → A → B) (P : list A → B → B → Prop), (∀ x : B, P [] x x) → (∀ (x : B) (a : A) (l : list A) (r : B), P l (f x a) r → P (a :: l) x r) → ∀ (l : list A) (x : B), P l x (fold_left f l x)∀ (A B : Type) (f : B → A → B) (P : list A → B → B → Prop), (∀ x : B, P [] x x) → (∀ (x : B) (a : A) (l : list A) (r : B), P l (f x a) r → P (a :: l) x r) → ∀ (l : list A) (x : B), P l x (fold_left f l x)A, B: Type
f: B → A → B
P: list A → B → B → Prop
Hstart: ∀ x : B, P [] x x
Hstep: ∀ (x : B) (a : A) (l : list A) (r : B), P l (f x a) r → P (a :: l) x r∀ x : B, P [] x (fold_left f [] x)A, B: Type
f: B → A → B
P: list A → B → B → Prop
Hstart: ∀ x : B, P [] x x
Hstep: ∀ (x : B) (a : A) (l : list A) (r : B), P l (f x a) r → P (a :: l) x r
a: A
l: list A
IHl: ∀ x : B, P l x (fold_left f l x)∀ x : B, P (a :: l) x (fold_left f (a :: l) x)by apply Hstart.A, B: Type
f: B → A → B
P: list A → B → B → Prop
Hstart: ∀ x : B, P [] x x
Hstep: ∀ (x : B) (a : A) (l : list A) (r : B), P l (f x a) r → P (a :: l) x r∀ x : B, P [] x (fold_left f [] x)by intros x; apply Hstep, IHl. Qed.A, B: Type
f: B → A → B
P: list A → B → B → Prop
Hstart: ∀ x : B, P [] x x
Hstep: ∀ (x : B) (a : A) (l : list A) (r : B), P l (f x a) r → P (a :: l) x r
a: A
l: list A
IHl: ∀ x : B, P l x (fold_left f l x)∀ x : B, P (a :: l) x (fold_left f (a :: l) x)
An induction principle for fold_left which
decomposes the list from the right.
∀ (A B : Type) (f : B → A → B) (x0 : B) (P : list A → B → Prop), P [] x0 → (∀ (l : list A) (a : A) (x : B), P l x → P (l ++ [a]) (f x a)) → ∀ l : list A, P l (fold_left f l x0)∀ (A B : Type) (f : B → A → B) (x0 : B) (P : list A → B → Prop), P [] x0 → (∀ (l : list A) (a : A) (x : B), P l x → P (l ++ [a]) (f x a)) → ∀ l : list A, P l (fold_left f l x0)A, B: Type
f: B → A → B
x0: B
P: list A → B → Prop
Hstart: P [] x0
Hstep: ∀ (l : list A) (a : A) (x : B), P l x → P (l ++ [a]) (f x a)P [] (fold_left f [] x0)A, B: Type
f: B → A → B
x0: B
P: list A → B → Prop
Hstart: P [] x0
Hstep: ∀ (l : list A) (a : A) (x : B), P l x → P (l ++ [a]) (f x a)
x: A
l: list A
IHl: P l (fold_left f l x0)P (l ++ [x]) (fold_left f (l ++ [x]) x0)by apply Hstart.A, B: Type
f: B → A → B
x0: B
P: list A → B → Prop
Hstart: P [] x0
Hstep: ∀ (l : list A) (a : A) (x : B), P l x → P (l ++ [a]) (f x a)P [] (fold_left f [] x0)by rewrite fold_left_app; apply Hstep. Qed. Section sec_suffix_quantifiers.A, B: Type
f: B → A → B
x0: B
P: list A → B → Prop
Hstart: P [] x0
Hstep: ∀ (l : list A) (a : A) (x : B), P l x → P (l ++ [a]) (f x a)
x: A
l: list A
IHl: P l (fold_left f l x0)P (l ++ [x]) (fold_left f (l ++ [x]) x0)
Quantifiers for all suffixes
Context [A : Type] (P : list A -> Prop) . Inductive ExistsSuffix : list A -> Prop := | SHere : forall l, P l -> ExistsSuffix l | SFurther : forall a l, ExistsSuffix l -> ExistsSuffix (a :: l). Inductive ForAllSuffix : list A -> Prop := | SNil : P [] -> ForAllSuffix [] | SHereAndFurther : forall a l, P (a :: l) -> ForAllSuffix l -> ForAllSuffix (a :: l).A: Type
P: list A → Prop∀ l : list A, ForAllSuffix l → P lby inversion 1. Qed.A: Type
P: list A → Prop∀ l : list A, ForAllSuffix l → P lA: Type
P: list A → Prop∀ (a : A) (l : list A), ForAllSuffix (a :: l) → ForAllSuffix lby inversion 1. Qed.A: Type
P: list A → Prop∀ (a : A) (l : list A), ForAllSuffix (a :: l) → ForAllSuffix lA: Type
P: list A → Prop∀ (m : nat) (l : list A), ForAllSuffix l → ForAllSuffix (drop m l)A: Type
P: list A → Prop∀ (m : nat) (l : list A), ForAllSuffix l → ForAllSuffix (drop m l)by apply fsFurther in Hall; apply IHm. Qed.A: Type
P: list A → Prop
m: nat
IHm: ∀ l : list A, ForAllSuffix l → ForAllSuffix (drop m l)
a: A
l: list A
Hall: ForAllSuffix (a :: l)ForAllSuffix (drop m l)A: Type
P: list A → Prop∀ Inv : list A → Prop, (∀ l : list A, Inv l → P l) → (∀ (a : A) (l : list A), Inv (a :: l) → Inv l) → ∀ l : list A, Inv l → ForAllSuffix lA: Type
P: list A → Prop∀ Inv : list A → Prop, (∀ l : list A, Inv l → P l) → (∀ (a : A) (l : list A), Inv (a :: l) → Inv l) → ∀ l : list A, Inv l → ForAllSuffix lA: Type
P, Inv: list A → Prop
InvThenP: ∀ l : list A, Inv l → P l
InvIsStable: ∀ (a : A) (l : list A), Inv (a :: l) → Inv l
H: Inv []ForAllSuffix []A: Type
P, Inv: list A → Prop
InvThenP: ∀ l : list A, Inv l → P l
InvIsStable: ∀ (a : A) (l : list A), Inv (a :: l) → Inv l
a: A
l: list A
IHl: Inv l → ForAllSuffix l
H: Inv (a :: l)ForAllSuffix (a :: l)by constructor; apply InvThenP.A: Type
P, Inv: list A → Prop
InvThenP: ∀ l : list A, Inv l → P l
InvIsStable: ∀ (a : A) (l : list A), Inv (a :: l) → Inv l
H: Inv []ForAllSuffix []A: Type
P, Inv: list A → Prop
InvThenP: ∀ l : list A, Inv l → P l
InvIsStable: ∀ (a : A) (l : list A), Inv (a :: l) → Inv l
a: A
l: list A
IHl: Inv l → ForAllSuffix l
H: Inv (a :: l)ForAllSuffix (a :: l)A: Type
P, Inv: list A → Prop
InvThenP: ∀ l : list A, Inv l → P l
InvIsStable: ∀ (a : A) (l : list A), Inv (a :: l) → Inv l
a: A
l: list A
IHl: Inv l → ForAllSuffix l
H: Inv (a :: l)P (a :: l)A: Type
P, Inv: list A → Prop
InvThenP: ∀ l : list A, Inv l → P l
InvIsStable: ∀ (a : A) (l : list A), Inv (a :: l) → Inv l
a: A
l: list A
IHl: Inv l → ForAllSuffix l
H: Inv (a :: l)ForAllSuffix lby apply InvThenP.A: Type
P, Inv: list A → Prop
InvThenP: ∀ l : list A, Inv l → P l
InvIsStable: ∀ (a : A) (l : list A), Inv (a :: l) → Inv l
a: A
l: list A
IHl: Inv l → ForAllSuffix l
H: Inv (a :: l)P (a :: l)by eapply IHl, InvIsStable. Qed. End sec_suffix_quantifiers.A: Type
P, Inv: list A → Prop
InvThenP: ∀ l : list A, Inv l → P l
InvIsStable: ∀ (a : A) (l : list A), Inv (a :: l) → Inv l
a: A
l: list A
IHl: Inv l → ForAllSuffix l
H: Inv (a :: l)ForAllSuffix l∀ (A : Type) (P Q : list A → Prop), (∀ l : list A, P l → Q l) → ∀ l : list A, ForAllSuffix P l → ForAllSuffix Q lby induction 2; constructor; auto. Qed. Definition ForAllSuffix2 [A : Type] (R : A -> A -> Prop) : list A -> Prop := ForAllSuffix (fun l => match l with | a :: b :: _ => R a b | _ => True end).∀ (A : Type) (P Q : list A → Prop), (∀ l : list A, P l → Q l) → ∀ l : list A, ForAllSuffix P l → ForAllSuffix Q l∀ (A : Type) (R : A → A → Prop), Transitive R → ∀ (a b : A) (l : list A), ForAllSuffix2 R (a :: b :: l) → ForAllSuffix2 R (a :: l)∀ (A : Type) (R : A → A → Prop), Transitive R → ∀ (a b : A) (l : list A), ForAllSuffix2 R (a :: b :: l) → ForAllSuffix2 R (a :: l)A: Type
R: A → A → Prop
HT: Transitive R
a, b: A
l: list A
H: ForAllSuffix2 R (a :: b :: l)
H2: R a b
H3: ForAllSuffix (λ l : list A, match l with | [] => True | [a] => True | a :: b :: _ => R a b end) (b :: l)ForAllSuffix2 R (a :: l)A: Type
R: A → A → Prop
HT: Transitive R
a, b: A
H: ForAllSuffix2 R [a; b]
H2: R a b
H3: ForAllSuffix (λ l : list A, match l with | [] => True | [a] => True | a :: b :: _ => R a b end) [b]ForAllSuffix2 R [a]A: Type
R: A → A → Prop
HT: Transitive R
a, b, a0: A
l: list A
H: ForAllSuffix2 R (a :: b :: a0 :: l)
H2: R a b
H3: ForAllSuffix (λ l : list A, match l with | [] => True | [a] => True | a :: b :: _ => R a b end) (b :: a0 :: l)ForAllSuffix2 R (a :: a0 :: l)by repeat constructor.A: Type
R: A → A → Prop
HT: Transitive R
a, b: A
H: ForAllSuffix2 R [a; b]
H2: R a b
H3: ForAllSuffix (λ l : list A, match l with | [] => True | [a] => True | a :: b :: _ => R a b end) [b]ForAllSuffix2 R [a]A: Type
R: A → A → Prop
HT: Transitive R
a, b, a0: A
l: list A
H: ForAllSuffix2 R (a :: b :: a0 :: l)
H2: R a b
H3: ForAllSuffix (λ l : list A, match l with | [] => True | [a] => True | a :: b :: _ => R a b end) (b :: a0 :: l)ForAllSuffix2 R (a :: a0 :: l)by constructor; [transitivity b |]. Qed.A: Type
R: A → A → Prop
HT: Transitive R
a, b, a0: A
l: list A
H: ForAllSuffix2 R (a :: b :: a0 :: l)
H2: R a b
H3: ForAllSuffix (λ l : list A, match l with | [] => True | [a] => True | a :: b :: _ => R a b end) (b :: a0 :: l)
H4: R b a0
H5: ForAllSuffix (λ l : list A, match l with | [] => True | [a] => True | a :: b :: _ => R a b end) (a0 :: l)ForAllSuffix2 R (a :: a0 :: l)∀ (A : Type) (R : A → A → Prop), Transitive R → ∀ (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (l : list A), ForAllSuffix2 R l → ForAllSuffix2 R (filter P l)∀ (A : Type) (R : A → A → Prop), Transitive R → ∀ (P : A → Prop) (Pdec : ∀ a : A, Decision (P a)) (l : list A), ForAllSuffix2 R l → ForAllSuffix2 R (filter P l)A: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l: list A
IHl: ForAllSuffix2 R l → ForAllSuffix2 R (filter P l)
Hl: ForAllSuffix2 R (a :: l)ForAllSuffix2 R (filter P (a :: l))A: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l: list A
IHl: ForAllSuffix2 R l → ForAllSuffix2 R (filter P l)
Hl: ForAllSuffix2 R (a :: l)ForAllSuffix2 R (if decide (P a) then a :: filter P l else filter P l)A: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l: list A
Hl: ForAllSuffix2 R (a :: l)
IHl: ForAllSuffix2 R (filter P l)ForAllSuffix2 R (if decide (P a) then a :: filter P l else filter P l)A: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l: list A
Hl: ForAllSuffix2 R (a :: l)
IHl: ForAllSuffix2 R (filter P l)
H: P aForAllSuffix2 R (a :: filter P l)A: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a: A
l: list A
Hl: ForAllSuffix2 R (a :: l)
IHl: ForAllSuffix2 R (filter P l)
H: P amatch filter P l with | [] => True | b :: _ => R a b endA: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a, a0: A
l: list A
Hl: ForAllSuffix2 R (a :: a0 :: l)
IHl: ForAllSuffix2 R (a :: l) → match filter P l with | [] => True | b :: _ => R a b endmatch (if decide (P a0) then a0 :: filter P l else filter P l) with | [] => True | b :: _ => R a b endA: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a, a0: A
l: list A
Hl: ForAllSuffix2 R (a :: a0 :: l)
IHl: ForAllSuffix2 R (a :: l) → match filter P l with | [] => True | b :: _ => R a b end
H: P a0R a a0A: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a, a0: A
l: list A
Hl: ForAllSuffix2 R (a :: a0 :: l)
IHl: ForAllSuffix2 R (a :: l) → match filter P l with | [] => True | b :: _ => R a b end
H: ¬ P a0match filter P l with | [] => True | b :: _ => R a b endby inversion Hl.A: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a, a0: A
l: list A
Hl: ForAllSuffix2 R (a :: a0 :: l)
IHl: ForAllSuffix2 R (a :: l) → match filter P l with | [] => True | b :: _ => R a b end
H: P a0R a a0by apply IHl; eapply fsFurther2_transitive. Qed.A: Type
R: A → A → Prop
HT: Transitive R
P: A → Prop
Pdec: ∀ a : A, Decision (P a)
a, a0: A
l: list A
Hl: ForAllSuffix2 R (a :: a0 :: l)
IHl: ForAllSuffix2 R (a :: l) → match filter P l with | [] => True | b :: _ => R a b end
H: ¬ P a0match filter P l with | [] => True | b :: _ => R a b end∀ (A : Type) (l m n : list A), l ⊆ m → m ⊆ n → l ⊆ n∀ (A : Type) (l m n : list A), l ⊆ m → m ⊆ n → l ⊆ nby apply Hmn, Hlm. Qed.A: Type
l, m, n: list A
Hlm: l ⊆ m
Hmn: m ⊆ n
x: A
y: x ∈ lx ∈ nA: Type
EqDecision0: EqDecision ARelDecision subseteqA: Type
EqDecision0: EqDecision ARelDecision subseteqA: Type
EqDecision0: EqDecision A∀ y : list A, Decision ([] ⊆ y)A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)∀ y : list A, Decision (a :: x ⊆ y)by left; apply list_subseteq_nil.A: Type
EqDecision0: EqDecision A∀ y : list A, Decision ([] ⊆ y)A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)∀ y : list A, Decision (a :: x ⊆ y)A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)
y: list A
Hsub: x ⊆ yDecision (a :: x ⊆ y)A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)
y: list A
Hnsub: x ⊈ yDecision (a :: x ⊆ y)A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)
y: list A
Hsub: x ⊆ yDecision (a :: x ⊆ y)A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)
y: list A
Hsub: x ⊆ y
e: a ∈ yDecision (a :: x ⊆ y)A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)
y: list A
Hsub: x ⊆ y
n: a ∉ yDecision (a :: x ⊆ y)by left; inversion 1; subst; [| apply Hsub].A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)
y: list A
Hsub: x ⊆ y
e: a ∈ yDecision (a :: x ⊆ y)by right; intros Hsub'; contradict n; apply Hsub'; left.A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)
y: list A
Hsub: x ⊆ y
n: a ∉ yDecision (a :: x ⊆ y)A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)
y: list A
Hnsub: x ⊈ yDecision (a :: x ⊆ y)by intros b Hb; apply Hsub; right. Qed.A: Type
EqDecision0: EqDecision A
a: A
x: list A
IHx: ∀ y : list A, Decision (x ⊆ y)
y: list A
Hsub: a :: x ⊆ yx ⊆ y∀ (A : Type) (l1 l2 : list A), NoDup (l1 ++ l2) → NoDup l1by intros * [? _]%NoDup_app. Qed.∀ (A : Type) (l1 l2 : list A), NoDup (l1 ++ l2) → NoDup l1∀ (A : Type) (l1 l2 : list A), NoDup l1 → l1 ⊆ l2 → length l1 ≤ length l2by intros; apply submseteq_length, NoDup_submseteq. Qed.∀ (A : Type) (l1 l2 : list A), NoDup l1 → l1 ⊆ l2 → length l1 ≤ length l2∀ (A : Type) (x : A) (l1 l2 : list A), x :: l1 ⊆+ l2 → l1 ⊆+ l2by intros A x l1 l2; apply submseteq_trans, submseteq_cons. Qed.∀ (A : Type) (x : A) (l1 l2 : list A), x :: l1 ⊆+ l2 → l1 ⊆+ l2∀ (A : Type) (l1 l2 : list A), l1 ⊆+ l2 → l1 ⊆ l2by intros A l1 l2 H ? Hx; eapply elem_of_submseteq. Qed.∀ (A : Type) (l1 l2 : list A), l1 ⊆+ l2 → l1 ⊆ l2∀ (A : Type) (n : nat) (l l' : list A) (x : A), take n l = l' ++ [x] → ∃ n' : nat, n = S n'∀ (A : Type) (n : nat) (l l' : list A) (x : A), take n l = l' ++ [x] → ∃ n' : nat, n = S n'A: Type
l, l': list A
x: A
H: take 0 l = l' ++ [x]∃ n' : nat, 0 = S n'A: Type
n': nat
IHn': ∀ (l l' : list A) (x : A), take n' l = l' ++ [x] → ∃ n'0 : nat, n' = S n'0
l, l': list A
x: A
H: take (S n') l = l' ++ [x]∃ n'0 : nat, S n' = S n'0by rewrite take_0 in H; apply app_cons_not_nil in H.A: Type
l, l': list A
x: A
H: take 0 l = l' ++ [x]∃ n' : nat, 0 = S n'by exists n'. Qed.A: Type
n': nat
IHn': ∀ (l l' : list A) (x : A), take n' l = l' ++ [x] → ∃ n'0 : nat, n' = S n'0
l, l': list A
x: A
H: take (S n') l = l' ++ [x]∃ n'0 : nat, S n' = S n'0∀ (A B : Type) (x : A) (y : B) (la : list A) (lb : list B), (x, y) ∈ list_prod la lb ↔ x ∈ la ∧ y ∈ lbby intros; rewrite elem_of_list_In, in_prod_iff, <- !elem_of_list_In. Qed.∀ (A B : Type) (x : A) (y : B) (la : list A) (lb : list B), (x, y) ∈ list_prod la lb ↔ x ∈ la ∧ y ∈ lb
lastn returns a suffix of length
n
from the list l
.
Definition lastn {A : Type} (n : nat) (l : list A) : list A :=
rev (take n (rev l)).
If the list is [], then the result of lastn is also [].
∀ (A : Type) (n : nat), lastn n [] = []by intros A n; unfold lastn; cbn; rewrite take_nil. Qed.∀ (A : Type) (n : nat), lastn n [] = []
If
n
is zero, then the result of lastn is [].
∀ (A : Type) (l : list A), lastn 0 l = []by intros A l; unfold lastn; rewrite take_0. Qed.∀ (A : Type) (l : list A), lastn 0 l = []
If
n
is greater than the length of the list, lastn returns the whole list.
∀ (A : Type) (n : nat) (l : list A), length l ≤ n → lastn n l = l∀ (A : Type) (n : nat) (l : list A), length l ≤ n → lastn n l = lA: Type
n: nat
l: list A
Hge: length l ≤ nlastn n l = lA: Type
n: nat
l: list A
Hge: length l ≤ nrev (take n (rev l)) = lA: Type
n: nat
l: list A
Hge: length l ≤ nrev (rev l) = lA: Type
n: nat
l: list A
Hge: length l ≤ nlength (rev l) ≤ nby rewrite rev_involutive.A: Type
n: nat
l: list A
Hge: length l ≤ nrev (rev l) = lby rewrite rev_length. Qed.A: Type
n: nat
l: list A
Hge: length l ≤ nlength (rev l) ≤ n
lastn skips the prefix of the list as long as the suffix is long enough.
∀ (A : Type) (n : nat) (l1 l2 : list A), n ≤ length l2 → lastn n (l1 ++ l2) = lastn n l2∀ (A : Type) (n : nat) (l1 l2 : list A), n ≤ length l2 → lastn n (l1 ++ l2) = lastn n l2A: Type
n: nat
l1, l2: list A
Hlt: n ≤ length l2lastn n (l1 ++ l2) = lastn n l2A: Type
n: nat
l1, l2: list A
Hlt: n ≤ length l2rev (take n (rev (l1 ++ l2))) = rev (take n (rev l2))by rewrite rev_length; lia. Qed.A: Type
n: nat
l1, l2: list A
Hlt: n ≤ length l2n ≤ length (rev l2)
lastn either skips the head of the list or not, depending on how big a suffix we want.
∀ (A : Type) (n : nat) (h : A) (t : list A), lastn n (h :: t) = (if decide (S (length t) ≤ n) then h :: t else lastn n t)∀ (A : Type) (n : nat) (h : A) (t : list A), lastn n (h :: t) = (if decide (S (length t) ≤ n) then h :: t else lastn n t)A: Type
n: nat
h: A
t: list Alastn n (h :: t) = (if decide (S (length t) ≤ n) then h :: t else lastn n t)A: Type
n: nat
h: A
t: list A
H: S (length t) ≤ nlastn n (h :: t) = h :: tA: Type
n: nat
h: A
t: list A
H: ¬ S (length t) ≤ nlastn n (h :: t) = lastn n tby rewrite lastn_ge; cbn; [| lia].A: Type
n: nat
h: A
t: list A
H: S (length t) ≤ nlastn n (h :: t) = h :: tby rewrite (lastn_app_le _ [h] t); [| lia]. Qed.A: Type
n: nat
h: A
t: list A
H: ¬ S (length t) ≤ nlastn n (h :: t) = lastn n t
If
l1
is a prefix of l2
, then the reverse of l1
is a suffix of l2
.
∀ (A : Type) (l1 l2 : list A), l1 `prefix_of` l2 → rev l1 `suffix_of` rev l2∀ (A : Type) (l1 l2 : list A), l1 `prefix_of` l2 → rev l1 `suffix_of` rev l2A: Type
l1, l: list Arev l1 `suffix_of` rev (l1 ++ l)by exists (rev l). Qed.A: Type
l1, l: list Arev l1 `suffix_of` rev l ++ rev l1
If
n1
is less than (or equal to) n2
, then lastn n1 l
is shorter than
lastn n2 l
and therefore is its suffix.
∀ (A : Type) (l : list A) (n1 n2 : nat), n1 ≤ n2 → lastn n1 l `suffix_of` lastn n2 l∀ (A : Type) (l : list A) (n1 n2 : nat), n1 ≤ n2 → lastn n1 l `suffix_of` lastn n2 lA: Type
l: list A
n1, n2: nat
Hle: n1 ≤ n2lastn n1 l `suffix_of` lastn n2 lA: Type
l: list A
n1, n2: nat
Hle: n1 ≤ n2rev (take n1 (rev l)) `suffix_of` rev (take n2 (rev l))A: Type
l: list A
n1, n2: nat
Hle: n1 ≤ n2take n1 (rev l) `prefix_of` take n2 (rev l)A: Type
l: list A
n1, n2: nat
Hle: n1 ≤ n2take n2 (rev l) = take n1 (rev l) ++ take (n2 - n1) (drop n1 (rev l))by f_equal; lia. Qed.A: Type
l: list A
n1, n2: nat
Hle: n1 ≤ n2take n2 (rev l) = take (n1 + (n2 - n1)) (rev l)
The length of
lastn n l
is the smaller of n
and the length of l
.
∀ (A : Type) (n : nat) (l : list A), length (lastn n l) = n `min` length l∀ (A : Type) (n : nat) (l : list A), length (lastn n l) = n `min` length lA: Type
n: nat
l: list Alength (lastn n l) = n `min` length lby rewrite rev_length, take_length, rev_length. Qed. Program Definition not_null_element `{EqDecision A} [l : list A] (Hl : l <> []) : dsig (fun i => i ∈ l) := dexist (is_Some_proj (proj2 (head_is_Some l) Hl)) _.A: Type
n: nat
l: list Alength (rev (take n (rev l))) = n `min` length l∀ A : Type, EqDecision A → ∀ (l : list A) (Hl : l ≠ []), (λ i : A, i ∈ l) (is_Some_proj (proj2 (head_is_Some l) Hl))by intros A ? [| h t] ?; [| left]. Qed. Program Definition element_of_subseteq `{EqDecision A} [l1 l2 : list A] (Hsub : l1 ⊆ l2) (di : dsig (fun i => i ∈ l1)) : dsig (fun i => i ∈ l2) := dexist (` di) _.∀ A : Type, EqDecision A → ∀ (l : list A) (Hl : l ≠ []), (λ i : A, i ∈ l) (is_Some_proj (proj2 (head_is_Some l) Hl))∀ (A : Type) (EqDecision0 : EqDecision A) (l1 l2 : list A), l1 ⊆ l2 → ∀ di : dsig (λ i : A, i ∈ l1), (λ i : A, i ∈ l2) (`di)by intros; cbn; destruct_dec_sig di i Hi Heq; subst; apply Hsub. Qed. Definition element_of_filter `{EqDecision A} [P : A -> Prop] `{forall x, Decision (P x)} [l : list A] : dsig (fun i => i ∈ filter P l) -> dsig (fun i => i ∈ l) := element_of_subseteq (list_filter_subseteq P l).∀ (A : Type) (EqDecision0 : EqDecision A) (l1 l2 : list A), l1 ⊆ l2 → ∀ di : dsig (λ i : A, i ∈ l1), (λ i : A, i ∈ l2) (`di)
Section sec_max_prefix. Context {A : Type} `{EqDecision A} .A: Type
EqDecision0: EqDecision A∀ l : list A, max_prefix [] l = ([], l, [])done. Qed.A: Type
EqDecision0: EqDecision A∀ l : list A, max_prefix [] l = ([], l, [])A: Type
EqDecision0: EqDecision A∀ l : list A, max_prefix l [] = (l, [], [])by destruct l. Qed.A: Type
EqDecision0: EqDecision A∀ l : list A, max_prefix l [] = (l, [], [])A: Type
EqDecision0: EqDecision A∀ l : list A, max_prefix l l = ([], [], l)A: Type
EqDecision0: EqDecision A∀ l : list A, max_prefix l l = ([], [], l)A: Type
EqDecision0: EqDecision A
h: A
t: list A
IHt: max_prefix t t = ([], [], t)(if decide_rel eq h h then prod_map id (cons h) (max_prefix t t) else (h :: t, h :: t, [])) = ([], [], h :: t)by rewrite IHt; cbn. Qed.A: Type
EqDecision0: EqDecision A
h: A
t: list A
IHt: max_prefix t t = ([], [], t)
H: h = hprod_map id (cons h) (max_prefix t t) = ([], [], h :: t)A: Type
EqDecision0: EqDecision A∀ l1 l2 : list A, head l1 ≠ head l2 → max_prefix l1 l2 = (l1, l2, [])A: Type
EqDecision0: EqDecision A∀ l1 l2 : list A, head l1 ≠ head l2 → max_prefix l1 l2 = (l1, l2, [])by case_decide; [congruence |]. Qed.A: Type
EqDecision0: EqDecision A
a: A
l: list A
a0: A
l0: list A
Hneq: Some a ≠ Some a0(if decide_rel eq a a0 then prod_map id (cons a) (max_prefix l l0) else (a :: l, a0 :: l0, [])) = (a :: l, a0 :: l0, [])A: Type
EqDecision0: EqDecision A∀ l l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → max_prefix (l ++ l1) (l ++ l2) = (r1, r2, l ++ p)A: Type
EqDecision0: EqDecision A∀ l l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → max_prefix (l ++ l1) (l ++ l2) = (r1, r2, l ++ p)A: Type
EqDecision0: EqDecision A
h: A
t: list A
IHt: ∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → max_prefix (t ++ l1) (t ++ l2) = (r1, r2, t ++ p)
l1, l2, p, r1, r2: list A
Heq: max_prefix l1 l2 = (r1, r2, p)(if decide_rel eq h h then prod_map id (cons h) (max_prefix (t ++ l1) (t ++ l2)) else (h :: t ++ l1, h :: t ++ l2, [])) = (r1, r2, h :: t ++ p)by apply IHt in Heq as ->; cbn. Qed.A: Type
EqDecision0: EqDecision A
h: A
t: list A
IHt: ∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → max_prefix (t ++ l1) (t ++ l2) = (r1, r2, t ++ p)
l1, l2, p, r1, r2: list A
Heq: max_prefix l1 l2 = (r1, r2, p)
H: h = hprod_map id (cons h) (max_prefix (t ++ l1) (t ++ l2)) = (r1, r2, h :: t ++ p)A: Type
EqDecision0: EqDecision A∀ l l1 l2 : list A, max_prefix (l ++ l1) (l ++ l2) = (let '(r1, r2, p) := max_prefix l1 l2 in (r1, r2, l ++ p))A: Type
EqDecision0: EqDecision A∀ l l1 l2 : list A, max_prefix (l ++ l1) (l ++ l2) = (let '(r1, r2, p) := max_prefix l1 l2 in (r1, r2, l ++ p))A: Type
EqDecision0: EqDecision A
l, l1, l2: list Amax_prefix (l ++ l1) (l ++ l2) = (let '(r1, r2, p) := max_prefix l1 l2 in (r1, r2, l ++ p))by eapply max_prefix_app in Heq. Qed.A: Type
EqDecision0: EqDecision A
l, l1, l2, l0, l3, l4: list A
Heq: max_prefix l1 l2 = (l0, l3, l4)max_prefix (l ++ l1) (l ++ l2) = (l0, l3, l ++ l4)A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2A: Type
EqDecision0: EqDecision A
l1, l2, p: list A
a: A
l: list A
a0: A
l0: list A
Heq: max_prefix l1 l2 = (a :: l, a0 :: l0, p)a :: l = [] ∧ a0 :: l0 = [] ∨ Some a ≠ Some a0by right; congruence. Qed.A: Type
EqDecision0: EqDecision A
l1, l2, p: list A
a: A
l: list A
a0: A
l0: list A
Heq: a ≠ a0a :: l = [] ∧ a0 :: l0 = [] ∨ Some a ≠ Some a0A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) ↔ l1 = p ++ r1 ∧ l2 = p ++ r2 ∧ (r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2)A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) ↔ l1 = p ++ r1 ∧ l2 = p ++ r2 ∧ (r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2)A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list Amax_prefix l1 l2 = (r1, r2, p) → l1 = p ++ r1 ∧ l2 = p ++ r2 ∧ (r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2)A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list Al1 = p ++ r1 ∧ l2 = p ++ r2 ∧ (r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2) → max_prefix l1 l2 = (r1, r2, p)A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list Amax_prefix l1 l2 = (r1, r2, p) → l1 = p ++ r1 ∧ l2 = p ++ r2 ∧ (r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2)A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list A
H: max_prefix l1 l2 = (r1, r2, p)l2 = p ++ r2 ∧ (r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2)by eapply max_prefix_head_inv.A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list A
H: max_prefix l1 l2 = (r1, r2, p)r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list Al1 = p ++ r1 ∧ l2 = p ++ r2 ∧ (r1 = [] ∧ r2 = [] ∨ head r1 ≠ head r2) → max_prefix l1 l2 = (r1, r2, p)A: Type
EqDecision0: EqDecision A
p: list Amax_prefix (p ++ []) (p ++ []) = ([], [], p)A: Type
EqDecision0: EqDecision A
p, r1, r2: list A
H: head r1 ≠ head r2max_prefix (p ++ r1) (p ++ r2) = (r1, r2, p)by rewrite app_nil_r, max_prefix_diag.A: Type
EqDecision0: EqDecision A
p: list Amax_prefix (p ++ []) (p ++ []) = ([], [], p)by rewrite max_prefix_app_let, max_prefix_head, app_nil_r. Qed.A: Type
EqDecision0: EqDecision A
p, r1, r2: list A
H: head r1 ≠ head r2max_prefix (p ++ r1) (p ++ r2) = (r1, r2, p)A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → max_prefix l2 l1 = (r2, r1, p)A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → max_prefix l2 l1 = (r2, r1, p)A: Type
EqDecision0: EqDecision A
h1: A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix l2 t1 = (r2, r1, p)
h2: A
t2: list A∀ p r1 r2 : list A, (if decide_rel eq h1 h2 then prod_map id (cons h1) (max_prefix t1 t2) else (h1 :: t1, h2 :: t2, [])) = (r1, r2, p) → (if decide_rel eq h2 h1 then prod_map id (cons h2) (max_prefix t2 t1) else (h2 :: t2, h1 :: t1, [])) = (r2, r1, p)A: Type
EqDecision0: EqDecision A
h1: A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix l2 t1 = (r2, r1, p)
h2: A
t2, p, r1, r2: list A(if decide_rel eq h1 h2 then prod_map id (cons h1) (max_prefix t1 t2) else (h1 :: t1, h2 :: t2, [])) = (r1, r2, p) → (if decide_rel eq h2 h1 then prod_map id (cons h2) (max_prefix t2 t1) else (h2 :: t2, h1 :: t1, [])) = (r2, r1, p)A: Type
EqDecision0: EqDecision A
h1: A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix l2 t1 = (r2, r1, p)
h2: A
t2, p, r1, r2, l, l0, l1: list A
Heq: max_prefix t1 t2 = (l, l0, l1)(if decide_rel eq h1 h2 then prod_map id (cons h1) (l, l0, l1) else (h1 :: t1, h2 :: t2, [])) = (r1, r2, p) → (if decide_rel eq h2 h1 then prod_map id (cons h2) (max_prefix t2 t1) else (h2 :: t2, h1 :: t1, [])) = (r2, r1, p)by erewrite IHt1. Qed.A: Type
EqDecision0: EqDecision A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix l2 t1 = (r2, r1, p)
h2: A
t2, l, l0, l1: list A
Heq: max_prefix t1 t2 = (l, l0, l1)
H: h2 = h2prod_map id (cons h2) (max_prefix t2 t1) = (l0, l, h2 :: l1)A: Type
EqDecision0: EqDecision A∀ l1 l2 : list A, max_prefix l2 l1 = (let '(r1, r2, p) := max_prefix l1 l2 in (r2, r1, p))A: Type
EqDecision0: EqDecision A∀ l1 l2 : list A, max_prefix l2 l1 = (let '(r1, r2, p) := max_prefix l1 l2 in (r2, r1, p))A: Type
EqDecision0: EqDecision A
l1, l2: list Amax_prefix l2 l1 = (let '(r1, r2, p) := max_prefix l1 l2 in (r2, r1, p))by apply max_prefix_comm in Heq. Qed.A: Type
EqDecision0: EqDecision A
l1, l2, l, l0, l3: list A
Heq: max_prefix l1 l2 = (l, l0, l3)max_prefix l2 l1 = (l0, l, l3)A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])A: Type
EqDecision0: EqDecision A
h1: A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])
h2: A
t2: list A∀ p r1 r2 : list A, (if decide_rel eq h1 h2 then prod_map id (cons h1) (max_prefix t1 t2) else (h1 :: t1, h2 :: t2, [])) = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])A: Type
EqDecision0: EqDecision A
h1: A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])
h2: A
t2, p, r1, r2: list A(if decide_rel eq h1 h2 then prod_map id (cons h1) (max_prefix t1 t2) else (h1 :: t1, h2 :: t2, [])) = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])A: Type
EqDecision0: EqDecision A
h1: A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])
h2: A
t2, p, r1, r2, l, l0, l1: list A
Heq: max_prefix t1 t2 = (l, l0, l1)(if decide_rel eq h1 h2 then prod_map id (cons h1) (l, l0, l1) else (h1 :: t1, h2 :: t2, [])) = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])A: Type
EqDecision0: EqDecision A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])
h2: A
t2, l, l0, l1: list A
Heq: max_prefix t1 t2 = (l, l0, l1)max_prefix l l0 = (l, l0, [])A: Type
EqDecision0: EqDecision A
h1: A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])
h2: A
t2, l, l0, l1: list A
Heq: max_prefix t1 t2 = (l, l0, l1)
H: h1 ≠ h2(if decide_rel eq h1 h2 then prod_map id (cons h1) (max_prefix t1 t2) else (h1 :: t1, h2 :: t2, [])) = (h1 :: t1, h2 :: t2, [])by apply IHt1 in Heq.A: Type
EqDecision0: EqDecision A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])
h2: A
t2, l, l0, l1: list A
Heq: max_prefix t1 t2 = (l, l0, l1)max_prefix l l0 = (l, l0, [])by case_decide. Qed.A: Type
EqDecision0: EqDecision A
h1: A
t1: list A
IHt1: ∀ l2 p r1 r2 : list A, max_prefix t1 l2 = (r1, r2, p) → max_prefix r1 r2 = (r1, r2, [])
h2: A
t2, l, l0, l1: list A
Heq: max_prefix t1 t2 = (l, l0, l1)
H: h1 ≠ h2(if decide_rel eq h1 h2 then prod_map id (cons h1) (max_prefix t1 t2) else (h1 :: t1, h2 :: t2, [])) = (h1 :: t1, h2 :: t2, [])A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 p' : list A, max_prefix l1 l2 = (r1, r2, p) → p' `prefix_of` l1 → p' `prefix_of` l2 → length p' ≤ length pA: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 p' : list A, max_prefix l1 l2 = (r1, r2, p) → p' `prefix_of` l1 → p' `prefix_of` l2 → length p' ≤ length pA: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2, p': list A
Hlc: max_prefix l1 l2 = (r1, r2, p)
Hp1: p' `prefix_of` l1
Hp2: p' `prefix_of` l2length p' ≤ length pby eapply max_prefix_max_alt. Qed.A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2, p': list A
Hlc: max_prefix l1 l2 = (r1, r2, p)
Hp1: p' `prefix_of` l1
Hp2: p' `prefix_of` l2
H0: max_prefix l1 l2 = (r1, r2, p)p' `prefix_of` pA: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → r1 `suffix_of` l1 ∧ r2 `suffix_of` l2A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_prefix l1 l2 = (r1, r2, p) → r1 `suffix_of` l1 ∧ r2 `suffix_of` l2A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list A
Hprefix: max_prefix l1 l2 = (r1, r2, p)r1 `suffix_of` l1 ∧ r2 `suffix_of` l2by split; apply suffix_app_r. Qed. End sec_max_prefix.A: Type
EqDecision0: EqDecision A
p, r1, r2: list Ar1 `suffix_of` p ++ r1 ∧ r2 `suffix_of` p ++ r2
Section sec_max_suffix. Context {A : Type} `{EqDecision A} .A: Type
EqDecision0: EqDecision A∀ l : list A, max_suffix l l = ([], [], l)A: Type
EqDecision0: EqDecision A∀ l : list A, max_suffix l l = ([], [], l)A: Type
EqDecision0: EqDecision A
l: list Amax_suffix l l = ([], [], l)by rewrite max_prefix_diag, reverse_involutive; cbn. Qed.A: Type
EqDecision0: EqDecision A
l: list A(let (p, k3) := max_prefix (reverse l) (reverse l) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3)) = ([], [], l)A: Type
EqDecision0: EqDecision A∀ l l1 l2 : list A, max_suffix (l1 ++ l) (l2 ++ l) = (let '(r1, r2, p) := max_suffix l1 l2 in (r1, r2, p ++ l))A: Type
EqDecision0: EqDecision A∀ l l1 l2 : list A, max_suffix (l1 ++ l) (l2 ++ l) = (let '(r1, r2, p) := max_suffix l1 l2 in (r1, r2, p ++ l))A: Type
EqDecision0: EqDecision A
l, l1, l2: list Amax_suffix (l1 ++ l) (l2 ++ l) = (let '(r1, r2, p) := max_suffix l1 l2 in (r1, r2, p ++ l))A: Type
EqDecision0: EqDecision A
l, l1, l2: list A(let (p, k3) := max_prefix (reverse (l1 ++ l)) (reverse (l2 ++ l)) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3)) = (let '(r1, r2, p) := let (p, k3) := max_prefix (reverse l1) (reverse l2) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3) in (r1, r2, p ++ l))A: Type
EqDecision0: EqDecision A
l, l1, l2: list A(let (p, k3) := let '(r1, r2, p) := max_prefix (reverse l1) (reverse l2) in (r1, r2, reverse l ++ p) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3)) = (let '(r1, r2, p) := let (p, k3) := max_prefix (reverse l1) (reverse l2) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3) in (r1, r2, p ++ l))by rewrite reverse_app, reverse_involutive. Qed.A: Type
EqDecision0: EqDecision A
l, l1, l2, l0, l3, l4: list A
Heq: max_prefix (reverse l1) (reverse l2) = (l0, l3, l4)(reverse l0, reverse l3, reverse (reverse l ++ l4)) = (reverse l0, reverse l3, reverse l4 ++ l)A: Type
EqDecision0: EqDecision A∀ l1 l2 : list A, last l1 ≠ last l2 → max_suffix l1 l2 = (l1, l2, [])A: Type
EqDecision0: EqDecision A∀ l1 l2 : list A, last l1 ≠ last l2 → max_suffix l1 l2 = (l1, l2, [])A: Type
EqDecision0: EqDecision A
l1, l2: list A
Hlast: last l1 ≠ last l2max_suffix l1 l2 = (l1, l2, [])A: Type
EqDecision0: EqDecision A
l1, l2: list A
Hlast: last l1 ≠ last l2(let (p, k3) := max_prefix (reverse l1) (reverse l2) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3)) = (l1, l2, [])A: Type
EqDecision0: EqDecision A
l1, l2: list A
Hlast: last l1 ≠ last l2(reverse (reverse l1), reverse (reverse l2), reverse []) = (l1, l2, [])A: Type
EqDecision0: EqDecision A
l1, l2: list A
Hlast: last l1 ≠ last l2head (reverse l1) ≠ head (reverse l2)by rewrite !reverse_involutive; cbn.A: Type
EqDecision0: EqDecision A
l1, l2: list A
Hlast: last l1 ≠ last l2(reverse (reverse l1), reverse (reverse l2), reverse []) = (l1, l2, [])by rewrite !head_reverse. Qed.A: Type
EqDecision0: EqDecision A
l1, l2: list A
Hlast: last l1 ≠ last l2head (reverse l1) ≠ head (reverse l2)A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_suffix l1 l2 = (r1, r2, p) → r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_suffix l1 l2 = (r1, r2, p) → r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list A
Heq: max_suffix l1 l2 = (r1, r2, p)r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2, r1': list A
h1: A
r2': list A
h2: A
Heq: max_suffix l1 l2 = (r1' ++ [h1], r2' ++ [h2], p)
Heq1: r1 = r1' ++ [h1]
Heq2: r2 = r2' ++ [h2]r1' ++ [h1] = [] ∧ r2' ++ [h2] = [] ∨ Some h1 ≠ Some h2by apply max_suffix_max_snoc in Heq. Qed.A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2, r1', r2': list A
h2: A
Heq1: r1 = r1' ++ [h2]
Heq: max_suffix l1 l2 = (r1' ++ [h2], r2' ++ [h2], p)
Heq2: r2 = r2' ++ [h2]FalseA: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_suffix l1 l2 = (r1, r2, p) ↔ l1 = r1 ++ p ∧ l2 = r2 ++ p ∧ (r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2)A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_suffix l1 l2 = (r1, r2, p) ↔ l1 = r1 ++ p ∧ l2 = r2 ++ p ∧ (r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2)A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list Amax_suffix l1 l2 = (r1, r2, p) → l1 = r1 ++ p ∧ l2 = r2 ++ p ∧ (r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2)A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list Al1 = r1 ++ p ∧ l2 = r2 ++ p ∧ (r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2) → max_suffix l1 l2 = (r1, r2, p)A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list Amax_suffix l1 l2 = (r1, r2, p) → l1 = r1 ++ p ∧ l2 = r2 ++ p ∧ (r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2)A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list A
H: max_suffix l1 l2 = (r1, r2, p)l2 = r2 ++ p ∧ (r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2)by eapply max_suffix_last_inv.A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list A
H: max_suffix l1 l2 = (r1, r2, p)r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list Al1 = r1 ++ p ∧ l2 = r2 ++ p ∧ (r1 = [] ∧ r2 = [] ∨ last r1 ≠ last r2) → max_suffix l1 l2 = (r1, r2, p)A: Type
EqDecision0: EqDecision A
p: list Amax_suffix p p = ([], [], p)A: Type
EqDecision0: EqDecision A
p, r1, r2: list A
H: last r1 ≠ last r2max_suffix (r1 ++ p) (r2 ++ p) = (r1, r2, p)by rewrite max_suffix_diag.A: Type
EqDecision0: EqDecision A
p: list Amax_suffix p p = ([], [], p)by rewrite max_suffix_app_let, max_suffix_last. Qed.A: Type
EqDecision0: EqDecision A
p, r1, r2: list A
H: last r1 ≠ last r2max_suffix (r1 ++ p) (r2 ++ p) = (r1, r2, p)A: Type
EqDecision0: EqDecision A∀ l1 l2 : list A, max_suffix l2 l1 = (let '(r1, r2, p) := max_suffix l1 l2 in (r2, r1, p))A: Type
EqDecision0: EqDecision A∀ l1 l2 : list A, max_suffix l2 l1 = (let '(r1, r2, p) := max_suffix l1 l2 in (r2, r1, p))A: Type
EqDecision0: EqDecision A
l1, l2: list Amax_suffix l2 l1 = (let '(r1, r2, p) := max_suffix l1 l2 in (r2, r1, p))A: Type
EqDecision0: EqDecision A
l1, l2: list A(let (p, k3) := max_prefix (reverse l2) (reverse l1) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3)) = (let '(r1, r2, p) := let (p, k3) := max_prefix (reverse l1) (reverse l2) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3) in (r2, r1, p))by destruct (max_prefix (reverse l1) (reverse l2)) as [[]]. Qed.A: Type
EqDecision0: EqDecision A
l1, l2: list A(let (p, k3) := let '(r1, r2, p) := max_prefix (reverse l1) (reverse l2) in (r2, r1, p) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3)) = (let '(r1, r2, p) := let (p, k3) := max_prefix (reverse l1) (reverse l2) in let (k1, k2) := p in (reverse k1, reverse k2, reverse k3) in (r2, r1, p))A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_suffix l1 l2 = (r1, r2, p) → p `suffix_of` l1 ∧ p `suffix_of` l2A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_suffix l1 l2 = (r1, r2, p) → p `suffix_of` l1 ∧ p `suffix_of` l2A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list A
Hsuffix: max_suffix l1 l2 = (r1, r2, p)p `suffix_of` l1 ∧ p `suffix_of` l2by split; apply suffix_app_r. Qed.A: Type
EqDecision0: EqDecision A
p, r1, r2: list Ap `suffix_of` r1 ++ p ∧ p `suffix_of` r2 ++ pA: Type
EqDecision0: EqDecision A∀ l l1 l2 : list A, l `suffix_of` l1 → l `suffix_of` l2 → let '(_, _, p) := max_suffix l1 l2 in l `suffix_of` pA: Type
EqDecision0: EqDecision A∀ l l1 l2 : list A, l `suffix_of` l1 → l `suffix_of` l2 → let '(_, _, p) := max_suffix l1 l2 in l `suffix_of` pA: Type
EqDecision0: EqDecision A
l, l1, l2: list A
H: l `suffix_of` l1
H0: l `suffix_of` l2let '(_, _, p) := max_suffix l1 l2 in l `suffix_of` pby eapply max_suffix_max_alt. Qed.A: Type
EqDecision0: EqDecision A
l, l1, l2: list A
H: l `suffix_of` l1
H0: l `suffix_of` l2
l0, l3, l4: list A
Heq: max_suffix l1 l2 = (l0, l3, l4)l `suffix_of` l4A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 p' : list A, max_suffix l1 l2 = (r1, r2, p) → p' `suffix_of` l1 → p' `suffix_of` l2 → length p' ≤ length pA: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 p' : list A, max_suffix l1 l2 = (r1, r2, p) → p' `suffix_of` l1 → p' `suffix_of` l2 → length p' ≤ length pA: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2, p': list A
Hlc: max_suffix l1 l2 = (r1, r2, p)
Hp1: p' `suffix_of` l1
Hp2: p' `suffix_of` l2length p' ≤ length pby eapply max_suffix_max_alt. Qed.A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2, p': list A
Hlc: max_suffix l1 l2 = (r1, r2, p)
Hp1: p' `suffix_of` l1
Hp2: p' `suffix_of` l2
H0: max_suffix l1 l2 = (r1, r2, p)p' `suffix_of` pA: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_suffix l1 l2 = (r1, r2, p) → r1 `prefix_of` l1 ∧ r2 `prefix_of` l2A: Type
EqDecision0: EqDecision A∀ l1 l2 p r1 r2 : list A, max_suffix l1 l2 = (r1, r2, p) → r1 `prefix_of` l1 ∧ r2 `prefix_of` l2A: Type
EqDecision0: EqDecision A
l1, l2, p, r1, r2: list A
Hsuffix: max_suffix l1 l2 = (r1, r2, p)r1 `prefix_of` l1 ∧ r2 `prefix_of` l2by split; apply prefix_app_r. Qed. End sec_max_suffix. Program Fixpoint Exists_choose_first `{P : A -> Prop} `{forall a, Decision (P a)} {l : list A} (Hl : Exists P l) {struct l} : A := match l with | [] => _ | a :: l => if decide (P a) then a else @Exists_choose_first A P _ l _ end.A: Type
EqDecision0: EqDecision A
p, r1, r2: list Ar1 `prefix_of` r1 ++ p ∧ r2 `prefix_of` r2 ++ p∀ (A : Type) (P : A → Prop), (∀ a : A, Decision (P a)) → ∀ l : list A, Exists P l → [] = l → Aby intros; exfalso; subst; inversion Hl. Qed.∀ (A : Type) (P : A → Prop), (∀ a : A, Decision (P a)) → ∀ l : list A, Exists P l → [] = l → A∀ (A : Type) (P : A → Prop), (∀ a : A, Decision (P a)) → ∀ l0 : list A, Exists P l0 → ∀ (a : A) (l : list A), a :: l = l0 → ¬ P a → Exists P lby intros; subst; apply Exists_cons in Hl as []. Qed.∀ (A : Type) (P : A → Prop), (∀ a : A, Decision (P a)) → ∀ l0 : list A, Exists P l0 → ∀ (a : A) (l : list A), a :: l = l0 → ¬ P a → Exists P l∀ (A : Type) (P : A → Prop) (H : ∀ a : A, Decision (P a)) (l : list A) (Hl : Exists P l), P (Exists_choose_first Hl)∀ (A : Type) (P : A → Prop) (H : ∀ a : A, Decision (P a)) (l : list A) (Hl : Exists P l), P (Exists_choose_first Hl)by case_decide; [| apply IHl]. Qed.A: Type
P: A → Prop
H: ∀ a : A, Decision (P a)
a: A
l: list A
IHl: ∀ Hl : Exists P l, P (Exists_choose_first Hl)
Hl: Exists P (a :: l)P match decide (P a) with | left _ => a | right x => Exists_choose_first (Exists_choose_first_obligation_2 A P (a :: l) Hl a l eq_refl x) end