Library zoo.common.list
Require Ltac2.Ltac2.
Require stdpp.list.
Require stdpp.sorting.
Require Import zoo.prelude.
Require Import zoo.common.math.
Require Import zoo.options.
Export stdpp.list.
Export stdpp.sorting.
Create HintDb simp_length.
#[global] Hint Rewrite
@length_reverse
@length_app
@length_insert
@length_take
@length_drop
@length_fmap
@length_replicate
@length_seq
@length_seqZ
@length_zip_with
: simp_length.
Tactic Notation "simp_length" :=
autorewrite with simp_length; try done.
Tactic Notation "simp_length" "/=" :=
repeat (progress csimpl in × || simp_length).
Tactic Notation "simp_length" "in" ne_hyp_list(Hs) :=
autorewrite with simp_length in Hs; try done.
Tactic Notation "simp_length" "/=" "in" ne_hyp_list(Hs) :=
repeat (progress csimpl in × || simp_length in Hs).
Tactic Notation "simp_length" "in" "*" :=
autorewrite with simp_length in *; try done.
Tactic Notation "simp_length" "/=" "in" "*" :=
repeat (progress csimpl in × || simp_length in × ).
Module lengths.
Import Ltac2.
Ltac2 main () :=
Control.enter (fun () ⇒
List.iter (fun (hyp, _, ty) ⇒
lazy_match! ty with
| _ = _ ⇒
try (apply (f_equal length) in $hyp as ?)
| _ ≡ₚ _ ⇒
apply Permutation_length in $hyp as ?
| _ ⊆+ _ ⇒
apply submseteq_length in $hyp as ?
| _ `prefix_of` _ ⇒
apply prefix_length in $hyp as ?
| _ ⇒
()
end
) (Control.hyps ())
).
End lengths.
Tactic Notation "lengths" :=
ltac2:(lengths.main ());
simp_length in ×.
Tactic Notation "lengths" "/=" :=
ltac2:(lengths.main ());
simp_length/= in ×.
Section basic.
Context {A : Type}.
Implicit Type x y z : A.
Implicit Type l : list A.
Lemma listーeq l1 l2 :
l1 = l2 ↔
length l1 = length l2 ∧
∀ i x1 x2,
l1 !! i = Some x1 →
l2 !! i = Some x2 →
x1 = x2.
Lemma appーnotーnil l1 l2 :
l1 ≠ [] ∨ l2 ≠ [] →
l1 ++ l2 ≠ [].
Lemma appーnotーnilーl l1 l2 :
l1 ≠ [] →
l1 ++ l2 ≠ [].
Lemma appーnotーnilーr l1 l2 :
l2 ≠ [] →
l1 ++ l2 ≠ [].
Lemma lookupーappーrーSome l1 l2 i y :
length l1 ≤ i →
l2 !! (i - length l1) = Some y →
(l1 ++ l2) !! i = Some y.
Lemma lookupーconsーrーSome x l i y :
0 < i →
l !! (i - 1) = Some y →
(x :: l) !! i = Some y.
Lemma elem_ofーappーl l1 l2 x :
x ∈ l1 →
x ∈ l1 ++ l2.
Lemma elem_ofーappーr l1 l2 x :
x ∈ l2 →
x ∈ l1 ++ l2.
Lemma reverseーnilーiff l :
reverse l = [] ↔
l = [].
Lemma foldrーinsertーstrong `(f : A → B → B) comp l i x y acc :
l !! i = Some x →
( ∀ x acc,
f x (f y acc) = f y (f x acc)
) →
( ∀ acc,
f (comp y x) acc = f y (f x acc)
) →
foldr f acc (<[i := comp y x]> l) = f y (foldr f acc l).
Lemma foldrーinsertーstrong' op `{!Assoc (=) op} `{!Comm (=) op} comp l i x y acc :
l !! i = Some x →
( ∀ acc,
op (comp y x) acc = op y (op x acc)
) →
foldr op acc (<[i := comp y x]> l) = op y (foldr op acc l).
Lemma foldrーinsert op `{!Assoc (=) op} `{!Comm (=) op} l i x y acc :
l !! i = Some x →
foldr op acc (<[i := op y x]> l) = op y (foldr op acc l).
Lemma lengthーlookupーlast l i :
is_Some (l !! i) →
l !! ˖i = None →
length l = ˖i.
Lemma tailーapp l1 l2 :
l1 ≠ [] →
tail (l1 ++ l2) = tail l1 ++ l2.
Lemma lengthーtail l :
length (tail l) ≤ length l.
Lemma headーapp l1 l2 :
0 < length l1 →
head (l1 ++ l2) = head l1.
Lemma headーappーcons l1 x l2 :
head (l1 ++ x :: l2) = head (l1 ++ [x]).
Lemma headーdropーSome l i x :
l !! i = Some x →
head (drop i l) = Some x.
Lemma headーdrop l i :
head (drop i l) = l !! i.
Lemma hdーcorrect default l x :
0 < length l →
hd default l = x →
head l = Some x.
Lemma hdーapp default l1 l2 :
0 < length l1 →
hd default (l1 ++ l2) = hd default l1.
Lemma hdーappーcons default l1 x l2 :
hd default (l1 ++ x :: l2) = hd default (l1 ++ [x]).
Lemma hdーdropーSome default l i x :
l !! i = Some x →
hd default (drop i l) = x.
Lemma lastーcons' x l :
last (x :: l) = Some $ default x (last l).
Lemma lastーtake l i x :
l !! i = Some x →
last (take ˖i l) = Some x.
Lemma lastーtake' l i :
is_Some (l !! i) →
last (take i l) = nat۰elim None (l !!.) i.
Lemma lastーremovelast l x :
last l = Some x →
l = removelast l ++ [x].
Lemma dropーlookupーNone l i :
l !! i = None →
drop i l = [].
Lemma dropーconsーinv i l x l' :
drop i l = x :: l' →
l !! i = Some x ∧
l' = drop ˖i l.
Lemma insertーconsーl i x y l :
i = 0 →
<[i := x]> (y :: l) = x :: l.
Lemma insertーconsーr i x y l :
0 < i →
<[i := x]> (y :: l) = y :: <[i - 1 := x]> l.
Lemma insertーappーrー0 i x l1 l2 :
i = length l1 →
<[i := x]> (l1 ++ l2) = l1 ++ <[0 := x]> l2.
Lemma listーdeleteーinsertーeq l i x :
i < length l →
delete i (<[i := x]> l) = delete i l.
End basic.
Section suffix.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l : list A.
Lemma suffixーtail l1 l2 :
l1 `suffix_of` l2 →
tail l1 `suffix_of` l2.
Lemma suffixーfmap `(f : A → B) `{!Inj (=) (=) f} l1 l2 :
suffix (f <$> l1) (f <$> l2) →
suffix l1 l2.
End suffix.
Section seqZ.
Lemma seqZーprefix {i n1} n2 :
(0 ≤ n2 ≤ n1)%Z →
seqZ i n2 `prefix_of` seqZ i n1.
Lemma seqZーsuffix {i1 n1} i2 n2 :
(i1 ≤ i2 ≤ i1 + n1)%Z →
(i2 - i1 = n1 - n2)%Z →
seqZ i2 n2 `suffix_of` seqZ i1 n1.
End seqZ.
Section zip.
Context {A1 A2 : Type}.
Lemma prod_mapーzip {B1 B2} (f1 : A1 → B1) (f2 : A2 → B2) l1 l2 :
prod_map f1 f2 <$> (zip l1 l2) = zip (f1 <$> l1) (f2 <$> l2).
End zip.
Section zip3_with.
Context {A1 A2 A3 B : Type}.
Implicit Type f : A1 → A2 → A3 → B.
Fixpoint zip3_with f l1 l2 l3 :=
match l1, l2, l3 with
| x1 :: l1, x2 :: l2, x3 :: l3 ⇒
f x1 x2 x3 :: zip3_with f l1 l2 l3
| _, _, _ ⇒
[]
end.
#[global] Arguments zip3_with _ !_ !_ !_ / : assert.
Lemma lengthーzip3_with f l1 l2 l3 :
length l1 = length l2 →
length l1 = length l3 →
length (zip3_with f l1 l2 l3) = length l1.
Lemma lookupーzip3_withーSome f l1 l2 l3 i x :
zip3_with f l1 l2 l3 !! i = Some x ↔
∃ x1 x2 x3,
l1 !! i = Some x1 ∧
l2 !! i = Some x2 ∧
l3 !! i = Some x3 ∧
x = f x1 x2 x3.
End zip3_with.
#[global] Hint Rewrite
@lengthーzip3_with
: simp_length.
Section zip3.
Context {A1 A2 A3 : Type}.
Definition zip3 :=
zip3_with (B := A1 × A2 × A3) $ λ x1 x2 x3,
(x1, x2, x3).
Lemma zip3ーcons x1 l1 x2 l2 x3 l3 :
zip3 (x1 :: l1) (x2 :: l2) (x3 :: l3) = (x1, x2, x3) :: zip3 l1 l2 l3.
Lemma lengthーzip3 l1 l2 l3 :
length l1 = length l2 →
length l1 = length l3 →
length (zip3 l1 l2 l3) = length l1.
Lemma zipーzip l1 l2 l3 :
zip (zip l1 l2) l3 = zip3 l1 l2 l3.
End zip3.
#[global] Hint Rewrite
@lengthーzip3
: simp_length.
Section foldri.
Implicit Type i : nat.
Fixpoint foldri' `(f : nat → A → B → B) acc l i :=
match l with
| [] ⇒
acc
| x :: l ⇒
f i x (foldri' f acc l ˖i)
end.
#[global] Arguments foldri' _ _ _ _ !_ _ / : assert.
Definition foldri `(f : nat → A → B → B) acc l :=
foldri' f acc l 0.
#[local] Lemma foldri'ーapp `(f : nat → A → B → B) acc l1 l2 i :
foldri' f acc (l1 ++ l2) i =
foldri' f (foldri' f acc l2 (i + (length l1))) l1 i.
Lemma foldriーapp `(f : nat → A → B → B) acc l1 l2 :
foldri f acc (l1 ++ l2) =
foldri f (foldri' f acc l2 (length l1)) l1.
#[local] Lemma foldri'ーfmap `(f : nat → A → B → B) `(g : C → A) acc l i :
foldri' f acc (g <$> l) i = foldri' (λ i x, f i (g x)) acc l i.
Lemma foldriーfmap `(f : nat → A → B → B) `(g : C → A) acc l :
foldri f acc (g <$> l) = foldri (λ i x, f i (g x)) acc l.
#[local] Lemma foldri'ーcomm `(f : nat → A → B → B) `(g : B → C) h acc l i :
( ∀ i x acc,
h i x (g acc) = g (f i x acc)
) →
foldri' h (g acc) l i = g (foldri' f acc l i).
Lemma foldriーcomm `(f : nat → A → B → B) `(g : B → C) h acc l :
( ∀ i x acc,
h i x (g acc) = g (f i x acc)
) →
foldri h (g acc) l = g (foldri f acc l).
End foldri.
Section foldr2.
Context {A1 A2 B : Type}.
Fixpoint foldr2 (f : A1 → A2 → B → B) acc l1 l2 :=
match l1 with
| [] ⇒
acc
| x1 :: l1 ⇒
match l2 with
| [] ⇒
acc
| x2 :: l2 ⇒
f x1 x2 (foldr2 f acc l1 l2)
end
end.
#[global] Arguments foldr2 _ _ !_ !_ / : assert.
Lemma foldr2ーapp f acc l11 l12 l21 l22 :
length l11 = length l21 →
foldr2 f acc (l11 ++ l12) (l21 ++ l22) =
foldr2 f (foldr2 f acc l12 l22) l11 l21.
End foldr2.
Section Forall.
Context `(P : A → Prop).
Lemma Forallーelem_of l x :
Forall P l →
x ∈ l →
P x.
End Forall.
Section Forall'.
Context `(P : A → Prop).
Fixpoint Forall' l :=
match l with
| [] ⇒
True
| x :: l ⇒
P x ∧ Forall' l
end.
#[global] Arguments Forall' !_ / : assert.
Lemma Forall'ーForall l :
Forall' l ↔ Forall P l.
End Forall'.
Section Foralli.
Context `(P : nat → A → Prop).
#[local] Fixpoint Foralli' l i :=
match l with
| [] ⇒
True
| x :: l ⇒
P i x ∧ Foralli' l ˖i
end.
#[global] Arguments Foralli' !_ _ / : assert.
Definition Foralli l :=
Foralli' l 0.
#[local] Lemma Foralli'ーlookup₁ l i j x :
Foralli' l i →
l !! j = Some x →
P (i + j) x.
Lemma Foralliーlookup₁ {l} i x :
Foralli l →
l !! i = Some x →
P i x.
Lemma Foralli'ーlookup₂ l i :
(∀ j x, l !! j = Some x → P (i + j) x) →
Foralli' l i.
Lemma Foralliーlookup₂ l :
(∀ i x, l !! i = Some x → P i x) →
Foralli l.
Lemma Foralliーlookup l :
Foralli l ↔
∀ i x, l !! i = Some x → P i x.
End Foralli.
Section Forall2.
Context `(P : A1 → A1 → Prop).
Lemma Forall2ーinsertーl {l1 l2} i x1 x2 :
l2 !! i = Some x2 →
Forall2 P l1 l2 →
P x1 x2 →
Forall2 P (<[i := x1]> l1) l2.
Lemma Forall2ーinsertーr {l1 l2} i x1 x2 :
l1 !! i = Some x1 →
Forall2 P l1 l2 →
P x1 x2 →
Forall2 P l1 (<[i := x2]> l2).
End Forall2.
Section Forall2'.
Context `(P : A1 → A2 → Prop).
Fixpoint Forall2' l1 l2 :=
match l1, l2 with
| [], [] ⇒
True
| x1 :: l1, x2 :: l2 ⇒
P x1 x2 ∧ Forall2' l1 l2
| _, _ ⇒
False
end.
#[global] Arguments Forall2' !_ !_ / : assert.
Lemma Forall2'ーForall2 l1 l2 :
Forall2' l1 l2 ↔ Forall2 P l1 l2.
#[global] Instance Forall2'ーdec `{!RelDecision P} :
RelDecision Forall2'.
Lemma Forall2'ーlength l1 l2 :
Forall2' l1 l2 →
length l1 = length l2.
End Forall2'.
Section Forall2'.
Context `(P : A → A → Prop).
Lemma Forall2'ーrefl :
(∀ x, P x x) →
Reflexive (Forall2' P).
#[global] Instance Forall2'ーreflexive `{!Reflexive P} :
Reflexive (Forall2' P).
Lemma Forall2'ーsym :
(∀ x1 x2, P x1 x2 → P x2 x1) →
Symmetric (Forall2' P).
#[global] Instance Forall2'ーsymmetric `{!Symmetric P} :
Symmetric (Forall2' P).
Lemma Forall2'ーtrans :
(∀ x1 x2 x3, P x1 x2 → P x2 x3 → P x1 x3) →
Transitive (Forall2' P).
#[global] Instance Forall2'ーtransitive `{!Transitive P} :
Transitive (Forall2' P).
End Forall2'.
Section Forall2i.
Context `(P : nat → A1 → A2 → Prop).
#[local] Fixpoint Forall2i' l1 l2 i :=
match l1, l2 with
| [], [] ⇒
True
| x1 :: l1, x2 :: l2 ⇒
P i x1 x2 ∧ Forall2i' l1 l2 ˖i
| _, _ ⇒
False
end.
#[global] Arguments Forall2i' !_ !_ _ / : assert.
Definition Forall2i l1 l2 :=
Forall2i' l1 l2 0.
#[local] Lemma Forall2i'ーlength l1 l2 i :
Forall2i' l1 l2 i →
length l1 = length l2.
Lemma Forall2iーlength l1 l2 :
Forall2i l1 l2 →
length l1 = length l2.
#[local] Lemma Forall2i'ーlookupーlr l1 l2 i j x1 x2 :
Forall2i' l1 l2 i →
l1 !! j = Some x1 →
l2 !! j = Some x2 →
P (i + j) x1 x2.
Lemma Forall2iーlookupーlr {l1 l2} i x1 x2 :
Forall2i l1 l2 →
l1 !! i = Some x1 →
l2 !! i = Some x2 →
P i x1 x2.
Lemma Forall2iーlookupーr l1 l2 i x1 :
Forall2i l1 l2 →
l1 !! i = Some x1 →
∃ x2,
l2 !! i = Some x2 ∧
P i x1 x2.
Lemma Forall2iーlookupーl l1 l2 i x2 :
Forall2i l1 l2 →
l2 !! i = Some x2 →
∃ x1,
l1 !! i = Some x1 ∧
P i x1 x2.
#[local] Lemma Forall2i'ーsame_lengthーlookup₂ l1 l2 i :
length l1 = length l2 →
( ∀ j x1 x2,
l1 !! j = Some x1 →
l2 !! j = Some x2 →
P (i + j) x1 x2
) →
Forall2i' l1 l2 i.
Lemma Forall2iーsame_lengthーlookup₂ l1 l2 :
length l1 = length l2 →
( ∀ i x1 x2,
l1 !! i = Some x1 →
l2 !! i = Some x2 →
P i x1 x2
) →
Forall2i l1 l2.
Lemma Forall2iーsame_lengthーlookup l1 l2 :
Forall2i l1 l2 ↔
length l1 = length l2 ∧
∀ i x1 x2,
l1 !! i = Some x1 →
l2 !! i = Some x2 →
P i x1 x2.
End Forall2i.
Section fmap.
Context {A B : Type}.
Implicit Type x : A.
Implicit Type 𝑥 : B.
Implicit Type l : list A.
Implicit Type 𝑙 : list B.
Implicit Type f : A → B.
Lemma fmapーappーconsーinv f l 𝑙1 𝑥 𝑙2 :
f <$> l = 𝑙1 ++ 𝑥 :: 𝑙2 →
∃ l1 x l2,
l = l1 ++ x :: l2 ∧
𝑙1 = f <$> l1 ∧
𝑥 = f x ∧
𝑙2 = f <$> l2.
Lemma fmapーsnocーinv f l 𝑙 𝑥 :
f <$> l = 𝑙 ++ [𝑥] →
∃ l' x,
l = l' ++ [x] ∧
𝑙 = f <$> l' ∧
𝑥 = f x.
Lemma listーfmapーaltーForall2ーl f 𝑙 l :
Forall2 (λ b a, b = f a) 𝑙 l →
𝑙 = f <$> l.
Lemma listーfmapーaltーForall2ーr f l 𝑙 :
Forall2 (λ a b, f a = b) l 𝑙 →
𝑙 = f <$> l.
End fmap.
Section Permutation.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l : list A.
#[global] Instance Permutationーdisjoint :
Proper (Permutation ==> Permutation ==> iff) (disjoint (A := list A)).
Lemma Permutationーswap' l i1 x1 i2 x2 :
l !! i1 = Some x1 →
l !! i2 = Some x2 →
<[i1 := x2]> (<[i2 := x1]> l) ≡ₚ l.
End Permutation.
Section slice.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l : list A.
Definition slice i n l :=
take n (drop i l).
Lemma sliceーcons i n x l :
l !! i = Some x →
x :: slice ˖i n l = slice i ˖n l.
Lemma sliceーcons' i n x l :
l !! i = Some x →
n ≠ 0 →
x :: slice ˖i (n - 1) l = slice i n l.
Lemma sliceーsnoc i n l x :
l !! (i + n) = Some x →
slice i n l ++ [x] = slice i ˖n l.
Lemma lengthーslice i n l :
length (slice i n l) = n `min` (length l - i).
Lemma lengthーslice' i n l :
i + n ≤ length l →
length (slice i n l) = n.
Lemma sliceーlookupーSomeーinv i n l k x :
slice i n l !! k = Some x →
k < n.
Lemma sliceー0 n l :
slice 0 n l = take n l.
End slice.
#[global] Hint Rewrite
@lengthーslice
: simp_length.
Section with_slice.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l s : list A.
Definition with_slice i n l s :=
take i l ++ s ++ drop (i + n) l.
Lemma lengthーwith_slice i n l s :
length (with_slice i n l s) = i `min` length l + length s + (length l - i - n).
Lemma lengthーwith_slice' i n l s :
i + n ≤ length l →
length s = n →
length (with_slice i n l s) = length l.
Lemma with_sliceー0 n l s :
with_slice 0 n l s = s ++ drop n l.
Lemma with_sliceーall n l s :
length l ≤ n →
with_slice 0 n l s = s.
Lemma with_sliceーappーl i n l1 l2 s :
i + n ≤ length l1 →
with_slice i n (l1 ++ l2) s = with_slice i n l1 s ++ l2.
Lemma with_sliceーappーr i n l1 l2 s :
length l1 ≤ i →
with_slice i n (l1 ++ l2) s = l1 ++ with_slice (i - length l1) n l2 s.
Lemma with_sliceーappーlength n l1 l2 s :
with_slice (length l1) n (l1 ++ l2) s = l1 ++ s ++ drop n l2.
Lemma with_sliceーappーlength' i n l1 l2 s :
i = length l1 →
with_slice i n (l1 ++ l2) s = l1 ++ s ++ drop n l2.
Lemma with_sliceーsliceーnil i l s :
with_slice i 0 l [] = l.
Lemma with_sliceーsliceーsnoc i n l s x :
i + n < length l →
length s = n →
with_slice i ˖n l (s ++ [x]) = <[i + n := x]> (with_slice i n l s).
Lemma with_sliceーlookupーleft {i n l s} k x :
l !! k = Some x →
k < i →
with_slice i n l s !! k = Some x.
Lemma with_sliceーlookupーmiddle {i n l s} k x :
s !! (k - i) = Some x →
i ≤ length l →
i ≤ k →
with_slice i n l s !! k = Some x.
Lemma with_sliceーlookupーmiddle' {i n l s} k1 k2 x :
s !! k2 = Some x →
k2 = k1 - i →
i ≤ length l →
i ≤ k1 →
with_slice i n l s !! k1 = Some x.
Lemma with_sliceーlookupーright {i n l s} k x :
l !! k = Some x →
length s = n →
i + n ≤ k →
with_slice i n l s !! k = Some x.
End with_slice.
#[global] Hint Rewrite
@lengthーwith_slice
: simp_length.
Section rotation.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l : list A.
Definition rotation n l :=
drop n l ++ take n l.
Lemma rotationー0 l :
rotation 0 l = l.
Lemma rotationーS n x l :
n ≤ length l →
rotation ˖n (x :: l) = rotation n (l ++ [x]).
Lemma rotationーadd n1 n2 l :
n1 + n2 = length l →
rotation n1 (rotation n2 l) = rotation (n1 + n2) l.
Lemma rotationーlength n l :
n = length l →
rotation n l = l.
Lemma rotationーPermutation n l :
rotation n l ≡ₚ l.
Lemma lengthーrotation n l :
length (rotation n l) = length l.
Lemma rotationーreplicate n k x :
rotation n (replicate k x) = replicate k x.
End rotation.
#[global] Hint Rewrite
@lengthーrotation
: simp_length.
Section omap.
Context {A : Type}.
Context {B : Type}.
Implicit Type x y : A.
Implicit Type 𝑥 𝑦 : B.
Implicit Type o : option B.
Implicit Type l : list A.
Implicit Type 𝑙 : list B.
Implicit Type f : A → option B.
Lemma lengthーomap f l :
length (omap f l) ≤ length l.
Lemma listーomapーinsertーNone {f l} i x1 x2 o :
l !! i = Some x1 →
f x1 = None →
f x2 = o →
omap f (<[i := x2]> l) ≡ₚ
match o with
| None ⇒
id
| Some 𝑥 ⇒
cons 𝑥
end $
omap f l.
Lemma listーomapーinsertーNoneーSome {f l} i x1 x2 𝑥 :
l !! i = Some x1 →
f x1 = None →
f x2 = Some 𝑥 →
omap f (<[i := x2]> l) ≡ₚ 𝑥 :: omap f l.
Lemma listーomapーinsertーNoneーNone {f l} i x1 x2 :
l !! i = Some x1 →
f x1 = None →
f x2 = None →
omap f (<[i := x2]> l) ≡ₚ omap f l.
Lemma listーomapーinsertーSomeーNone {f l} i x1 𝑥 x2 :
l !! i = Some x1 →
f x1 = Some 𝑥 →
f x2 = None →
omap f (<[i := x2]> l) = delete (length $ omap f $ take i l) (omap f l).
End omap.
#[global] Hint Rewrite
@lengthーomap
: simp_length.
Section oflatten.
Context {A : Type}.
Implicit Type x y : A.
Implicit Type o : option A.
Implicit Type l : list (option A).
Definition oflatten l :=
omap id l.
Lemma lengthーoflatten l :
length (oflatten l) ≤ length l.
Lemma oflattenーcons o l :
oflatten (o :: l) = from_option (λ x, [x]) [] o ++ oflatten l.
Lemma oflattenーconsーNone l :
oflatten (None :: l) = oflatten l.
Lemma oflattenーconsーSome x l :
oflatten (Some x :: l) = x :: oflatten l.
Lemma oflattenーapp l1 l2 :
oflatten (l1 ++ l2) = oflatten l1 ++ oflatten l2.
Lemma oflattenーsnoc l o :
oflatten (l ++ [o]) = oflatten l ++ from_option (λ x, [x]) [] o.
Lemma oflattenーsnocーNone l :
oflatten (l ++ [None]) = oflatten l.
Lemma oflattenーsnocーSome l x :
oflatten (l ++ [Some x]) = oflatten l ++ [x].
Lemma elem_ofーoflatten l x :
x ∈ oflatten l ↔
Some x ∈ l.
Lemma oflattenーlookupーSome l i x :
l !! i = Some $ Some x →
oflatten l !! (length $ oflatten $ take i l) = Some x.
Lemma oflattenーinsertーNone {l} i o :
l !! i = Some None →
oflatten (<[i := o]> l) ≡ₚ
match o with
| None ⇒
id
| Some x ⇒
cons x
end $
oflatten l.
Lemma oflattenーinsertーNoneーSome {l} i x :
l !! i = Some None →
oflatten (<[i := Some x]> l) ≡ₚ x :: oflatten l.
Lemma oflattenーinsertーNoneーNone {l} i x :
l !! i = Some None →
oflatten (<[i := None]> l) ≡ₚ oflatten l.
Lemma oflattenーinsertーSomeーNone {l} i x :
l !! i = Some $ Some x →
oflatten (<[i := None]> l) = delete (length $ oflatten $ take i l) (oflatten l).
End oflatten.
#[global] Hint Rewrite
@lengthーoflatten
: simp_length.
Section Sorted.
Context `(R : A → A → Prop).
Implicit Type x : A.
Implicit Type l : list A.
Lemma StronglySortedーnil :
StronglySorted R [].
Lemma StronglySortedーsingleton x :
StronglySorted R [x].
Lemma StronglySortedーtrivial l :
length l ≤ 1 →
StronglySorted R l.
Lemma StronglySortedーappーcons `{!Transitive R} l1 x l2 :
StronglySorted R l1 →
Forall (flip R x) l1 →
Forall (R x) l2 →
StronglySorted R l2 →
StronglySorted R (l1 ++ x :: l2).
End Sorted.
Require stdpp.list.
Require stdpp.sorting.
Require Import zoo.prelude.
Require Import zoo.common.math.
Require Import zoo.options.
Export stdpp.list.
Export stdpp.sorting.
Create HintDb simp_length.
#[global] Hint Rewrite
@length_reverse
@length_app
@length_insert
@length_take
@length_drop
@length_fmap
@length_replicate
@length_seq
@length_seqZ
@length_zip_with
: simp_length.
Tactic Notation "simp_length" :=
autorewrite with simp_length; try done.
Tactic Notation "simp_length" "/=" :=
repeat (progress csimpl in × || simp_length).
Tactic Notation "simp_length" "in" ne_hyp_list(Hs) :=
autorewrite with simp_length in Hs; try done.
Tactic Notation "simp_length" "/=" "in" ne_hyp_list(Hs) :=
repeat (progress csimpl in × || simp_length in Hs).
Tactic Notation "simp_length" "in" "*" :=
autorewrite with simp_length in *; try done.
Tactic Notation "simp_length" "/=" "in" "*" :=
repeat (progress csimpl in × || simp_length in × ).
Module lengths.
Import Ltac2.
Ltac2 main () :=
Control.enter (fun () ⇒
List.iter (fun (hyp, _, ty) ⇒
lazy_match! ty with
| _ = _ ⇒
try (apply (f_equal length) in $hyp as ?)
| _ ≡ₚ _ ⇒
apply Permutation_length in $hyp as ?
| _ ⊆+ _ ⇒
apply submseteq_length in $hyp as ?
| _ `prefix_of` _ ⇒
apply prefix_length in $hyp as ?
| _ ⇒
()
end
) (Control.hyps ())
).
End lengths.
Tactic Notation "lengths" :=
ltac2:(lengths.main ());
simp_length in ×.
Tactic Notation "lengths" "/=" :=
ltac2:(lengths.main ());
simp_length/= in ×.
Section basic.
Context {A : Type}.
Implicit Type x y z : A.
Implicit Type l : list A.
Lemma listーeq l1 l2 :
l1 = l2 ↔
length l1 = length l2 ∧
∀ i x1 x2,
l1 !! i = Some x1 →
l2 !! i = Some x2 →
x1 = x2.
Lemma appーnotーnil l1 l2 :
l1 ≠ [] ∨ l2 ≠ [] →
l1 ++ l2 ≠ [].
Lemma appーnotーnilーl l1 l2 :
l1 ≠ [] →
l1 ++ l2 ≠ [].
Lemma appーnotーnilーr l1 l2 :
l2 ≠ [] →
l1 ++ l2 ≠ [].
Lemma lookupーappーrーSome l1 l2 i y :
length l1 ≤ i →
l2 !! (i - length l1) = Some y →
(l1 ++ l2) !! i = Some y.
Lemma lookupーconsーrーSome x l i y :
0 < i →
l !! (i - 1) = Some y →
(x :: l) !! i = Some y.
Lemma elem_ofーappーl l1 l2 x :
x ∈ l1 →
x ∈ l1 ++ l2.
Lemma elem_ofーappーr l1 l2 x :
x ∈ l2 →
x ∈ l1 ++ l2.
Lemma reverseーnilーiff l :
reverse l = [] ↔
l = [].
Lemma foldrーinsertーstrong `(f : A → B → B) comp l i x y acc :
l !! i = Some x →
( ∀ x acc,
f x (f y acc) = f y (f x acc)
) →
( ∀ acc,
f (comp y x) acc = f y (f x acc)
) →
foldr f acc (<[i := comp y x]> l) = f y (foldr f acc l).
Lemma foldrーinsertーstrong' op `{!Assoc (=) op} `{!Comm (=) op} comp l i x y acc :
l !! i = Some x →
( ∀ acc,
op (comp y x) acc = op y (op x acc)
) →
foldr op acc (<[i := comp y x]> l) = op y (foldr op acc l).
Lemma foldrーinsert op `{!Assoc (=) op} `{!Comm (=) op} l i x y acc :
l !! i = Some x →
foldr op acc (<[i := op y x]> l) = op y (foldr op acc l).
Lemma lengthーlookupーlast l i :
is_Some (l !! i) →
l !! ˖i = None →
length l = ˖i.
Lemma tailーapp l1 l2 :
l1 ≠ [] →
tail (l1 ++ l2) = tail l1 ++ l2.
Lemma lengthーtail l :
length (tail l) ≤ length l.
Lemma headーapp l1 l2 :
0 < length l1 →
head (l1 ++ l2) = head l1.
Lemma headーappーcons l1 x l2 :
head (l1 ++ x :: l2) = head (l1 ++ [x]).
Lemma headーdropーSome l i x :
l !! i = Some x →
head (drop i l) = Some x.
Lemma headーdrop l i :
head (drop i l) = l !! i.
Lemma hdーcorrect default l x :
0 < length l →
hd default l = x →
head l = Some x.
Lemma hdーapp default l1 l2 :
0 < length l1 →
hd default (l1 ++ l2) = hd default l1.
Lemma hdーappーcons default l1 x l2 :
hd default (l1 ++ x :: l2) = hd default (l1 ++ [x]).
Lemma hdーdropーSome default l i x :
l !! i = Some x →
hd default (drop i l) = x.
Lemma lastーcons' x l :
last (x :: l) = Some $ default x (last l).
Lemma lastーtake l i x :
l !! i = Some x →
last (take ˖i l) = Some x.
Lemma lastーtake' l i :
is_Some (l !! i) →
last (take i l) = nat۰elim None (l !!.) i.
Lemma lastーremovelast l x :
last l = Some x →
l = removelast l ++ [x].
Lemma dropーlookupーNone l i :
l !! i = None →
drop i l = [].
Lemma dropーconsーinv i l x l' :
drop i l = x :: l' →
l !! i = Some x ∧
l' = drop ˖i l.
Lemma insertーconsーl i x y l :
i = 0 →
<[i := x]> (y :: l) = x :: l.
Lemma insertーconsーr i x y l :
0 < i →
<[i := x]> (y :: l) = y :: <[i - 1 := x]> l.
Lemma insertーappーrー0 i x l1 l2 :
i = length l1 →
<[i := x]> (l1 ++ l2) = l1 ++ <[0 := x]> l2.
Lemma listーdeleteーinsertーeq l i x :
i < length l →
delete i (<[i := x]> l) = delete i l.
End basic.
Section suffix.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l : list A.
Lemma suffixーtail l1 l2 :
l1 `suffix_of` l2 →
tail l1 `suffix_of` l2.
Lemma suffixーfmap `(f : A → B) `{!Inj (=) (=) f} l1 l2 :
suffix (f <$> l1) (f <$> l2) →
suffix l1 l2.
End suffix.
Section seqZ.
Lemma seqZーprefix {i n1} n2 :
(0 ≤ n2 ≤ n1)%Z →
seqZ i n2 `prefix_of` seqZ i n1.
Lemma seqZーsuffix {i1 n1} i2 n2 :
(i1 ≤ i2 ≤ i1 + n1)%Z →
(i2 - i1 = n1 - n2)%Z →
seqZ i2 n2 `suffix_of` seqZ i1 n1.
End seqZ.
Section zip.
Context {A1 A2 : Type}.
Lemma prod_mapーzip {B1 B2} (f1 : A1 → B1) (f2 : A2 → B2) l1 l2 :
prod_map f1 f2 <$> (zip l1 l2) = zip (f1 <$> l1) (f2 <$> l2).
End zip.
Section zip3_with.
Context {A1 A2 A3 B : Type}.
Implicit Type f : A1 → A2 → A3 → B.
Fixpoint zip3_with f l1 l2 l3 :=
match l1, l2, l3 with
| x1 :: l1, x2 :: l2, x3 :: l3 ⇒
f x1 x2 x3 :: zip3_with f l1 l2 l3
| _, _, _ ⇒
[]
end.
#[global] Arguments zip3_with _ !_ !_ !_ / : assert.
Lemma lengthーzip3_with f l1 l2 l3 :
length l1 = length l2 →
length l1 = length l3 →
length (zip3_with f l1 l2 l3) = length l1.
Lemma lookupーzip3_withーSome f l1 l2 l3 i x :
zip3_with f l1 l2 l3 !! i = Some x ↔
∃ x1 x2 x3,
l1 !! i = Some x1 ∧
l2 !! i = Some x2 ∧
l3 !! i = Some x3 ∧
x = f x1 x2 x3.
End zip3_with.
#[global] Hint Rewrite
@lengthーzip3_with
: simp_length.
Section zip3.
Context {A1 A2 A3 : Type}.
Definition zip3 :=
zip3_with (B := A1 × A2 × A3) $ λ x1 x2 x3,
(x1, x2, x3).
Lemma zip3ーcons x1 l1 x2 l2 x3 l3 :
zip3 (x1 :: l1) (x2 :: l2) (x3 :: l3) = (x1, x2, x3) :: zip3 l1 l2 l3.
Lemma lengthーzip3 l1 l2 l3 :
length l1 = length l2 →
length l1 = length l3 →
length (zip3 l1 l2 l3) = length l1.
Lemma zipーzip l1 l2 l3 :
zip (zip l1 l2) l3 = zip3 l1 l2 l3.
End zip3.
#[global] Hint Rewrite
@lengthーzip3
: simp_length.
Section foldri.
Implicit Type i : nat.
Fixpoint foldri' `(f : nat → A → B → B) acc l i :=
match l with
| [] ⇒
acc
| x :: l ⇒
f i x (foldri' f acc l ˖i)
end.
#[global] Arguments foldri' _ _ _ _ !_ _ / : assert.
Definition foldri `(f : nat → A → B → B) acc l :=
foldri' f acc l 0.
#[local] Lemma foldri'ーapp `(f : nat → A → B → B) acc l1 l2 i :
foldri' f acc (l1 ++ l2) i =
foldri' f (foldri' f acc l2 (i + (length l1))) l1 i.
Lemma foldriーapp `(f : nat → A → B → B) acc l1 l2 :
foldri f acc (l1 ++ l2) =
foldri f (foldri' f acc l2 (length l1)) l1.
#[local] Lemma foldri'ーfmap `(f : nat → A → B → B) `(g : C → A) acc l i :
foldri' f acc (g <$> l) i = foldri' (λ i x, f i (g x)) acc l i.
Lemma foldriーfmap `(f : nat → A → B → B) `(g : C → A) acc l :
foldri f acc (g <$> l) = foldri (λ i x, f i (g x)) acc l.
#[local] Lemma foldri'ーcomm `(f : nat → A → B → B) `(g : B → C) h acc l i :
( ∀ i x acc,
h i x (g acc) = g (f i x acc)
) →
foldri' h (g acc) l i = g (foldri' f acc l i).
Lemma foldriーcomm `(f : nat → A → B → B) `(g : B → C) h acc l :
( ∀ i x acc,
h i x (g acc) = g (f i x acc)
) →
foldri h (g acc) l = g (foldri f acc l).
End foldri.
Section foldr2.
Context {A1 A2 B : Type}.
Fixpoint foldr2 (f : A1 → A2 → B → B) acc l1 l2 :=
match l1 with
| [] ⇒
acc
| x1 :: l1 ⇒
match l2 with
| [] ⇒
acc
| x2 :: l2 ⇒
f x1 x2 (foldr2 f acc l1 l2)
end
end.
#[global] Arguments foldr2 _ _ !_ !_ / : assert.
Lemma foldr2ーapp f acc l11 l12 l21 l22 :
length l11 = length l21 →
foldr2 f acc (l11 ++ l12) (l21 ++ l22) =
foldr2 f (foldr2 f acc l12 l22) l11 l21.
End foldr2.
Section Forall.
Context `(P : A → Prop).
Lemma Forallーelem_of l x :
Forall P l →
x ∈ l →
P x.
End Forall.
Section Forall'.
Context `(P : A → Prop).
Fixpoint Forall' l :=
match l with
| [] ⇒
True
| x :: l ⇒
P x ∧ Forall' l
end.
#[global] Arguments Forall' !_ / : assert.
Lemma Forall'ーForall l :
Forall' l ↔ Forall P l.
End Forall'.
Section Foralli.
Context `(P : nat → A → Prop).
#[local] Fixpoint Foralli' l i :=
match l with
| [] ⇒
True
| x :: l ⇒
P i x ∧ Foralli' l ˖i
end.
#[global] Arguments Foralli' !_ _ / : assert.
Definition Foralli l :=
Foralli' l 0.
#[local] Lemma Foralli'ーlookup₁ l i j x :
Foralli' l i →
l !! j = Some x →
P (i + j) x.
Lemma Foralliーlookup₁ {l} i x :
Foralli l →
l !! i = Some x →
P i x.
Lemma Foralli'ーlookup₂ l i :
(∀ j x, l !! j = Some x → P (i + j) x) →
Foralli' l i.
Lemma Foralliーlookup₂ l :
(∀ i x, l !! i = Some x → P i x) →
Foralli l.
Lemma Foralliーlookup l :
Foralli l ↔
∀ i x, l !! i = Some x → P i x.
End Foralli.
Section Forall2.
Context `(P : A1 → A1 → Prop).
Lemma Forall2ーinsertーl {l1 l2} i x1 x2 :
l2 !! i = Some x2 →
Forall2 P l1 l2 →
P x1 x2 →
Forall2 P (<[i := x1]> l1) l2.
Lemma Forall2ーinsertーr {l1 l2} i x1 x2 :
l1 !! i = Some x1 →
Forall2 P l1 l2 →
P x1 x2 →
Forall2 P l1 (<[i := x2]> l2).
End Forall2.
Section Forall2'.
Context `(P : A1 → A2 → Prop).
Fixpoint Forall2' l1 l2 :=
match l1, l2 with
| [], [] ⇒
True
| x1 :: l1, x2 :: l2 ⇒
P x1 x2 ∧ Forall2' l1 l2
| _, _ ⇒
False
end.
#[global] Arguments Forall2' !_ !_ / : assert.
Lemma Forall2'ーForall2 l1 l2 :
Forall2' l1 l2 ↔ Forall2 P l1 l2.
#[global] Instance Forall2'ーdec `{!RelDecision P} :
RelDecision Forall2'.
Lemma Forall2'ーlength l1 l2 :
Forall2' l1 l2 →
length l1 = length l2.
End Forall2'.
Section Forall2'.
Context `(P : A → A → Prop).
Lemma Forall2'ーrefl :
(∀ x, P x x) →
Reflexive (Forall2' P).
#[global] Instance Forall2'ーreflexive `{!Reflexive P} :
Reflexive (Forall2' P).
Lemma Forall2'ーsym :
(∀ x1 x2, P x1 x2 → P x2 x1) →
Symmetric (Forall2' P).
#[global] Instance Forall2'ーsymmetric `{!Symmetric P} :
Symmetric (Forall2' P).
Lemma Forall2'ーtrans :
(∀ x1 x2 x3, P x1 x2 → P x2 x3 → P x1 x3) →
Transitive (Forall2' P).
#[global] Instance Forall2'ーtransitive `{!Transitive P} :
Transitive (Forall2' P).
End Forall2'.
Section Forall2i.
Context `(P : nat → A1 → A2 → Prop).
#[local] Fixpoint Forall2i' l1 l2 i :=
match l1, l2 with
| [], [] ⇒
True
| x1 :: l1, x2 :: l2 ⇒
P i x1 x2 ∧ Forall2i' l1 l2 ˖i
| _, _ ⇒
False
end.
#[global] Arguments Forall2i' !_ !_ _ / : assert.
Definition Forall2i l1 l2 :=
Forall2i' l1 l2 0.
#[local] Lemma Forall2i'ーlength l1 l2 i :
Forall2i' l1 l2 i →
length l1 = length l2.
Lemma Forall2iーlength l1 l2 :
Forall2i l1 l2 →
length l1 = length l2.
#[local] Lemma Forall2i'ーlookupーlr l1 l2 i j x1 x2 :
Forall2i' l1 l2 i →
l1 !! j = Some x1 →
l2 !! j = Some x2 →
P (i + j) x1 x2.
Lemma Forall2iーlookupーlr {l1 l2} i x1 x2 :
Forall2i l1 l2 →
l1 !! i = Some x1 →
l2 !! i = Some x2 →
P i x1 x2.
Lemma Forall2iーlookupーr l1 l2 i x1 :
Forall2i l1 l2 →
l1 !! i = Some x1 →
∃ x2,
l2 !! i = Some x2 ∧
P i x1 x2.
Lemma Forall2iーlookupーl l1 l2 i x2 :
Forall2i l1 l2 →
l2 !! i = Some x2 →
∃ x1,
l1 !! i = Some x1 ∧
P i x1 x2.
#[local] Lemma Forall2i'ーsame_lengthーlookup₂ l1 l2 i :
length l1 = length l2 →
( ∀ j x1 x2,
l1 !! j = Some x1 →
l2 !! j = Some x2 →
P (i + j) x1 x2
) →
Forall2i' l1 l2 i.
Lemma Forall2iーsame_lengthーlookup₂ l1 l2 :
length l1 = length l2 →
( ∀ i x1 x2,
l1 !! i = Some x1 →
l2 !! i = Some x2 →
P i x1 x2
) →
Forall2i l1 l2.
Lemma Forall2iーsame_lengthーlookup l1 l2 :
Forall2i l1 l2 ↔
length l1 = length l2 ∧
∀ i x1 x2,
l1 !! i = Some x1 →
l2 !! i = Some x2 →
P i x1 x2.
End Forall2i.
Section fmap.
Context {A B : Type}.
Implicit Type x : A.
Implicit Type 𝑥 : B.
Implicit Type l : list A.
Implicit Type 𝑙 : list B.
Implicit Type f : A → B.
Lemma fmapーappーconsーinv f l 𝑙1 𝑥 𝑙2 :
f <$> l = 𝑙1 ++ 𝑥 :: 𝑙2 →
∃ l1 x l2,
l = l1 ++ x :: l2 ∧
𝑙1 = f <$> l1 ∧
𝑥 = f x ∧
𝑙2 = f <$> l2.
Lemma fmapーsnocーinv f l 𝑙 𝑥 :
f <$> l = 𝑙 ++ [𝑥] →
∃ l' x,
l = l' ++ [x] ∧
𝑙 = f <$> l' ∧
𝑥 = f x.
Lemma listーfmapーaltーForall2ーl f 𝑙 l :
Forall2 (λ b a, b = f a) 𝑙 l →
𝑙 = f <$> l.
Lemma listーfmapーaltーForall2ーr f l 𝑙 :
Forall2 (λ a b, f a = b) l 𝑙 →
𝑙 = f <$> l.
End fmap.
Section Permutation.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l : list A.
#[global] Instance Permutationーdisjoint :
Proper (Permutation ==> Permutation ==> iff) (disjoint (A := list A)).
Lemma Permutationーswap' l i1 x1 i2 x2 :
l !! i1 = Some x1 →
l !! i2 = Some x2 →
<[i1 := x2]> (<[i2 := x1]> l) ≡ₚ l.
End Permutation.
Section slice.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l : list A.
Definition slice i n l :=
take n (drop i l).
Lemma sliceーcons i n x l :
l !! i = Some x →
x :: slice ˖i n l = slice i ˖n l.
Lemma sliceーcons' i n x l :
l !! i = Some x →
n ≠ 0 →
x :: slice ˖i (n - 1) l = slice i n l.
Lemma sliceーsnoc i n l x :
l !! (i + n) = Some x →
slice i n l ++ [x] = slice i ˖n l.
Lemma lengthーslice i n l :
length (slice i n l) = n `min` (length l - i).
Lemma lengthーslice' i n l :
i + n ≤ length l →
length (slice i n l) = n.
Lemma sliceーlookupーSomeーinv i n l k x :
slice i n l !! k = Some x →
k < n.
Lemma sliceー0 n l :
slice 0 n l = take n l.
End slice.
#[global] Hint Rewrite
@lengthーslice
: simp_length.
Section with_slice.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l s : list A.
Definition with_slice i n l s :=
take i l ++ s ++ drop (i + n) l.
Lemma lengthーwith_slice i n l s :
length (with_slice i n l s) = i `min` length l + length s + (length l - i - n).
Lemma lengthーwith_slice' i n l s :
i + n ≤ length l →
length s = n →
length (with_slice i n l s) = length l.
Lemma with_sliceー0 n l s :
with_slice 0 n l s = s ++ drop n l.
Lemma with_sliceーall n l s :
length l ≤ n →
with_slice 0 n l s = s.
Lemma with_sliceーappーl i n l1 l2 s :
i + n ≤ length l1 →
with_slice i n (l1 ++ l2) s = with_slice i n l1 s ++ l2.
Lemma with_sliceーappーr i n l1 l2 s :
length l1 ≤ i →
with_slice i n (l1 ++ l2) s = l1 ++ with_slice (i - length l1) n l2 s.
Lemma with_sliceーappーlength n l1 l2 s :
with_slice (length l1) n (l1 ++ l2) s = l1 ++ s ++ drop n l2.
Lemma with_sliceーappーlength' i n l1 l2 s :
i = length l1 →
with_slice i n (l1 ++ l2) s = l1 ++ s ++ drop n l2.
Lemma with_sliceーsliceーnil i l s :
with_slice i 0 l [] = l.
Lemma with_sliceーsliceーsnoc i n l s x :
i + n < length l →
length s = n →
with_slice i ˖n l (s ++ [x]) = <[i + n := x]> (with_slice i n l s).
Lemma with_sliceーlookupーleft {i n l s} k x :
l !! k = Some x →
k < i →
with_slice i n l s !! k = Some x.
Lemma with_sliceーlookupーmiddle {i n l s} k x :
s !! (k - i) = Some x →
i ≤ length l →
i ≤ k →
with_slice i n l s !! k = Some x.
Lemma with_sliceーlookupーmiddle' {i n l s} k1 k2 x :
s !! k2 = Some x →
k2 = k1 - i →
i ≤ length l →
i ≤ k1 →
with_slice i n l s !! k1 = Some x.
Lemma with_sliceーlookupーright {i n l s} k x :
l !! k = Some x →
length s = n →
i + n ≤ k →
with_slice i n l s !! k = Some x.
End with_slice.
#[global] Hint Rewrite
@lengthーwith_slice
: simp_length.
Section rotation.
Context {A : Type}.
Implicit Type x : A.
Implicit Type l : list A.
Definition rotation n l :=
drop n l ++ take n l.
Lemma rotationー0 l :
rotation 0 l = l.
Lemma rotationーS n x l :
n ≤ length l →
rotation ˖n (x :: l) = rotation n (l ++ [x]).
Lemma rotationーadd n1 n2 l :
n1 + n2 = length l →
rotation n1 (rotation n2 l) = rotation (n1 + n2) l.
Lemma rotationーlength n l :
n = length l →
rotation n l = l.
Lemma rotationーPermutation n l :
rotation n l ≡ₚ l.
Lemma lengthーrotation n l :
length (rotation n l) = length l.
Lemma rotationーreplicate n k x :
rotation n (replicate k x) = replicate k x.
End rotation.
#[global] Hint Rewrite
@lengthーrotation
: simp_length.
Section omap.
Context {A : Type}.
Context {B : Type}.
Implicit Type x y : A.
Implicit Type 𝑥 𝑦 : B.
Implicit Type o : option B.
Implicit Type l : list A.
Implicit Type 𝑙 : list B.
Implicit Type f : A → option B.
Lemma lengthーomap f l :
length (omap f l) ≤ length l.
Lemma listーomapーinsertーNone {f l} i x1 x2 o :
l !! i = Some x1 →
f x1 = None →
f x2 = o →
omap f (<[i := x2]> l) ≡ₚ
match o with
| None ⇒
id
| Some 𝑥 ⇒
cons 𝑥
end $
omap f l.
Lemma listーomapーinsertーNoneーSome {f l} i x1 x2 𝑥 :
l !! i = Some x1 →
f x1 = None →
f x2 = Some 𝑥 →
omap f (<[i := x2]> l) ≡ₚ 𝑥 :: omap f l.
Lemma listーomapーinsertーNoneーNone {f l} i x1 x2 :
l !! i = Some x1 →
f x1 = None →
f x2 = None →
omap f (<[i := x2]> l) ≡ₚ omap f l.
Lemma listーomapーinsertーSomeーNone {f l} i x1 𝑥 x2 :
l !! i = Some x1 →
f x1 = Some 𝑥 →
f x2 = None →
omap f (<[i := x2]> l) = delete (length $ omap f $ take i l) (omap f l).
End omap.
#[global] Hint Rewrite
@lengthーomap
: simp_length.
Section oflatten.
Context {A : Type}.
Implicit Type x y : A.
Implicit Type o : option A.
Implicit Type l : list (option A).
Definition oflatten l :=
omap id l.
Lemma lengthーoflatten l :
length (oflatten l) ≤ length l.
Lemma oflattenーcons o l :
oflatten (o :: l) = from_option (λ x, [x]) [] o ++ oflatten l.
Lemma oflattenーconsーNone l :
oflatten (None :: l) = oflatten l.
Lemma oflattenーconsーSome x l :
oflatten (Some x :: l) = x :: oflatten l.
Lemma oflattenーapp l1 l2 :
oflatten (l1 ++ l2) = oflatten l1 ++ oflatten l2.
Lemma oflattenーsnoc l o :
oflatten (l ++ [o]) = oflatten l ++ from_option (λ x, [x]) [] o.
Lemma oflattenーsnocーNone l :
oflatten (l ++ [None]) = oflatten l.
Lemma oflattenーsnocーSome l x :
oflatten (l ++ [Some x]) = oflatten l ++ [x].
Lemma elem_ofーoflatten l x :
x ∈ oflatten l ↔
Some x ∈ l.
Lemma oflattenーlookupーSome l i x :
l !! i = Some $ Some x →
oflatten l !! (length $ oflatten $ take i l) = Some x.
Lemma oflattenーinsertーNone {l} i o :
l !! i = Some None →
oflatten (<[i := o]> l) ≡ₚ
match o with
| None ⇒
id
| Some x ⇒
cons x
end $
oflatten l.
Lemma oflattenーinsertーNoneーSome {l} i x :
l !! i = Some None →
oflatten (<[i := Some x]> l) ≡ₚ x :: oflatten l.
Lemma oflattenーinsertーNoneーNone {l} i x :
l !! i = Some None →
oflatten (<[i := None]> l) ≡ₚ oflatten l.
Lemma oflattenーinsertーSomeーNone {l} i x :
l !! i = Some $ Some x →
oflatten (<[i := None]> l) = delete (length $ oflatten $ take i l) (oflatten l).
End oflatten.
#[global] Hint Rewrite
@lengthーoflatten
: simp_length.
Section Sorted.
Context `(R : A → A → Prop).
Implicit Type x : A.
Implicit Type l : list A.
Lemma StronglySortedーnil :
StronglySorted R [].
Lemma StronglySortedーsingleton x :
StronglySorted R [x].
Lemma StronglySortedーtrivial l :
length l ≤ 1 →
StronglySorted R l.
Lemma StronglySortedーappーcons `{!Transitive R} l1 x l2 :
StronglySorted R l1 →
Forall (flip R x) l1 →
Forall (R x) l2 →
StronglySorted R l2 →
StronglySorted R (l1 ++ x :: l2).
End Sorted.