Compare commits

...

29 Commits

Author SHA1 Message Date
Kim Morrison
02ef843981 fix 2025-03-25 22:22:37 +11:00
Kim Morrison
cdeee2d301 fix tests 2025-03-25 21:28:53 +11:00
Kim Morrison
1b3473c093 fix 2025-03-25 19:49:51 +11:00
Kim Morrison
085a87986b fix 2025-03-25 19:20:44 +11:00
Kim Morrison
90f8efdd50 fix 2025-03-25 19:15:40 +11:00
Kim Morrison
2c86c7a7de fixes 2025-03-25 19:10:02 +11:00
Kim Morrison
3677c3cc77 fixes 2025-03-25 18:56:06 +11:00
Kim Morrison
23857e93a4 fixing tests blind 2025-03-25 18:43:46 +11:00
Kim Morrison
0d68c3baba fixes 2025-03-25 17:39:36 +11:00
Kim Morrison
d1deff0ba7 zip 2025-03-25 17:36:58 +11:00
Kim Morrison
59abc1cfdc TakeDrop 2025-03-25 17:24:14 +11:00
Kim Morrison
dd8fc3f349 range 2025-03-25 16:49:12 +11:00
Kim Morrison
0df4175565 monadic 2025-03-25 16:10:13 +11:00
Kim Morrison
a800ad7efc mapIdx 2025-03-25 15:57:49 +11:00
Kim Morrison
880dfff899 insertIdx 2025-03-25 15:50:31 +11:00
Kim Morrison
72d55dedd6 finRange 2025-03-25 15:33:10 +11:00
Kim Morrison
978a630bb5 fix 2025-03-25 15:33:07 +11:00
Kim Morrison
d9ce8273d4 find 2025-03-25 15:30:48 +11:00
Kim Morrison
af709ffce6 erase 2025-03-25 15:11:01 +11:00
Kim Morrison
b2669302c2 count 2025-03-25 14:54:01 +11:00
Kim Morrison
28233d2312 Attach 2025-03-25 14:10:18 +11:00
Kim Morrison
dcaffbb3dc Lex 2025-03-25 13:30:04 +11:00
Kim Morrison
e99370ec6b fixes 2025-03-25 13:24:29 +11:00
Kim Morrison
5cd9afbcf6 fixes 2025-03-25 13:18:46 +11:00
Kim Morrison
f158d8ce46 Vector.Lemmas 2025-03-25 13:08:54 +11:00
Kim Morrison
321bdfbfb3 Array.Lemmas 2025-03-25 12:20:42 +11:00
Kim Morrison
792a6246d3 List/Lemmas.lean 2025-03-25 11:29:53 +11:00
Kim Morrison
538f79a788 fixes 2025-03-25 11:29:14 +11:00
Kim Morrison
e0b51b527d Array.Basic(Aux) 2025-03-25 11:29:14 +11:00
80 changed files with 2385 additions and 2320 deletions

View File

@@ -109,7 +109,7 @@ well-founded recursion mechanism to prove that the function terminates.
simp
@[simp]
theorem pmap_eq_map (p : α Prop) (f : α β) (xs : Array α) (H) :
theorem pmap_eq_map {p : α Prop} {f : α β} {xs : Array α} (H) :
@pmap _ _ p (fun a _ => f a) xs H = map f xs := by
cases xs; simp
@@ -120,13 +120,13 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a,
simp only [List.pmap_toArray, mk.injEq]
rw [List.pmap_congr_left _ h]
theorem map_pmap {p : α Prop} (g : β γ) (f : a, p a β) (xs H) :
theorem map_pmap {p : α Prop} {g : β γ} {f : a, p a β} {xs : Array α} (H) :
map g (pmap f xs H) = pmap (fun a h => g (f a h)) xs H := by
cases xs
simp [List.map_pmap]
theorem pmap_map {p : β Prop} (g : b, p b γ) (f : α β) (xs H) :
pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem _ h) := by
theorem pmap_map {p : β Prop} {g : b, p b γ} {f : α β} {xs : Array α} (H) :
pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem h) := by
cases xs
simp [List.pmap_map]
@@ -153,13 +153,13 @@ theorem attachWith_congr {xs ys : Array α} (w : xs = ys) {P : α → Prop} {H :
cases xs
simp [attachWith_congr (List.push_toArray _ _)]
theorem pmap_eq_map_attach {p : α Prop} (f : a, p a β) (xs H) :
theorem pmap_eq_map_attach {p : α Prop} {f : a, p a β} {xs : Array α} (H) :
pmap f xs H = xs.attach.map fun x => f x.1 (H _ x.2) := by
cases xs
simp [List.pmap_eq_map_attach]
@[simp]
theorem pmap_eq_attachWith {p q : α Prop} (f : a, p a q a) (xs H) :
theorem pmap_eq_attachWith {p q : α Prop} {f : a, p a q a} {xs : Array α} (H) :
pmap (fun a h => a, f a h) xs H = xs.attachWith q (fun x h => f x (H x h)) := by
cases xs
simp [List.pmap_eq_attachWith]
@@ -172,17 +172,18 @@ theorem attach_map_val (xs : Array α) (f : α → β) :
@[deprecated attach_map_val (since := "2025-02-17")]
abbrev attach_map_coe := @attach_map_val
-- The argument `xs : Array α` is explicit to allow rewriting from right to left.
theorem attach_map_subtype_val (xs : Array α) : xs.attach.map Subtype.val = xs := by
cases xs; simp
theorem attachWith_map_val {p : α Prop} (f : α β) (xs : Array α) (H : a xs, p a) :
theorem attachWith_map_val {p : α Prop} {f : α β} {xs : Array α} (H : a xs, p a) :
((xs.attachWith p H).map fun (i : { i // p i}) => f i) = xs.map f := by
cases xs; simp
@[deprecated attachWith_map_val (since := "2025-02-17")]
abbrev attachWith_map_coe := @attachWith_map_val
theorem attachWith_map_subtype_val {p : α Prop} (xs : Array α) (H : a xs, p a) :
theorem attachWith_map_subtype_val {p : α Prop} {xs : Array α} (H : a xs, p a) :
(xs.attachWith p H).map Subtype.val = xs := by
cases xs; simp
@@ -194,7 +195,7 @@ theorem mem_attach (xs : Array α) : ∀ x, x ∈ xs.attach
exact m
@[simp]
theorem mem_attachWith (xs : Array α) {q : α Prop} (H) (x : {x // q x}) :
theorem mem_attachWith {xs : Array α} {q : α Prop} (H) (x : {x // q x}) :
x xs.attachWith q H x.1 xs := by
cases xs
simp
@@ -250,10 +251,11 @@ theorem attachWith_ne_empty_iff {xs : Array α} {P : α → Prop} {H : ∀ a ∈
cases xs; simp
@[simp]
theorem getElem?_pmap {p : α Prop} (f : a, p a β) {xs : Array α} (h : a xs, p a) (i : Nat) :
theorem getElem?_pmap {p : α Prop} {f : a, p a β} {xs : Array α} (h : a xs, p a) (i : Nat) :
(pmap f xs h)[i]? = Option.pmap f xs[i]? fun x H => h x (mem_of_getElem? H) := by
cases xs; simp
-- The argument `f` is explicit to allow rewriting from right to left.
@[simp]
theorem getElem_pmap {p : α Prop} (f : a, p a β) {xs : Array α} (h : a xs, p a) {i : Nat}
(hi : i < (pmap f xs h).size) :
@@ -283,37 +285,37 @@ theorem getElem_attach {xs : Array α} {i : Nat} (h : i < xs.attach.size) :
xs.attach[i] = xs[i]'(by simpa using h), getElem_mem (by simpa using h) :=
getElem_attachWith h
@[simp] theorem pmap_attach (xs : Array α) {p : {x // x xs} Prop} (f : a, p a β) (H) :
@[simp] theorem pmap_attach {xs : Array α} {p : {x // x xs} Prop} {f : a, p a β} (H) :
pmap f xs.attach H =
xs.pmap (P := fun a => h : a xs, p a, h)
(fun a h => f a, h.1 h.2) (fun a h => h, H a, h (by simp)) := by
ext <;> simp
@[simp] theorem pmap_attachWith (xs : Array α) {p : {x // q x} Prop} (f : a, p a β) (H₁ H₂) :
@[simp] theorem pmap_attachWith {xs : Array α} {p : {x // q x} Prop} {f : a, p a β} (H₁ H₂) :
pmap f (xs.attachWith q H₁) H₂ =
xs.pmap (P := fun a => h : q a, p a, h)
(fun a h => f a, h.1 h.2) (fun a h => H₁ _ h, H₂ a, H₁ _ h (by simpa)) := by
ext <;> simp
theorem foldl_pmap (xs : Array α) {P : α Prop} (f : (a : α) P a β)
(H : (a : α), a xs P a) (g : γ β γ) (x : γ) :
theorem foldl_pmap {xs : Array α} {P : α Prop} {f : (a : α) P a β}
(H : (a : α), a xs P a) (g : γ β γ) (x : γ) :
(xs.pmap f H).foldl g x = xs.attach.foldl (fun acc a => g acc (f a.1 (H _ a.2))) x := by
rw [pmap_eq_map_attach, foldl_map]
theorem foldr_pmap (xs : Array α) {P : α Prop} (f : (a : α) P a β)
(H : (a : α), a xs P a) (g : β γ γ) (x : γ) :
theorem foldr_pmap {xs : Array α} {P : α Prop} {f : (a : α) P a β}
(H : (a : α), a xs P a) (g : β γ γ) (x : γ) :
(xs.pmap f H).foldr g x = xs.attach.foldr (fun a acc => g (f a.1 (H _ a.2)) acc) x := by
rw [pmap_eq_map_attach, foldr_map]
@[simp] theorem foldl_attachWith
(xs : Array α) {q : α Prop} (H : a, a xs q a) {f : β { x // q x} β} {b} (w : stop = xs.size) :
{xs : Array α} {q : α Prop} (H : a, a xs q a) {f : β { x // q x} β} {b} (w : stop = xs.size) :
(xs.attachWith q H).foldl f b 0 stop = xs.attach.foldl (fun b a, h => f b a, H _ h) b := by
subst w
rcases xs with xs
simp [List.foldl_attachWith, List.foldl_map]
@[simp] theorem foldr_attachWith
(xs : Array α) {q : α Prop} (H : a, a xs q a) {f : { x // q x} β β} {b} (w : start = xs.size) :
{xs : Array α} {q : α Prop} (H : a, a xs q a) {f : { x // q x} β β} {b} (w : start = xs.size) :
(xs.attachWith q H).foldr f b start 0 = xs.attach.foldr (fun a acc => f a.1, H _ a.2 acc) b := by
subst w
rcases xs with xs
@@ -329,7 +331,7 @@ Unfortunately this can't be applied by `simp` because of the higher order unific
and even when rewriting we need to specify the function explicitly.
See however `foldl_subtype` below.
-/
theorem foldl_attach (xs : Array α) (f : β α β) (b : β) :
theorem foldl_attach {xs : Array α} {f : β α β} {b : β} :
xs.attach.foldl (fun acc t => f acc t.1) b = xs.foldl f b := by
rcases xs with xs
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray,
@@ -348,7 +350,7 @@ Unfortunately this can't be applied by `simp` because of the higher order unific
and even when rewriting we need to specify the function explicitly.
See however `foldr_subtype` below.
-/
theorem foldr_attach (xs : Array α) (f : α β β) (b : β) :
theorem foldr_attach {xs : Array α} {f : α β β} {b : β} :
xs.attach.foldr (fun t acc => f t.1 acc) b = xs.foldr f b := by
rcases xs with xs
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray,
@@ -357,31 +359,31 @@ theorem foldr_attach (xs : Array α) (f : α → β → β) (b : β) :
ext
simpa using fun a => List.mem_of_getElem? a
theorem attach_map {xs : Array α} (f : α β) :
(xs.map f).attach = xs.attach.map (fun x, h => f x, mem_map_of_mem f h) := by
theorem attach_map {xs : Array α} {f : α β} :
(xs.map f).attach = xs.attach.map (fun x, h => f x, mem_map_of_mem h) := by
cases xs
ext <;> simp
theorem attachWith_map {xs : Array α} (f : α β) {P : β Prop} {H : (b : β), b xs.map f P b} :
(xs.map f).attachWith P H = (xs.attachWith (P f) (fun _ h => H _ (mem_map_of_mem f h))).map
theorem attachWith_map {xs : Array α} {f : α β} {P : β Prop} (H : (b : β), b xs.map f P b) :
(xs.map f).attachWith P H = (xs.attachWith (P f) (fun _ h => H _ (mem_map_of_mem h))).map
fun x, h => f x, h := by
cases xs
simp [List.attachWith_map]
@[simp] theorem map_attachWith {xs : Array α} {P : α Prop} {H : (a : α), a xs P a}
(f : { x // P x } β) :
{f : { x // P x } β} :
(xs.attachWith P H).map f = xs.attach.map fun x, h => f x, H _ h := by
cases xs <;> simp_all
theorem map_attachWith_eq_pmap {xs : Array α} {P : α Prop} {H : (a : α), a xs P a}
(f : { x // P x } β) :
{f : { x // P x } β} :
(xs.attachWith P H).map f =
xs.pmap (fun a (h : a xs P a) => f a, H _ h.1) (fun a h => h, H a h) := by
cases xs
ext <;> simp
/-- See also `pmap_eq_map_attach` for writing `pmap` in terms of `map` and `attach`. -/
theorem map_attach_eq_pmap {xs : Array α} (f : { x // x xs } β) :
theorem map_attach_eq_pmap {xs : Array α} {f : { x // x xs } β} :
xs.attach.map f = xs.pmap (fun a h => f a, h) (fun _ => id) := by
cases xs
ext <;> simp
@@ -393,14 +395,14 @@ theorem attach_filterMap {xs : Array α} {f : α → Option β} :
(xs.filterMap f).attach = xs.attach.filterMap
fun x, h => (f x).pbind (fun b m => some b, mem_filterMap.mpr x, h, m) := by
cases xs
rw [attach_congr (List.filterMap_toArray f _)]
rw [attach_congr List.filterMap_toArray]
simp [List.attach_filterMap, List.map_filterMap, Function.comp_def]
theorem attach_filter {xs : Array α} (p : α Bool) :
(xs.filter p).attach = xs.attach.filterMap
fun x => if w : p x.1 then some x.1, mem_filter.mpr x.2, w else none := by
cases xs
rw [attach_congr (List.filter_toArray p _)]
rw [attach_congr List.filter_toArray]
simp [List.attach_filter, List.map_filterMap, Function.comp_def]
-- We are still missing here `attachWith_filterMap` and `attachWith_filter`.
@@ -422,14 +424,14 @@ theorem filter_attachWith {q : α → Prop} {xs : Array α} {p : {x // q x} →
cases xs
simp [Function.comp_def, List.filter_map]
theorem pmap_pmap {p : α Prop} {q : β Prop} (g : a, p a β) (f : b, q b γ) (xs H₁ H₂) :
theorem pmap_pmap {p : α Prop} {q : β Prop} {g : a, p a β} {f : b, q b γ} {xs} (H₁ H₂) :
pmap f (pmap g xs H₁) H₂ =
pmap (α := { x // x xs }) (fun a h => f (g a h) (H₂ (g a h) (mem_pmap_of_mem a.2))) xs.attach
(fun a _ => H₁ a a.2) := by
cases xs
simp [List.pmap_pmap, List.pmap_map]
@[simp] theorem pmap_append {p : ι Prop} (f : a : ι, p a α) (xs ys : Array ι)
@[simp] theorem pmap_append {p : ι Prop} {f : a : ι, p a α} {xs ys : Array ι}
(h : a xs ++ ys, p a) :
(xs ++ ys).pmap f h =
(xs.pmap f fun a ha => h a (mem_append_left ys ha)) ++
@@ -438,13 +440,13 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f
cases ys
simp
theorem pmap_append' {p : α Prop} (f : a : α, p a β) (xs ys : Array α)
theorem pmap_append' {p : α Prop} {f : a : α, p a β} {xs ys : Array α}
(h₁ : a xs, p a) (h₂ : a ys, p a) :
((xs ++ ys).pmap f fun a ha => (mem_append.1 ha).elim (h₁ a) (h₂ a)) =
xs.pmap f h₁ ++ ys.pmap f h₂ :=
pmap_append f xs ys _
pmap_append _
@[simp] theorem attach_append (xs ys : Array α) :
@[simp] theorem attach_append {xs ys : Array α} :
(xs ++ ys).attach = xs.attach.map (fun x, h => x, mem_append_left ys h) ++
ys.attach.map fun x, h => x, mem_append_right xs h := by
cases xs
@@ -458,12 +460,12 @@ theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (xs ys : Arr
ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by
simp [attachWith, attach_append, map_pmap, pmap_append]
@[simp] theorem pmap_reverse {P : α Prop} (f : (a : α) P a β) (xs : Array α)
@[simp] theorem pmap_reverse {P : α Prop} {f : (a : α) P a β} {xs : Array α}
(H : (a : α), a xs.reverse P a) :
xs.reverse.pmap f H = (xs.pmap f (fun a h => H a (by simpa using h))).reverse := by
induction xs <;> simp_all
theorem reverse_pmap {P : α Prop} (f : (a : α) P a β) (xs : Array α)
theorem reverse_pmap {P : α Prop} {f : (a : α) P a β} {xs : Array α}
(H : (a : α), a xs P a) :
(xs.pmap f H).reverse = xs.reverse.pmap f (fun a h => H a (by simpa using h)) := by
rw [pmap_reverse]
@@ -481,18 +483,18 @@ theorem reverse_attachWith {P : α → Prop} {xs : Array α}
cases xs
simp
@[simp] theorem attach_reverse (xs : Array α) :
@[simp] theorem attach_reverse {xs : Array α} :
xs.reverse.attach = xs.attach.reverse.map fun x, h => x, by simpa using h := by
cases xs
rw [attach_congr (List.reverse_toArray _)]
rw [attach_congr List.reverse_toArray]
simp
theorem reverse_attach (xs : Array α) :
theorem reverse_attach {xs : Array α} :
xs.attach.reverse = xs.reverse.attach.map fun x, h => x, by simpa using h := by
cases xs
simp
@[simp] theorem back?_pmap {P : α Prop} (f : (a : α) P a β) (xs : Array α)
@[simp] theorem back?_pmap {P : α Prop} {f : (a : α) P a β} {xs : Array α}
(H : (a : α), a xs P a) :
(xs.pmap f H).back? = xs.attach.back?.map fun a, m => f a (H a m) := by
cases xs
@@ -511,19 +513,19 @@ theorem back?_attach {xs : Array α} :
simp
@[simp]
theorem countP_attach (xs : Array α) (p : α Bool) :
theorem countP_attach {xs : Array α} {p : α Bool} :
xs.attach.countP (fun a : {x // x xs} => p a) = xs.countP p := by
cases xs
simp [Function.comp_def]
@[simp]
theorem countP_attachWith {p : α Prop} (xs : Array α) (H : a xs, p a) (q : α Bool) :
theorem countP_attachWith {p : α Prop} {q : α Bool} {xs : Array α} {H : a xs, p a} :
(xs.attachWith p H).countP (fun a : {x // p x} => q a) = xs.countP q := by
cases xs
simp
@[simp]
theorem count_attach [DecidableEq α] (xs : Array α) (a : {x // x xs}) :
theorem count_attach [DecidableEq α] {xs : Array α} {a : {x // x xs}} :
xs.attach.count a = xs.count a := by
rcases xs with xs
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.count_toArray]
@@ -532,12 +534,12 @@ theorem count_attach [DecidableEq α] (xs : Array α) (a : {x // x ∈ xs}) :
rw [List.countP_pmap, List.countP_attach (p := (fun x => x == a.1)), List.count]
@[simp]
theorem count_attachWith [DecidableEq α] {p : α Prop} (xs : Array α) (H : a xs, p a) (a : {x // p x}) :
theorem count_attachWith [DecidableEq α] {p : α Prop} {xs : Array α} (H : a xs, p a) {a : {x // p x}} :
(xs.attachWith p H).count a = xs.count a := by
cases xs
simp
@[simp] theorem countP_pmap {p : α Prop} (g : a, p a β) (f : β Bool) (xs : Array α) (H₁) :
@[simp] theorem countP_pmap {p : α Prop} {g : a, p a β} {f : β Bool} {xs : Array α} (H₁) :
(xs.pmap g H₁).countP f =
xs.attach.countP (fun a, m => f (g a (H₁ a m))) := by
simp [pmap_eq_map_attach, countP_map, Function.comp_def]
@@ -752,65 +754,64 @@ abbrev unattach_mkArray := @unattach_replicate
/-! ### Well-founded recursion preprocessing setup -/
@[wf_preprocess] theorem Array.map_wfParam (xs : Array α) (f : α β) :
@[wf_preprocess] theorem map_wfParam {xs : Array α} {f : α β} :
(wfParam xs).map f = xs.attach.unattach.map f := by
simp [wfParam]
@[wf_preprocess] theorem Array.map_unattach (P : α Prop) (xs : Array (Subtype P)) (f : α β) :
@[wf_preprocess] theorem map_unattach {P : α Prop} {xs : Array (Subtype P)} {f : α β} :
xs.unattach.map f = xs.map fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]
@[wf_preprocess] theorem foldl_wfParam (xs : Array α) (f : β α β) (x : β) :
@[wf_preprocess] theorem foldl_wfParam {xs : Array α} {f : β α β} {x : β} :
(wfParam xs).foldl f x = xs.attach.unattach.foldl f x := by
simp [wfParam]
@[wf_preprocess] theorem foldl_unattach (P : α Prop) (xs : Array (Subtype P)) (f : β α β) (x : β):
@[wf_preprocess] theorem foldl_unattach {P : α Prop} {xs : Array (Subtype P)} {f : β α β} {x : β} :
xs.unattach.foldl f x = xs.foldl (fun s x, h =>
binderNameHint s f <| binderNameHint x (f s) <| binderNameHint h () <| f s (wfParam x)) x := by
simp [wfParam]
@[wf_preprocess] theorem foldr_wfParam (xs : Array α) (f : α β β) (x : β) :
@[wf_preprocess] theorem foldr_wfParam {xs : Array α} {f : α β β} {x : β} :
(wfParam xs).foldr f x = xs.attach.unattach.foldr f x := by
simp [wfParam]
@[wf_preprocess] theorem foldr_unattach (P : α Prop) (xs : Array (Subtype P)) (f : α β β) (x : β):
@[wf_preprocess] theorem foldr_unattach {P : α Prop} {xs : Array (Subtype P)} {f : α β β} {x : β} :
xs.unattach.foldr f x = xs.foldr (fun x, h s =>
binderNameHint x f <| binderNameHint s (f x) <| binderNameHint h () <| f (wfParam x) s) x := by
simp [wfParam]
@[wf_preprocess] theorem filter_wfParam (xs : Array α) (f : α Bool) :
@[wf_preprocess] theorem filter_wfParam {xs : Array α} {f : α Bool} :
(wfParam xs).filter f = xs.attach.unattach.filter f:= by
simp [wfParam]
@[wf_preprocess] theorem filter_unattach (P : α Prop) (xs : Array (Subtype P)) (f : α Bool) :
@[wf_preprocess] theorem filter_unattach {P : α Prop} {xs : Array (Subtype P)} {f : α Bool} :
xs.unattach.filter f = (xs.filter (fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x))).unattach := by
simp [wfParam]
@[wf_preprocess] theorem reverse_wfParam (xs : Array α) :
@[wf_preprocess] theorem reverse_wfParam {xs : Array α} :
(wfParam xs).reverse = xs.attach.unattach.reverse := by simp [wfParam]
@[wf_preprocess] theorem reverse_unattach (P : α Prop) (xs : Array (Subtype P)) :
@[wf_preprocess] theorem reverse_unattach {P : α Prop} {xs : Array (Subtype P)} :
xs.unattach.reverse = xs.reverse.unattach := by simp
@[wf_preprocess] theorem filterMap_wfParam (xs : Array α) (f : α Option β) :
@[wf_preprocess] theorem filterMap_wfParam {xs : Array α} {f : α Option β} :
(wfParam xs).filterMap f = xs.attach.unattach.filterMap f := by
simp [wfParam]
@[wf_preprocess] theorem filterMap_unattach (P : α Prop) (xs : Array (Subtype P)) (f : α Option β) :
@[wf_preprocess] theorem filterMap_unattach {P : α Prop} {xs : Array (Subtype P)} {f : α Option β} :
xs.unattach.filterMap f = xs.filterMap fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]
@[wf_preprocess] theorem flatMap_wfParam (xs : Array α) (f : α Array β) :
@[wf_preprocess] theorem flatMap_wfParam {xs : Array α} {f : α Array β} :
(wfParam xs).flatMap f = xs.attach.unattach.flatMap f := by
simp [wfParam]
@[wf_preprocess] theorem flatMap_unattach (P : α Prop) (xs : Array (Subtype P)) (f : α Array β) :
@[wf_preprocess] theorem flatMap_unattach {P : α Prop} {xs : Array (Subtype P)} {f : α Array β} :
xs.unattach.flatMap f = xs.flatMap fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]
end Array

View File

@@ -38,14 +38,14 @@ namespace Array
/-! ### Preliminary theorems -/
@[simp] theorem size_set (xs : Array α) (i : Nat) (v : α) (h : i < xs.size) :
@[simp] theorem size_set {xs : Array α} {i : Nat} {v : α} (h : i < xs.size) :
(set xs i v h).size = xs.size :=
List.length_set ..
@[simp] theorem size_push (xs : Array α) (v : α) : (push xs v).size = xs.size + 1 :=
@[simp] theorem size_push {xs : Array α} (v : α) : (push xs v).size = xs.size + 1 :=
List.length_concat ..
theorem ext (xs ys : Array α)
theorem ext {xs ys : Array α}
(h₁ : xs.size = ys.size)
(h₂ : (i : Nat) (hi₁ : i < xs.size) (hi₂ : i < ys.size) xs[i] = ys[i])
: xs = ys := by
@@ -83,10 +83,10 @@ theorem ext (xs ys : Array α)
theorem ext' {xs ys : Array α} (h : xs.toList = ys.toList) : xs = ys := by
cases xs; cases ys; simp at h; rw [h]
@[simp] theorem toArrayAux_eq (as : List α) (acc : Array α) : (as.toArrayAux acc).toList = acc.toList ++ as := by
@[simp] theorem toArrayAux_eq {as : List α} {acc : Array α} : (as.toArrayAux acc).toList = acc.toList ++ as := by
induction as generalizing acc <;> simp [*, List.toArrayAux, Array.push, List.append_assoc, List.concat_eq_append]
@[simp] theorem toArray_toList (xs : Array α) : xs.toList.toArray = xs := rfl
@[simp] theorem toArray_toList {xs : Array α} : xs.toList.toArray = xs := rfl
@[simp] theorem getElem_toList {xs : Array α} {i : Nat} (h : i < xs.size) : xs.toList[i] = xs[i] := rfl
@@ -120,12 +120,12 @@ namespace List
abbrev toArray_toList := @Array.toArray_toList
-- This does not need to be a simp lemma, as already after the `whnfR` the right hand side is `as`.
theorem toList_toArray (as : List α) : as.toArray.toList = as := rfl
theorem toList_toArray {as : List α} : as.toArray.toList = as := rfl
@[deprecated toList_toArray (since := "2025-02-17")]
abbrev _root_.Array.toList_toArray := @List.toList_toArray
@[simp] theorem size_toArray (as : List α) : as.toArray.size = as.length := by simp [Array.size]
@[simp] theorem size_toArray {as : List α} : as.toArray.size = as.length := by simp [Array.size]
@[deprecated size_toArray (since := "2025-02-17")]
abbrev _root_.Array.size_toArray := @List.size_toArray
@@ -144,7 +144,7 @@ end List
namespace Array
theorem size_eq_length_toList (xs : Array α) : xs.size = xs.toList.length := rfl
theorem size_eq_length_toList {xs : Array α} : xs.size = xs.toList.length := rfl
@[deprecated toList_toArray (since := "2024-09-09")] abbrev data_toArray := @List.toList_toArray
@@ -192,7 +192,7 @@ Examples:
def pop (xs : Array α) : Array α where
toList := xs.toList.dropLast
@[simp] theorem size_pop (xs : Array α) : xs.pop.size = xs.size - 1 := by
@[simp] theorem size_pop {xs : Array α} : xs.pop.size = xs.size - 1 := by
match xs with
| [] => rfl
| a::as => simp [pop, Nat.succ_sub_succ_eq_sub, size]
@@ -240,11 +240,11 @@ def swap (xs : Array α) (i j : @& Nat) (hi : i < xs.size := by get_elem_tactic)
let v₁ := xs[i]
let v₂ := xs[j]
let xs' := xs.set i v₂
xs'.set j v₁ (Nat.lt_of_lt_of_eq hj (size_set xs i v₂ _).symm)
xs'.set j v₁ (Nat.lt_of_lt_of_eq hj (size_set _).symm)
@[simp] theorem size_swap (xs : Array α) (i j : Nat) {hi hj} : (xs.swap i j hi hj).size = xs.size := by
@[simp] theorem size_swap {xs : Array α} {i j : Nat} {hi hj} : (xs.swap i j hi hj).size = xs.size := by
show ((xs.set i xs[j]).set j xs[i]
(Nat.lt_of_lt_of_eq hj (size_set xs i xs[j] _).symm)).size = xs.size
(Nat.lt_of_lt_of_eq hj (size_set _).symm)).size = xs.size
rw [size_set, size_set]
/--
@@ -465,7 +465,7 @@ Examples:
-/
abbrev take (xs : Array α) (i : Nat) : Array α := extract xs 0 i
@[simp] theorem take_eq_extract (xs : Array α) (i : Nat) : xs.take i = xs.extract 0 i := rfl
@[simp] theorem take_eq_extract {xs : Array α} {i : Nat} : xs.take i = xs.extract 0 i := rfl
/--
Removes the first `i` elements of `xs`. If `xs` has fewer than `i` elements, the new array is empty.
@@ -479,7 +479,7 @@ Examples:
-/
abbrev drop (xs : Array α) (i : Nat) : Array α := extract xs i xs.size
@[simp] theorem drop_eq_extract (xs : Array α) (i : Nat) : xs.drop i = xs.extract i xs.size := rfl
@[simp] theorem drop_eq_extract {xs : Array α} {i : Nat} : xs.drop i = xs.extract i xs.size := rfl
@[inline]
unsafe def modifyMUnsafe [Monad m] (xs : Array α) (i : Nat) (f : α m α) : m (Array α) := do
@@ -490,7 +490,7 @@ unsafe def modifyMUnsafe [Monad m] (xs : Array α) (i : Nat) (f : α → m α) :
-- of the element type, and that it is valid to store `box(0)` in any array.
let xs' := xs.set i (unsafeCast ())
let v f v
pure <| xs'.set i v (Nat.lt_of_lt_of_eq h (size_set xs ..).symm)
pure <| xs'.set i v (Nat.lt_of_lt_of_eq h (size_set ..).symm)
else
pure xs
@@ -1026,7 +1026,7 @@ instance : ForM m (Array α) α where
forM xs f := Array.forM f xs
-- We simplify `Array.forM` to `forM`.
@[simp] theorem forM_eq_forM [Monad m] (f : α m PUnit) :
@[simp] theorem forM_eq_forM [Monad m] {f : α m PUnit} :
Array.forM f as 0 as.size = forM as f := rfl
/--
@@ -1735,7 +1735,7 @@ def popWhile (p : α → Bool) (as : Array α) : Array α :=
as
decreasing_by simp_wf; decreasing_trivial_pre_omega
@[simp] theorem popWhile_empty (p : α Bool) :
@[simp] theorem popWhile_empty {p : α Bool} :
popWhile p #[] = #[] := by
simp [popWhile]
@@ -1784,7 +1784,7 @@ termination_by xs.size - i
decreasing_by simp_wf; exact Nat.sub_succ_lt_self _ _ h
-- This is required in `Lean.Data.PersistentHashMap`.
@[simp] theorem size_eraseIdx (xs : Array α) (i : Nat) (h) : (xs.eraseIdx i h).size = xs.size - 1 := by
@[simp] theorem size_eraseIdx {xs : Array α} (i : Nat) (h) : (xs.eraseIdx i h).size = xs.size - 1 := by
induction xs, i, h using Array.eraseIdx.induct with
| @case1 xs i h h' xs' ih =>
unfold eraseIdx

View File

@@ -17,7 +17,7 @@ theorem Array.of_push_eq_push {as bs : Array α} (h : as.push a = bs.push b) : a
cases as; cases bs
simp_all
private theorem List.size_toArrayAux (as : List α) (bs : Array α) : (as.toArrayAux bs).size = as.length + bs.size := by
private theorem List.size_toArrayAux {as : List α} {bs : Array α} : (as.toArrayAux bs).size = as.length + bs.size := by
induction as generalizing bs with
| nil => simp [toArrayAux]
| cons a as ih => simp +arith [toArrayAux, *]
@@ -35,7 +35,7 @@ private theorem List.of_toArrayAux_eq_toArrayAux {as bs : List α} {cs ds : Arra
have := Array.of_push_eq_push ih₂
simp [this]
theorem List.toArray_eq_toArray_eq (as bs : List α) : (as.toArray = bs.toArray) = (as = bs) := by
theorem List.toArray_eq_toArray_eq {as bs : List α} : (as.toArray = bs.toArray) = (as = bs) := by
simp
/--

View File

@@ -42,35 +42,35 @@ def get! {α : Type u} [Inhabited α] (a : @& Array α) (i : @& Nat) : α :=
Array.getD a i default
theorem foldlM_toList.aux [Monad m]
(f : β α m β) (xs : Array α) (i j) (H : xs.size i + j) (b) :
{f : β α m β} {xs : Array α} {i j} (H : xs.size i + j) {b} :
foldlM.loop f xs xs.size (Nat.le_refl _) i j b = (xs.toList.drop j).foldlM f b := by
unfold foldlM.loop
split; split
· cases Nat.not_le_of_gt _ (Nat.zero_add _ H)
· rename_i i; rw [Nat.succ_add] at H
simp [foldlM_toList.aux f xs i (j+1) H]
simp [foldlM_toList.aux (j := j+1) H]
rw (occs := [2]) [ List.getElem_cons_drop_succ_eq_drop _]
rfl
· rw [List.drop_of_length_le (Nat.ge_of_not_lt _)]; rfl
@[simp] theorem foldlM_toList [Monad m]
(f : β α m β) (init : β) (xs : Array α) :
{f : β α m β} {init : β} {xs : Array α} :
xs.toList.foldlM f init = xs.foldlM f init := by
simp [foldlM, foldlM_toList.aux]
@[simp] theorem foldl_toList (f : β α β) (init : β) (xs : Array α) :
@[simp] theorem foldl_toList (f : β α β) {init : β} {xs : Array α} :
xs.toList.foldl f init = xs.foldl f init :=
List.foldl_eq_foldlM .. foldlM_toList ..
theorem foldrM_eq_reverse_foldlM_toList.aux [Monad m]
(f : α β m β) (xs : Array α) (init : β) (i h) :
{f : α β m β} {xs : Array α} {init : β} {i} (h) :
(xs.toList.take i).reverse.foldlM (fun x y => f y x) init = foldrM.fold f xs 0 i h init := by
unfold foldrM.fold
match i with
| 0 => simp [List.foldlM, List.take]
| i+1 => rw [ List.take_concat_get _ _ h]; simp [ (aux f xs · i)]
| i+1 => rw [ List.take_concat_get h]; simp [ aux]
theorem foldrM_eq_reverse_foldlM_toList [Monad m] (f : α β m β) (init : β) (xs : Array α) :
theorem foldrM_eq_reverse_foldlM_toList [Monad m] {f : α β m β} {init : β} {xs : Array α} :
xs.foldrM f init = xs.toList.reverse.foldlM (fun x y => f y x) init := by
have : xs = #[] 0 < xs.size :=
match xs with | [] => .inl rfl | a::l => .inr (Nat.zero_lt_succ _)
@@ -78,31 +78,31 @@ theorem foldrM_eq_reverse_foldlM_toList [Monad m] (f : α → β → m β) (init
simp [foldrM, h, foldrM_eq_reverse_foldlM_toList.aux, List.take_length]
@[simp] theorem foldrM_toList [Monad m]
(f : α β m β) (init : β) (xs : Array α) :
{f : α β m β} {init : β} {xs : Array α} :
xs.toList.foldrM f init = xs.foldrM f init := by
rw [foldrM_eq_reverse_foldlM_toList, List.foldlM_reverse]
@[simp] theorem foldr_toList (f : α β β) (init : β) (xs : Array α) :
@[simp] theorem foldr_toList (f : α β β) {init : β} {xs : Array α} :
xs.toList.foldr f init = xs.foldr f init :=
List.foldr_eq_foldrM .. foldrM_toList ..
@[simp] theorem push_toList (xs : Array α) (a : α) : (xs.push a).toList = xs.toList ++ [a] := by
@[simp] theorem push_toList {xs : Array α} {a : α} : (xs.push a).toList = xs.toList ++ [a] := by
simp [push, List.concat_eq_append]
@[simp] theorem toListAppend_eq (xs : Array α) (l : List α) : xs.toListAppend l = xs.toList ++ l := by
@[simp] theorem toListAppend_eq {xs : Array α} {l : List α} : xs.toListAppend l = xs.toList ++ l := by
simp [toListAppend, foldr_toList]
@[simp] theorem toListImpl_eq (xs : Array α) : xs.toListImpl = xs.toList := by
@[simp] theorem toListImpl_eq {xs : Array α} : xs.toListImpl = xs.toList := by
simp [toListImpl, foldr_toList]
@[simp] theorem toList_pop (xs : Array α) : xs.pop.toList = xs.toList.dropLast := rfl
@[simp] theorem toList_pop {xs : Array α} : xs.pop.toList = xs.toList.dropLast := rfl
@[deprecated toList_pop (since := "2025-02-17")]
abbrev pop_toList := @Array.toList_pop
@[simp] theorem append_eq_append (xs ys : Array α) : xs.append ys = xs ++ ys := rfl
@[simp] theorem append_eq_append {xs ys : Array α} : xs.append ys = xs ++ ys := rfl
@[simp] theorem toList_append (xs ys : Array α) :
@[simp] theorem toList_append {xs ys : Array α} :
(xs ++ ys).toList = xs.toList ++ ys.toList := by
rw [ append_eq_append]; unfold Array.append
rw [ foldl_toList]
@@ -110,25 +110,24 @@ abbrev pop_toList := @Array.toList_pop
@[simp] theorem toList_empty : (#[] : Array α).toList = [] := rfl
@[simp] theorem append_empty (xs : Array α) : xs ++ #[] = xs := by
@[simp] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by
apply ext'; simp only [toList_append, toList_empty, List.append_nil]
@[deprecated append_empty (since := "2025-01-13")]
abbrev append_nil := @append_empty
@[simp] theorem empty_append (xs : Array α) : #[] ++ xs = xs := by
@[simp] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
apply ext'; simp only [toList_append, toList_empty, List.nil_append]
@[deprecated empty_append (since := "2025-01-13")]
abbrev nil_append := @empty_append
@[simp] theorem append_assoc (xs ys zs : Array α) : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by
@[simp] theorem append_assoc {xs ys zs : Array α} : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by
apply ext'; simp only [toList_append, List.append_assoc]
@[simp] theorem appendList_eq_append
(xs : Array α) (l : List α) : xs.appendList l = xs ++ l := rfl
@[simp] theorem appendList_eq_append {xs : Array α} {l : List α} : xs.appendList l = xs ++ l := rfl
@[simp] theorem toList_appendList (xs : Array α) (l : List α) :
@[simp] theorem toList_appendList {xs : Array α} {l : List α} :
(xs ++ l).toList = xs.toList ++ l := by
rw [ appendList_eq_append]; unfold Array.appendList
induction l generalizing xs <;> simp [*]
@@ -138,25 +137,23 @@ abbrev appendList_toList := @toList_appendList
@[deprecated "Use the reverse direction of `foldrM_toList`." (since := "2024-11-13")]
theorem foldrM_eq_foldrM_toList [Monad m]
(f : α β m β) (init : β) (xs : Array α) :
{f : α β m β} {init : β} {xs : Array α} :
xs.foldrM f init = xs.toList.foldrM f init := by
simp
@[deprecated "Use the reverse direction of `foldlM_toList`." (since := "2024-11-13")]
theorem foldlM_eq_foldlM_toList [Monad m]
(f : β α m β) (init : β) (xs : Array α) :
{f : β α m β} {init : β} {xs : Array α} :
xs.foldlM f init = xs.toList.foldlM f init:= by
simp
@[deprecated "Use the reverse direction of `foldr_toList`." (since := "2024-11-13")]
theorem foldr_eq_foldr_toList
(f : α β β) (init : β) (xs : Array α) :
theorem foldr_eq_foldr_toList {f : α β β} {init : β} {xs : Array α} :
xs.foldr f init = xs.toList.foldr f init := by
simp
@[deprecated "Use the reverse direction of `foldl_toList`." (since := "2024-11-13")]
theorem foldl_eq_foldl_toList
(f : β α β) (init : β) (xs : Array α) :
theorem foldl_eq_foldl_toList {f : β α β} {init : β} {xs : Array α} :
xs.foldl f init = xs.toList.foldl f init:= by
simp

View File

@@ -21,9 +21,9 @@ open Nat
/-! ### countP -/
section countP
variable (p q : α Bool)
variable {p q : α Bool}
@[simp] theorem _root_.List.countP_toArray (l : List α) : countP p l.toArray = l.countP p := by
@[simp] theorem _root_.List.countP_toArray {l : List α} : countP p l.toArray = l.countP p := by
simp [countP]
induction l with
| nil => rfl
@@ -31,32 +31,32 @@ variable (p q : α → Bool)
simp only [List.foldr_cons, ih, List.countP_cons]
split <;> simp_all
@[simp] theorem countP_toList (xs : Array α) : xs.toList.countP p = countP p xs := by
@[simp] theorem countP_toList {xs : Array α} : xs.toList.countP p = countP p xs := by
cases xs
simp
@[simp] theorem countP_empty : countP p #[] = 0 := rfl
@[simp] theorem countP_push_of_pos (xs) (pa : p a) : countP p (xs.push a) = countP p xs + 1 := by
@[simp] theorem countP_push_of_pos {xs : Array α} (pa : p a) : countP p (xs.push a) = countP p xs + 1 := by
rcases xs with xs
simp_all
@[simp] theorem countP_push_of_neg (xs) (pa : ¬p a) : countP p (xs.push a) = countP p xs := by
@[simp] theorem countP_push_of_neg {xs : Array α} (pa : ¬p a) : countP p (xs.push a) = countP p xs := by
rcases xs with xs
simp_all
theorem countP_push (a : α) (xs) : countP p (xs.push a) = countP p xs + if p a then 1 else 0 := by
theorem countP_push {a : α} {xs : Array α} : countP p (xs.push a) = countP p xs + if p a then 1 else 0 := by
rcases xs with xs
simp_all
@[simp] theorem countP_singleton (a : α) : countP p #[a] = if p a then 1 else 0 := by
@[simp] theorem countP_singleton {a : α} : countP p #[a] = if p a then 1 else 0 := by
simp [countP_push]
theorem size_eq_countP_add_countP (xs) : xs.size = countP p xs + countP (fun a => ¬p a) xs := by
theorem size_eq_countP_add_countP {xs : Array α} : xs.size = countP p xs + countP (fun a => ¬p a) xs := by
rcases xs with xs
simp [List.length_eq_countP_add_countP (p := p)]
theorem countP_eq_size_filter (xs) : countP p xs = (filter p xs).size := by
theorem countP_eq_size_filter {xs : Array α} : countP p xs = (filter p xs).size := by
rcases xs with xs
simp [List.countP_eq_length_filter]
@@ -68,7 +68,7 @@ theorem countP_le_size : countP p xs ≤ xs.size := by
simp only [countP_eq_size_filter]
apply size_filter_le
@[simp] theorem countP_append (xs ys) : countP p (xs ++ ys) = countP p xs + countP p ys := by
@[simp] theorem countP_append {xs ys : Array α} : countP p (xs ++ ys) = countP p xs + countP p ys := by
rcases xs with xs
rcases ys with ys
simp
@@ -88,24 +88,23 @@ theorem countP_le_size : countP p xs ≤ xs.size := by
rcases xs with xs
simp
theorem countP_replicate (p : α Bool) (a : α) (n : Nat) :
countP p (replicate n a) = if p a then n else 0 := by
theorem countP_replicate {a : α} {n : Nat} : countP p (replicate n a) = if p a then n else 0 := by
simp [ List.toArray_replicate, List.countP_replicate]
@[deprecated countP_replicate (since := "2025-03-18")]
abbrev countP_mkArray := @countP_replicate
theorem boole_getElem_le_countP (p : α Bool) (xs : Array α) (i : Nat) (h : i < xs.size) :
theorem boole_getElem_le_countP {xs : Array α} {i : Nat} (h : i < xs.size) :
(if p xs[i] then 1 else 0) xs.countP p := by
rcases xs with xs
simp [List.boole_getElem_le_countP]
theorem countP_set (p : α Bool) (xs : Array α) (i : Nat) (a : α) (h : i < xs.size) :
theorem countP_set {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) :
(xs.set i a).countP p = xs.countP p - (if p xs[i] then 1 else 0) + (if p a then 1 else 0) := by
rcases xs with xs
simp [List.countP_set, h]
theorem countP_filter (xs : Array α) :
theorem countP_filter {xs : Array α} :
countP p (filter q xs) = countP (fun a => p a && q a) xs := by
rcases xs with xs
simp [List.countP_filter]
@@ -118,37 +117,35 @@ theorem countP_filter (xs : Array α) :
funext xs
simp
@[simp] theorem countP_map (p : β Bool) (f : α β) (xs : Array α) :
@[simp] theorem countP_map {p : β Bool} {f : α β} {xs : Array α} :
countP p (map f xs) = countP (p f) xs := by
rcases xs with xs
simp
theorem size_filterMap_eq_countP (f : α Option β) (xs : Array α) :
theorem size_filterMap_eq_countP {f : α Option β} {xs : Array α} :
(filterMap f xs).size = countP (fun a => (f a).isSome) xs := by
rcases xs with xs
simp [List.length_filterMap_eq_countP]
theorem countP_filterMap (p : β Bool) (f : α Option β) (xs : Array α) :
theorem countP_filterMap {p : β Bool} {f : α Option β} {xs : Array α} :
countP p (filterMap f xs) = countP (fun a => ((f a).map p).getD false) xs := by
rcases xs with xs
simp [List.countP_filterMap]
@[simp] theorem countP_flatten (xss : Array (Array α)) :
@[simp] theorem countP_flatten {xss : Array (Array α)} :
countP p xss.flatten = (xss.map (countP p)).sum := by
cases xss using array₂_induction
simp [List.countP_flatten, Function.comp_def]
theorem countP_flatMap (p : β Bool) (xs : Array α) (f : α Array β) :
theorem countP_flatMap {p : β Bool} {xs : Array α} {f : α Array β} :
countP p (xs.flatMap f) = sum (map (countP p f) xs) := by
rcases xs with xs
simp [List.countP_flatMap, Function.comp_def]
@[simp] theorem countP_reverse (xs : Array α) : countP p xs.reverse = countP p xs := by
@[simp] theorem countP_reverse {xs : Array α} : countP p xs.reverse = countP p xs := by
rcases xs with xs
simp [List.countP_reverse]
variable {p q}
theorem countP_mono_left (h : x xs, p x q x) : countP p xs countP q xs := by
rcases xs with xs
simpa using List.countP_mono_left (by simpa using h)
@@ -165,62 +162,62 @@ section count
variable [BEq α]
@[simp] theorem _root_.List.count_toArray (l : List α) (a : α) : count a l.toArray = l.count a := by
@[simp] theorem _root_.List.count_toArray {l : List α} {a : α} : count a l.toArray = l.count a := by
simp [count, List.count_eq_countP]
@[simp] theorem count_toList (xs : Array α) (a : α) : xs.toList.count a = xs.count a := by
@[simp] theorem count_toList {xs : Array α} {a : α} : xs.toList.count a = xs.count a := by
cases xs
simp
@[simp] theorem count_empty (a : α) : count a #[] = 0 := rfl
@[simp] theorem count_empty {a : α} : count a #[] = 0 := rfl
theorem count_push (a b : α) (xs : Array α) :
theorem count_push {a b : α} {xs : Array α} :
count a (xs.push b) = count a xs + if b == a then 1 else 0 := by
simp [count, countP_push]
theorem count_eq_countP (a : α) (xs : Array α) : count a xs = countP (· == a) xs := rfl
theorem count_eq_countP {a : α} {xs : Array α} : count a xs = countP (· == a) xs := rfl
theorem count_eq_countP' {a : α} : count a = countP (· == a) := by
funext xs
apply count_eq_countP
theorem count_le_size (a : α) (xs : Array α) : count a xs xs.size := countP_le_size _
theorem count_le_size {a : α} {xs : Array α} : count a xs xs.size := countP_le_size
theorem count_le_count_push (a b : α) (xs : Array α) : count a xs count a (xs.push b) := by
theorem count_le_count_push {a b : α} {xs : Array α} : count a xs count a (xs.push b) := by
simp [count_push]
theorem count_singleton (a b : α) : count a #[b] = if b == a then 1 else 0 := by
theorem count_singleton {a b : α} : count a #[b] = if b == a then 1 else 0 := by
simp [count_eq_countP]
@[simp] theorem count_append (a : α) : xs ys, count a (xs ++ ys) = count a xs + count a ys :=
countP_append _
@[simp] theorem count_append {a : α} {xs ys : Array α} : count a (xs ++ ys) = count a xs + count a ys :=
countP_append
@[simp] theorem count_flatten (a : α) (xss : Array (Array α)) :
@[simp] theorem count_flatten {a : α} {xss : Array (Array α)} :
count a xss.flatten = (xss.map (count a)).sum := by
cases xss using array₂_induction
simp [List.count_flatten, Function.comp_def]
@[simp] theorem count_reverse (a : α) (xs : Array α) : count a xs.reverse = count a xs := by
@[simp] theorem count_reverse {a : α} {xs : Array α} : count a xs.reverse = count a xs := by
rcases xs with xs
simp
theorem boole_getElem_le_count (a : α) (xs : Array α) (i : Nat) (h : i < xs.size) :
theorem boole_getElem_le_count {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) :
(if xs[i] == a then 1 else 0) xs.count a := by
rw [count_eq_countP]
apply boole_getElem_le_countP (· == a)
apply boole_getElem_le_countP (p := (· == a))
theorem count_set (a b : α) (xs : Array α) (i : Nat) (h : i < xs.size) :
theorem count_set {xs : Array α} {i : Nat} {a b : α} (h : i < xs.size) :
(xs.set i a).count b = xs.count b - (if xs[i] == b then 1 else 0) + (if a == b then 1 else 0) := by
simp [count_eq_countP, countP_set, h]
variable [LawfulBEq α]
@[simp] theorem count_push_self (a : α) (xs : Array α) : count a (xs.push a) = count a xs + 1 := by
@[simp] theorem count_push_self {a : α} {xs : Array α} : count a (xs.push a) = count a xs + 1 := by
simp [count_push]
@[simp] theorem count_push_of_ne (h : b a) (xs : Array α) : count a (xs.push b) = count a xs := by
@[simp] theorem count_push_of_ne {xs : Array α} (h : b a) : count a (xs.push b) = count a xs := by
simp_all [count_push, h]
theorem count_singleton_self (a : α) : count a #[a] = 1 := by simp
theorem count_singleton_self {a : α} : count a #[a] = 1 := by simp
@[simp]
theorem count_pos_iff {a : α} {xs : Array α} : 0 < count a xs a xs := by
@@ -244,24 +241,24 @@ theorem count_eq_size {xs : Array α} : count a xs = xs.size ↔ ∀ b ∈ xs, a
· simpa using h b hb
· rw [h b hb, beq_self_eq_true]
@[simp] theorem count_replicate_self (a : α) (n : Nat) : count a (replicate n a) = n := by
@[simp] theorem count_replicate_self {a : α} {n : Nat} : count a (replicate n a) = n := by
simp [ List.toArray_replicate]
@[deprecated count_replicate_self (since := "2025-03-18")]
abbrev count_mkArray_self := @count_replicate_self
theorem count_replicate (a b : α) (n : Nat) : count a (replicate n b) = if b == a then n else 0 := by
theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by
simp [ List.toArray_replicate, List.count_replicate]
@[deprecated count_replicate (since := "2025-03-18")]
abbrev count_mkArray := @count_replicate
theorem filter_beq (xs : Array α) (a : α) : xs.filter (· == a) = replicate (count a xs) a := by
theorem filter_beq {xs : Array α} (a : α) : xs.filter (· == a) = replicate (count a xs) a := by
rcases xs with xs
simp [List.filter_beq]
theorem filter_eq {α} [DecidableEq α] (xs : Array α) (a : α) : xs.filter (· = a) = replicate (count a xs) a :=
filter_beq xs a
theorem filter_eq {α} [DecidableEq α] {xs : Array α} (a : α) : xs.filter (· = a) = replicate (count a xs) a :=
filter_beq a
theorem replicate_count_eq_of_count_eq_size {xs : Array α} (h : count a xs = xs.size) :
replicate (count a xs) a = xs := by
@@ -276,17 +273,17 @@ abbrev mkArray_count_eq_of_count_eq_size := @replicate_count_eq_of_count_eq_size
rcases xs with xs
simp [List.count_filter, h]
theorem count_le_count_map [DecidableEq β] (xs : Array α) (f : α β) (x : α) :
theorem count_le_count_map [DecidableEq β] {xs : Array α} {f : α β} {x : α} :
count x xs count (f x) (map f xs) := by
rcases xs with xs
simp [List.count_le_count_map, countP_map]
theorem count_filterMap {α} [BEq β] (b : β) (f : α Option β) (xs : Array α) :
theorem count_filterMap {α} [BEq β] {b : β} {f : α Option β} {xs : Array α} :
count b (filterMap f xs) = countP (fun a => f a == some b) xs := by
rcases xs with xs
simp [List.count_filterMap, countP_filterMap]
theorem count_flatMap {α} [BEq β] (xs : Array α) (f : α Array β) (x : β) :
theorem count_flatMap {α} [BEq β] {xs : Array α} {f : α Array β} {x : β} :
count x (xs.flatMap f) = sum (map (count x f) xs) := by
rcases xs with xs
simp [List.count_flatMap, countP_flatMap, Function.comp_def]

View File

@@ -71,7 +71,7 @@ theorem isEqv_eq_decide (xs ys : Array α) (r) :
theorem eq_of_isEqv [DecidableEq α] (xs ys : Array α) (h : Array.isEqv xs ys (fun x y => x = y)) : xs = ys := by
have h, h' := rel_of_isEqv h
exact ext _ _ h (fun i lt _ => by simpa using h' i lt)
exact ext h (fun i lt _ => by simpa using h' i lt)
private theorem isEqvAux_self (r : α α Bool) (hr : a, r a a) (xs : Array α) (i : Nat) (h : i xs.size) :
Array.isEqvAux xs xs rfl r i h = true := by

View File

@@ -46,6 +46,7 @@ theorem exists_of_eraseP {xs : Array α} {a} (hm : a ∈ xs) (hp : p a) :
obtain a, l₁, l₂, h₁, h₂, rfl, h₃ := List.exists_of_eraseP (by simpa using hm) (hp)
refine a, l₁, l₂, by simpa using h₁, h₂, by simp, by simpa using h₃
-- The arguments are explicit here, so this lemma can be used as a case split.
theorem exists_or_eq_self_of_eraseP (p) (xs : Array α) :
xs.eraseP p = xs
a ys zs, ( b ys, ¬p b) p a xs = ys.push a ++ zs xs.eraseP p = ys ++ zs :=
@@ -69,13 +70,13 @@ theorem size_eraseP {xs : Array α} : (xs.eraseP p).size = if xs.any p then xs.s
rw [eraseP_of_forall_getElem_not]
simp_all
theorem size_eraseP_le (xs : Array α) : (xs.eraseP p).size xs.size := by
theorem size_eraseP_le {xs : Array α} : (xs.eraseP p).size xs.size := by
rcases xs with xs
simpa using List.length_eraseP_le xs
simpa using List.length_eraseP_le
theorem le_size_eraseP (xs : Array α) : xs.size - 1 (xs.eraseP p).size := by
theorem le_size_eraseP {xs : Array α} : xs.size - 1 (xs.eraseP p).size := by
rcases xs with xs
simpa using List.le_length_eraseP xs
simpa using List.le_length_eraseP
theorem mem_of_mem_eraseP {xs : Array α} : a xs.eraseP p a xs := by
rcases xs with xs
@@ -89,19 +90,19 @@ theorem mem_of_mem_eraseP {xs : Array α} : a ∈ xs.eraseP p → a ∈ xs := by
rcases xs with xs
simp
theorem eraseP_map (f : β α) (xs : Array β) : (xs.map f).eraseP p = (xs.eraseP (p f)).map f := by
theorem eraseP_map {f : β α} {xs : Array β} : (xs.map f).eraseP p = (xs.eraseP (p f)).map f := by
rcases xs with xs
simpa using List.eraseP_map f xs
simpa using List.eraseP_map
theorem eraseP_filterMap (f : α Option β) (xs : Array α) :
theorem eraseP_filterMap {f : α Option β} {xs : Array α} :
(filterMap f xs).eraseP p = filterMap f (xs.eraseP (fun x => match f x with | some y => p y | none => false)) := by
rcases xs with xs
simpa using List.eraseP_filterMap f xs
simpa using List.eraseP_filterMap
theorem eraseP_filter (f : α Bool) (xs : Array α) :
theorem eraseP_filter {f : α Bool} {xs : Array α} :
(filter f xs).eraseP p = filter f (xs.eraseP (fun x => p x && f x)) := by
rcases xs with xs
simpa using List.eraseP_filter f xs
simpa using List.eraseP_filter
theorem eraseP_append_left {a : α} (pa : p a) {xs : Array α} {ys : Array α} (h : a xs) :
(xs ++ ys).eraseP p = xs.eraseP p ++ ys := by
@@ -122,7 +123,7 @@ theorem eraseP_append {xs : Array α} {ys : Array α} :
simp only [List.append_toArray, List.eraseP_toArray, List.eraseP_append, List.any_toArray]
split <;> simp
theorem eraseP_replicate (n : Nat) (a : α) (p : α Bool) :
theorem eraseP_replicate {n : Nat} {a : α} {p : α Bool} :
(replicate n a).eraseP p = if p a then replicate (n - 1) a else replicate n a := by
simp only [ List.toArray_replicate, List.eraseP_toArray, List.eraseP_replicate]
split <;> simp
@@ -175,10 +176,12 @@ theorem erase_of_not_mem [LawfulBEq α] {a : α} {xs : Array α} (h : a ∉ xs)
rcases xs with xs
simp [List.erase_of_not_mem (by simpa using h)]
-- The arguments are intentionally explicit.
theorem erase_eq_eraseP' (a : α) (xs : Array α) : xs.erase a = xs.eraseP (· == a) := by
rcases xs with xs
simp [List.erase_eq_eraseP']
-- The arguments are intentionally explicit.
theorem erase_eq_eraseP [LawfulBEq α] (a : α) (xs : Array α) : xs.erase a = xs.eraseP (a == ·) := by
rcases xs with xs
simp [List.erase_eq_eraseP]
@@ -202,19 +205,19 @@ theorem exists_erase_eq [LawfulBEq α] {a : α} {xs : Array α} (h : a ∈ xs) :
(xs.erase a).size = xs.size - 1 := by
rw [erase_eq_eraseP]; exact size_eraseP_of_mem h (beq_self_eq_true a)
theorem size_erase [LawfulBEq α] (a : α) (xs : Array α) :
theorem size_erase [LawfulBEq α] {a : α} {xs : Array α} :
(xs.erase a).size = if a xs then xs.size - 1 else xs.size := by
rw [erase_eq_eraseP, size_eraseP]
congr
simp [mem_iff_getElem, eq_comm (a := a)]
theorem size_erase_le (a : α) (xs : Array α) : (xs.erase a).size xs.size := by
theorem size_erase_le {a : α} {xs : Array α} : (xs.erase a).size xs.size := by
rcases xs with xs
simpa using List.length_erase_le a xs
simpa using List.length_erase_le
theorem le_size_erase [LawfulBEq α] (a : α) (xs : Array α) : xs.size - 1 (xs.erase a).size := by
theorem le_size_erase [LawfulBEq α] {a : α} {xs : Array α} : xs.size - 1 (xs.erase a).size := by
rcases xs with xs
simpa using List.le_length_erase a xs
simpa using List.le_length_erase
theorem mem_of_mem_erase {a b : α} {xs : Array α} (h : a xs.erase b) : a xs := by
rcases xs with xs
@@ -228,10 +231,10 @@ theorem mem_of_mem_erase {a b : α} {xs : Array α} (h : a ∈ xs.erase b) : a
rw [erase_eq_eraseP', eraseP_eq_self_iff]
simp [forall_mem_ne']
theorem erase_filter [LawfulBEq α] (f : α Bool) (xs : Array α) :
theorem erase_filter [LawfulBEq α] {f : α Bool} {xs : Array α} :
(filter f xs).erase a = filter f (xs.erase a) := by
rcases xs with xs
simpa using List.erase_filter f xs
simpa using List.erase_filter
theorem erase_append_left [LawfulBEq α] {xs : Array α} (ys) (h : a xs) :
(xs ++ ys).erase a = xs.erase a ++ ys := by
@@ -252,7 +255,7 @@ theorem erase_append [LawfulBEq α] {a : α} {xs ys : Array α} :
simp only [List.append_toArray, List.erase_toArray, List.erase_append, mem_toArray]
split <;> simp
theorem erase_replicate [LawfulBEq α] (n : Nat) (a b : α) :
theorem erase_replicate [LawfulBEq α] {n : Nat} {a b : α} :
(replicate n a).erase b = if b == a then replicate (n - 1) a else replicate n a := by
simp only [ List.toArray_replicate, List.erase_toArray]
simp only [List.erase_replicate, beq_iff_eq, List.toArray_replicate]
@@ -261,10 +264,12 @@ theorem erase_replicate [LawfulBEq α] (n : Nat) (a b : α) :
@[deprecated erase_replicate (since := "2025-03-18")]
abbrev erase_mkArray := @erase_replicate
theorem erase_comm [LawfulBEq α] (a b : α) (xs : Array α) :
-- The arguments `a b` are explicit,
-- so they can be specified to prevent `simp` repeatedly applying the lemma.
theorem erase_comm [LawfulBEq α] (a b : α) {xs : Array α} :
(xs.erase a).erase b = (xs.erase b).erase a := by
rcases xs with xs
simpa using List.erase_comm a b xs
simpa using List.erase_comm a b
theorem erase_eq_iff [LawfulBEq α] {a : α} {xs : Array α} :
xs.erase a = ys
@@ -304,7 +309,8 @@ theorem eraseIdx_eq_eraseIdxIfInBounds {xs : Array α} {i : Nat} (h : i < xs.siz
xs.eraseIdx i h = xs.eraseIdxIfInBounds i := by
simp [eraseIdxIfInBounds, h]
theorem eraseIdx_eq_take_drop_succ (xs : Array α) (i : Nat) (h) : xs.eraseIdx i = xs.take i ++ xs.drop (i + 1) := by
theorem eraseIdx_eq_take_drop_succ {xs : Array α} {i : Nat} (h) :
xs.eraseIdx i h = xs.take i ++ xs.drop (i + 1) := by
rcases xs with xs
simp only [List.size_toArray] at h
simp only [List.eraseIdx_toArray, List.eraseIdx_eq_take_drop_succ, take_eq_extract,
@@ -313,24 +319,24 @@ theorem eraseIdx_eq_take_drop_succ (xs : Array α) (i : Nat) (h) : xs.eraseIdx i
rw [List.take_of_length_le]
simp
theorem getElem?_eraseIdx (xs : Array α) (i : Nat) (h : i < xs.size) (j : Nat) :
theorem getElem?_eraseIdx {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} :
(xs.eraseIdx i)[j]? = if j < i then xs[j]? else xs[j + 1]? := by
rcases xs with xs
simp [List.getElem?_eraseIdx]
theorem getElem?_eraseIdx_of_lt (xs : Array α) (i : Nat) (h : i < xs.size) (j : Nat) (h' : j < i) :
theorem getElem?_eraseIdx_of_lt {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} (h' : j < i) :
(xs.eraseIdx i)[j]? = xs[j]? := by
rw [getElem?_eraseIdx]
simp [h']
theorem getElem?_eraseIdx_of_ge (xs : Array α) (i : Nat) (h : i < xs.size) (j : Nat) (h' : i j) :
theorem getElem?_eraseIdx_of_ge {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} (h' : i j) :
(xs.eraseIdx i)[j]? = xs[j + 1]? := by
rw [getElem?_eraseIdx]
simp only [dite_eq_ite, ite_eq_right_iff]
intro h'
omega
theorem getElem_eraseIdx (xs : Array α) (i : Nat) (h : i < xs.size) (j : Nat) (h' : j < (xs.eraseIdx i).size) :
theorem getElem_eraseIdx {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} (h' : j < (xs.eraseIdx i).size) :
(xs.eraseIdx i)[j] = if h'' : j < i then
xs[j]
else
@@ -388,18 +394,18 @@ theorem mem_eraseIdx_iff_getElem? {x : α} {xs : Array α} {k} {h} : x ∈ xs.er
rcases xs with xs
simp [List.mem_eraseIdx_iff_getElem?, *]
theorem erase_eq_eraseIdx_of_idxOf [BEq α] [LawfulBEq α] (xs : Array α) (a : α) (i : Nat) (w : xs.idxOf a = i) (h : i < xs.size) :
theorem erase_eq_eraseIdx_of_idxOf [BEq α] [LawfulBEq α] {xs : Array α} {a : α} {i : Nat} (w : xs.idxOf a = i) (h : i < xs.size) :
xs.erase a = xs.eraseIdx i := by
rcases xs with xs
simp at w
simp [List.erase_eq_eraseIdx_of_idxOf, *]
theorem getElem_eraseIdx_of_lt (xs : Array α) (i : Nat) (w : i < xs.size) (j : Nat) (h : j < (xs.eraseIdx i).size) (h' : j < i) :
theorem getElem_eraseIdx_of_lt {xs : Array α} {i : Nat} (w : i < xs.size) {j : Nat} (h : j < (xs.eraseIdx i).size) (h' : j < i) :
(xs.eraseIdx i)[j] = xs[j] := by
rcases xs with xs
simp [List.getElem_eraseIdx_of_lt, *]
theorem getElem_eraseIdx_of_ge (xs : Array α) (i : Nat) (w : i < xs.size) (j : Nat) (h : j < (xs.eraseIdx i).size) (h' : i j) :
theorem getElem_eraseIdx_of_ge {xs : Array α} {i : Nat} (w : i < xs.size) {j : Nat} (h : j < (xs.eraseIdx i).size) (h' : i j) :
(xs.eraseIdx i)[j] = xs[j + 1]'(by simp at h; omega) := by
rcases xs with xs
simp [List.getElem_eraseIdx_of_ge, *]

View File

@@ -322,32 +322,32 @@ theorem reverse_extract {as : Array α} {i j : Nat} :
/-! ### takeWhile -/
theorem takeWhile_map (f : α β) (p : β Bool) (as : Array α) :
theorem takeWhile_map {f : α β} {p : β Bool} {as : Array α} :
(as.map f).takeWhile p = (as.takeWhile (p f)).map f := by
rcases as with as
simp [List.takeWhile_map]
theorem popWhile_map (f : α β) (p : β Bool) (as : Array α) :
theorem popWhile_map {f : α β} {p : β Bool} {as : Array α} :
(as.map f).popWhile p = (as.popWhile (p f)).map f := by
rcases as with as
simp [List.dropWhile_map, List.map_reverse]
theorem takeWhile_filterMap (f : α Option β) (p : β Bool) (as : Array α) :
theorem takeWhile_filterMap {f : α Option β} {p : β Bool} {as : Array α} :
(as.filterMap f).takeWhile p = (as.takeWhile fun a => (f a).all p).filterMap f := by
rcases as with as
simp [List.takeWhile_filterMap]
theorem popWhile_filterMap (f : α Option β) (p : β Bool) (as : Array α) :
theorem popWhile_filterMap {f : α Option β} {p : β Bool} {as : Array α} :
(as.filterMap f).popWhile p = (as.popWhile fun a => (f a).all p).filterMap f := by
rcases as with as
simp [List.dropWhile_filterMap, List.filterMap_reverse]
theorem takeWhile_filter (p q : α Bool) (as : Array α) :
theorem takeWhile_filter {p q : α Bool} {as : Array α} :
(as.filter p).takeWhile q = (as.takeWhile fun a => !p a || q a).filter p := by
rcases as with as
simp [List.takeWhile_filter]
theorem popWhile_filter (p q : α Bool) (as : Array α) :
theorem popWhile_filter {p q : α Bool} {as : Array α} :
(as.filter p).popWhile q = (as.popWhile fun a => !p a || q a).filter p := by
rcases as with as
simp [List.dropWhile_filter, List.filter_reverse]
@@ -390,28 +390,28 @@ theorem popWhile_append {xs ys : Array α} :
rw [List.dropWhile_append_of_pos]
simpa
@[simp] theorem takeWhile_replicate_eq_filter (p : α Bool) :
@[simp] theorem takeWhile_replicate_eq_filter {p : α Bool} :
(replicate n a).takeWhile p = (replicate n a).filter p := by
simp [ List.toArray_replicate]
@[deprecated takeWhile_replicate_eq_filter (since := "2025-03-18")]
abbrev takeWhile_mkArray_eq_filter := @takeWhile_replicate_eq_filter
theorem takeWhile_replicate (p : α Bool) :
theorem takeWhile_replicate {p : α Bool} :
(replicate n a).takeWhile p = if p a then replicate n a else #[] := by
simp [takeWhile_replicate_eq_filter, filter_replicate]
@[deprecated takeWhile_replicate (since := "2025-03-18")]
abbrev takeWhile_mkArray := @takeWhile_replicate
@[simp] theorem popWhile_replicate_eq_filter_not (p : α Bool) :
@[simp] theorem popWhile_replicate_eq_filter_not {p : α Bool} :
(replicate n a).popWhile p = (replicate n a).filter (fun a => !p a) := by
simp [ List.toArray_replicate, List.filter_reverse]
@[deprecated popWhile_replicate_eq_filter_not (since := "2025-03-18")]
abbrev popWhile_mkArray_eq_filter_not := @popWhile_replicate_eq_filter_not
theorem popWhile_replicate (p : α Bool) :
theorem popWhile_replicate {p : α Bool} :
(replicate n a).popWhile p = if p a then #[] else replicate n a := by
simp only [popWhile_replicate_eq_filter_not, size_replicate, filter_replicate, Bool.not_eq_eq_eq_not,
Bool.not_true]

View File

@@ -21,23 +21,23 @@ Examples:
-/
protected def finRange (n : Nat) : Array (Fin n) := ofFn fun i => i
@[simp] theorem size_finRange (n) : (Array.finRange n).size = n := by
@[simp] theorem size_finRange {n} : (Array.finRange n).size = n := by
simp [Array.finRange]
@[simp] theorem getElem_finRange (i : Nat) (h : i < (Array.finRange n).size) :
(Array.finRange n)[i] = Fin.cast (size_finRange n) i, h := by
@[simp] theorem getElem_finRange {i : Nat} (h : i < (Array.finRange n).size) :
(Array.finRange n)[i] = Fin.cast size_finRange i, h := by
simp [Array.finRange]
@[simp] theorem finRange_zero : Array.finRange 0 = #[] := by simp [Array.finRange]
theorem finRange_succ (n) : Array.finRange (n+1) = #[0] ++ (Array.finRange n).map Fin.succ := by
theorem finRange_succ {n} : Array.finRange (n+1) = #[0] ++ (Array.finRange n).map Fin.succ := by
ext
· simp [Nat.add_comm]
· simp [getElem_append]
split <;>
· simp; omega
theorem finRange_succ_last (n) :
theorem finRange_succ_last {n} :
Array.finRange (n+1) = (Array.finRange n).map Fin.castSucc ++ #[Fin.last n] := by
ext
· simp
@@ -47,7 +47,7 @@ theorem finRange_succ_last (n) :
· simp_all
omega
theorem finRange_reverse (n) : (Array.finRange n).reverse = (Array.finRange n).map Fin.rev := by
theorem finRange_reverse {n} : (Array.finRange n).reverse = (Array.finRange n).map Fin.rev := by
ext i h
· simp
· simp

View File

@@ -21,10 +21,10 @@ open Nat
/-! ### findSome? -/
@[simp] theorem findSomeRev?_push_of_isSome (xs : Array α) (h : (f a).isSome) : (xs.push a).findSomeRev? f = f a := by
@[simp] theorem findSomeRev?_push_of_isSome {xs : Array α} (h : (f a).isSome) : (xs.push a).findSomeRev? f = f a := by
cases xs; simp_all
@[simp] theorem findSomeRev?_push_of_isNone (xs : Array α) (h : (f a).isNone) : (xs.push a).findSomeRev? f = xs.findSomeRev? f := by
@[simp] theorem findSomeRev?_push_of_isNone {xs : Array α} (h : (f a).isNone) : (xs.push a).findSomeRev? f = xs.findSomeRev? f := by
cases xs; simp_all
theorem exists_of_findSome?_eq_some {f : α Option β} {xs : Array α} (w : xs.findSome? f = some b) :
@@ -48,31 +48,31 @@ theorem findSome?_eq_some_iff {f : α → Option β} {xs : Array α} {b : β} :
· rintro xs, a, ys, h₀, h₁, h₂
exact xs.toList, a, ys.toList, by simpa using congrArg toList h₀, h₁, by simpa
@[simp] theorem findSome?_guard (xs : Array α) : findSome? (Option.guard fun x => p x) xs = find? p xs := by
@[simp] theorem findSome?_guard {xs : Array α} : findSome? (Option.guard fun x => p x) xs = find? p xs := by
cases xs; simp
theorem find?_eq_findSome?_guard (xs : Array α) : find? p xs = findSome? (Option.guard fun x => p x) xs :=
(findSome?_guard xs).symm
theorem find?_eq_findSome?_guard {xs : Array α} : find? p xs = findSome? (Option.guard fun x => p x) xs :=
findSome?_guard.symm
@[simp] theorem getElem?_zero_filterMap (f : α Option β) (xs : Array α) : (xs.filterMap f)[0]? = xs.findSome? f := by
@[simp] theorem getElem?_zero_filterMap {f : α Option β} {xs : Array α} : (xs.filterMap f)[0]? = xs.findSome? f := by
cases xs; simp [ List.head?_eq_getElem?]
@[simp] theorem getElem_zero_filterMap (f : α Option β) (xs : Array α) (h) :
@[simp] theorem getElem_zero_filterMap {f : α Option β} {xs : Array α} (h) :
(xs.filterMap f)[0] = (xs.findSome? f).get (by cases xs; simpa [List.length_filterMap_eq_countP] using h) := by
cases xs; simp [ List.head_eq_getElem, getElem?_zero_filterMap]
@[simp] theorem back?_filterMap (f : α Option β) (xs : Array α) : (xs.filterMap f).back? = xs.findSomeRev? f := by
@[simp] theorem back?_filterMap {f : α Option β} {xs : Array α} : (xs.filterMap f).back? = xs.findSomeRev? f := by
cases xs; simp
@[simp] theorem back!_filterMap [Inhabited β] (f : α Option β) (xs : Array α) :
@[simp] theorem back!_filterMap [Inhabited β] {f : α Option β} {xs : Array α} :
(xs.filterMap f).back! = (xs.findSomeRev? f).getD default := by
cases xs; simp
@[simp] theorem map_findSome? (f : α Option β) (g : β γ) (xs : Array α) :
@[simp] theorem map_findSome? {f : α Option β} {g : β γ} {xs : Array α} :
(xs.findSome? f).map g = xs.findSome? (Option.map g f) := by
cases xs; simp
theorem findSome?_map (f : β γ) (xs : Array β) : findSome? p (xs.map f) = xs.findSome? (p f) := by
theorem findSome?_map {f : β γ} {xs : Array β} : findSome? p (xs.map f) = xs.findSome? (p f) := by
cases xs; simp [List.findSome?_map]
theorem findSome?_append {xs ys : Array α} : (xs ++ ys).findSome? f = (xs.findSome? f).or (ys.findSome? f) := by
@@ -129,15 +129,15 @@ abbrev findSome?_mkArray_of_isNone := @findSome?_replicate_of_isNone
/-! ### find? -/
@[simp] theorem find?_singleton (a : α) (p : α Bool) :
@[simp] theorem find?_singleton {a : α} {p : α Bool} :
#[a].find? p = if p a then some a else none := by
simp [singleton_eq_toArray_singleton]
@[simp] theorem findRev?_push_of_pos (xs : Array α) (h : p a) :
@[simp] theorem findRev?_push_of_pos {xs : Array α} (h : p a) :
findRev? p (xs.push a) = some a := by
cases xs; simp [h]
@[simp] theorem findRev?_cons_of_neg (xs : Array α) (h : ¬p a) :
@[simp] theorem findRev?_cons_of_neg {xs : Array α} (h : ¬p a) :
findRev? p (xs.push a) = findRev? p xs := by
cases xs; simp [h]
@@ -183,28 +183,28 @@ theorem get_find?_mem {xs : Array α} (h) : (xs.find? p).get h ∈ xs := by
(xs.filter p).find? q = xs.find? (fun a => p a q a) := by
cases xs; simp
@[simp] theorem getElem?_zero_filter (p : α Bool) (xs : Array α) :
@[simp] theorem getElem?_zero_filter {p : α Bool} {xs : Array α} :
(xs.filter p)[0]? = xs.find? p := by
cases xs; simp [ List.head?_eq_getElem?]
@[simp] theorem getElem_zero_filter (p : α Bool) (xs : Array α) (h) :
@[simp] theorem getElem_zero_filter {p : α Bool} {xs : Array α} (h) :
(xs.filter p)[0] =
(xs.find? p).get (by cases xs; simpa [ List.countP_eq_length_filter] using h) := by
cases xs
simp [List.getElem_zero_eq_head]
@[simp] theorem back?_filter (p : α Bool) (xs : Array α) : (xs.filter p).back? = xs.findRev? p := by
@[simp] theorem back?_filter {p : α Bool} {xs : Array α} : (xs.filter p).back? = xs.findRev? p := by
cases xs; simp
@[simp] theorem back!_filter [Inhabited α] (p : α Bool) (xs : Array α) :
@[simp] theorem back!_filter [Inhabited α] {p : α Bool} {xs : Array α} :
(xs.filter p).back! = (xs.findRev? p).get! := by
cases xs; simp [Option.get!_eq_getD]
@[simp] theorem find?_filterMap (xs : Array α) (f : α Option β) (p : β Bool) :
@[simp] theorem find?_filterMap {xs : Array α} {f : α Option β} {p : β Bool} :
(xs.filterMap f).find? p = (xs.find? (fun a => (f a).any p)).bind f := by
cases xs; simp
@[simp] theorem find?_map (f : β α) (xs : Array β) :
@[simp] theorem find?_map {f : β α} {xs : Array β} :
find? p (xs.map f) = (xs.find? (p f)).map f := by
cases xs; simp
@@ -214,7 +214,7 @@ theorem get_find?_mem {xs : Array α} (h) : (xs.find? p).get h ∈ xs := by
cases ys
simp
@[simp] theorem find?_flatten (xss : Array (Array α)) (p : α Bool) :
@[simp] theorem find?_flatten {xss : Array (Array α)} {p : α Bool} :
xss.flatten.find? p = xss.findSome? (·.find? p) := by
cases xss using array₂_induction
simp [List.findSome?_map, Function.comp_def]
@@ -254,7 +254,7 @@ theorem find?_flatten_eq_some_iff {xss : Array (Array α)} {p : α → Bool} {a
@[deprecated find?_flatten_eq_some_iff (since := "2025-02-03")]
abbrev find?_flatten_eq_some := @find?_flatten_eq_some_iff
@[simp] theorem find?_flatMap (xs : Array α) (f : α Array β) (p : β Bool) :
@[simp] theorem find?_flatMap {xs : Array α} {f : α Array β} {p : β Bool} :
(xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by
cases xs
simp [List.find?_flatMap, Array.flatMap_toArray]
@@ -311,15 +311,15 @@ abbrev find?_mkArray_eq_some_iff := @find?_replicate_eq_some_iff
@[deprecated find?_replicate_eq_some_iff (since := "2025-02-03")]
abbrev find?_mkArray_eq_some := @find?_replicate_eq_some_iff
@[simp] theorem get_find?_replicate (n : Nat) (a : α) (p : α Bool) (h) :
@[simp] theorem get_find?_replicate {n : Nat} {a : α} {p : α Bool} (h) :
((replicate n a).find? p).get h = a := by
simp [ List.toArray_replicate]
@[deprecated get_find?_replicate (since := "2025-03-18")]
abbrev get_find?_mkArray := @get_find?_replicate
theorem find?_pmap {P : α Prop} (f : (a : α) P a β) (xs : Array α)
(H : (a : α), a xs P a) (p : β Bool) :
theorem find?_pmap {P : α Prop} {f : (a : α) P a β} {xs : Array α}
(H : (a : α), a xs P a) {p : β Bool} :
(xs.pmap f H).find? p = (xs.attach.find? (fun a, m => p (f a (H a m)))).map fun a, m => f a (H a m) := by
simp only [pmap_eq_map_attach, find?_map]
rfl
@@ -359,7 +359,7 @@ theorem findIdx_eq_size_of_false {p : α → Bool} {xs : Array α} (h : ∀ x
rcases xs with xs
simp_all
theorem findIdx_le_size (p : α Bool) {xs : Array α} : xs.findIdx p xs.size := by
theorem findIdx_le_size {p : α Bool} {xs : Array α} : xs.findIdx p xs.size := by
by_cases e : x xs, p x
· exact Nat.le_of_lt (findIdx_lt_size_of_exists e)
· simp at e
@@ -373,7 +373,7 @@ theorem findIdx_lt_size {p : α → Bool} {xs : Array α} :
/-- `p` does not hold for elements with indices less than `xs.findIdx p`. -/
theorem not_of_lt_findIdx {p : α Bool} {xs : Array α} {i : Nat} (h : i < xs.findIdx p) :
p (xs[i]'(Nat.le_trans h (findIdx_le_size p))) = false := by
p (xs[i]'(Nat.le_trans h findIdx_le_size)) = false := by
rcases xs with xs
simpa using List.not_of_lt_findIdx (by simpa using h)
@@ -404,7 +404,7 @@ theorem findIdx_eq {p : α → Bool} {xs : Array α} {i : Nat} (h : i < xs.size)
simp at h3
simp_all [not_of_lt_findIdx h3]
theorem findIdx_append (p : α Bool) (xs ys : Array α) :
theorem findIdx_append {p : α Bool} {xs ys : Array α} :
(xs ++ ys).findIdx p =
if xs.findIdx p < xs.size then xs.findIdx p else ys.findIdx p + xs.size := by
rcases xs with xs
@@ -492,7 +492,8 @@ theorem of_findIdx?_eq_none {xs : Array α} {p : α → Bool} (w : xs.findIdx? p
rcases xs with xs
simpa using List.of_findIdx?_eq_none (by simpa using w)
@[simp] theorem findIdx?_map (f : β α) (xs : Array β) : findIdx? p (xs.map f) = xs.findIdx? (p f) := by
@[simp] theorem findIdx?_map {f : β α} {xs : Array β} {p : α Bool} :
findIdx? p (xs.map f) = xs.findIdx? (p f) := by
rcases xs with xs
simp [List.findIdx?_map]

View File

@@ -23,7 +23,7 @@ theorem extLit {n : Nat}
(xs ys : Array α)
(hsz₁ : xs.size = n) (hsz₂ : ys.size = n)
(h : (i : Nat) (hi : i < n) xs.getLit i hsz₁ hi = ys.getLit i hsz₂ hi) : xs = ys :=
Array.ext xs ys (hsz₁.trans hsz₂.symm) fun i hi₁ _ => h i (hsz₁ hi₁)
Array.ext (hsz₁.trans hsz₂.symm) fun i hi₁ _ => h i (hsz₁ hi₁)
def toListLitAux (xs : Array α) (n : Nat) (hsz : xs.size = n) : (i : Nat), i xs.size List α List α
| 0, _, acc => acc

View File

@@ -30,13 +30,13 @@ section InsertIdx
variable {a : α}
@[simp] theorem toList_insertIdx (xs : Array α) (i x) (h) :
@[simp] theorem toList_insertIdx {xs : Array α} {i : Nat} {x : α} (h : i xs.size) :
(xs.insertIdx i x h).toList = xs.toList.insertIdx i x := by
rcases xs with xs
simp
@[simp]
theorem insertIdx_zero (xs : Array α) (x : α) : xs.insertIdx 0 x = #[x] ++ xs := by
theorem insertIdx_zero {xs : Array α} {x : α} : xs.insertIdx 0 x = #[x] ++ xs := by
rcases xs with xs
simp
@@ -44,7 +44,7 @@ theorem insertIdx_zero (xs : Array α) (x : α) : xs.insertIdx 0 x = #[x] ++ xs
rcases xs with xs
simp [List.length_insertIdx, h]
theorem eraseIdx_insertIdx (i : Nat) (xs : Array α) (h : i xs.size) :
theorem eraseIdx_insertIdx {i : Nat} {xs : Array α} (h : i xs.size) :
(xs.insertIdx i a).eraseIdx i (by simp; omega) = xs := by
rcases xs with xs
simp_all
@@ -54,27 +54,27 @@ theorem insertIdx_eraseIdx_of_ge {as : Array α}
(as.eraseIdx i).insertIdx j a =
(as.insertIdx (j + 1) a (by simp at w₂; omega)).eraseIdx i (by simp_all; omega) := by
cases as
simpa using List.insertIdx_eraseIdx_of_ge _ _ _ (by simpa) (by simpa)
simpa using List.insertIdx_eraseIdx_of_ge (by simpa) (by simpa)
theorem insertIdx_eraseIdx_of_le {as : Array α}
(w₁ : i < as.size) (w₂ : j (as.eraseIdx i).size) (h : j i) :
(as.eraseIdx i).insertIdx j a =
(as.insertIdx j a (by simp at w₂; omega)).eraseIdx (i + 1) (by simp_all) := by
cases as
simpa using List.insertIdx_eraseIdx_of_le _ _ _ (by simpa) (by simpa)
simpa using List.insertIdx_eraseIdx_of_le (by simpa) (by simpa)
theorem insertIdx_comm (a b : α) (i j : Nat) (xs : Array α) (_ : i j) (_ : j xs.size) :
theorem insertIdx_comm (a b : α) {i j : Nat} {xs : Array α} (_ : i j) (_ : j xs.size) :
(xs.insertIdx i a).insertIdx (j + 1) b (by simpa) =
(xs.insertIdx j b).insertIdx i a (by simp; omega) := by
rcases xs with xs
simpa using List.insertIdx_comm a b i j _ (by simpa) (by simpa)
simpa using List.insertIdx_comm a b (by simpa) (by simpa)
theorem mem_insertIdx {xs : Array α} {h : i xs.size} : a xs.insertIdx i b h a = b a xs := by
rcases xs with xs
simpa using List.mem_insertIdx (by simpa)
@[simp]
theorem insertIdx_size_self (xs : Array α) (x : α) : xs.insertIdx xs.size x = xs.push x := by
theorem insertIdx_size_self {xs : Array α} {x : α} : xs.insertIdx xs.size x = xs.push x := by
rcases xs with xs
simp

File diff suppressed because it is too large Load Diff

View File

@@ -14,18 +14,18 @@ namespace Array
/-! ### Lexicographic ordering -/
@[simp] theorem _root_.List.lt_toArray [LT α] (l₁ l₂ : List α) : l₁.toArray < l₂.toArray l₁ < l₂ := Iff.rfl
@[simp] theorem _root_.List.le_toArray [LT α] (l₁ l₂ : List α) : l₁.toArray l₂.toArray l₁ l₂ := Iff.rfl
@[simp] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray l₁ < l₂ := Iff.rfl
@[simp] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray l₂.toArray l₁ l₂ := Iff.rfl
@[simp] theorem lt_toList [LT α] (xs ys : Array α) : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp] theorem le_toList [LT α] (xs ys : Array α) : xs.toList ys.toList xs ys := Iff.rfl
@[simp] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ys.toList xs ys := Iff.rfl
protected theorem not_lt_iff_ge [LT α] (l₁ l₂ : List α) : ¬ l₁ < l₂ l₂ l₁ := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] (l₁ l₂ : List α) :
protected theorem not_lt_iff_ge [LT α] {l₁ l₂ : List α} : ¬ l₁ < l₂ l₂ l₁ := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {l₁ l₂ : List α} :
¬ l₁ l₂ l₂ < l₁ :=
Decidable.not_not
@[simp] theorem lex_empty [BEq α] {lt : α α Bool} (xs : Array α) : xs.lex #[] lt = false := by
@[simp] theorem lex_empty [BEq α] {lt : α α Bool} {xs : Array α} : xs.lex #[] lt = false := by
simp [lex, Id.run]
@[simp] theorem singleton_lex_singleton [BEq α] {lt : α α Bool} : #[a].lex #[b] lt = lt a b := by
@@ -45,7 +45,7 @@ private theorem cons_lex_cons [BEq α] {lt : αα → Bool} {a b : α} {xs
cases a == b <;> simp
· simp
@[simp] theorem _root_.List.lex_toArray [BEq α] (lt : α α Bool) (l₁ l₂ : List α) :
@[simp] theorem _root_.List.lex_toArray [BEq α] {lt : α α Bool} {l₁ l₂ : List α} :
l₁.toArray.lex l₂.toArray lt = l₁.lex l₂ lt := by
induction l₁ generalizing l₂ with
| nil => cases l₂ <;> simp [lex, Id.run]
@@ -55,7 +55,7 @@ private theorem cons_lex_cons [BEq α] {lt : αα → Bool} {a b : α} {xs
| cons y l₂ =>
rw [List.toArray_cons, List.toArray_cons y, cons_lex_cons, List.lex, ih]
@[simp] theorem lex_toList [BEq α] (lt : α α Bool) (xs ys : Array α) :
@[simp] theorem lex_toList [BEq α] {lt : α α Bool} {xs ys : Array α} :
xs.toList.lex ys.toList lt = xs.lex ys lt := by
cases xs <;> cases ys <;> simp
@@ -68,7 +68,7 @@ instance ltIrrefl [LT α] [Std.Irrefl (· < · : αα → Prop)] : Std.Irre
@[simp] theorem not_lt_empty [LT α] (xs : Array α) : ¬ xs < #[] := List.not_lt_nil xs.toList
@[simp] theorem empty_le [LT α] (xs : Array α) : #[] xs := List.nil_le xs.toList
@[simp] theorem le_empty [LT α] (xs : Array α) : xs #[] xs = #[] := by
@[simp] theorem le_empty [LT α] {xs : Array α} : xs #[] xs = #[] := by
cases xs
simp

View File

@@ -42,66 +42,66 @@ theorem mapFinIdx_induction (xs : Array α) (f : (i : Nat) → α → (h : i < x
· exact (hs j (by omega) hm).2
simp [mapFinIdx, mapFinIdxM]; exact go rfl nofun h0
theorem mapFinIdx_spec (xs : Array α) (f : (i : Nat) α (h : i < xs.size) β)
(p : (i : Nat) β (h : i < xs.size) Prop) (hs : i h, p i (f i xs[i] h) h) :
theorem mapFinIdx_spec {xs : Array α} {f : (i : Nat) α (h : i < xs.size) β}
{p : (i : Nat) β (h : i < xs.size) Prop} (hs : i h, p i (f i xs[i] h) h) :
eq : (Array.mapFinIdx xs f).size = xs.size,
i h, p i ((Array.mapFinIdx xs f)[i]) h :=
(mapFinIdx_induction _ _ (fun _ => True) trivial p fun _ _ _ => hs .., trivial).2
@[simp] theorem size_mapFinIdx (xs : Array α) (f : (i : Nat) α (h : i < xs.size) β) :
@[simp] theorem size_mapFinIdx {xs : Array α} {f : (i : Nat) α (h : i < xs.size) β} :
(xs.mapFinIdx f).size = xs.size :=
(mapFinIdx_spec (p := fun _ _ _ => True) (hs := fun _ _ => trivial)).1
@[simp] theorem size_zipIdx (xs : Array α) (k : Nat) : (xs.zipIdx k).size = xs.size :=
Array.size_mapFinIdx _ _
@[simp] theorem size_zipIdx {xs : Array α} {k : Nat} : (xs.zipIdx k).size = xs.size :=
Array.size_mapFinIdx
@[deprecated size_zipIdx (since := "2025-01-21")] abbrev size_zipWithIndex := @size_zipIdx
@[simp] theorem getElem_mapFinIdx (xs : Array α) (f : (i : Nat) α (h : i < xs.size) β) (i : Nat)
@[simp] theorem getElem_mapFinIdx {xs : Array α} {f : (i : Nat) α (h : i < xs.size) β} {i : Nat}
(h : i < (xs.mapFinIdx f).size) :
(xs.mapFinIdx f)[i] = f i (xs[i]'(by simp_all)) (by simp_all) :=
(mapFinIdx_spec _ _ (fun i b h => b = f i xs[i] h) fun _ _ => rfl).2 i _
(mapFinIdx_spec (p := fun i b h => b = f i xs[i] h) fun _ _ => rfl).2 i _
@[simp] theorem getElem?_mapFinIdx (xs : Array α) (f : (i : Nat) α (h : i < xs.size) β) (i : Nat) :
@[simp] theorem getElem?_mapFinIdx {xs : Array α} {f : (i : Nat) α (h : i < xs.size) β} {i : Nat} :
(xs.mapFinIdx f)[i]? =
xs[i]?.pbind fun b h => f i b (getElem?_eq_some_iff.1 h).1 := by
simp only [getElem?_def, size_mapFinIdx, getElem_mapFinIdx]
split <;> simp_all
@[simp] theorem toList_mapFinIdx (xs : Array α) (f : (i : Nat) α (h : i < xs.size) β) :
@[simp] theorem toList_mapFinIdx {xs : Array α} {f : (i : Nat) α (h : i < xs.size) β} :
(xs.mapFinIdx f).toList = xs.toList.mapFinIdx (fun i a h => f i a (by simpa)) := by
apply List.ext_getElem <;> simp
/-! ### mapIdx -/
theorem mapIdx_induction (f : Nat α β) (xs : Array α)
(motive : Nat Prop) (h0 : motive 0)
(p : (i : Nat) β (h : i < xs.size) Prop)
theorem mapIdx_induction {f : Nat α β} {xs : Array α}
{motive : Nat Prop} (h0 : motive 0)
{p : (i : Nat) β (h : i < xs.size) Prop}
(hs : i h, motive i p i (f i xs[i]) h motive (i + 1)) :
motive xs.size eq : (xs.mapIdx f).size = xs.size,
i h, p i ((xs.mapIdx f)[i]) h :=
mapFinIdx_induction xs (fun i a _ => f i a) motive h0 p hs
theorem mapIdx_spec (f : Nat α β) (xs : Array α)
(p : (i : Nat) β (h : i < xs.size) Prop) (hs : i h, p i (f i xs[i]) h) :
theorem mapIdx_spec {f : Nat α β} {xs : Array α}
{p : (i : Nat) β (h : i < xs.size) Prop} (hs : i h, p i (f i xs[i]) h) :
eq : (xs.mapIdx f).size = xs.size,
i h, p i ((xs.mapIdx f)[i]) h :=
(mapIdx_induction _ _ (fun _ => True) trivial p fun _ _ _ => hs .., trivial).2
(mapIdx_induction (motive := fun _ => True) trivial fun _ _ _ => hs .., trivial).2
@[simp] theorem size_mapIdx (f : Nat α β) (xs : Array α) : (xs.mapIdx f).size = xs.size :=
@[simp] theorem size_mapIdx {f : Nat α β} {xs : Array α} : (xs.mapIdx f).size = xs.size :=
(mapIdx_spec (p := fun _ _ _ => True) (hs := fun _ _ => trivial)).1
@[simp] theorem getElem_mapIdx (f : Nat α β) (xs : Array α) (i : Nat)
@[simp] theorem getElem_mapIdx {f : Nat α β} {xs : Array α} {i : Nat}
(h : i < (xs.mapIdx f).size) :
(xs.mapIdx f)[i] = f i (xs[i]'(by simp_all)) :=
(mapIdx_spec _ _ (fun i b h => b = f i xs[i]) fun _ _ => rfl).2 i (by simp_all)
(mapIdx_spec (p := fun i b h => b = f i xs[i]) fun _ _ => rfl).2 i (by simp_all)
@[simp] theorem getElem?_mapIdx (f : Nat α β) (xs : Array α) (i : Nat) :
@[simp] theorem getElem?_mapIdx {f : Nat α β} {xs : Array α} {i : Nat} :
(xs.mapIdx f)[i]? =
xs[i]?.map (f i) := by
simp [getElem?_def, size_mapIdx, getElem_mapIdx]
@[simp] theorem toList_mapIdx (f : Nat α β) (xs : Array α) :
@[simp] theorem toList_mapIdx {f : Nat α β} {xs : Array α} :
(xs.mapIdx f).toList = xs.toList.mapIdx (fun i a => f i a) := by
apply List.ext_getElem <;> simp
@@ -109,11 +109,11 @@ end Array
namespace List
@[simp] theorem mapFinIdx_toArray (l : List α) (f : (i : Nat) α (h : i < l.length) β) :
@[simp] theorem mapFinIdx_toArray {l : List α} {f : (i : Nat) α (h : i < l.length) β} :
l.toArray.mapFinIdx f = (l.mapFinIdx f).toArray := by
ext <;> simp
@[simp] theorem mapIdx_toArray (f : Nat α β) (l : List α) :
@[simp] theorem mapIdx_toArray {f : Nat α β} {l : List α} :
l.toArray.mapIdx f = (l.mapIdx f).toArray := by
ext <;> simp
@@ -123,7 +123,7 @@ namespace Array
/-! ### zipIdx -/
@[simp] theorem getElem_zipIdx (xs : Array α) (k : Nat) (i : Nat) (h : i < (xs.zipIdx k).size) :
@[simp] theorem getElem_zipIdx {xs : Array α} {k : Nat} {i : Nat} (h : i < (xs.zipIdx k).size) :
(xs.zipIdx k)[i] = (xs[i]'(by simp_all), k + i) := by
simp [zipIdx]
@@ -137,7 +137,7 @@ abbrev getElem_zipWithIndex := @getElem_zipIdx
@[deprecated zipIdx_toArray (since := "2025-01-21")]
abbrev zipWithIndex_toArray := @zipIdx_toArray
@[simp] theorem toList_zipIdx (xs : Array α) (k : Nat) :
@[simp] theorem toList_zipIdx {xs : Array α} {k : Nat} :
(xs.zipIdx k).toList = xs.toList.zipIdx k := by
rcases xs with xs
simp
@@ -452,8 +452,8 @@ end Array
namespace List
theorem mapFinIdxM_toArray [Monad m] [LawfulMonad m] (l : List α)
(f : (i : Nat) α (h : i < l.length) m β) :
theorem mapFinIdxM_toArray [Monad m] [LawfulMonad m] {l : List α}
{f : (i : Nat) α (h : i < l.length) m β} :
l.toArray.mapFinIdxM f = toArray <$> l.mapFinIdxM f := by
let rec go (i : Nat) (acc : Array β) (inv : i + acc.size = l.length) :
Array.mapFinIdxM.map l.toArray f i acc.size inv acc
@@ -464,17 +464,17 @@ theorem mapFinIdxM_toArray [Monad m] [LawfulMonad m] (l : List α)
rw [Nat.zero_add] at inv
simp only [Array.mapFinIdxM.map, inv, drop_length, mapFinIdxM.go, map_pure]
| k + 1 =>
conv => enter [2, 2, 3]; rw [ getElem_cons_drop l acc.size (by omega)]
conv => enter [2, 2, 3]; rw [ getElem_cons_drop (by omega)]
simp only [Array.mapFinIdxM.map, mapFinIdxM.go, _root_.map_bind]
congr; funext x
conv => enter [1, 4]; rw [ Array.size_push _ x]
conv => enter [2, 2, 3]; rw [ Array.size_push _ x]
conv => enter [1, 4]; rw [ Array.size_push x]
conv => enter [2, 2, 3]; rw [ Array.size_push x]
refine go k (acc.push x) _
simp only [Array.mapFinIdxM, mapFinIdxM]
exact go _ #[] _
theorem mapIdxM_toArray [Monad m] [LawfulMonad m] (l : List α)
(f : Nat α m β) :
theorem mapIdxM_toArray [Monad m] [LawfulMonad m] {l : List α}
{f : Nat α m β} :
l.toArray.mapIdxM f = toArray <$> l.mapIdxM f := by
let rec go (bs : List α) (acc : Array β) (inv : bs.length + acc.size = l.length) :
mapFinIdxM.go l (fun i a h => f i a) bs acc inv = mapIdxM.go f bs acc := by
@@ -490,14 +490,14 @@ end List
namespace Array
theorem toList_mapFinIdxM [Monad m] [LawfulMonad m] (xs : Array α)
(f : (i : Nat) α (h : i < xs.size) m β) :
theorem toList_mapFinIdxM [Monad m] [LawfulMonad m] {xs : Array α}
{f : (i : Nat) α (h : i < xs.size) m β} :
toList <$> xs.mapFinIdxM f = xs.toList.mapFinIdxM f := by
rw [List.mapFinIdxM_toArray]
simp only [Functor.map_map, id_map']
theorem toList_mapIdxM [Monad m] [LawfulMonad m] (xs : Array α)
(f : Nat α m β) :
theorem toList_mapIdxM [Monad m] [LawfulMonad m] {xs : Array α}
{f : Nat α m β} :
toList <$> xs.mapIdxM f = xs.toList.mapIdxM f := by
rw [List.mapIdxM_toArray]
simp only [Functor.map_map, id_map']

View File

@@ -23,20 +23,20 @@ open Nat
/-! ### mapM -/
@[simp] theorem mapM_pure [Monad m] [LawfulMonad m] (xs : Array α) (f : α β) :
@[simp] theorem mapM_pure [Monad m] [LawfulMonad m] {xs : Array α} {f : α β} :
xs.mapM (m := m) (pure <| f ·) = pure (xs.map f) := by
induction xs; simp_all
@[simp] theorem mapM_id {xs : Array α} {f : α Id β} : xs.mapM f = xs.map f :=
mapM_pure _ _
mapM_pure
@[simp] theorem mapM_append [Monad m] [LawfulMonad m] (f : α m β) {xs ys : Array α} :
@[simp] theorem mapM_append [Monad m] [LawfulMonad m] {f : α m β} {xs ys : Array α} :
(xs ++ ys).mapM f = (return ( xs.mapM f) ++ ( ys.mapM f)) := by
rcases xs with xs
rcases ys with ys
simp
theorem mapM_eq_foldlM_push [Monad m] [LawfulMonad m] (f : α m β) (xs : Array α) :
theorem mapM_eq_foldlM_push [Monad m] [LawfulMonad m] {f : α m β} {xs : Array α} :
mapM f xs = xs.foldlM (fun acc a => return (acc.push ( f a))) #[] := by
rcases xs with xs
simp only [List.mapM_toArray, bind_pure_comp, List.size_toArray, List.foldlM_toArray']
@@ -53,21 +53,21 @@ theorem mapM_eq_foldlM_push [Monad m] [LawfulMonad m] (f : α → m β) (xs : Ar
/-! ### foldlM and foldrM -/
theorem foldlM_map [Monad m] (f : β₁ β₂) (g : α β₂ m α) (xs : Array β₁) (init : α) (w : stop = xs.size) :
theorem foldlM_map [Monad m] {f : β₁ β₂} {g : α β₂ m α} {xs : Array β₁} {init : α} {w : stop = xs.size} :
(xs.map f).foldlM g init 0 stop = xs.foldlM (fun x y => g x (f y)) init 0 stop := by
subst w
cases xs
simp [List.foldlM_map]
theorem foldrM_map [Monad m] [LawfulMonad m] (f : β₁ β₂) (g : β₂ α m α) (xs : Array β₁)
(init : α) (w : start = xs.size) :
theorem foldrM_map [Monad m] [LawfulMonad m] {f : β₁ β₂} {g : β₂ α m α} {xs : Array β₁}
{init : α} {w : start = xs.size} :
(xs.map f).foldrM g init start 0 = xs.foldrM (fun x y => g (f x) y) init start 0 := by
subst w
cases xs
simp [List.foldrM_map]
theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α Option β) (g : γ β m γ)
(xs : Array α) (init : γ) (w : stop = (xs.filterMap f).size) :
theorem foldlM_filterMap [Monad m] [LawfulMonad m] {f : α Option β} {g : γ β m γ} {xs : Array α}
{init : γ} {w : stop = (xs.filterMap f).size} :
(xs.filterMap f).foldlM g init 0 stop =
xs.foldlM (fun x y => match f y with | some b => g x b | none => pure x) init := by
subst w
@@ -75,8 +75,8 @@ theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g :
simp [List.foldlM_filterMap]
rfl
theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α Option β) (g : β γ m γ)
(xs : Array α) (init : γ) (w : start = (xs.filterMap f).size) :
theorem foldrM_filterMap [Monad m] [LawfulMonad m] {f : α Option β} {g : β γ m γ} {xs : Array α}
{init : γ} {w : start = (xs.filterMap f).size} :
(xs.filterMap f).foldrM g init start 0 =
xs.foldrM (fun x y => match f x with | some b => g b y | none => pure y) init := by
subst w
@@ -84,16 +84,16 @@ theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g :
simp [List.foldrM_filterMap]
rfl
theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α Bool) (g : β α m β)
(xs : Array α) (init : β) (w : stop = (xs.filter p).size) :
theorem foldlM_filter [Monad m] [LawfulMonad m] {p : α Bool} {g : β α m β} {xs : Array α}
{init : β} {w : stop = (xs.filter p).size} :
(xs.filter p).foldlM g init 0 stop =
xs.foldlM (fun x y => if p y then g x y else pure x) init := by
subst w
cases xs
simp [List.foldlM_filter]
theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α Bool) (g : α β m β)
(xs : Array α) (init : β) (w : start = (xs.filter p).size) :
theorem foldrM_filter [Monad m] [LawfulMonad m] {p : α Bool} {g : α β m β} {xs : Array α}
{init : β} {w : start = (xs.filter p).size} :
(xs.filter p).foldrM g init start 0 =
xs.foldrM (fun x y => if p x then g x y else pure y) init := by
subst w
@@ -101,7 +101,7 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β
simp [List.foldrM_filter]
@[simp] theorem foldlM_attachWith [Monad m]
(xs : Array α) {q : α Prop} (H : a, a xs q a) {f : β { x // q x} m β} {b} (w : stop = xs.size):
{xs : Array α} {q : α Prop} (H : a, a xs q a) {f : β { x // q x} m β} {b} (w : stop = xs.size):
(xs.attachWith q H).foldlM f b 0 stop =
xs.attach.foldlM (fun b a, h => f b a, H _ h) b := by
subst w
@@ -109,7 +109,8 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β
simp [List.foldlM_map]
@[simp] theorem foldrM_attachWith [Monad m] [LawfulMonad m]
(xs : Array α) {q : α Prop} (H : a, a xs q a) {f : { x // q x} β m β} {b} (w : start = xs.size):
{xs : Array α} {q : α Prop} (H : a, a xs q a) {f : { x // q x} β m β} {b}
{w : start = xs.size} :
(xs.attachWith q H).foldrM f b start 0 =
xs.attach.foldrM (fun a acc => f a.1, H _ a.2 acc) b := by
subst w
@@ -124,13 +125,13 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β
cases as <;> cases bs
simp_all
@[simp] theorem forM_append [Monad m] [LawfulMonad m] (xs ys : Array α) (f : α m PUnit) :
@[simp] theorem forM_append [Monad m] [LawfulMonad m] {xs ys : Array α} {f : α m PUnit} :
forM (xs ++ ys) f = (do forM xs f; forM ys f) := by
rcases xs with xs
rcases ys with ys
simp
@[simp] theorem forM_map [Monad m] [LawfulMonad m] (xs : Array α) (g : α β) (f : β m PUnit) :
@[simp] theorem forM_map [Monad m] [LawfulMonad m] {xs : Array α} {g : α β} {f : β m PUnit} :
forM (xs.map g) f = forM xs (fun a => f (g a)) := by
rcases xs with xs
simp
@@ -152,7 +153,7 @@ We can express a for loop over an array as a fold,
in which whenever we reach `.done b` we keep that value through the rest of the fold.
-/
theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
(xs : Array α) (f : (a : α) a xs β m (ForInStep β)) (init : β) :
{xs : Array α} (f : (a : α) a xs β m (ForInStep β)) (init : β) :
forIn' xs init f = ForInStep.value <$>
xs.attach.foldlM (fun b a, m => match b with
| .yield b => f a m b
@@ -163,29 +164,29 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
/-- We can express a for loop over an array which always yields as a fold. -/
@[simp] theorem forIn'_yield_eq_foldlM [Monad m] [LawfulMonad m]
(xs : Array α) (f : (a : α) a xs β m γ) (g : (a : α) a xs β γ β) (init : β) :
{xs : Array α} (f : (a : α) a xs β m γ) (g : (a : α) a xs β γ β) (init : β) :
forIn' xs init (fun a m b => (fun c => .yield (g a m b c)) <$> f a m b) =
xs.attach.foldlM (fun b a, m => g a m b <$> f a m b) init := by
rcases xs with xs
simp [List.foldlM_map]
@[simp] theorem forIn'_pure_yield_eq_foldl [Monad m] [LawfulMonad m]
(xs : Array α) (f : (a : α) a xs β β) (init : β) :
{xs : Array α} (f : (a : α) a xs β β) (init : β) :
forIn' xs init (fun a m b => pure (.yield (f a m b))) =
pure (f := m) (xs.attach.foldl (fun b a, h => f a h b) init) := by
rcases xs with xs
simp [List.forIn'_pure_yield_eq_foldl, List.foldl_map]
@[simp] theorem forIn'_yield_eq_foldl
(xs : Array α) (f : (a : α) a xs β β) (init : β) :
{xs : Array α} (f : (a : α) a xs β β) (init : β) :
forIn' (m := Id) xs init (fun a m b => .yield (f a m b)) =
xs.attach.foldl (fun b a, h => f a h b) init := by
rcases xs with xs
simp [List.foldl_map]
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
(xs : Array α) (g : α β) (f : (b : β) b xs.map g γ m (ForInStep γ)) :
forIn' (xs.map g) init f = forIn' xs init fun a h y => f (g a) (mem_map_of_mem g h) y := by
{xs : Array α} (g : α β) (f : (b : β) b xs.map g γ m (ForInStep γ)) :
forIn' (xs.map g) init f = forIn' xs init fun a h y => f (g a) (mem_map_of_mem h) y := by
rcases xs with xs
simp
@@ -194,7 +195,7 @@ We can express a for loop over an array as a fold,
in which whenever we reach `.done b` we keep that value through the rest of the fold.
-/
theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
(f : α β m (ForInStep β)) (init : β) (xs : Array α) :
{xs : Array α} (f : α β m (ForInStep β)) (init : β) :
forIn xs init f = ForInStep.value <$>
xs.foldlM (fun b a => match b with
| .yield b => f a b
@@ -205,40 +206,40 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
/-- We can express a for loop over an array which always yields as a fold. -/
@[simp] theorem forIn_yield_eq_foldlM [Monad m] [LawfulMonad m]
(xs : Array α) (f : α β m γ) (g : α β γ β) (init : β) :
{xs : Array α} (f : α β m γ) (g : α β γ β) (init : β) :
forIn xs init (fun a b => (fun c => .yield (g a b c)) <$> f a b) =
xs.foldlM (fun b a => g a b <$> f a b) init := by
rcases xs with xs
simp [List.foldlM_map]
@[simp] theorem forIn_pure_yield_eq_foldl [Monad m] [LawfulMonad m]
(xs : Array α) (f : α β β) (init : β) :
{xs : Array α} (f : α β β) (init : β) :
forIn xs init (fun a b => pure (.yield (f a b))) =
pure (f := m) (xs.foldl (fun b a => f a b) init) := by
rcases xs with xs
simp [List.forIn_pure_yield_eq_foldl, List.foldl_map]
@[simp] theorem forIn_yield_eq_foldl
(xs : Array α) (f : α β β) (init : β) :
{xs : Array α} (f : α β β) (init : β) :
forIn (m := Id) xs init (fun a b => .yield (f a b)) =
xs.foldl (fun b a => f a b) init := by
rcases xs with xs
simp [List.foldl_map]
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
(xs : Array α) (g : α β) (f : β γ m (ForInStep γ)) :
{xs : Array α} {g : α β} {f : β γ m (ForInStep γ)} :
forIn (xs.map g) init f = forIn xs init fun a y => f (g a) y := by
rcases xs with xs
simp
/-! ### allM and anyM -/
@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] (p : α Bool) (xs : Array α) :
@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] {p : α Bool} {xs : Array α} :
xs.anyM (m := m) (pure <| p ·) = pure (xs.any p) := by
cases xs
simp
@[simp] theorem allM_pure [Monad m] [LawfulMonad m] (p : α Bool) (xs : Array α) :
@[simp] theorem allM_pure [Monad m] [LawfulMonad m] {p : α Bool} {xs : Array α} :
xs.allM (m := m) (pure <| p ·) = pure (xs.all p) := by
cases xs
simp
@@ -246,13 +247,13 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
/-! ### findM? and findSomeM? -/
@[simp]
theorem findM?_pure {m} [Monad m] [LawfulMonad m] (p : α Bool) (xs : Array α) :
theorem findM?_pure {m} [Monad m] [LawfulMonad m] {p : α Bool} {xs : Array α} :
findM? (m := m) (pure <| p ·) xs = pure (xs.find? p) := by
cases xs
simp
@[simp]
theorem findSomeM?_pure [Monad m] [LawfulMonad m] (f : α Option β) (xs : Array α) :
theorem findSomeM?_pure [Monad m] [LawfulMonad m] {f : α Option β} {xs : Array α} :
findSomeM? (m := m) (pure <| f ·) xs = pure (xs.findSome? f) := by
cases xs
simp
@@ -261,7 +262,7 @@ end Array
namespace List
theorem filterM_toArray [Monad m] [LawfulMonad m] (l : List α) (p : α m Bool) :
theorem filterM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α m Bool} :
l.toArray.filterM p = toArray <$> l.filterM p := by
simp only [Array.filterM, filterM, foldlM_toArray, bind_pure_comp, Functor.map_map]
conv => lhs; rw [ reverse_nil]
@@ -276,24 +277,24 @@ theorem filterM_toArray [Monad m] [LawfulMonad m] (l : List α) (p : α → m Bo
exact ih (x :: acc)
/-- Variant of `filterM_toArray` with a side condition for the stop position. -/
@[simp] theorem filterM_toArray' [Monad m] [LawfulMonad m] (l : List α) (p : α m Bool) (w : stop = l.length) :
@[simp] theorem filterM_toArray' [Monad m] [LawfulMonad m] {l : List α} {p : α m Bool} (w : stop = l.length) :
l.toArray.filterM p 0 stop = toArray <$> l.filterM p := by
subst w
rw [filterM_toArray]
theorem filterRevM_toArray [Monad m] [LawfulMonad m] (l : List α) (p : α m Bool) :
theorem filterRevM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α m Bool} :
l.toArray.filterRevM p = toArray <$> l.filterRevM p := by
simp [Array.filterRevM, filterRevM]
rw [ foldlM_reverse, foldlM_toArray, Array.filterM, filterM_toArray]
simp only [filterM, bind_pure_comp, Functor.map_map, reverse_toArray, reverse_reverse]
/-- Variant of `filterRevM_toArray` with a side condition for the start position. -/
@[simp] theorem filterRevM_toArray' [Monad m] [LawfulMonad m] (l : List α) (p : α m Bool) (w : start = l.length) :
@[simp] theorem filterRevM_toArray' [Monad m] [LawfulMonad m] {l : List α} {p : α m Bool} (w : start = l.length) :
l.toArray.filterRevM p start 0 = toArray <$> l.filterRevM p := by
subst w
rw [filterRevM_toArray]
theorem filterMapM_toArray [Monad m] [LawfulMonad m] (l : List α) (f : α m (Option β)) :
theorem filterMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α m (Option β)} :
l.toArray.filterMapM f = toArray <$> l.filterMapM f := by
simp [Array.filterMapM, filterMapM]
conv => lhs; rw [ reverse_nil]
@@ -306,12 +307,12 @@ theorem filterMapM_toArray [Monad m] [LawfulMonad m] (l : List α) (f : α → m
· simp only [pure_bind]; rw [ List.reverse_cons]; exact ih _
/-- Variant of `filterMapM_toArray` with a side condition for the stop position. -/
@[simp] theorem filterMapM_toArray' [Monad m] [LawfulMonad m] (l : List α) (f : α m (Option β)) (w : stop = l.length) :
@[simp] theorem filterMapM_toArray' [Monad m] [LawfulMonad m] {l : List α} {f : α m (Option β)} (w : stop = l.length) :
l.toArray.filterMapM f 0 stop = toArray <$> l.filterMapM f := by
subst w
rw [filterMapM_toArray]
@[simp] theorem flatMapM_toArray [Monad m] [LawfulMonad m] (l : List α) (f : α m (Array β)) :
@[simp] theorem flatMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α m (Array β)} :
l.toArray.flatMapM f = toArray <$> l.flatMapM (fun a => Array.toList <$> f a) := by
simp only [Array.flatMapM, bind_pure_comp, foldlM_toArray, flatMapM]
conv => lhs; arg 2; change [].reverse.flatten.toArray
@@ -352,22 +353,22 @@ namespace Array
subst w
simp [flatMapM, h]
theorem toList_filterM [Monad m] [LawfulMonad m] (xs : Array α) (p : α m Bool) :
theorem toList_filterM [Monad m] [LawfulMonad m] {xs : Array α} {p : α m Bool} :
toList <$> xs.filterM p = xs.toList.filterM p := by
rw [List.filterM_toArray]
simp only [Functor.map_map, id_map']
theorem toList_filterRevM [Monad m] [LawfulMonad m] (xs : Array α) (p : α m Bool) :
theorem toList_filterRevM [Monad m] [LawfulMonad m] {xs : Array α} {p : α m Bool} :
toList <$> xs.filterRevM p = xs.toList.filterRevM p := by
rw [List.filterRevM_toArray]
simp only [Functor.map_map, id_map']
theorem toList_filterMapM [Monad m] [LawfulMonad m] (xs : Array α) (f : α m (Option β)) :
theorem toList_filterMapM [Monad m] [LawfulMonad m] {xs : Array α} {f : α m (Option β)} :
toList <$> xs.filterMapM f = xs.toList.filterMapM f := by
rw [List.filterMapM_toArray]
simp only [Functor.map_map, id_map']
theorem toList_flatMapM [Monad m] [LawfulMonad m] (xs : Array α) (f : α m (Array β)) :
theorem toList_flatMapM [Monad m] [LawfulMonad m] {xs : Array α} {f : α m (Array β)} :
toList <$> xs.flatMapM f = xs.toList.flatMapM (fun a => toList <$> f a) := by
rw [List.flatMapM_toArray]
simp only [Functor.map_map, id_map']
@@ -387,11 +388,11 @@ and simplifies these to the function directly taking the value.
simp
rw [List.foldlM_subtype hf]
@[wf_preprocess] theorem foldlM_wfParam [Monad m] (xs : Array α) (f : β α m β) (init : β) :
@[wf_preprocess] theorem foldlM_wfParam [Monad m] {xs : Array α} {f : β α m β} {init : β} :
(wfParam xs).foldlM f init = xs.attach.unattach.foldlM f init := by
simp [wfParam]
@[wf_preprocess] theorem foldlM_unattach [Monad m] (P : α Prop) (xs : Array (Subtype P)) (f : β α m β) (init : β) :
@[wf_preprocess] theorem foldlM_unattach [Monad m] {P : α Prop} {xs : Array (Subtype P)} {f : β α m β} {init : β} :
xs.unattach.foldlM f init = xs.foldlM (init := init) fun b x, h =>
binderNameHint b f <| binderNameHint x (f b) <| binderNameHint h () <|
f b (wfParam x) := by
@@ -411,11 +412,11 @@ and simplifies these to the function directly taking the value.
rw [List.foldrM_subtype hf]
@[wf_preprocess] theorem foldrM_wfParam [Monad m] [LawfulMonad m] (xs : Array α) (f : α β m β) (init : β) :
@[wf_preprocess] theorem foldrM_wfParam [Monad m] [LawfulMonad m] {xs : Array α} {f : α β m β} {init : β} :
(wfParam xs).foldrM f init = xs.attach.unattach.foldrM f init := by
simp [wfParam]
@[wf_preprocess] theorem foldrM_unattach [Monad m] [LawfulMonad m] (P : α Prop) (xs : Array (Subtype P)) (f : α β m β) (init : β):
@[wf_preprocess] theorem foldrM_unattach [Monad m] [LawfulMonad m] {P : α Prop} {xs : Array (Subtype P)} {f : α β m β} {init : β} :
xs.unattach.foldrM f init = xs.foldrM (init := init) fun x, h b =>
binderNameHint x f <| binderNameHint h () <| binderNameHint b (f x) <|
f (wfParam x) b := by
@@ -432,11 +433,11 @@ and simplifies these to the function directly taking the value.
simp
rw [List.mapM_subtype hf]
@[wf_preprocess] theorem mapM_wfParam [Monad m] [LawfulMonad m] (xs : Array α) (f : α m β) :
@[wf_preprocess] theorem mapM_wfParam [Monad m] [LawfulMonad m] {xs : Array α} {f : α m β} :
(wfParam xs).mapM f = xs.attach.unattach.mapM f := by
simp [wfParam]
@[wf_preprocess] theorem mapM_unattach [Monad m] [LawfulMonad m] (P : α Prop) (xs : Array (Subtype P)) (f : α m β) :
@[wf_preprocess] theorem mapM_unattach [Monad m] [LawfulMonad m] {P : α Prop} {xs : Array (Subtype P)} {f : α m β} :
xs.unattach.mapM f = xs.mapM fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]
@@ -451,12 +452,12 @@ and simplifies these to the function directly taking the value.
@[wf_preprocess] theorem filterMapM_wfParam [Monad m] [LawfulMonad m]
(xs : Array α) (f : α m (Option β)) :
{xs : Array α} {f : α m (Option β)} :
(wfParam xs).filterMapM f = xs.attach.unattach.filterMapM f := by
simp [wfParam]
@[wf_preprocess] theorem filterMapM_unattach [Monad m] [LawfulMonad m]
(P : α Prop) (xs : Array (Subtype P)) (f : α m (Option β)) :
{P : α Prop} {xs : Array (Subtype P)} {f : α m (Option β)} :
xs.unattach.filterMapM f = xs.filterMapM fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]
@@ -470,12 +471,12 @@ and simplifies these to the function directly taking the value.
simp [hf]
@[wf_preprocess] theorem flatMapM_wfParam [Monad m] [LawfulMonad m]
(xs : Array α) (f : α m (Array β)) :
{xs : Array α} {f : α m (Array β)} :
(wfParam xs).flatMapM f = xs.attach.unattach.flatMapM f := by
simp [wfParam]
@[wf_preprocess] theorem flatMapM_unattach [Monad m] [LawfulMonad m]
(P : α Prop) (xs : Array (Subtype P)) (f : α m (Array β)) :
{P : α Prop} {xs : Array (Subtype P)} {f : α m (Array β)} :
xs.unattach.flatMapM f = xs.flatMapM fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]

View File

@@ -16,10 +16,10 @@ set_option linter.indexVariables true -- Enforce naming conventions for index va
namespace Array
@[simp] theorem ofFn_zero (f : Fin 0 α) : ofFn f = #[] := by
@[simp] theorem ofFn_zero {f : Fin 0 α} : ofFn f = #[] := by
simp [ofFn, ofFn.go]
theorem ofFn_succ (f : Fin (n+1) α) :
theorem ofFn_succ {f : Fin (n+1) α} :
ofFn f = (ofFn (fun (i : Fin n) => f i.castSucc)).push (f n, by omega) := by
ext i h₁ h₂
· simp
@@ -30,10 +30,10 @@ theorem ofFn_succ (f : Fin (n+1) → α) :
simp at h₁ h₂
omega
@[simp] theorem _rooy_.List.toArray_ofFn (f : Fin n α) : (List.ofFn f).toArray = Array.ofFn f := by
@[simp] theorem _root_.List.toArray_ofFn {f : Fin n α} : (List.ofFn f).toArray = Array.ofFn f := by
ext <;> simp
@[simp] theorem toList_ofFn (f : Fin n α) : (Array.ofFn f).toList = List.ofFn f := by
@[simp] theorem toList_ofFn {f : Fin n α} : (Array.ofFn f).toList = List.ofFn f := by
apply List.ext_getElem <;> simp
@[simp]
@@ -42,7 +42,7 @@ theorem ofFn_eq_empty_iff {f : Fin n → α} : ofFn f = #[] ↔ n = 0 := by
simp
@[simp 500]
theorem mem_ofFn {n} (f : Fin n α) (a : α) : a ofFn f i, f i = a := by
theorem mem_ofFn {n} {f : Fin n α} {a : α} : a ofFn f i, f i = a := by
constructor
· intro w
obtain i, h, rfl := getElem_of_mem w

View File

@@ -26,14 +26,14 @@ open Nat
/-! ### range' -/
theorem range'_succ (s n step) : range' s (n + 1) step = #[s] ++ range' (s + step) n step := by
theorem range'_succ {s n step} : range' s (n + 1) step = #[s] ++ range' (s + step) n step := by
rw [ toList_inj]
simp [List.range'_succ]
@[simp] theorem range'_eq_empty_iff : range' s n step = #[] n = 0 := by
rw [ size_eq_zero_iff, size_range']
theorem range'_ne_empty_iff (s : Nat) {n step : Nat} : range' s n step #[] n 0 := by
theorem range'_ne_empty_iff : range' s n step #[] n 0 := by
cases n <;> simp
@[simp] theorem range'_zero : range' s 0 step = #[] := by
@@ -57,13 +57,13 @@ theorem mem_range' {n} : m ∈ range' s n step ↔ ∃ i < n, m = s + step * i :
theorem pop_range' : (range' s n step).pop = range' s (n - 1) step := by
ext <;> simp
theorem map_add_range' (a) (s n step) : map (a + ·) (range' s n step) = range' (a + s) n step := by
theorem map_add_range' {a} (s n step) : map (a + ·) (range' s n step) = range' (a + s) n step := by
ext <;> simp <;> omega
theorem range'_succ_left : range' (s + 1) n step = (range' s n step).map (· + 1) := by
ext <;> simp <;> omega
theorem range'_append (s m n step : Nat) :
theorem range'_append {s m n step : Nat} :
range' s m step ++ range' (s + step * m) n step = range' s (m + n) step := by
ext i h₁ h₂
· simp
@@ -74,13 +74,13 @@ theorem range'_append (s m n step : Nat) :
have : step * m step * i := by exact mul_le_mul_left step h
omega
@[simp] theorem range'_append_1 (s m n : Nat) :
range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append s m n 1
@[simp] theorem range'_append_1 {s m n : Nat} :
range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append (step := 1)
theorem range'_concat (s n : Nat) : range' s (n + 1) step = range' s n step ++ #[s + step * n] := by
simpa using (range'_append s n 1 step).symm
theorem range'_concat {s n : Nat} : range' s (n + 1) step = range' s n step ++ #[s + step * n] := by
simpa using range'_append.symm
theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ #[s + n] := by
theorem range'_1_concat {s n : Nat} : range' s (n + 1) = range' s n ++ #[s + n] := by
simp [range'_concat]
@[simp] theorem mem_range'_1 : m range' s n s m m < s + n := by
@@ -88,7 +88,7 @@ theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ #[s + n]
fun i, h, e => e Nat.le_add_right .., Nat.add_lt_add_left h _,
fun h₁, h₂ => m - s, Nat.sub_lt_left_of_lt_add h₁ h₂, (Nat.add_sub_cancel' h₁).symm
theorem map_sub_range' (a s n : Nat) (h : a s) :
theorem map_sub_range' {a s n : Nat} (h : a s) :
map (· - a) (range' s n step) = range' (s - a) n step := by
conv => lhs; rw [ Nat.add_sub_cancel' h]
rw [ map_add_range', map_map, (?_ : __ = _), map_id]
@@ -121,10 +121,10 @@ theorem erase_range' :
/-! ### range -/
theorem range_eq_range' (n : Nat) : range n = range' 0 n := by
theorem range_eq_range' {n : Nat} : range n = range' 0 n := by
simp [range, range']
theorem range_succ_eq_map (n : Nat) : range (n + 1) = #[0] ++ map succ (range n) := by
theorem range_succ_eq_map {n : Nat} : range (n + 1) = #[0] ++ map succ (range n) := by
ext i h₁ h₂
· simp
omega
@@ -133,7 +133,7 @@ theorem range_succ_eq_map (n : Nat) : range (n + 1) = #[0] ++ map succ (range n)
succ_eq_add_one, dite_eq_ite]
split <;> omega
theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) := by
theorem range'_eq_map_range {s n : Nat} : range' s n = map (s + ·) (range n) := by
rw [range_eq_range', map_add_range']; rfl
@[simp] theorem range_eq_empty_iff {n : Nat} : range n = #[] n = 0 := by
@@ -142,7 +142,7 @@ theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) :=
theorem range_ne_empty_iff {n : Nat} : range n #[] n 0 := by
cases n <;> simp
theorem range_succ (n : Nat) : range (succ n) = range n ++ #[n] := by
theorem range_succ {n : Nat} : range (succ n) = range n ++ #[n] := by
ext i h₁ h₂
· simp
· simp only [succ_eq_add_one, size_range] at h₁
@@ -150,11 +150,11 @@ theorem range_succ (n : Nat) : range (succ n) = range n ++ #[n] := by
dite_eq_ite]
split <;> omega
theorem range_add (n m : Nat) : range (n + m) = range n ++ (range m).map (n + ·) := by
theorem range_add {n m : Nat} : range (n + m) = range n ++ (range m).map (n + ·) := by
rw [ range'_eq_map_range]
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 n m).symm
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 (s := 0)).symm
theorem reverse_range' (s n : Nat) : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by
theorem reverse_range' {s n : Nat} : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by
simp [ toList_inj, List.reverse_range']
@[simp]
@@ -163,9 +163,9 @@ theorem mem_range {m n : Nat} : m ∈ range n ↔ m < n := by
theorem not_mem_range_self {n : Nat} : n range n := by simp
theorem self_mem_range_succ (n : Nat) : n range (n + 1) := by simp
theorem self_mem_range_succ {n : Nat} : n range (n + 1) := by simp
@[simp] theorem take_range (i n : Nat) : take (range n) i = range (min i n) := by
@[simp] theorem take_range {i n : Nat} : take (range n) i = range (min i n) := by
ext <;> simp
@[simp] theorem find?_range_eq_some {n : Nat} {i : Nat} {p : Nat Bool} :
@@ -188,48 +188,50 @@ theorem zipIdx_eq_empty_iff {xs : Array α} {i : Nat} : xs.zipIdx i = #[] ↔ xs
simp
@[simp]
theorem getElem?_zipIdx (xs : Array α) (i j) : (zipIdx xs i)[j]? = xs[j]?.map fun a => (a, i + j) := by
theorem getElem?_zipIdx {xs : Array α} {i j} : (zipIdx xs i)[j]? = xs[j]?.map fun a => (a, i + j) := by
simp [getElem?_def]
theorem map_snd_add_zipIdx_eq_zipIdx (xs : Array α) (n k : Nat) :
theorem map_snd_add_zipIdx_eq_zipIdx {xs : Array α} {n k : Nat} :
map (Prod.map id (· + n)) (zipIdx xs k) = zipIdx xs (n + k) :=
ext_getElem? fun i by simp [(· ·), Nat.add_comm, Nat.add_left_comm]; rfl
-- Arguments are explicit for parity with `zipIdx_map_fst`.
@[simp]
theorem zipIdx_map_snd (i) (xs : Array α) : map Prod.snd (zipIdx xs i) = range' i xs.size := by
cases xs
simp
-- Arguments are explicit so we can rewrite from right to left.
@[simp]
theorem zipIdx_map_fst (i) (xs : Array α) : map Prod.fst (zipIdx xs i) = xs := by
cases xs
simp
theorem zipIdx_eq_zip_range' (xs : Array α) {i : Nat} : xs.zipIdx i = xs.zip (range' i xs.size) := by
theorem zipIdx_eq_zip_range' {xs : Array α} {i : Nat} : xs.zipIdx i = xs.zip (range' i xs.size) := by
simp [zip_of_prod (zipIdx_map_fst _ _) (zipIdx_map_snd _ _)]
@[simp]
theorem unzip_zipIdx_eq_prod (xs : Array α) {i : Nat} :
theorem unzip_zipIdx_eq_prod {xs : Array α} {i : Nat} :
(xs.zipIdx i).unzip = (xs, range' i xs.size) := by
simp only [zipIdx_eq_zip_range', unzip_zip, size_range']
/-- Replace `zipIdx` with a starting index `n+1` with `zipIdx` starting from `n`,
followed by a `map` increasing the indices by one. -/
theorem zipIdx_succ (xs : Array α) (i : Nat) :
theorem zipIdx_succ {xs : Array α} {i : Nat} :
xs.zipIdx (i + 1) = (xs.zipIdx i).map (fun a, j => (a, j + 1)) := by
cases xs
simp [List.zipIdx_succ]
/-- Replace `zipIdx` with a starting index with `zipIdx` starting from 0,
followed by a `map` increasing the indices. -/
theorem zipIdx_eq_map_add (xs : Array α) (i : Nat) :
theorem zipIdx_eq_map_add {xs : Array α} {i : Nat} :
xs.zipIdx i = (xs.zipIdx 0).map (fun a, j => (a, i + j)) := by
cases xs
simp only [zipIdx_toArray, List.map_toArray, mk.injEq]
rw [List.zipIdx_eq_map_add]
@[simp]
theorem zipIdx_singleton (x : α) (k : Nat) : zipIdx #[x] k = #[(x, k)] :=
theorem zipIdx_singleton {x : α} {k : Nat} : zipIdx #[x] k = #[(x, k)] :=
rfl
theorem mk_add_mem_zipIdx_iff_getElem? {k i : Nat} {x : α} {xs : Array α} :
@@ -248,13 +250,13 @@ theorem snd_lt_add_of_mem_zipIdx {x : α × Nat} {k : Nat} {xs : Array α} (h :
theorem snd_lt_of_mem_zipIdx {x : α × Nat} {k : Nat} {xs : Array α} (h : x zipIdx xs k) : x.2 < xs.size + k := by
simpa [Nat.add_comm] using snd_lt_add_of_mem_zipIdx h
theorem map_zipIdx (f : α β) (xs : Array α) (k : Nat) :
theorem map_zipIdx {f : α β} {xs : Array α} {k : Nat} :
map (Prod.map f id) (zipIdx xs k) = zipIdx (xs.map f) k := by
cases xs
simp [List.map_zipIdx]
theorem fst_mem_of_mem_zipIdx {x : α × Nat} {xs : Array α} {k : Nat} (h : x zipIdx xs k) : x.1 xs :=
zipIdx_map_fst k xs mem_map_of_mem _ h
zipIdx_map_fst k xs mem_map_of_mem h
theorem fst_eq_of_mem_zipIdx {x : α × Nat} {xs : Array α} {k : Nat} (h : x zipIdx xs k) :
x.1 = xs[x.2 - k]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) := by
@@ -271,12 +273,12 @@ theorem mem_zipIdx' {x : α} {i : Nat} {xs : Array α} (h : (x, i) ∈ xs.zipIdx
i < xs.size x = xs[i]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) :=
by simpa using snd_lt_add_of_mem_zipIdx h, fst_eq_of_mem_zipIdx h
theorem zipIdx_map (xs : Array α) (k : Nat) (f : α β) :
theorem zipIdx_map {xs : Array α} {k : Nat} {f : α β} :
zipIdx (xs.map f) k = (zipIdx xs k).map (Prod.map f id) := by
cases xs
simp [List.zipIdx_map]
theorem zipIdx_append (xs ys : Array α) (k : Nat) :
theorem zipIdx_append {xs ys : Array α} {k : Nat} :
zipIdx (xs ++ ys) k = zipIdx xs k ++ zipIdx ys (k + xs.size) := by
cases xs
cases ys

View File

@@ -26,7 +26,7 @@ end List
namespace Array
theorem exists_of_uset (xs : Array α) (i d h) :
theorem exists_of_uset {xs : Array α} {i d} (h) :
l₁ l₂, xs.toList = l₁ ++ xs[i] :: l₂ List.length l₁ = i.toNat
(xs.uset i d h).toList = l₁ ++ d :: l₂ := by
simpa only [ugetElem_eq_getElem, getElem_toList, uset, toList_set] using

View File

@@ -22,19 +22,19 @@ open Nat
/-! ### zipWith -/
theorem zipWith_comm (f : α β γ) (as : Array α) (bs : Array β) :
theorem zipWith_comm {f : α β γ} {as : Array α} {bs : Array β} :
zipWith f as bs = zipWith (fun b a => f a b) bs as := by
cases as
cases bs
simpa using List.zipWith_comm _ _ _
simpa using List.zipWith_comm
theorem zipWith_comm_of_comm (f : α α β) (comm : x y : α, f x y = f y x) (xs ys : Array α) :
theorem zipWith_comm_of_comm {f : α α β} (comm : x y : α, f x y = f y x) {xs ys : Array α} :
zipWith f xs ys = zipWith f ys xs := by
rw [zipWith_comm]
simp only [comm]
@[simp]
theorem zipWith_self (f : α α δ) (xs : Array α) : zipWith f xs xs = xs.map fun a => f a a := by
theorem zipWith_self {f : α α δ} {xs : Array α} : zipWith f xs xs = xs.map fun a => f a a := by
cases xs
simp
@@ -74,31 +74,31 @@ theorem getElem?_zip_eq_some {as : Array α} {bs : Array β} {z : α × β} {i :
exact _, _, h₀, h₁, rfl
@[simp]
theorem zipWith_map {μ} (f : γ δ μ) (g : α γ) (h : β δ) (as : Array α) (bs : Array β) :
theorem zipWith_map {μ} {f : γ δ μ} {g : α γ} {h : β δ} {as : Array α} {bs : Array β} :
zipWith f (as.map g) (bs.map h) = zipWith (fun a b => f (g a) (h b)) as bs := by
cases as
cases bs
simp [List.zipWith_map]
theorem zipWith_map_left (as : Array α) (bs : Array β) (f : α α') (g : α' β γ) :
theorem zipWith_map_left {as : Array α} {bs : Array β} {f : α α'} {g : α' β γ} :
zipWith g (as.map f) bs = zipWith (fun a b => g (f a) b) as bs := by
cases as
cases bs
simp [List.zipWith_map_left]
theorem zipWith_map_right (as : Array α) (bs : Array β) (f : β β') (g : α β' γ) :
theorem zipWith_map_right {as : Array α} {bs : Array β} {f : β β'} {g : α β' γ} :
zipWith g as (bs.map f) = zipWith (fun a b => g a (f b)) as bs := by
cases as
cases bs
simp [List.zipWith_map_right]
theorem zipWith_foldr_eq_zip_foldr {f : α β γ} (i : δ):
theorem zipWith_foldr_eq_zip_foldr {f : α β γ} {i : δ} :
(zipWith f as bs).foldr g i = (zip as bs).foldr (fun p r => g (f p.1 p.2) r) i := by
cases as
cases bs
simp [List.zipWith_foldr_eq_zip_foldr]
theorem zipWith_foldl_eq_zip_foldl {f : α β γ} (i : δ):
theorem zipWith_foldl_eq_zip_foldl {f : α β γ} {i : δ} :
(zipWith f as bs).foldl g i = (zip as bs).foldl (fun r p => g r (f p.1 p.2)) i := by
cases as
cases bs
@@ -108,7 +108,7 @@ theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} (i : δ):
theorem zipWith_eq_empty_iff {f : α β γ} {as : Array α} {bs : Array β} : zipWith f as bs = #[] as = #[] bs = #[] := by
cases as <;> cases bs <;> simp
theorem map_zipWith {δ : Type _} (f : α β) (g : γ δ α) (cs : Array γ) (ds : Array δ) :
theorem map_zipWith {δ : Type _} {f : α β} {g : γ δ α} {cs : Array γ} {ds : Array δ} :
map f (zipWith g cs ds) = zipWith (fun x y => f (g x y)) cs ds := by
cases cs
cases ds
@@ -124,7 +124,7 @@ theorem extract_zipWith : (zipWith f as bs).extract i j = zipWith f (as.extract
cases bs
simp [List.drop_zipWith, List.take_zipWith]
theorem zipWith_append (f : α β γ) (as as' : Array α) (bs bs' : Array β)
theorem zipWith_append {f : α β γ} {as as' : Array α} {bs bs' : Array β}
(h : as.size = bs.size) :
zipWith f (as ++ as') (bs ++ bs') = zipWith f as bs ++ zipWith f as' bs' := by
cases as
@@ -156,13 +156,13 @@ theorem zipWith_eq_append_iff {f : α → β → γ} {as : Array α} {bs : Array
@[deprecated zipWith_replicate (since := "2025-03-18")]
abbrev zipWith_mkArray := @zipWith_replicate
theorem map_uncurry_zip_eq_zipWith (f : α β γ) (as : Array α) (bs : Array β) :
theorem map_uncurry_zip_eq_zipWith {f : α β γ} {as : Array α} {bs : Array β} :
map (Function.uncurry f) (as.zip bs) = zipWith f as bs := by
cases as
cases bs
simp [List.map_uncurry_zip_eq_zipWith]
theorem map_zip_eq_zipWith (f : α × β γ) (as : Array α) (bs : Array β) :
theorem map_zip_eq_zipWith {f : α × β γ} {as : Array α} {bs : Array β} :
map f (as.zip bs) = zipWith (Function.curry f) as bs := by
cases as
cases bs
@@ -203,21 +203,21 @@ theorem getElem_zip {as : Array α} {bs : Array β} {i : Nat} {h : i < (zip as b
(as[i]'(lt_size_left_of_zip h), bs[i]'(lt_size_right_of_zip h)) :=
getElem_zipWith (hi := by simpa using h)
theorem zip_eq_zipWith (as : Array α) (bs : Array β) : zip as bs = zipWith Prod.mk as bs := by
theorem zip_eq_zipWith {as : Array α} {bs : Array β} : zip as bs = zipWith Prod.mk as bs := by
cases as
cases bs
simp [List.zip_eq_zipWith]
theorem zip_map (f : α γ) (g : β δ) (as : Array α) (bs : Array β) :
theorem zip_map {f : α γ} {g : β δ} {as : Array α} {bs : Array β} :
zip (as.map f) (bs.map g) = (zip as bs).map (Prod.map f g) := by
cases as
cases bs
simp [List.zip_map]
theorem zip_map_left (f : α γ) (as : Array α) (bs : Array β) :
theorem zip_map_left {f : α γ} {as : Array α} {bs : Array β} :
zip (as.map f) bs = (zip as bs).map (Prod.map f id) := by rw [ zip_map, map_id]
theorem zip_map_right (f : β γ) (as : Array α) (bs : Array β) :
theorem zip_map_right {f : β γ} {as : Array α} {bs : Array β} :
zip as (bs.map f) = (zip as bs).map (Prod.map id f) := by rw [ zip_map, map_id]
theorem zip_append {as bs : Array α} {cs ds : Array β} (_h : as.size = cs.size) :
@@ -228,7 +228,7 @@ theorem zip_append {as bs : Array α} {cs ds : Array β} (_h : as.size = cs.size
cases ds
simp_all [List.zip_append]
theorem zip_map' (f : α β) (g : α γ) (xs : Array α) :
theorem zip_map' {f : α β} {g : α γ} {xs : Array α} :
zip (xs.map f) (xs.map g) = xs.map fun a => (f a, g a) := by
cases xs
simp [List.zip_map']
@@ -238,25 +238,25 @@ theorem of_mem_zip {a b} {as : Array α} {bs : Array β} : (a, b) ∈ zip as bs
cases bs
simpa using List.of_mem_zip
theorem map_fst_zip (as : Array α) (bs : Array β) (h : as.size bs.size) :
theorem map_fst_zip {as : Array α} {bs : Array β} (h : as.size bs.size) :
map Prod.fst (zip as bs) = as := by
cases as
cases bs
simp_all [List.map_fst_zip]
theorem map_snd_zip (as : Array α) (bs : Array β) (h : bs.size as.size) :
theorem map_snd_zip {as : Array α} {bs : Array β} (h : bs.size as.size) :
map Prod.snd (zip as bs) = bs := by
cases as
cases bs
simp_all [List.map_snd_zip]
theorem map_prod_left_eq_zip {xs : Array α} (f : α β) :
theorem map_prod_left_eq_zip {xs : Array α} {f : α β} :
(xs.map fun x => (x, f x)) = xs.zip (xs.map f) := by
rw [ zip_map']
congr
simp
theorem map_prod_right_eq_zip {xs : Array α} (f : α β) :
theorem map_prod_right_eq_zip {xs : Array α} {f : α β} :
(xs.map fun x => (f x, x)) = (xs.map f).zip xs := by
rw [ zip_map']
congr
@@ -280,7 +280,7 @@ theorem zip_eq_append_iff {as : Array α} {bs : Array β} :
@[deprecated zip_replicate (since := "2025-03-18")]
abbrev zip_mkArray := @zip_replicate
theorem zip_eq_zip_take_min (as : Array α) (bs : Array β) :
theorem zip_eq_zip_take_min {as : Array α} {bs : Array β} :
zip as bs = zip (as.take (min as.size bs.size)) (bs.take (min as.size bs.size)) := by
cases as
cases bs
@@ -298,25 +298,25 @@ theorem getElem?_zipWithAll {f : Option α → Option β → γ} {i : Nat} :
simp [List.getElem?_zipWithAll]
rfl
theorem zipWithAll_map {μ} (f : Option γ Option δ μ) (g : α γ) (h : β δ) (as : Array α) (bs : Array β) :
theorem zipWithAll_map {μ} {f : Option γ Option δ μ} {g : α γ} {h : β δ} {as : Array α} {bs : Array β} :
zipWithAll f (as.map g) (bs.map h) = zipWithAll (fun a b => f (g <$> a) (h <$> b)) as bs := by
cases as
cases bs
simp [List.zipWithAll_map]
theorem zipWithAll_map_left (as : Array α) (bs : Array β) (f : α α') (g : Option α' Option β γ) :
theorem zipWithAll_map_left {as : Array α} {bs : Array β} {f : α α'} {g : Option α' Option β γ} :
zipWithAll g (as.map f) bs = zipWithAll (fun a b => g (f <$> a) b) as bs := by
cases as
cases bs
simp [List.zipWithAll_map_left]
theorem zipWithAll_map_right (as : Array α) (bs : Array β) (f : β β') (g : Option α Option β' γ) :
theorem zipWithAll_map_right {as : Array α} {bs : Array β} {f : β β'} {g : Option α Option β' γ} :
zipWithAll g as (bs.map f) = zipWithAll (fun a b => g a (f <$> b)) as bs := by
cases as
cases bs
simp [List.zipWithAll_map_right]
theorem map_zipWithAll {δ : Type _} (f : α β) (g : Option γ Option δ α) (cs : Array γ) (ds : Array δ) :
theorem map_zipWithAll {δ : Type _} {f : α β} {g : Option γ Option δ α} {cs : Array γ} {ds : Array δ} :
map f (zipWithAll g cs ds) = zipWithAll (fun x y => f (g x y)) cs ds := by
cases cs
cases ds
@@ -337,10 +337,11 @@ abbrev zipWithAll_mkArray := @zipWithAll_replicate
@[simp] theorem unzip_snd : (unzip l).snd = l.map Prod.snd := by
induction l <;> simp_all
theorem unzip_eq_map (xs : Array (α × β)) : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by
theorem unzip_eq_map {xs : Array (α × β)} : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by
cases xs
simp [List.unzip_eq_map]
-- The argument `xs` is explicit so we can rewrite from right to left.
theorem zip_unzip (xs : Array (α × β)) : zip (unzip xs).1 (unzip xs).2 = xs := by
cases xs
simp only [List.unzip_toArray, Prod.map_fst, Prod.map_snd, List.zip_toArray, List.zip_unzip]

View File

@@ -65,9 +65,9 @@ well-founded recursion mechanism to prove that the function terminates.
| cons _ l', hL' => congrArg _ <| go l' fun _ hx => hL' (.tail _ hx)
exact go l h'
@[simp] theorem pmap_nil {P : α Prop} (f : a, P a β) : pmap f [] (by simp) = [] := rfl
@[simp] theorem pmap_nil {P : α Prop} {f : a, P a β} : pmap f [] (by simp) = [] := rfl
@[simp] theorem pmap_cons {P : α Prop} (f : a, P a β) (a : α) (l : List α) (h : b a :: l, P b) :
@[simp] theorem pmap_cons {P : α Prop} {f : a, P a β} {a : α} {l : List α} (h : b a :: l, P b) :
pmap f (a :: l) h = f a (forall_mem_cons.1 h).1 :: pmap f l (forall_mem_cons.1 h).2 := rfl
@[simp] theorem attach_nil : ([] : List α).attach = [] := rfl
@@ -75,7 +75,7 @@ well-founded recursion mechanism to prove that the function terminates.
@[simp] theorem attachWith_nil : ([] : List α).attachWith P H = [] := rfl
@[simp]
theorem pmap_eq_map (p : α Prop) (f : α β) (l : List α) (H) :
theorem pmap_eq_map {p : α Prop} {f : α β} {l : List α} (H) :
@pmap _ _ p (fun a _ => f a) l H = map f l := by
induction l
· rfl
@@ -86,18 +86,18 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a,
induction l with
| nil => rfl
| cons x l ih =>
rw [pmap, pmap, h _ (mem_cons_self _ _), ih fun a ha => h a (mem_cons_of_mem _ ha)]
rw [pmap, pmap, h _ mem_cons_self, ih fun a ha => h a (mem_cons_of_mem _ ha)]
@[deprecated pmap_congr_left (since := "2024-09-06")] abbrev pmap_congr := @pmap_congr_left
theorem map_pmap {p : α Prop} (g : β γ) (f : a, p a β) (l H) :
theorem map_pmap {p : α Prop} {g : β γ} {f : a, p a β} {l : List α} (H) :
map g (pmap f l H) = pmap (fun a h => g (f a h)) l H := by
induction l
· rfl
· simp only [*, pmap, map]
theorem pmap_map {p : β Prop} (g : b, p b γ) (f : α β) (l H) :
pmap g (map f l) H = pmap (fun a h => g (f a) h) l fun _ h => H _ (mem_map_of_mem _ h) := by
theorem pmap_map {p : β Prop} {g : b, p b γ} {f : α β} {l : List α} (H) :
pmap g (map f l) H = pmap (fun a h => g (f a) h) l fun _ h => H _ (mem_map_of_mem h) := by
induction l
· rfl
· simp only [*, pmap, map]
@@ -114,7 +114,7 @@ theorem attachWith_congr {l₁ l₂ : List α} (w : l₁ = l₂) {P : α → Pro
@[simp] theorem attach_cons {x : α} {xs : List α} :
(x :: xs).attach =
x, mem_cons_self x xs :: xs.attach.map fun y, h => y, mem_cons_of_mem x h := by
x, mem_cons_self :: xs.attach.map fun y, h => y, mem_cons_of_mem x h := by
simp only [attach, attachWith, pmap, map_pmap, cons.injEq, true_and]
apply pmap_congr_left
intros a _ m' _
@@ -122,42 +122,43 @@ theorem attachWith_congr {l₁ l₂ : List α} (w : l₁ = l₂) {P : α → Pro
@[simp]
theorem attachWith_cons {x : α} {xs : List α} {p : α Prop} (h : a x :: xs, p a) :
(x :: xs).attachWith p h = x, h x (mem_cons_self x xs) ::
(x :: xs).attachWith p h = x, h x (mem_cons_self) ::
xs.attachWith p (fun a ha h a (mem_cons_of_mem x ha)) :=
rfl
theorem pmap_eq_map_attach {p : α Prop} (f : a, p a β) (l H) :
theorem pmap_eq_map_attach {p : α Prop} {f : a, p a β} {l : List α} (H) :
pmap f l H = l.attach.map fun x => f x.1 (H _ x.2) := by
rw [attach, attachWith, map_pmap]; exact pmap_congr_left l fun _ _ _ _ => rfl
@[simp]
theorem pmap_eq_attachWith {p q : α Prop} (f : a, p a q a) (l H) :
theorem pmap_eq_attachWith {p q : α Prop} {f : a, p a q a} {l : List α} (H) :
pmap (fun a h => a, f a h) l H = l.attachWith q (fun x h => f x (H x h)) := by
induction l with
| nil => rfl
| cons a l ih =>
simp [pmap, attachWith, ih]
theorem attach_map_val (l : List α) (f : α β) :
theorem attach_map_val {l : List α} {f : α β} :
(l.attach.map fun (i : {i // i l}) => f i) = l.map f := by
rw [attach, attachWith, map_pmap]; exact pmap_eq_map _ _ _ _
rw [attach, attachWith, map_pmap]; exact pmap_eq_map _
@[deprecated attach_map_val (since := "2025-02-17")]
abbrev attach_map_coe := @attach_map_val
-- The argument `l : List α` is explicit to allow rewriting from right to left.
theorem attach_map_subtype_val (l : List α) : l.attach.map Subtype.val = l :=
(attach_map_val _ _).trans (List.map_id _)
attach_map_val.trans (List.map_id _)
theorem attachWith_map_val {p : α Prop} (f : α β) (l : List α) (H : a l, p a) :
theorem attachWith_map_val {p : α Prop} {f : α β} {l : List α} (H : a l, p a) :
((l.attachWith p H).map fun (i : { i // p i}) => f i) = l.map f := by
rw [attachWith, map_pmap]; exact pmap_eq_map _ _ _ _
rw [attachWith, map_pmap]; exact pmap_eq_map _
@[deprecated attachWith_map_val (since := "2025-02-17")]
abbrev attachWith_map_coe := @attachWith_map_val
theorem attachWith_map_subtype_val {p : α Prop} (l : List α) (H : a l, p a) :
theorem attachWith_map_subtype_val {p : α Prop} {l : List α} (H : a l, p a) :
(l.attachWith p H).map Subtype.val = l :=
(attachWith_map_val _ _ _).trans (List.map_id _)
(attachWith_map_val _).trans (List.map_id _)
@[simp]
theorem mem_attach (l : List α) : x, x l.attach
@@ -167,7 +168,7 @@ theorem mem_attach (l : List α) : ∀ x, x ∈ l.attach
exact m
@[simp]
theorem mem_attachWith (l : List α) {q : α Prop} (H) (x : {x // q x}) :
theorem mem_attachWith {l : List α} {q : α Prop} (H) (x : {x // q x}) :
x l.attachWith q H x.1 l := by
induction l with
| nil => simp
@@ -240,7 +241,7 @@ theorem attachWith_ne_nil_iff {l : List α} {P : α → Prop} {H : ∀ a ∈ l,
@[deprecated attach_ne_nil_iff (since := "2024-09-06")] abbrev attach_ne_nil := @attach_ne_nil_iff
@[simp]
theorem getElem?_pmap {p : α Prop} (f : a, p a β) {l : List α} (h : a l, p a) (i : Nat) :
theorem getElem?_pmap {p : α Prop} {f : a, p a β} {l : List α} (h : a l, p a) (i : Nat) :
(pmap f l h)[i]? = Option.pmap f l[i]? fun x H => h x (mem_of_getElem? H) := by
induction l generalizing i with
| nil => simp
@@ -257,6 +258,7 @@ theorem get?_pmap {p : α → Prop} (f : ∀ a, p a → β) {l : List α} (h :
simp only [get?_eq_getElem?]
simp [getElem?_pmap, h]
-- The argument `f` is explicit to allow rewriting from right to left.
@[simp]
theorem getElem_pmap {p : α Prop} (f : a, p a β) {l : List α} (h : a l, p a) {i : Nat}
(hn : i < (pmap f l h).length) :
@@ -302,19 +304,19 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) :
xs.attach[i] = xs[i]'(by simpa using h), getElem_mem (by simpa using h) :=
getElem_attachWith h
@[simp] theorem pmap_attach (l : List α) {p : {x // x l} Prop} (f : a, p a β) (H) :
@[simp] theorem pmap_attach {l : List α} {p : {x // x l} Prop} {f : a, p a β} (H) :
pmap f l.attach H =
l.pmap (P := fun a => h : a l, p a, h)
(fun a h => f a, h.1 h.2) (fun a h => h, H a, h (by simp)) := by
apply ext_getElem <;> simp
@[simp] theorem pmap_attachWith (l : List α) {p : {x // q x} Prop} (f : a, p a β) (H₁ H₂) :
@[simp] theorem pmap_attachWith {l : List α} {p : {x // q x} Prop} {f : a, p a β} (H₁ H₂) :
pmap f (l.attachWith q H₁) H₂ =
l.pmap (P := fun a => h : q a, p a, h)
(fun a h => f a, h.1 h.2) (fun a h => H₁ _ h, H₂ a, H₁ _ h (by simpa)) := by
apply ext_getElem <;> simp
@[simp] theorem head?_pmap {P : α Prop} (f : (a : α) P a β) (xs : List α)
@[simp] theorem head?_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs P a) :
(xs.pmap f H).head? = xs.attach.head?.map fun a, m => f a (H a m) := by
induction xs with
@@ -323,7 +325,7 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) :
simp at ih
simp [head?_pmap, ih]
@[simp] theorem head_pmap {P : α Prop} (f : (a : α) P a β) (xs : List α)
@[simp] theorem head_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs P a) (h : xs.pmap f H []) :
(xs.pmap f H).head h = f (xs.head (by simpa using h)) (H _ (head_mem _)) := by
induction xs with
@@ -342,7 +344,7 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) :
| nil => simp at h
| cons x xs => simp [head_attachWith, h]
@[simp] theorem head?_attach (xs : List α) :
@[simp] theorem head?_attach {xs : List α} :
xs.attach.head? = xs.head?.pbind (fun a h => some a, mem_of_mem_head? h) := by
cases xs <;> simp_all
@@ -352,7 +354,7 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) :
| nil => simp at h
| cons x xs => simp [head_attach, h]
@[simp] theorem tail_pmap {P : α Prop} (f : (a : α) P a β) (xs : List α)
@[simp] theorem tail_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs P a) :
(xs.pmap f H).tail = xs.tail.pmap f (fun a h => H a (mem_of_mem_tail h)) := by
cases xs <;> simp
@@ -362,29 +364,29 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) :
(xs.attachWith P H).tail = xs.tail.attachWith P (fun a h => H a (mem_of_mem_tail h)) := by
cases xs <;> simp
@[simp] theorem tail_attach (xs : List α) :
@[simp] theorem tail_attach {xs : List α} :
xs.attach.tail = xs.tail.attach.map (fun x, h => x, mem_of_mem_tail h) := by
cases xs <;> simp
theorem foldl_pmap (l : List α) {P : α Prop} (f : (a : α) P a β)
(H : (a : α), a l P a) (g : γ β γ) (x : γ) :
theorem foldl_pmap {l : List α} {P : α Prop} {f : (a : α) P a β}
(H : (a : α), a l P a) (g : γ β γ) (x : γ) :
(l.pmap f H).foldl g x = l.attach.foldl (fun acc a => g acc (f a.1 (H _ a.2))) x := by
rw [pmap_eq_map_attach, foldl_map]
theorem foldr_pmap (l : List α) {P : α Prop} (f : (a : α) P a β)
(H : (a : α), a l P a) (g : β γ γ) (x : γ) :
theorem foldr_pmap {l : List α} {P : α Prop} {f : (a : α) P a β}
(H : (a : α), a l P a) (g : β γ γ) (x : γ) :
(l.pmap f H).foldr g x = l.attach.foldr (fun a acc => g (f a.1 (H _ a.2)) acc) x := by
rw [pmap_eq_map_attach, foldr_map]
@[simp] theorem foldl_attachWith
(l : List α) {q : α Prop} (H : a, a l q a) {f : β { x // q x} β} {b} :
{l : List α} {q : α Prop} (H : a, a l q a) {f : β { x // q x } β} {b} :
(l.attachWith q H).foldl f b = l.attach.foldl (fun b a, h => f b a, H _ h) b := by
induction l generalizing b with
| nil => simp
| cons a l ih => simp [ih, foldl_map]
@[simp] theorem foldr_attachWith
(l : List α) {q : α Prop} (H : a, a l q a) {f : { x // q x} β β} {b} :
{l : List α} {q : α Prop} (H : a, a l q a) {f : { x // q x } β β} {b} :
(l.attachWith q H).foldr f b = l.attach.foldr (fun a acc => f a.1, H _ a.2 acc) b := by
induction l generalizing b with
| nil => simp
@@ -400,7 +402,7 @@ Unfortunately this can't be applied by `simp` because of the higher order unific
and even when rewriting we need to specify the function explicitly.
See however `foldl_subtype` below.
-/
theorem foldl_attach (l : List α) (f : β α β) (b : β) :
theorem foldl_attach {l : List α} {f : β α β} {b : β} :
l.attach.foldl (fun acc t => f acc t.1) b = l.foldl f b := by
induction l generalizing b with
| nil => simp
@@ -416,28 +418,28 @@ Unfortunately this can't be applied by `simp` because of the higher order unific
and even when rewriting we need to specify the function explicitly.
See however `foldr_subtype` below.
-/
theorem foldr_attach (l : List α) (f : α β β) (b : β) :
theorem foldr_attach {l : List α} {f : α β β} {b : β} :
l.attach.foldr (fun t acc => f t.1 acc) b = l.foldr f b := by
induction l generalizing b with
| nil => simp
| cons a l ih => rw [foldr_cons, attach_cons, foldr_cons, foldr_map, ih]
theorem attach_map {l : List α} (f : α β) :
(l.map f).attach = l.attach.map (fun x, h => f x, mem_map_of_mem f h) := by
theorem attach_map {l : List α} {f : α β} :
(l.map f).attach = l.attach.map (fun x, h => f x, mem_map_of_mem h) := by
induction l <;> simp [*]
theorem attachWith_map {l : List α} (f : α β) {P : β Prop} {H : (b : β), b l.map f P b} :
(l.map f).attachWith P H = (l.attachWith (P f) (fun _ h => H _ (mem_map_of_mem f h))).map
theorem attachWith_map {l : List α} {f : α β} {P : β Prop} (H : (b : β), b l.map f P b) :
(l.map f).attachWith P H = (l.attachWith (P f) (fun _ h => H _ (mem_map_of_mem h))).map
fun x, h => f x, h := by
induction l <;> simp [*]
@[simp] theorem map_attachWith {l : List α} {P : α Prop} {H : (a : α), a l P a}
(f : { x // P x } β) :
{f : { x // P x } β} :
(l.attachWith P H).map f = l.attach.map fun x, h => f x, H _ h := by
induction l <;> simp_all
theorem map_attachWith_eq_pmap {l : List α} {P : α Prop} {H : (a : α), a l P a}
(f : { x // P x } β) :
{f : { x // P x } β} :
(l.attachWith P H).map f =
l.pmap (fun a (h : a l P a) => f a, H _ h.1) (fun a h => h, H a h) := by
induction l with
@@ -448,7 +450,7 @@ theorem map_attachWith_eq_pmap {l : List α} {P : α → Prop} {H : ∀ (a : α)
simp
/-- See also `pmap_eq_map_attach` for writing `pmap` in terms of `map` and `attach`. -/
theorem map_attach_eq_pmap {l : List α} (f : { x // x l } β) :
theorem map_attach_eq_pmap {l : List α} {f : { x // x l } β} :
l.attach.map f = l.pmap (fun a h => f a, h) (fun _ => id) := by
induction l with
| nil => rfl
@@ -494,7 +496,7 @@ theorem attach_filterMap {l : List α} {f : α → Option β} :
theorem attach_filter {l : List α} (p : α Bool) :
(l.filter p).attach = l.attach.filterMap
fun x => if w : p x.1 then some x.1, mem_filter.mpr x.2, w else none := by
rw [attach_congr (congrFun (filterMap_eq_filter _).symm _), attach_filterMap, map_filterMap]
rw [attach_congr (congrFun filterMap_eq_filter.symm _), attach_filterMap, map_filterMap]
simp only [Option.guard]
congr
ext1
@@ -521,13 +523,13 @@ theorem filter_attachWith {q : α → Prop} {l : List α} {p : {x // q x} → Bo
simp only [attachWith_cons, filter_cons]
split <;> simp_all [Function.comp_def, filter_map]
theorem pmap_pmap {p : α Prop} {q : β Prop} (g : a, p a β) (f : b, q b γ) (l H₁ H₂) :
theorem pmap_pmap {p : α Prop} {q : β Prop} {g : a, p a β} {f : b, q b γ} {l} (H₁ H₂) :
pmap f (pmap g l H₁) H₂ =
pmap (α := { x // x l }) (fun a h => f (g a h) (H₂ (g a h) (mem_pmap_of_mem a.2))) l.attach
(fun a _ => H₁ a a.2) := by
simp [pmap_eq_map_attach, attach_map]
@[simp] theorem pmap_append {p : ι Prop} (f : a : ι, p a α) (l₁ l₂ : List ι)
@[simp] theorem pmap_append {p : ι Prop} {f : a : ι, p a α} {l₁ l₂ : List ι}
(h : a l₁ ++ l₂, p a) :
(l₁ ++ l₂).pmap f h =
(l₁.pmap f fun a ha => h a (mem_append_left l₂ ha)) ++
@@ -538,13 +540,13 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f
dsimp only [pmap, cons_append]
rw [ih]
theorem pmap_append' {p : α Prop} (f : a : α, p a β) (l₁ l₂ : List α)
theorem pmap_append' {p : α Prop} {f : a : α, p a β} {l₁ l₂ : List α}
(h₁ : a l₁, p a) (h₂ : a l₂, p a) :
((l₁ ++ l₂).pmap f fun a ha => (List.mem_append.1 ha).elim (h₁ a) (h₂ a)) =
l₁.pmap f h₁ ++ l₂.pmap f h₂ :=
pmap_append f l₁ l₂ _
pmap_append _
@[simp] theorem attach_append (xs ys : List α) :
@[simp] theorem attach_append {xs ys : List α} :
(xs ++ ys).attach = xs.attach.map (fun x, h => x, mem_append_left ys h) ++
ys.attach.map fun x, h => x, mem_append_right xs h := by
simp only [attach, attachWith, pmap, map_pmap, pmap_append]
@@ -557,12 +559,12 @@ theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (l₁ l₂ :
ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by
simp only [attachWith, attach_append, map_pmap, pmap_append]
@[simp] theorem pmap_reverse {P : α Prop} (f : (a : α) P a β) (xs : List α)
@[simp] theorem pmap_reverse {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs.reverse P a) :
xs.reverse.pmap f H = (xs.pmap f (fun a h => H a (by simpa using h))).reverse := by
induction xs <;> simp_all
theorem reverse_pmap {P : α Prop} (f : (a : α) P a β) (xs : List α)
theorem reverse_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs P a) :
(xs.pmap f H).reverse = xs.reverse.pmap f (fun a h => H a (by simpa using h)) := by
rw [pmap_reverse]
@@ -578,21 +580,21 @@ theorem reverse_attachWith {P : α → Prop} {xs : List α}
(xs.attachWith P H).reverse = (xs.reverse.attachWith P (fun a h => H a (by simpa using h))) :=
reverse_pmap ..
@[simp] theorem attach_reverse (xs : List α) :
@[simp] theorem attach_reverse {xs : List α} :
xs.reverse.attach = xs.attach.reverse.map fun x, h => x, by simpa using h := by
simp only [attach, attachWith, reverse_pmap, map_pmap]
apply pmap_congr_left
intros
rfl
theorem reverse_attach (xs : List α) :
theorem reverse_attach {xs : List α} :
xs.attach.reverse = xs.reverse.attach.map fun x, h => x, by simpa using h := by
simp only [attach, attachWith, reverse_pmap, map_pmap]
apply pmap_congr_left
intros
rfl
@[simp] theorem getLast?_pmap {P : α Prop} (f : (a : α) P a β) (xs : List α)
@[simp] theorem getLast?_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs P a) :
(xs.pmap f H).getLast? = xs.attach.getLast?.map fun a, m => f a (H a m) := by
simp only [getLast?_eq_head?_reverse]
@@ -600,7 +602,7 @@ theorem reverse_attach (xs : List α) :
simp only [Option.map_map]
congr
@[simp] theorem getLast_pmap {P : α Prop} (f : (a : α) P a β) (xs : List α)
@[simp] theorem getLast_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs P a) (h : xs.pmap f H []) :
(xs.pmap f H).getLast h = f (xs.getLast (by simpa using h)) (H _ (getLast_mem _)) := by
simp only [getLast_eq_head_reverse]
@@ -629,26 +631,26 @@ theorem getLast_attach {xs : List α} (h : xs.attach ≠ []) :
simp only [getLast_eq_head_reverse, reverse_attach, head_map, head_attach]
@[simp]
theorem countP_attach (l : List α) (p : α Bool) :
theorem countP_attach {l : List α} {p : α Bool} :
l.attach.countP (fun a : {x // x l} => p a) = l.countP p := by
simp only [ Function.comp_apply (g := Subtype.val), countP_map, attach_map_subtype_val]
@[simp]
theorem countP_attachWith {p : α Prop} (l : List α) (H : a l, p a) (q : α Bool) :
theorem countP_attachWith {p : α Prop} {q : α Bool} {l : List α} (H : a l, p a) :
(l.attachWith p H).countP (fun a : {x // p x} => q a) = l.countP q := by
simp only [ Function.comp_apply (g := Subtype.val), countP_map, attachWith_map_subtype_val]
@[simp]
theorem count_attach [DecidableEq α] (l : List α) (a : {x // x l}) :
theorem count_attach [DecidableEq α] {l : List α} {a : {x // x l}} :
l.attach.count a = l.count a :=
Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attach _ _
Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attach
@[simp]
theorem count_attachWith [DecidableEq α] {p : α Prop} (l : List α) (H : a l, p a) (a : {x // p x}) :
theorem count_attachWith [DecidableEq α] {p : α Prop} {l : List α} (H : a l, p a) {a : {x // p x}} :
(l.attachWith p H).count a = l.count a :=
Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attachWith _ _ _
Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attachWith _
@[simp] theorem countP_pmap {p : α Prop} (g : a, p a β) (f : β Bool) (l : List α) (H₁) :
@[simp] theorem countP_pmap {p : α Prop} {g : a, p a β} {f : β Bool} {l : List α} (H₁) :
(l.pmap g H₁).countP f =
l.attach.countP (fun a, m => f (g a (H₁ a m))) := by
simp [pmap_eq_map_attach, countP_map, Function.comp_def]
@@ -835,62 +837,62 @@ and simplifies these to the function directly taking the value.
/-! ### Well-founded recursion preprocessing setup -/
@[wf_preprocess] theorem map_wfParam (xs : List α) (f : α β) :
@[wf_preprocess] theorem map_wfParam {xs : List α} {f : α β} :
(wfParam xs).map f = xs.attach.unattach.map f := by
simp [wfParam]
@[wf_preprocess] theorem map_unattach (P : α Prop) (xs : List (Subtype P)) (f : α β) :
@[wf_preprocess] theorem map_unattach {P : α Prop} {xs : List (Subtype P)} {f : α β} :
xs.unattach.map f = xs.map fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]
@[wf_preprocess] theorem foldl_wfParam (xs : List α) (f : β α β) (x : β) :
@[wf_preprocess] theorem foldl_wfParam {xs : List α} {f : β α β} {x : β} :
(wfParam xs).foldl f x = xs.attach.unattach.foldl f x := by
simp [wfParam]
@[wf_preprocess] theorem foldl_unattach (P : α Prop) (xs : List (Subtype P)) (f : β α β) (x : β):
@[wf_preprocess] theorem foldl_unattach {P : α Prop} {xs : List (Subtype P)} {f : β α β} {x : β} :
xs.unattach.foldl f x = xs.foldl (fun s x, h =>
binderNameHint s f <| binderNameHint x (f s) <| binderNameHint h () <| f s (wfParam x)) x := by
simp [wfParam]
@[wf_preprocess] theorem foldr_wfParam (xs : List α) (f : α β β) (x : β) :
@[wf_preprocess] theorem foldr_wfParam {xs : List α} {f : α β β} {x : β} :
(wfParam xs).foldr f x = xs.attach.unattach.foldr f x := by
simp [wfParam]
@[wf_preprocess] theorem foldr_unattach (P : α Prop) (xs : List (Subtype P)) (f : α β β) (x : β):
@[wf_preprocess] theorem foldr_unattach {P : α Prop} {xs : List (Subtype P)} {f : α β β} {x : β} :
xs.unattach.foldr f x = xs.foldr (fun x, h s =>
binderNameHint x f <| binderNameHint s (f x) <| binderNameHint h () <| f (wfParam x) s) x := by
simp [wfParam]
@[wf_preprocess] theorem filter_wfParam (xs : List α) (f : α Bool) :
@[wf_preprocess] theorem filter_wfParam {xs : List α} {f : α Bool} :
(wfParam xs).filter f = xs.attach.unattach.filter f:= by
simp [wfParam]
@[wf_preprocess] theorem filter_unattach (P : α Prop) (xs : List (Subtype P)) (f : α Bool) :
@[wf_preprocess] theorem filter_unattach {P : α Prop} {xs : List (Subtype P)} {f : α Bool} :
xs.unattach.filter f = (xs.filter (fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x))).unattach := by
simp [wfParam]
@[wf_preprocess] theorem reverse_wfParam (xs : List α) :
@[wf_preprocess] theorem reverse_wfParam {xs : List α} :
(wfParam xs).reverse = xs.attach.unattach.reverse := by simp [wfParam]
@[wf_preprocess] theorem reverse_unattach (P : α Prop) (xs : List (Subtype P)) :
@[wf_preprocess] theorem reverse_unattach {P : α Prop} {xs : List (Subtype P)} :
xs.unattach.reverse = xs.reverse.unattach := by simp
@[wf_preprocess] theorem filterMap_wfParam (xs : List α) (f : α Option β) :
@[wf_preprocess] theorem filterMap_wfParam {xs : List α} {f : α Option β} :
(wfParam xs).filterMap f = xs.attach.unattach.filterMap f := by
simp [wfParam]
@[wf_preprocess] theorem filterMap_unattach (P : α Prop) (xs : List (Subtype P)) (f : α Option β) :
@[wf_preprocess] theorem filterMap_unattach {P : α Prop} {xs : List (Subtype P)} {f : α Option β} :
xs.unattach.filterMap f = xs.filterMap fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]
@[wf_preprocess] theorem flatMap_wfParam (xs : List α) (f : α List β) :
@[wf_preprocess] theorem flatMap_wfParam {xs : List α} {f : α List β} :
(wfParam xs).flatMap f = xs.attach.unattach.flatMap f := by
simp [wfParam]
@[wf_preprocess] theorem flatMap_unattach (P : α Prop) (xs : List (Subtype P)) (f : α List β) :
@[wf_preprocess] theorem flatMap_unattach {P : α Prop} {xs : List (Subtype P)} {f : α List β} :
xs.unattach.flatMap f = xs.flatMap fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]

View File

@@ -76,14 +76,14 @@ namespace List
@[simp] theorem length_nil : length ([] : List α) = 0 :=
rfl
@[simp] theorem length_singleton (a : α) : length [a] = 1 := rfl
@[simp] theorem length_singleton {a : α} : length [a] = 1 := rfl
@[simp] theorem length_cons {α} (a : α) (as : List α) : (cons a as).length = as.length + 1 :=
@[simp] theorem length_cons {a : α} {as : List α} : (cons a as).length = as.length + 1 :=
rfl
/-! ### set -/
@[simp] theorem length_set (as : List α) (i : Nat) (a : α) : (as.set i a).length = as.length := by
@[simp] theorem length_set {as : List α} {i : Nat} {a : α} : (as.set i a).length = as.length := by
induction as generalizing i with
| nil => rfl
| cons x xs ih =>
@@ -95,11 +95,11 @@ namespace List
-- As `List.foldl` is defined in `Init.Prelude`, we write the basic simplification lemmas here.
@[simp] theorem foldl_nil : [].foldl f b = b := rfl
@[simp] theorem foldl_cons (l : List α) (b : β) : (a :: l).foldl f b = l.foldl f (f b a) := rfl
@[simp] theorem foldl_cons {l : List α} {f : β α β} {b : β} : (a :: l).foldl f b = l.foldl f (f b a) := rfl
/-! ### concat -/
theorem length_concat (as : List α) (a : α) : (concat as a).length = as.length + 1 := by
theorem length_concat {as : List α} {a : α} : (concat as a).length = as.length + 1 := by
induction as with
| nil => rfl
| cons _ xs ih => simp [concat, ih]
@@ -125,9 +125,9 @@ protected def beq [BEq α] : List α → List α → Bool
| _, _ => false
@[simp] theorem beq_nil_nil [BEq α] : List.beq ([] : List α) ([] : List α) = true := rfl
@[simp] theorem beq_cons_nil [BEq α] (a : α) (as : List α) : List.beq (a::as) [] = false := rfl
@[simp] theorem beq_nil_cons [BEq α] (a : α) (as : List α) : List.beq [] (a::as) = false := rfl
theorem beq_cons₂ [BEq α] (a b : α) (as bs : List α) : List.beq (a::as) (b::bs) = (a == b && List.beq as bs) := rfl
@[simp] theorem beq_cons_nil [BEq α] {a : α} {as : List α} : List.beq (a::as) [] = false := rfl
@[simp] theorem beq_nil_cons [BEq α] {a : α} {as : List α} : List.beq [] (a::as) = false := rfl
theorem beq_cons₂ [BEq α] {a b : α} {as bs : List α} : List.beq (a::as) (b::bs) = (a == b && List.beq as bs) := rfl
instance [BEq α] : BEq (List α) := List.beq
@@ -344,8 +344,8 @@ def getLastD : (as : List α) → (fallback : α) → α
| a::as, _ => getLast (a::as) (fun h => List.noConfusion h)
-- These aren't `simp` lemmas since we always simplify `getLastD` in terms of `getLast?`.
theorem getLastD_nil (a) : @getLastD α [] a = a := rfl
theorem getLastD_cons (a b l) : @getLastD α (b::l) a = getLastD l b := by cases l <;> rfl
theorem getLastD_nil {a : α} : getLastD [] a = a := rfl
theorem getLastD_cons {a b : α} {l} : getLastD (b::l) a = getLastD l b := by cases l <;> rfl
/-! ## Head and tail -/
@@ -357,7 +357,7 @@ Returns the first element of a non-empty list.
def head : (as : List α) as [] α
| a::_, _ => a
@[simp] theorem head_cons : @head α (a::l) h = a := rfl
@[simp] theorem head_cons {a : α} {l : List α} {h} : head (a::l) h = a := rfl
/-! ### head? -/
@@ -375,8 +375,8 @@ def head? : List α → Option α
| [] => none
| a::_ => some a
@[simp] theorem head?_nil : @head? α [] = none := rfl
@[simp] theorem head?_cons : @head? α (a::l) = some a := rfl
@[simp] theorem head?_nil : head? ([] : List α) = none := rfl
@[simp] theorem head?_cons {a : α} {l : List α} : head? (a::l) = some a := rfl
/-! ### headD -/
@@ -394,8 +394,8 @@ def headD : (as : List α) → (fallback : α) → α
| [], fallback => fallback
| a::_, _ => a
@[simp] theorem headD_nil : @headD α [] d = d := rfl
@[simp] theorem headD_cons : @headD α (a::l) d = a := rfl
@[simp] theorem headD_nil {d : α} : headD [] d = d := rfl
@[simp] theorem headD_cons {a : α} {l : List α} {d : α} : headD (a::l) d = a := rfl
/-! ### tail -/
@@ -412,8 +412,8 @@ def tail : List α → List α
| [] => []
| _::as => as
@[simp] theorem tail_nil : @tail α [] = [] := rfl
@[simp] theorem tail_cons : @tail α (a::as) = as := rfl
@[simp] theorem tail_nil : tail ([] : List α) = [] := rfl
@[simp] theorem tail_cons {a : α} {as : List α} : tail (a::as) = as := rfl
/-! ### tail? -/
@@ -433,8 +433,8 @@ def tail? : List α → Option (List α)
| [] => none
| _::as => some as
@[simp] theorem tail?_nil : @tail? α [] = none := rfl
@[simp] theorem tail?_cons : @tail? α (a::l) = some l := rfl
@[simp] theorem tail?_nil : tail? ([] : List α) = none := rfl
@[simp] theorem tail?_cons {a : α} {l : List α} : tail? (a::l) = some l := rfl
/-! ### tailD -/
@@ -456,8 +456,8 @@ def tailD (l fallback : List α) : List α :=
| [] => fallback
| _ :: tl => tl
@[simp] theorem tailD_nil : @tailD α [] l' = l' := rfl
@[simp] theorem tailD_cons : @tailD α (a::l) l' = l := rfl
@[simp] theorem tailD_nil {l' : List α} : tailD [] l' = l' := rfl
@[simp] theorem tailD_cons {a : α} {l : List α} {l' : List α} : tailD (a::l) l' = l := rfl
/-! ## Basic `List` operations.
@@ -483,7 +483,7 @@ Examples:
| a::as => f a :: map f as
@[simp] theorem map_nil {f : α β} : map f [] = [] := rfl
@[simp] theorem map_cons (f : α β) a l : map f (a :: l) = f a :: map f l := rfl
@[simp] theorem map_cons {f : α β} {a : α} {l : List α} : map f (a :: l) = f a :: map f l := rfl
/-! ### filter -/
@@ -503,7 +503,7 @@ def filter (p : α → Bool) : (l : List α) → List α
| true => a :: filter p as
| false => filter p as
@[simp] theorem filter_nil (p : α Bool) : filter p [] = [] := rfl
@[simp] theorem filter_nil {p : α Bool} : filter p [] = [] := rfl
/-! ### filterMap -/
@@ -529,8 +529,8 @@ Example:
| none => filterMap f as
| some b => b :: filterMap f as
@[simp] theorem filterMap_nil (f : α Option β) : filterMap f [] = [] := rfl
theorem filterMap_cons (f : α Option β) (a : α) (l : List α) :
@[simp] theorem filterMap_nil {f : α Option β} : filterMap f [] = [] := rfl
theorem filterMap_cons {f : α Option β} {a : α} {l : List α} :
filterMap f (a :: l) =
match f a with
| none => filterMap f l
@@ -554,7 +554,8 @@ Examples:
| a :: l => f a (foldr f init l)
@[simp] theorem foldr_nil : [].foldr f b = b := rfl
@[simp] theorem foldr_cons (l : List α) : (a :: l).foldr f b = f a (l.foldr f b) := rfl
@[simp] theorem foldr_cons {a} {l : List α} {f : α β β} {b} :
(a :: l).foldr f b = f a (l.foldr f b) := rfl
/-! ### reverse -/
@@ -584,10 +585,11 @@ def reverse (as : List α) : List α :=
@[simp] theorem reverse_nil : reverse ([] : List α) = [] := rfl
theorem reverseAux_reverseAux (as bs cs : List α) : reverseAux (reverseAux as bs) cs = reverseAux bs (reverseAux (reverseAux as []) cs) := by
theorem reverseAux_reverseAux {as bs cs : List α} :
reverseAux (reverseAux as bs) cs = reverseAux bs (reverseAux (reverseAux as []) cs) := by
induction as generalizing bs cs with
| nil => rfl
| cons a as ih => simp [reverseAux, ih (a::bs), ih [a]]
| cons a as ih => simp [reverseAux, ih (bs := a::bs), ih (bs := [a])]
/-! ### append -/
@@ -633,10 +635,10 @@ def appendTR (as bs : List α) : List α :=
instance : Append (List α) := List.append
@[simp] theorem append_eq (as bs : List α) : List.append as bs = as ++ bs := rfl
@[simp] theorem append_eq {as bs : List α} : List.append as bs = as ++ bs := rfl
@[simp] theorem nil_append (as : List α) : [] ++ as = as := rfl
@[simp] theorem cons_append (a : α) (as bs : List α) : (a::as) ++ bs = a::(as ++ bs) := rfl
@[simp] theorem cons_append {a : α} {as bs : List α} : (a::as) ++ bs = a::(as ++ bs) := rfl
@[simp] theorem append_nil (as : List α) : as ++ [] = as := by
induction as with
@@ -648,7 +650,7 @@ instance : Std.LawfulIdentity (α := List α) (· ++ ·) [] where
left_id := nil_append
right_id := append_nil
@[simp] theorem length_append (as bs : List α) : (as ++ bs).length = as.length + bs.length := by
@[simp] theorem length_append {as bs : List α} : (as ++ bs).length = as.length + bs.length := by
induction as with
| nil => simp
| cons _ as ih => simp [ih, Nat.succ_add]
@@ -660,21 +662,22 @@ instance : Std.LawfulIdentity (α := List α) (· ++ ·) [] where
instance : Std.Associative (α := List α) (· ++ ·) := append_assoc
-- Arguments are explicit as there is often ambiguity inferring the arguments.
theorem append_cons (as : List α) (b : α) (bs : List α) : as ++ b :: bs = as ++ [b] ++ bs := by
simp
@[simp] theorem concat_eq_append (as : List α) (a : α) : as.concat a = as ++ [a] := by
@[simp] theorem concat_eq_append {as : List α} {a : α} : as.concat a = as ++ [a] := by
induction as <;> simp [concat, *]
theorem reverseAux_eq_append (as bs : List α) : reverseAux as bs = reverseAux as [] ++ bs := by
theorem reverseAux_eq_append {as bs : List α} : reverseAux as bs = reverseAux as [] ++ bs := by
induction as generalizing bs with
| nil => simp [reverseAux]
| cons a as ih =>
simp [reverseAux]
rw [ih (a :: bs), ih [a], append_assoc]
rw [ih (bs := a :: bs), ih (bs := [a]), append_assoc]
rfl
@[simp] theorem reverse_cons (a : α) (as : List α) : reverse (a :: as) = reverse as ++ [a] := by
@[simp] theorem reverse_cons {a : α} {as : List α} : reverse (a :: as) = reverse as ++ [a] := by
simp [reverse, reverseAux]
rw [ reverseAux_eq_append]
@@ -725,8 +728,8 @@ Examples:
-/
@[inline] def flatMap {α : Type u} {β : Type v} (b : α List β) (as : List α) : List β := flatten (map b as)
@[simp] theorem flatMap_nil (f : α List β) : List.flatMap f [] = [] := by simp [flatten, List.flatMap]
@[simp] theorem flatMap_cons x xs (f : α List β) :
@[simp] theorem flatMap_nil {f : α List β} : List.flatMap f [] = [] := by simp [flatten, List.flatMap]
@[simp] theorem flatMap_cons {x : α} {xs : List α} {f : α List β} :
List.flatMap f (x :: xs) = f x ++ List.flatMap f xs := by simp [flatten, List.flatMap]
set_option linter.missingDocs false in
@@ -749,10 +752,10 @@ def replicate : (n : Nat) → (a : α) → List α
| 0, _ => []
| n+1, a => a :: replicate n a
@[simp] theorem replicate_zero : replicate 0 a = [] := rfl
theorem replicate_succ (a : α) (n) : replicate (n+1) a = a :: replicate n a := rfl
@[simp] theorem replicate_zero {a : α} : replicate 0 a = [] := rfl
theorem replicate_succ {a : α} {n : Nat} : replicate (n+1) a = a :: replicate n a := rfl
@[simp] theorem length_replicate (n : Nat) (a : α) : (replicate n a).length = n := by
@[simp] theorem length_replicate {n : Nat} {a : α} : (replicate n a).length = n := by
induction n with
| zero => simp
| succ n ih => simp only [ih, replicate_succ, length_cons, Nat.succ_eq_add_one]
@@ -911,7 +914,7 @@ theorem mem_append_left {a : α} {as : List α} (bs : List α) : a ∈ as → a
| head => apply Mem.head
| tail => apply Mem.tail; assumption
theorem mem_append_right {b : α} {bs : List α} (as : List α) : b bs b as ++ bs := by
theorem mem_append_right {b : α} (as : List α) {bs : List α} : b bs b as ++ bs := by
intro h
induction as with
| nil => simp [h]
@@ -959,9 +962,9 @@ def take : (n : Nat) → (xs : List α) → List α
| _+1, [] => []
| n+1, a::as => a :: take n as
@[simp] theorem take_nil : ([] : List α).take i = [] := by cases i <;> rfl
@[simp] theorem take_zero (l : List α) : l.take 0 = [] := rfl
@[simp] theorem take_succ_cons : (a::as).take (i+1) = a :: as.take i := rfl
@[simp] theorem take_nil {i : Nat} : ([] : List α).take i = [] := by cases i <;> rfl
@[simp] theorem take_zero {l : List α} : l.take 0 = [] := rfl
@[simp] theorem take_succ_cons {a : α} {as : List α} {i : Nat} : (a::as).take (i+1) = a :: as.take i := rfl
/-! ### drop -/
@@ -983,8 +986,8 @@ def drop : (n : Nat) → (xs : List α) → List α
@[simp] theorem drop_nil : ([] : List α).drop i = [] := by
cases i <;> rfl
@[simp] theorem drop_zero (l : List α) : l.drop 0 = l := rfl
@[simp] theorem drop_succ_cons : (a :: l).drop (i + 1) = l.drop i := rfl
@[simp] theorem drop_zero {l : List α} : l.drop 0 = l := rfl
@[simp] theorem drop_succ_cons {a : α} {l : List α} {i : Nat} : (a :: l).drop (i + 1) = l.drop i := rfl
theorem drop_eq_nil_of_le {as : List α} {i : Nat} (h : as.length i) : as.drop i = [] := by
match as, i with
@@ -1009,7 +1012,7 @@ Examples:
abbrev extract (l : List α) (start : Nat := 0) (stop : Nat := l.length) : List α :=
(l.drop start).take (stop - start)
@[simp] theorem extract_eq_drop_take (l : List α) (start stop : Nat) :
@[simp] theorem extract_eq_drop_take {l : List α} {start stop : Nat} :
l.extract start stop = (l.drop start).take (stop - start) := rfl
/-! ### takeWhile -/
@@ -1102,12 +1105,10 @@ def dropLast {α} : List α → List α
-- Later this can be proved by `simp` via `[List.length_dropLast, List.length_cons, Nat.add_sub_cancel]`,
-- but we need this while bootstrapping `Array`.
@[simp] theorem length_dropLast_cons (a : α) (as : List α) : (a :: as).dropLast.length = as.length := by
@[simp] theorem length_dropLast_cons {a : α} {as : List α} : (a :: as).dropLast.length = as.length := by
match as with
| [] => rfl
| b::bs =>
have ih := length_dropLast_cons b bs
simp [dropLast, ih]
| b::bs => simp [dropLast, length_dropLast_cons]
/-! ### Subset -/
@@ -1500,8 +1501,8 @@ Examples:
| [] => []
| a :: l => f a :: l
@[simp] theorem modifyHead_nil (f : α α) : [].modifyHead f = [] := by rw [modifyHead]
@[simp] theorem modifyHead_cons (a : α) (l : List α) (f : α α) :
@[simp] theorem modifyHead_nil {f : α α} : [].modifyHead f = [] := by rw [modifyHead]
@[simp] theorem modifyHead_cons {a : α} {l : List α} {f : α α} :
(a :: l).modifyHead f = f a :: l := by rw [modifyHead]
/--
@@ -1566,7 +1567,7 @@ protected def erase {α} [BEq α] : List αα → List α
| false => a :: List.erase as b
@[simp] theorem erase_nil [BEq α] (a : α) : [].erase a = [] := rfl
theorem erase_cons [BEq α] (a b : α) (l : List α) :
theorem erase_cons [BEq α] {a b : α} {l : List α} :
(b :: l).erase a = if b == a then l else b :: l.erase a := by
simp only [List.erase]; split <;> simp_all
@@ -1668,7 +1669,7 @@ Examples:
| [], n => n
| a :: l, n => bif p a then n else go l (n + 1)
@[simp] theorem findIdx_nil {α : Type _} (p : α Bool) : [].findIdx p = 0 := rfl
@[simp] theorem findIdx_nil {p : α Bool} : [].findIdx p = 0 := rfl
/-! ### idxOf -/
@@ -1805,14 +1806,14 @@ Examples:
* `[(1, "one"), (3, "three"), (3, "other")].lookup 2 = none`
-/
def lookup [BEq α] : α List (α × β) Option β
| _, [] => none
| a, (k,b)::as => match a == k with
| _, [] => none
| a, (k, b) :: as => match a == k with
| true => some b
| false => lookup a as
@[simp] theorem lookup_nil [BEq α] : ([] : List (α × β)).lookup a = none := rfl
theorem lookup_cons [BEq α] {k : α} :
((k,b)::as).lookup a = match a == k with | true => some b | false => as.lookup a :=
((k, b)::as).lookup a = match a == k with | true => some b | false => as.lookup a :=
rfl
/-! ## Permutations -/
@@ -2220,9 +2221,9 @@ def intersperse (sep : α) : (l : List α) → List α
| [x] => [x]
| x::xs => x :: sep :: intersperse sep xs
@[simp] theorem intersperse_nil (sep : α) : ([] : List α).intersperse sep = [] := rfl
@[simp] theorem intersperse_single (sep : α) : [x].intersperse sep = [x] := rfl
@[simp] theorem intersperse_cons₂ (sep : α) :
@[simp] theorem intersperse_nil {sep : α} : ([] : List α).intersperse sep = [] := rfl
@[simp] theorem intersperse_single {x : α} {sep : α} : [x].intersperse sep = [x] := rfl
@[simp] theorem intersperse_cons₂ {x : α} {y : α} {zs : List α} {sep : α} :
(x::y::zs).intersperse sep = x::sep::((y::zs).intersperse sep) := rfl
/-! ### intercalate -/
@@ -2368,7 +2369,7 @@ then at runtime you will get non tail-recursive versions.
/-! ### length -/
theorem length_add_eq_lengthTRAux (as : List α) (n : Nat) : as.length + n = as.lengthTRAux n := by
theorem length_add_eq_lengthTRAux {as : List α} {n : Nat} : as.length + n = as.lengthTRAux n := by
induction as generalizing n with
| nil => simp [length, lengthTRAux]
| cons a as ih =>
@@ -2399,13 +2400,13 @@ where
| [], bs => bs.reverse
| a::as, bs => loop as (f a :: bs)
theorem mapTR_loop_eq (f : α β) (as : List α) (bs : List β) :
theorem mapTR_loop_eq {f : α β} {as : List α} {bs : List β} :
mapTR.loop f as bs = bs.reverse ++ map f as := by
induction as generalizing bs with
| nil => simp [mapTR.loop, map]
| cons a as ih =>
simp only [mapTR.loop, map]
rw [ih (f a :: bs), reverse_cons, append_assoc]
rw [ih (bs := f a :: bs), reverse_cons, append_assoc]
rfl
@[csimp] theorem map_eq_mapTR : @map = @mapTR :=
@@ -2433,7 +2434,7 @@ where
| true => loop as (a::acc)
| false => loop as acc
theorem filterTR_loop_eq (p : α Bool) (as bs : List α) :
theorem filterTR_loop_eq {p : α Bool} {as : List α} {bs : List α} :
filterTR.loop p as bs = bs.reverse ++ filter p as := by
induction as generalizing bs with
| nil => simp [filterTR.loop, filter]
@@ -2462,19 +2463,19 @@ def replicateTR {α : Type u} (n : Nat) (a : α) : List α :=
| n+1, as => loop n (a::as)
loop n []
theorem replicateTR_loop_replicate_eq (a : α) (m n : Nat) :
theorem replicateTR_loop_replicate_eq {a : α} {m n : Nat} :
replicateTR.loop a n (replicate m a) = replicate (n + m) a := by
induction n generalizing m with simp [replicateTR.loop]
| succ n ih => simp [Nat.succ_add]; exact ih (m+1)
| succ n ih => simp [Nat.succ_add]; exact ih (m := m+1)
theorem replicateTR_loop_eq : n, replicateTR.loop a n acc = replicate n a ++ acc
| 0 => rfl
| n+1 => by rw [ replicateTR_loop_replicate_eq _ 1 n, replicate, replicate,
| n+1 => by rw [ replicateTR_loop_replicate_eq, replicate, replicate,
replicateTR.loop, replicateTR_loop_eq n, replicateTR_loop_eq n, append_assoc]; rfl
@[csimp] theorem replicate_eq_replicateTR : @List.replicate = @List.replicateTR := by
apply funext; intro α; apply funext; intro n; apply funext; intro a
exact (replicateTR_loop_replicate_eq _ 0 n).symm
exact (replicateTR_loop_replicate_eq (m := 0)).symm
/-! ## Additional functions -/

View File

@@ -236,8 +236,8 @@ def foldlM {m : Type u → Type v} [Monad m] {s : Type u} {α : Type w} : (f : s
let s' f s a
List.foldlM f s' as
@[simp] theorem foldlM_nil [Monad m] (f : β α m β) (b) : [].foldlM f b = pure b := rfl
@[simp] theorem foldlM_cons [Monad m] (f : β α m β) (b) (a) (l : List α) :
@[simp] theorem foldlM_nil [Monad m] {f : β α m β} {b : β} : [].foldlM f b = pure b := rfl
@[simp] theorem foldlM_cons [Monad m] {f : β α m β} {b : β} {a : α} {l : List α} :
(a :: l).foldlM f b = f b a >>= l.foldlM f := by
simp [List.foldlM]
@@ -260,7 +260,7 @@ example [Monad m] (f : α → β → m β) :
def foldrM {m : Type u Type v} [Monad m] {s : Type u} {α : Type w} (f : α s m s) (init : s) (l : List α) : m s :=
l.reverse.foldlM (fun s a => f a s) init
@[simp] theorem foldrM_nil [Monad m] (f : α β m β) (b) : [].foldrM f b = pure b := rfl
@[simp] theorem foldrM_nil [Monad m] {f : α β m β} {b : β} : [].foldrM f b = pure b := rfl
/--
Maps `f` over the list and collects the results with `<|>`. The result for the end of the list is
@@ -382,7 +382,7 @@ def findSomeM? {m : Type u → Type v} [Monad m] {α : Type w} {β : Type u} (f
| none => findSomeM? f as
@[simp]
theorem findSomeM?_pure [Monad m] [LawfulMonad m] (f : α Option β) (as : List α) :
theorem findSomeM?_pure [Monad m] [LawfulMonad m] {f : α Option β} {as : List α} :
findSomeM? (m := m) (pure <| f ·) as = pure (as.findSome? f) := by
induction as with
| nil => rfl
@@ -393,10 +393,10 @@ theorem findSomeM?_pure [Monad m] [LawfulMonad m] (f : α → Option β) (as : L
| none => simp [ih]
@[simp]
theorem findSomeM?_id (f : α Option β) (as : List α) : findSomeM? (m := Id) f as = as.findSome? f :=
findSomeM?_pure _ _
theorem findSomeM?_id {f : α Option β} {as : List α} : findSomeM? (m := Id) f as = as.findSome? f :=
findSomeM?_pure
theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] (p : α m Bool) (as : List α) :
theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] {p : α m Bool} {as : List α} :
as.findM? p = as.findSomeM? fun a => return if ( p a) then some a else none := by
induction as with
| nil => rfl
@@ -420,7 +420,7 @@ theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] (p : α → m Bool) (as :
match ( f a this b) with
| ForInStep.done b => pure b
| ForInStep.yield b =>
have : Exists (fun bs => bs ++ as' = as) := have bs, h := h; bs ++ [a], by rw [ h, append_cons bs a as']
have : Exists (fun bs => bs ++ as' = as) := have bs, h := h; bs ++ [a], by rw [ h, append_cons (bs := as')]
loop as' b this
loop as init [], rfl
@@ -432,10 +432,10 @@ instance : ForIn' m (List α) α inferInstance where
-- We simplify `List.forIn'` to `forIn'`.
@[simp] theorem forIn'_eq_forIn' [Monad m] : @List.forIn' α β m _ = forIn' := rfl
@[simp] theorem forIn'_nil [Monad m] (f : (a : α) a [] β m (ForInStep β)) (b : β) : forIn' [] b f = pure b :=
@[simp] theorem forIn'_nil [Monad m] {f : (a : α) a [] β m (ForInStep β)} {b : β} : forIn' [] b f = pure b :=
rfl
@[simp] theorem forIn_nil [Monad m] (f : α β m (ForInStep β)) (b : β) : forIn [] b f = pure b :=
@[simp] theorem forIn_nil [Monad m] {f : α β m (ForInStep β)} {b : β} : forIn [] b f = pure b :=
rfl
instance : ForM m (List α) α where
@@ -444,9 +444,9 @@ instance : ForM m (List α) α where
-- We simplify `List.forM` to `forM`.
@[simp] theorem forM_eq_forM [Monad m] : @List.forM m _ α = forM := rfl
@[simp] theorem forM_nil [Monad m] (f : α m PUnit) : forM [] f = pure :=
@[simp] theorem forM_nil [Monad m] {f : α m PUnit} : forM [] f = pure :=
rfl
@[simp] theorem forM_cons [Monad m] (f : α m PUnit) (a : α) (as : List α) : forM (a::as) f = f a >>= fun _ => forM as f :=
@[simp] theorem forM_cons [Monad m] {f : α m PUnit} {a : α} {as : List α} : forM (a::as) f = f a >>= fun _ => forM as f :=
rfl
instance : Functor List where

View File

@@ -20,11 +20,11 @@ open Nat
/-! ### countP -/
section countP
variable (p q : α Bool)
variable {p q : α Bool}
@[simp] theorem countP_nil : countP p [] = 0 := rfl
protected theorem countP_go_eq_add (l) : countP.go p l n = n + countP.go p l 0 := by
protected theorem countP_go_eq_add {l} : countP.go p l n = n + countP.go p l 0 := by
induction l generalizing n with
| nil => rfl
| cons hd _ ih =>
@@ -32,40 +32,40 @@ protected theorem countP_go_eq_add (l) : countP.go p l n = n + countP.go p l 0 :
rw [ih (n := n + 1), ih (n := n), ih (n := 1)]
if h : p hd then simp [h, Nat.add_assoc] else simp [h]
@[simp] theorem countP_cons_of_pos (l) (pa : p a) : countP p (a :: l) = countP p l + 1 := by
@[simp] theorem countP_cons_of_pos {l} (pa : p a) : countP p (a :: l) = countP p l + 1 := by
have : countP.go p (a :: l) 0 = countP.go p l 1 := show cond .. = _ by rw [pa]; rfl
unfold countP
rw [this, Nat.add_comm, List.countP_go_eq_add]
@[simp] theorem countP_cons_of_neg (l) (pa : ¬p a) : countP p (a :: l) = countP p l := by
@[simp] theorem countP_cons_of_neg {l} (pa : ¬p a) : countP p (a :: l) = countP p l := by
simp [countP, countP.go, pa]
theorem countP_cons (a : α) (l) : countP p (a :: l) = countP p l + if p a then 1 else 0 := by
theorem countP_cons {a : α} {l : List α} : countP p (a :: l) = countP p l + if p a then 1 else 0 := by
by_cases h : p a <;> simp [h]
@[simp] theorem countP_singleton (a : α) : countP p [a] = if p a then 1 else 0 := by
@[simp] theorem countP_singleton {a : α} : countP p [a] = if p a then 1 else 0 := by
simp [countP_cons]
theorem length_eq_countP_add_countP (l) : length l = countP p l + countP (fun a => ¬p a) l := by
theorem length_eq_countP_add_countP (p : α Bool) {l : List α} : length l = countP p l + countP (fun a => ¬p a) l := by
induction l with
| nil => rfl
| cons hd _ ih =>
if h : p hd then
rw [countP_cons_of_pos _ _ h, countP_cons_of_neg _ _ _, length, ih]
rw [countP_cons_of_pos h, countP_cons_of_neg _, length, ih]
· rw [Nat.add_assoc, Nat.add_comm _ 1, Nat.add_assoc]
· simp [h]
else
rw [countP_cons_of_pos (fun a => ¬p a) _ _, countP_cons_of_neg _ _ h, length, ih]
rw [countP_cons_of_pos (p := fun a => ¬p a), countP_cons_of_neg h, length, ih]
· rfl
· simp [h]
theorem countP_eq_length_filter (l) : countP p l = length (filter p l) := by
theorem countP_eq_length_filter {l : List α} : countP p l = length (filter p l) := by
induction l with
| nil => rfl
| cons x l ih =>
if h : p x
then rw [countP_cons_of_pos p l h, ih, filter_cons_of_pos h, length]
else rw [countP_cons_of_neg p l h, ih, filter_cons_of_neg h]
then rw [countP_cons_of_pos h, ih, filter_cons_of_pos h, length]
else rw [countP_cons_of_neg h, ih, filter_cons_of_neg h]
theorem countP_eq_length_filter' : countP p = length filter p := by
funext l
@@ -75,7 +75,7 @@ theorem countP_le_length : countP p l ≤ l.length := by
simp only [countP_eq_length_filter]
apply length_filter_le
@[simp] theorem countP_append (l₁ l₂) : countP p (l₁ ++ l₂) = countP p l₁ + countP p l₂ := by
@[simp] theorem countP_append {l₁ l₂ : List α} : countP p (l₁ ++ l₂) = countP p l₁ + countP p l₂ := by
simp only [countP_eq_length_filter, filter_append, length_append]
@[simp] theorem countP_pos_iff {p} : 0 < countP p l a l, p a := by
@@ -92,12 +92,12 @@ theorem countP_le_length : countP p l ≤ l.length := by
@[simp] theorem countP_eq_length {p} : countP p l = l.length a l, p a := by
rw [countP_eq_length_filter, length_filter_eq_length_iff]
theorem countP_replicate (p : α Bool) (a : α) (n : Nat) :
theorem countP_replicate {p : α Bool} {a : α} {n : Nat} :
countP p (replicate n a) = if p a then n else 0 := by
simp only [countP_eq_length_filter, filter_replicate]
split <;> simp
theorem boole_getElem_le_countP (p : α Bool) (l : List α) (i : Nat) (h : i < l.length) :
theorem boole_getElem_le_countP {p : α Bool} {l : List α} {i : Nat} (h : i < l.length) :
(if p l[i] then 1 else 0) l.countP p := by
induction l generalizing i with
| nil => simp at h
@@ -107,25 +107,25 @@ theorem boole_getElem_le_countP (p : α → Bool) (l : List α) (i : Nat) (h : i
| succ i =>
simp only [length_cons, add_one_lt_add_one_iff] at h
simp only [getElem_cons_succ, countP_cons]
specialize ih _ h
specialize ih h
exact le_add_right_of_le ih
theorem Sublist.countP_le (s : l₁ <+ l₂) : countP p l₁ countP p l₂ := by
simp only [countP_eq_length_filter]
apply s.filter _ |>.length_le
theorem IsPrefix.countP_le (s : l₁ <+: l₂) : countP p l₁ countP p l₂ := s.sublist.countP_le _
theorem IsSuffix.countP_le (s : l₁ <:+ l₂) : countP p l₁ countP p l₂ := s.sublist.countP_le _
theorem IsInfix.countP_le (s : l₁ <:+: l₂) : countP p l₁ countP p l₂ := s.sublist.countP_le _
theorem IsPrefix.countP_le (s : l₁ <+: l₂) : countP p l₁ countP p l₂ := s.sublist.countP_le
theorem IsSuffix.countP_le (s : l₁ <:+ l₂) : countP p l₁ countP p l₂ := s.sublist.countP_le
theorem IsInfix.countP_le (s : l₁ <:+: l₂) : countP p l₁ countP p l₂ := s.sublist.countP_le
-- See `Init.Data.List.Nat.Count` for `Sublist.le_countP : countP p l₂ - (l₂.length - l₁.length) ≤ countP p l₁`.
theorem countP_tail_le (l) : countP p l.tail countP p l :=
(tail_sublist l).countP_le _
(tail_sublist l).countP_le
-- See `Init.Data.List.Nat.Count` for `le_countP_tail : countP p l - 1 ≤ countP p l.tail`.
theorem countP_filter (l : List α) :
theorem countP_filter {l : List α} :
countP p (filter q l) = countP (fun a => p a && q a) l := by
simp only [countP_eq_length_filter, filter_filter]
@@ -137,12 +137,12 @@ theorem countP_filter (l : List α) :
funext l
simp
@[simp] theorem countP_map (p : β Bool) (f : α β) :
l, countP p (map f l) = countP (p f) l
@[simp] theorem countP_map {p : β Bool} {f : α β} :
{l}, countP p (map f l) = countP (p f) l
| [] => rfl
| a :: l => by rw [map_cons, countP_cons, countP_cons, countP_map p f l]; rfl
| a :: l => by rw [map_cons, countP_cons, countP_cons, countP_map]; rfl
theorem length_filterMap_eq_countP (f : α Option β) (l : List α) :
theorem length_filterMap_eq_countP {f : α Option β} {l : List α} :
(filterMap f l).length = countP (fun a => (f a).isSome) l := by
induction l with
| nil => rfl
@@ -150,7 +150,7 @@ theorem length_filterMap_eq_countP (f : α → Option β) (l : List α) :
simp only [filterMap_cons, countP_cons]
split <;> simp [ih, *]
theorem countP_filterMap (p : β Bool) (f : α Option β) (l : List α) :
theorem countP_filterMap {p : β Bool} {f : α Option β} {l : List α} :
countP p (filterMap f l) = countP (fun a => ((f a).map p).getD false) l := by
simp only [countP_eq_length_filter, filter_filterMap, filterMap_eq_filter]
simp only [length_filterMap_eq_countP]
@@ -158,22 +158,20 @@ theorem countP_filterMap (p : β → Bool) (f : α → Option β) (l : List α)
ext a
simp +contextual [Option.getD_eq_iff, Option.isSome_eq_isSome]
@[simp] theorem countP_flatten (l : List (List α)) :
@[simp] theorem countP_flatten {l : List (List α)} :
countP p l.flatten = (l.map (countP p)).sum := by
simp only [countP_eq_length_filter, filter_flatten]
simp [countP_eq_length_filter']
@[deprecated countP_flatten (since := "2024-10-14")] abbrev countP_join := @countP_flatten
theorem countP_flatMap (p : β Bool) (l : List α) (f : α List β) :
theorem countP_flatMap {p : β Bool} {l : List α} {f : α List β} :
countP p (l.flatMap f) = sum (map (countP p f) l) := by
rw [List.flatMap, countP_flatten, map_map]
@[simp] theorem countP_reverse (l : List α) : countP p l.reverse = countP p l := by
@[simp] theorem countP_reverse {l : List α} : countP p l.reverse = countP p l := by
simp [countP_eq_length_filter, filter_reverse]
variable {p q}
theorem countP_mono_left (h : x l, p x q x) : countP p l countP q l := by
induction l with
| nil => apply Nat.le_refl
@@ -200,70 +198,69 @@ section count
variable [BEq α]
@[simp] theorem count_nil (a : α) : count a [] = 0 := rfl
@[simp] theorem count_nil {a : α} : count a [] = 0 := rfl
theorem count_cons (a b : α) (l : List α) :
theorem count_cons {a b : α} {l : List α} :
count a (b :: l) = count a l + if b == a then 1 else 0 := by
simp [count, countP_cons]
theorem count_eq_countP (a : α) (l : List α) : count a l = countP (· == a) l := rfl
theorem count_eq_countP {a : α} {l : List α} : count a l = countP (· == a) l := rfl
theorem count_eq_countP' {a : α} : count a = countP (· == a) := by
funext l
apply count_eq_countP
theorem count_tail : (l : List α) (a : α) (h : l []),
theorem count_tail : {l : List α} {a : α} (h : l []),
l.tail.count a = l.count a - if l.head h == a then 1 else 0
| _ :: _, a, _ => by simp [count_cons]
theorem count_le_length (a : α) (l : List α) : count a l l.length := countP_le_length _
theorem count_le_length {a : α} {l : List α} : count a l l.length := countP_le_length
theorem Sublist.count_le (h : l₁ <+ l₂) (a : α) : count a l₁ count a l₂ := h.countP_le _
theorem Sublist.count_le (a : α) (h : l₁ <+ l₂) : count a l₁ count a l₂ := h.countP_le
theorem IsPrefix.count_le (h : l₁ <+: l₂) (a : α) : count a l₁ count a l₂ := h.sublist.count_le _
theorem IsSuffix.count_le (h : l₁ <:+ l₂) (a : α) : count a l₁ count a l₂ := h.sublist.count_le _
theorem IsInfix.count_le (h : l₁ <:+: l₂) (a : α) : count a l₁ count a l₂ := h.sublist.count_le _
theorem IsPrefix.count_le (a : α) (h : l₁ <+: l₂) : count a l₁ count a l₂ := h.sublist.count_le a
theorem IsSuffix.count_le (a : α) (h : l₁ <:+ l₂) : count a l₁ count a l₂ := h.sublist.count_le a
theorem IsInfix.count_le (a : α) (h : l₁ <:+: l₂) : count a l₁ count a l₂ := h.sublist.count_le a
-- See `Init.Data.List.Nat.Count` for `Sublist.le_count : count a l₂ - (l₂.length - l₁.length) ≤ countP a l₁`.
theorem count_tail_le (a : α) (l) : count a l.tail count a l :=
(tail_sublist l).count_le _
theorem count_tail_le {a : α} {l : List α} : count a l.tail count a l :=
(tail_sublist l).count_le a
-- See `Init.Data.List.Nat.Count` for `le_count_tail : count a l - 1 ≤ count a l.tail`.
theorem count_le_count_cons (a b : α) (l : List α) : count a l count a (b :: l) :=
(sublist_cons_self _ _).count_le _
theorem count_le_count_cons {a b : α} {l : List α} : count a l count a (b :: l) :=
(sublist_cons_self _ _).count_le a
theorem count_singleton (a b : α) : count a [b] = if b == a then 1 else 0 := by
theorem count_singleton {a b : α} : count a [b] = if b == a then 1 else 0 := by
simp [count_cons]
@[simp] theorem count_append (a : α) : l₁ l₂, count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
countP_append _
@[simp] theorem count_append {a : α} {l₁ l₂ : List α} : count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
countP_append
theorem count_flatten (a : α) (l : List (List α)) : count a l.flatten = (l.map (count a)).sum := by
theorem count_flatten {a : α} {l : List (List α)} : count a l.flatten = (l.map (count a)).sum := by
simp only [count_eq_countP, countP_flatten, count_eq_countP']
@[deprecated count_flatten (since := "2024-10-14")] abbrev count_join := @count_flatten
@[simp] theorem count_reverse (a : α) (l : List α) : count a l.reverse = count a l := by
@[simp] theorem count_reverse {a : α} {l : List α} : count a l.reverse = count a l := by
simp only [count_eq_countP, countP_eq_length_filter, filter_reverse, length_reverse]
theorem boole_getElem_le_count (a : α) (l : List α) (i : Nat) (h : i < l.length) :
theorem boole_getElem_le_count {a : α} {l : List α} {i : Nat} (h : i < l.length) :
(if l[i] == a then 1 else 0) l.count a := by
rw [count_eq_countP]
apply boole_getElem_le_countP (· == a)
apply boole_getElem_le_countP (p := (· == a))
variable [LawfulBEq α]
@[simp] theorem count_cons_self (a : α) (l : List α) : count a (a :: l) = count a l + 1 := by
@[simp] theorem count_cons_self {a : α} {l : List α} : count a (a :: l) = count a l + 1 := by
simp [count_cons]
@[simp] theorem count_cons_of_ne (h : b a) (l : List α) : count a (b :: l) = count a l := by
@[simp] theorem count_cons_of_ne (h : b a) {l : List α} : count a (b :: l) = count a l := by
simp [count_cons, h]
theorem count_singleton_self (a : α) : count a [a] = 1 := by simp
theorem count_singleton_self {a : α} : count a [a] = 1 := by simp
theorem count_concat_self (a : α) (l : List α) :
count a (concat l a) = (count a l) + 1 := by simp
theorem count_concat_self {a : α} {l : List α} : count a (concat l a) = count a l + 1 := by simp
@[simp]
theorem count_pos_iff {a : α} {l : List α} : 0 < count a l a l := by
@@ -289,41 +286,40 @@ theorem count_eq_length {l : List α} : count a l = l.length ↔ ∀ b ∈ l, a
· simpa using h b hb
· rw [h b hb, beq_self_eq_true]
@[simp] theorem count_replicate_self (a : α) (n : Nat) : count a (replicate n a) = n :=
@[simp] theorem count_replicate_self {a : α} {n : Nat} : count a (replicate n a) = n :=
(count_eq_length.2 <| fun _ h => (eq_of_mem_replicate h).symm).trans (length_replicate ..)
theorem count_replicate (a b : α) (n : Nat) : count a (replicate n b) = if b == a then n else 0 := by
theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by
split <;> (rename_i h; simp only [beq_iff_eq] at h)
· exact b = a count_replicate_self ..
· exact count_eq_zero.2 <| mt eq_of_mem_replicate (Ne.symm h)
theorem filter_beq (l : List α) (a : α) : l.filter (· == a) = replicate (count a l) a := by
theorem filter_beq {l : List α} (a : α) : l.filter (· == a) = replicate (count a l) a := by
simp only [count, countP_eq_length_filter, eq_replicate_iff, mem_filter, beq_iff_eq]
exact trivial, fun _ h => h.2
theorem filter_eq {α} [DecidableEq α] (l : List α) (a : α) : l.filter (· = a) = replicate (count a l) a :=
filter_beq l a
theorem filter_eq {α} [DecidableEq α] {l : List α} (a : α) : l.filter (· = a) = replicate (count a l) a :=
filter_beq a
theorem le_count_iff_replicate_sublist {l : List α} : n count a l replicate n a <+ l := by
refine fun h => ?_, fun h => ?_
· exact ((replicate_sublist_replicate a).2 h).trans <| filter_beq l a filter_sublist _
· exact ((replicate_sublist_replicate a).2 h).trans <| filter_beq a filter_sublist
· simpa only [count_replicate_self] using h.count_le a
theorem replicate_count_eq_of_count_eq_length {l : List α} (h : count a l = length l) :
replicate (count a l) a = l :=
(le_count_iff_replicate_sublist.mp (Nat.le_refl _)).eq_of_length <|
(length_replicate (count a l) a).trans h
(le_count_iff_replicate_sublist.mp (Nat.le_refl _)).eq_of_length <| length_replicate.trans h
@[simp] theorem count_filter {l : List α} (h : p a) : count a (filter p l) = count a l := by
rw [count, countP_filter]; congr; funext b
simp; rintro rfl; exact h
theorem count_le_count_map [DecidableEq β] (l : List α) (f : α β) (x : α) :
theorem count_le_count_map [DecidableEq β] {l : List α} {f : α β} {x : α} :
count x l count (f x) (map f l) := by
rw [count, count, countP_map]
apply countP_mono_left; simp +contextual
theorem count_filterMap {α} [BEq β] (b : β) (f : α Option β) (l : List α) :
theorem count_filterMap {α} [BEq β] {b : β} {f : α Option β} {l : List α} :
count b (filterMap f l) = countP (fun a => f a == some b) l := by
rw [count_eq_countP, countP_filterMap]
congr
@@ -332,11 +328,11 @@ theorem count_filterMap {α} [BEq β] (b : β) (f : α → Option β) (l : List
· simp
· simp
theorem count_flatMap {α} [BEq β] (l : List α) (f : α List β) (x : β) :
count x (l.flatMap f) = sum (map (count x f) l) := countP_flatMap _ _ _
theorem count_flatMap {α} [BEq β] {l : List α} {f : α List β} {x : β} :
count x (l.flatMap f) = sum (map (count x f) l) := countP_flatMap
theorem count_erase (a b : α) :
l : List α, count a (l.erase b) = count a l - if b == a then 1 else 0
theorem count_erase {a b : α} :
{l : List α}, count a (l.erase b) = count a l - if b == a then 1 else 0
| [] => by simp
| c :: l => by
rw [erase_cons]
@@ -345,17 +341,17 @@ theorem count_erase (a b : α) :
rw [if_pos hc_beq, hc, count_cons, Nat.add_sub_cancel]
else
have hc_beq := beq_false_of_ne hc
simp only [hc_beq, if_false, count_cons, count_cons, count_erase a b l, reduceCtorEq]
simp only [hc_beq, if_false, count_cons, count_cons, count_erase, reduceCtorEq]
if ha : b = a then
rw [ha, eq_comm] at hc
rw [if_pos (beq_iff_eq.2 ha), if_neg (by simpa using Ne.symm hc), Nat.add_zero, Nat.add_zero]
else
rw [if_neg (by simpa using ha), Nat.sub_zero, Nat.sub_zero]
@[simp] theorem count_erase_self (a : α) (l : List α) :
@[simp] theorem count_erase_self {a : α} {l : List α} :
count a (List.erase l a) = count a l - 1 := by rw [count_erase, if_pos (by simp)]
@[simp] theorem count_erase_of_ne (ab : a b) (l : List α) : count a (l.erase b) = count a l := by
@[simp] theorem count_erase_of_ne (ab : a b) {l : List α} : count a (l.erase b) = count a l := by
rw [count_erase, if_neg (by simpa using ab.symm), Nat.sub_zero]
end count

View File

@@ -23,7 +23,7 @@ open Nat
@[simp] theorem eraseP_nil : [].eraseP p = [] := rfl
theorem eraseP_cons (a : α) (l : List α) :
theorem eraseP_cons {a : α} {l : List α} :
(a :: l).eraseP p = bif p a then l else a :: l.eraseP p := rfl
@[simp] theorem eraseP_cons_of_pos {l : List α} {p} (h : p a) : (a :: l).eraseP p = l := by
@@ -75,6 +75,7 @@ theorem exists_of_eraseP : ∀ {l : List α} {a} (_ : a ∈ l) (_ : p a),
c, b::l₁, l₂, (forall_mem_cons ..).2 pb, h₁,
h₂, by rw [h₃, cons_append], by simp [pb, h₄]
-- The arguments are explicit here, so this lemma can be used as a case split.
theorem exists_or_eq_self_of_eraseP (p) (l : List α) :
l.eraseP p = l
a l₁ l₂, ( b l₁, ¬p b) p a l = l₁ ++ a :: l₂ l.eraseP p = l₁ ++ l₂ :=
@@ -98,32 +99,32 @@ theorem length_eraseP {l : List α} : (l.eraseP p).length = if l.any p then l.le
rw [eraseP_of_forall_not]
simp_all
theorem eraseP_sublist (l : List α) : l.eraseP p <+ l := by
theorem eraseP_sublist {l : List α} : l.eraseP p <+ l := by
match exists_or_eq_self_of_eraseP p l with
| .inl h => rw [h]; apply Sublist.refl
| .inr c, l₁, l₂, _, _, h₃, h₄ => rw [h₄, h₃]; simp
theorem eraseP_subset (l : List α) : l.eraseP p l := (eraseP_sublist l).subset
theorem eraseP_subset {l : List α} : l.eraseP p l := eraseP_sublist.subset
protected theorem Sublist.eraseP : l₁ <+ l₂ l₁.eraseP p <+ l₂.eraseP p
| .slnil => Sublist.refl _
| .cons a s => by
by_cases h : p a
· simpa [h] using s.eraseP.trans (eraseP_sublist _)
· simpa [h] using s.eraseP.trans eraseP_sublist
· simpa [h] using s.eraseP.cons _
| .cons₂ a s => by
by_cases h : p a
· simpa [h] using s
· simpa [h] using s.eraseP
theorem length_eraseP_le (l : List α) : (l.eraseP p).length l.length :=
l.eraseP_sublist.length_le
theorem length_eraseP_le {l : List α} : (l.eraseP p).length l.length :=
eraseP_sublist.length_le
theorem le_length_eraseP (l : List α) : l.length - 1 (l.eraseP p).length := by
theorem le_length_eraseP {l : List α} : l.length - 1 (l.eraseP p).length := by
rw [length_eraseP]
split <;> simp
theorem mem_of_mem_eraseP {l : List α} : a l.eraseP p a l := (eraseP_subset _ ·)
theorem mem_of_mem_eraseP {l : List α} : a l.eraseP p a l := (eraseP_subset ·)
@[simp] theorem mem_eraseP_of_neg {l : List α} (pa : ¬p a) : a l.eraseP p a l := by
refine mem_of_mem_eraseP, fun al => ?_
@@ -135,7 +136,7 @@ theorem mem_of_mem_eraseP {l : List α} : a ∈ l.eraseP p → a ∈ l := (erase
simp [this] at al; simp [al]
@[simp] theorem eraseP_eq_self_iff {p} {l : List α} : l.eraseP p = l a l, ¬ p a := by
rw [ Sublist.length_eq (eraseP_sublist l), length_eraseP]
rw [ Sublist.length_eq eraseP_sublist, length_eraseP]
split <;> rename_i h
· simp only [any_eq_true, length_eq_zero_iff] at h
constructor
@@ -143,11 +144,11 @@ theorem mem_of_mem_eraseP {l : List α} : a ∈ l.eraseP p → a ∈ l := (erase
· intro; obtain x, m, h := h; simp_all
· simp_all
theorem eraseP_map (f : β α) : (l : List β), (map f l).eraseP p = map f (l.eraseP (p f))
theorem eraseP_map {f : β α} : {l : List β}, (map f l).eraseP p = map f (l.eraseP (p f))
| [] => rfl
| b::l => by by_cases h : p (f b) <;> simp [h, eraseP_map f l, eraseP_cons_of_pos]
| b::l => by by_cases h : p (f b) <;> simp [h, eraseP_map, eraseP_cons_of_pos]
theorem eraseP_filterMap (f : α Option β) : (l : List α),
theorem eraseP_filterMap {f : α Option β} : {l : List α},
(filterMap f l).eraseP p = filterMap f (l.eraseP (fun x => match f x with | some y => p y | none => false))
| [] => rfl
| a::l => by
@@ -161,7 +162,7 @@ theorem eraseP_filterMap (f : α → Option β) : ∀ (l : List α),
· simp only [w, cond_false]
rw [filterMap_cons_some h, eraseP_filterMap]
theorem eraseP_filter (f : α Bool) (l : List α) :
theorem eraseP_filter {f : α Bool} {l : List α} :
(filter f l).eraseP p = filter f (l.eraseP (fun x => p x && f x)) := by
rw [ filterMap_eq_filter, eraseP_filterMap]
congr
@@ -182,7 +183,7 @@ theorem eraseP_append_right :
| _ :: _, _, h => by
simp [(forall_mem_cons.1 h).1, eraseP_append_right _ (forall_mem_cons.1 h).2]
theorem eraseP_append (l₁ l₂ : List α) :
theorem eraseP_append {l₁ l₂ : List α} :
(l₁ ++ l₂).eraseP p = if l₁.any p then l₁.eraseP p ++ l₂ else l₁ ++ l₂.eraseP p := by
split <;> rename_i h
· simp only [any_eq_true] at h
@@ -192,7 +193,7 @@ theorem eraseP_append (l₁ l₂ : List α) :
rw [eraseP_append_right _]
simp_all
theorem eraseP_replicate (n : Nat) (a : α) (p : α Bool) :
theorem eraseP_replicate {n : Nat} {a : α} {p : α Bool} :
(replicate n a).eraseP p = if p a then replicate (n - 1) a else replicate n a := by
induction n with
| zero => simp
@@ -255,7 +256,7 @@ theorem eraseP_eq_iff {p} {l : List α} :
simp_all
theorem Pairwise.eraseP (q) : Pairwise p l Pairwise p (l.eraseP q) :=
Pairwise.sublist <| eraseP_sublist _
Pairwise.sublist <| eraseP_sublist
theorem Nodup.eraseP (p) : Nodup l Nodup (l.eraseP p) :=
Pairwise.eraseP p
@@ -274,11 +275,11 @@ theorem eraseP_comm {l : List α} (h : ∀ a ∈ l, ¬ p a ¬ q a) :
· simp [h₁, h₂, ih (fun b m => h b (mem_cons_of_mem _ m))]
· simp [h₁, h₂, ih (fun b m => h b (mem_cons_of_mem _ m))]
theorem head_eraseP_mem (xs : List α) (p : α Bool) (h) : (xs.eraseP p).head h xs :=
(eraseP_sublist xs).head_mem h
theorem head_eraseP_mem {xs : List α} {p : α Bool} (h) : (xs.eraseP p).head h xs :=
eraseP_sublist.head_mem h
theorem getLast_eraseP_mem (xs : List α) (p : α Bool) (h) : (xs.eraseP p).getLast h xs :=
(eraseP_sublist xs).getLast_mem h
theorem getLast_eraseP_mem {xs : List α} {p : α Bool} (h) : (xs.eraseP p).getLast h xs :=
eraseP_sublist.getLast_mem h
theorem eraseP_eq_eraseIdx {xs : List α} {p : α Bool} :
xs.eraseP p = match xs.findIdx? p with
@@ -299,6 +300,8 @@ theorem eraseP_eq_eraseIdx {xs : List α} {p : α → Bool} :
section erase
variable [BEq α]
-- The arguments are explicit to allow determining the type,
-- and to allow rewriting from right to left.
@[simp] theorem erase_cons_head [LawfulBEq α] (a : α) (l : List α) : (a :: l).erase a = l := by
simp [erase_cons]
@@ -311,6 +314,7 @@ theorem erase_of_not_mem [LawfulBEq α] {a : α} : ∀ {l : List α}, a ∉ l
rw [mem_cons, not_or] at h
simp only [erase_cons, if_neg, erase_of_not_mem h.2, beq_iff_eq, Ne.symm h.1, not_false_eq_true]
-- The arguments are intentionally explicit.
theorem erase_eq_eraseP' (a : α) (l : List α) : l.erase a = l.eraseP (· == a) := by
induction l
· simp
@@ -318,10 +322,11 @@ theorem erase_eq_eraseP' (a : α) (l : List α) : l.erase a = l.eraseP (· == a)
rw [erase_cons, eraseP_cons, ih]
if h : b == a then simp [h] else simp [h]
theorem erase_eq_eraseP [LawfulBEq α] (a : α) : l : List α, l.erase a = l.eraseP (a == ·)
-- The arguments are intentionally explicit.
theorem erase_eq_eraseP [LawfulBEq α] (a : α) : (l : List α), l.erase a = l.eraseP (a == ·)
| [] => rfl
| b :: l => by
if h : a = b then simp [h] else simp [h, Ne.symm h, erase_eq_eraseP a l]
if h : a = b then simp [h] else simp [h, Ne.symm h, erase_eq_eraseP (l := l)]
@[simp] theorem erase_eq_nil_iff [LawfulBEq α] {xs : List α} {a : α} :
xs.erase a = [] xs = [] xs = [a] := by
@@ -348,15 +353,15 @@ theorem exists_erase_eq [LawfulBEq α] {a : α} {l : List α} (h : a ∈ l) :
length (l.erase a) = length l - 1 := by
rw [erase_eq_eraseP]; exact length_eraseP_of_mem h (beq_self_eq_true a)
theorem length_erase [LawfulBEq α] (a : α) (l : List α) :
theorem length_erase [LawfulBEq α] {a : α} {l : List α} :
length (l.erase a) = if a l then length l - 1 else length l := by
rw [erase_eq_eraseP, length_eraseP]
split <;> split <;> simp_all
theorem erase_sublist (a : α) (l : List α) : l.erase a <+ l :=
theorem erase_sublist {a : α} {l : List α} : l.erase a <+ l :=
erase_eq_eraseP' a l eraseP_sublist ..
theorem erase_subset (a : α) (l : List α) : l.erase a l := (erase_sublist a l).subset
theorem erase_subset {a : α} {l : List α} : l.erase a l := erase_sublist.subset
theorem Sublist.erase (a : α) {l₁ l₂ : List α} (h : l₁ <+ l₂) : l₁.erase a <+ l₂.erase a := by
simp only [erase_eq_eraseP']; exact h.eraseP
@@ -364,14 +369,14 @@ theorem Sublist.erase (a : α) {l₁ l₂ : List α} (h : l₁ <+ l₂) : l₁.e
theorem IsPrefix.erase (a : α) {l₁ l₂ : List α} (h : l₁ <+: l₂) : l₁.erase a <+: l₂.erase a := by
simp only [erase_eq_eraseP']; exact h.eraseP
theorem length_erase_le (a : α) (l : List α) : (l.erase a).length l.length :=
(erase_sublist a l).length_le
theorem length_erase_le {a : α} {l : List α} : (l.erase a).length l.length :=
erase_sublist.length_le
theorem le_length_erase [LawfulBEq α] (a : α) (l : List α) : l.length - 1 (l.erase a).length := by
theorem le_length_erase [LawfulBEq α] {a : α} {l : List α} : l.length - 1 (l.erase a).length := by
rw [length_erase]
split <;> simp
theorem mem_of_mem_erase {a b : α} {l : List α} (h : a l.erase b) : a l := erase_subset _ _ h
theorem mem_of_mem_erase {a b : α} {l : List α} (h : a l.erase b) : a l := erase_subset h
@[simp] theorem mem_erase_of_ne [LawfulBEq α] {a b : α} {l : List α} (ab : a b) :
a l.erase b a l :=
@@ -381,7 +386,7 @@ theorem mem_of_mem_erase {a b : α} {l : List α} (h : a ∈ l.erase b) : a ∈
rw [erase_eq_eraseP', eraseP_eq_self_iff]
simp [forall_mem_ne']
theorem erase_filter [LawfulBEq α] (f : α Bool) (l : List α) :
theorem erase_filter [LawfulBEq α] {f : α Bool} {l : List α} :
(filter f l).erase a = filter f (l.erase a) := by
induction l with
| nil => rfl
@@ -412,12 +417,14 @@ theorem erase_append [LawfulBEq α] {a : α} {l₁ l₂ : List α} :
(l₁ ++ l₂).erase a = if a l₁ then l₁.erase a ++ l₂ else l₁ ++ l₂.erase a := by
simp [erase_eq_eraseP, eraseP_append]
theorem erase_replicate [LawfulBEq α] (n : Nat) (a b : α) :
theorem erase_replicate [LawfulBEq α] {n : Nat} {a b : α} :
(replicate n a).erase b = if b == a then replicate (n - 1) a else replicate n a := by
rw [erase_eq_eraseP]
simp [eraseP_replicate]
theorem erase_comm [LawfulBEq α] (a b : α) (l : List α) :
-- The arguments `a b` are explicit,
-- so they can be specified to prevent `simp` repeatedly applying the lemma.
theorem erase_comm [LawfulBEq α] (a b : α) {l : List α} :
(l.erase a).erase b = (l.erase b).erase a := by
if ab : a == b then rw [eq_of_beq ab] else ?_
if ha : a l then ?_ else
@@ -457,7 +464,7 @@ theorem erase_eq_iff [LawfulBEq α] {a : α} {l : List α} :
simp_all
theorem Pairwise.erase [LawfulBEq α] {l : List α} (a) : Pairwise p l Pairwise p (l.erase a) :=
Pairwise.sublist <| erase_sublist _ _
Pairwise.sublist <| erase_sublist
theorem Nodup.erase_eq_filter [LawfulBEq α] {l} (d : Nodup l) (a : α) : l.erase a = l.filter (· != a) := by
induction d with
@@ -482,10 +489,10 @@ theorem Nodup.erase [LawfulBEq α] (a : α) : Nodup l → Nodup (l.erase a) :=
Pairwise.erase a
theorem head_erase_mem (xs : List α) (a : α) (h) : (xs.erase a).head h xs :=
(erase_sublist a xs).head_mem h
erase_sublist.head_mem h
theorem getLast_erase_mem (xs : List α) (a : α) (h) : (xs.erase a).getLast h xs :=
(erase_sublist a xs).getLast_mem h
erase_sublist.getLast_mem h
theorem erase_eq_eraseIdx (l : List α) (a : α) :
l.erase a = match l.idxOf? a with
@@ -504,7 +511,7 @@ end erase
/-! ### eraseIdx -/
theorem length_eraseIdx (l : List α) (i : Nat) :
theorem length_eraseIdx {l : List α} {i : Nat} :
(l.eraseIdx i).length = if i < l.length then l.length - 1 else l.length := by
induction l generalizing i with
| nil => simp
@@ -521,7 +528,7 @@ theorem length_eraseIdx_of_lt {l : List α} {i} (h : i < length l) :
(l.eraseIdx i).length = length l - 1 := by
simp [length_eraseIdx, h]
@[simp] theorem eraseIdx_zero (l : List α) : eraseIdx l 0 = tail l := by cases l <;> rfl
@[simp] theorem eraseIdx_zero {l : List α} : eraseIdx l 0 = l.tail := by cases l <;> rfl
theorem eraseIdx_eq_take_drop_succ :
(l : List α) (i : Nat), l.eraseIdx i = l.take i ++ l.drop (i + 1)
@@ -552,12 +559,13 @@ abbrev eraseIdx_ne_nil := @eraseIdx_ne_nil_iff
theorem eraseIdx_sublist : (l : List α) (k : Nat), eraseIdx l k <+ l
| [], _ => by simp
| a::l, 0 => by simp
| a::l, k + 1 => by simp [eraseIdx_sublist l k]
| a::l, k + 1 => by simp [eraseIdx_sublist]
theorem mem_of_mem_eraseIdx {l : List α} {i : Nat} {a : α} (h : a l.eraseIdx i) : a l :=
(eraseIdx_sublist _ _).mem h
theorem eraseIdx_subset (l : List α) (k : Nat) : eraseIdx l k l := (eraseIdx_sublist l k).subset
theorem eraseIdx_subset {l : List α} {k : Nat} : eraseIdx l k l :=
(eraseIdx_sublist _ _).subset
@[simp]
theorem eraseIdx_eq_self : {l : List α} {k : Nat}, eraseIdx l k = l length l k
@@ -568,9 +576,11 @@ theorem eraseIdx_eq_self : ∀ {l : List α} {k : Nat}, eraseIdx l k = l ↔ len
theorem eraseIdx_of_length_le {l : List α} {k : Nat} (h : length l k) : eraseIdx l k = l := by
rw [eraseIdx_eq_self.2 h]
-- Arguments are intentionally explicit.
theorem length_eraseIdx_le (l : List α) (i : Nat) : length (l.eraseIdx i) length l :=
(eraseIdx_sublist l i).length_le
(eraseIdx_sublist _ _).length_le
-- Arguments are intentionally explicit.
theorem le_length_eraseIdx (l : List α) (i : Nat) : length l - 1 length (l.eraseIdx i) := by
rw [length_eraseIdx]
split <;> simp
@@ -623,7 +633,7 @@ protected theorem IsPrefix.eraseIdx {l l' : List α} (h : l <+: l') (k : Nat) :
-- `Init/Data/List/Nat/Basic.lean`.
theorem erase_eq_eraseIdx_of_idxOf [BEq α] [LawfulBEq α]
(l : List α) (a : α) (i : Nat) (w : l.idxOf a = i) :
{l : List α} {a : α} {i : Nat} (w : l.idxOf a = i) :
l.erase a = l.eraseIdx i := by
subst w
rw [erase_eq_iff]

View File

@@ -20,19 +20,19 @@ Examples:
-/
def finRange (n : Nat) : List (Fin n) := ofFn fun i => i
@[simp] theorem length_finRange (n) : (List.finRange n).length = n := by
@[simp] theorem length_finRange {n : Nat} : (List.finRange n).length = n := by
simp [List.finRange]
@[simp] theorem getElem_finRange (i : Nat) (h : i < (List.finRange n).length) :
(finRange n)[i] = Fin.cast (length_finRange n) i, h := by
@[simp] theorem getElem_finRange {i : Nat} (h : i < (List.finRange n).length) :
(finRange n)[i] = Fin.cast length_finRange i, h := by
simp [List.finRange]
@[simp] theorem finRange_zero : finRange 0 = [] := by simp [finRange, ofFn]
theorem finRange_succ (n) : finRange (n+1) = 0 :: (finRange n).map Fin.succ := by
theorem finRange_succ {n} : finRange (n+1) = 0 :: (finRange n).map Fin.succ := by
apply List.ext_getElem; simp; intro i; cases i <;> simp
theorem finRange_succ_last (n) :
theorem finRange_succ_last {n} :
finRange (n+1) = (finRange n).map Fin.castSucc ++ [Fin.last n] := by
apply List.ext_getElem
· simp
@@ -43,7 +43,7 @@ theorem finRange_succ_last (n) :
· rfl
· next h => exact Fin.eq_last_of_not_lt h
theorem finRange_reverse (n) : (finRange n).reverse = (finRange n).map Fin.rev := by
theorem finRange_reverse {n} : (finRange n).reverse = (finRange n).map Fin.rev := by
induction n with
| zero => simp
| succ n ih =>

View File

@@ -25,11 +25,11 @@ open Nat
/-! ### findSome? -/
@[simp] theorem findSome?_cons_of_isSome (l) (h : (f a).isSome) : findSome? f (a :: l) = f a := by
@[simp] theorem findSome?_cons_of_isSome {l} (h : (f a).isSome) : findSome? f (a :: l) = f a := by
simp only [findSome?]
split <;> simp_all
@[simp] theorem findSome?_cons_of_isNone (l) (h : (f a).isNone) : findSome? f (a :: l) = findSome? f l := by
@[simp] theorem findSome?_cons_of_isNone {l} (h : (f a).isNone) : findSome? f (a :: l) = findSome? f l := by
simp only [findSome?]
split <;> simp_all
@@ -89,7 +89,7 @@ theorem findSome?_eq_some_iff {f : α → Option β} {l : List α} {b : β} :
obtain rfl, rfl, rfl := h₁
exact l₁, a, l₂, rfl, h₂, fun a' w => h₃ a' (mem_cons_of_mem p w)
@[simp] theorem findSome?_guard (l : List α) : findSome? (Option.guard fun x => p x) l = find? p l := by
@[simp] theorem findSome?_guard {l : List α} : findSome? (Option.guard fun x => p x) l = find? p l := by
induction l with
| nil => simp
| cons x xs ih =>
@@ -101,33 +101,33 @@ theorem findSome?_eq_some_iff {f : α → Option β} {l : List α} {b : β} :
· simp only [Option.guard_eq_none] at h
simp [ih, h]
theorem find?_eq_findSome?_guard (l : List α) : find? p l = findSome? (Option.guard fun x => p x) l :=
(findSome?_guard l).symm
theorem find?_eq_findSome?_guard {l : List α} : find? p l = findSome? (Option.guard fun x => p x) l :=
findSome?_guard.symm
@[simp] theorem head?_filterMap (f : α Option β) (l : List α) : (l.filterMap f).head? = l.findSome? f := by
@[simp] theorem head?_filterMap {f : α Option β} {l : List α} : (l.filterMap f).head? = l.findSome? f := by
induction l with
| nil => simp
| cons x xs ih =>
simp only [filterMap_cons, findSome?_cons]
split <;> simp [*]
@[simp] theorem head_filterMap (f : α Option β) (l : List α) (h) :
@[simp] theorem head_filterMap {f : α Option β} {l : List α} (h) :
(l.filterMap f).head h = (l.findSome? f).get (by simp_all [Option.isSome_iff_ne_none]) := by
simp [head_eq_iff_head?_eq_some]
@[simp] theorem getLast?_filterMap (f : α Option β) (l : List α) : (l.filterMap f).getLast? = l.reverse.findSome? f := by
@[simp] theorem getLast?_filterMap {f : α Option β} {l : List α} : (l.filterMap f).getLast? = l.reverse.findSome? f := by
rw [getLast?_eq_head?_reverse]
simp [ filterMap_reverse]
@[simp] theorem getLast_filterMap (f : α Option β) (l : List α) (h) :
@[simp] theorem getLast_filterMap {f : α Option β} {l : List α} (h) :
(l.filterMap f).getLast h = (l.reverse.findSome? f).get (by simp_all [Option.isSome_iff_ne_none]) := by
simp [getLast_eq_iff_getLast?_eq_some]
@[simp] theorem map_findSome? (f : α Option β) (g : β γ) (l : List α) :
@[simp] theorem map_findSome? {f : α Option β} {g : β γ} {l : List α} :
(l.findSome? f).map g = l.findSome? (Option.map g f) := by
induction l <;> simp [findSome?_cons]; split <;> simp [*]
theorem findSome?_map (f : β γ) (l : List β) : findSome? p (l.map f) = l.findSome? (p f) := by
theorem findSome?_map {f : β γ} {l : List β} : findSome? p (l.map f) = l.findSome? (p f) := by
induction l with
| nil => simp
| cons x xs ih =>
@@ -202,14 +202,14 @@ theorem IsInfix.findSome?_eq_none {l₁ l₂ : List α} {f : α → Option β} (
/-! ### find? -/
@[simp] theorem find?_singleton (a : α) (p : α Bool) : [a].find? p = if p a then some a else none := by
@[simp] theorem find?_singleton {a : α} {p : α Bool} : [a].find? p = if p a then some a else none := by
simp only [find?]
split <;> simp_all
@[simp] theorem find?_cons_of_pos (l) (h : p a) : find? p (a :: l) = some a := by
@[simp] theorem find?_cons_of_pos {l} (h : p a) : find? p (a :: l) = some a := by
simp [find?, h]
@[simp] theorem find?_cons_of_neg (l) (h : ¬p a) : find? p (a :: l) = find? p l := by
@[simp] theorem find?_cons_of_neg {l} (h : ¬p a) : find? p (a :: l) = find? p l := by
simp [find?, h]
@[simp] theorem find?_eq_none : find? p l = none x l, ¬ p x := by
@@ -230,7 +230,7 @@ theorem find?_eq_some_iff_append :
cases as with
| nil => simp_all
| cons a as =>
specialize h₂ a (mem_cons_self _ _)
specialize h₂ a mem_cons_self
simp only [cons_append] at h₁
obtain rfl, - := h₁
simp_all
@@ -279,7 +279,7 @@ theorem mem_of_find?_eq_some : ∀ {l}, find? p l = some a → a ∈ l
· exact H .head _
· exact .tail _ (mem_of_find?_eq_some H)
theorem get_find?_mem (xs : List α) (p : α Bool) (h) : (xs.find? p).get h xs := by
theorem get_find?_mem {xs : List α} {p : α Bool} (h) : (xs.find? p).get h xs := by
induction xs with
| nil => simp at h
| cons x xs ih =>
@@ -290,7 +290,7 @@ theorem get_find?_mem (xs : List α) (p : α → Bool) (h) : (xs.find? p).get h
right
apply ih
@[simp] theorem find?_filter (xs : List α) (p : α Bool) (q : α Bool) :
@[simp] theorem find?_filter {xs : List α} {p : α Bool} {q : α Bool} :
(xs.filter p).find? q = xs.find? (fun a => p a q a) := by
induction xs with
| nil => simp
@@ -300,22 +300,22 @@ theorem get_find?_mem (xs : List α) (p : α → Bool) (h) : (xs.find? p).get h
· simp only [find?_cons]
split <;> simp_all
@[simp] theorem head?_filter (p : α Bool) (l : List α) : (l.filter p).head? = l.find? p := by
@[simp] theorem head?_filter {p : α Bool} {l : List α} : (l.filter p).head? = l.find? p := by
rw [ filterMap_eq_filter, head?_filterMap, findSome?_guard]
@[simp] theorem head_filter (p : α Bool) (l : List α) (h) :
@[simp] theorem head_filter {p : α Bool} {l : List α} (h) :
(l.filter p).head h = (l.find? p).get (by simp_all [Option.isSome_iff_ne_none]) := by
simp [head_eq_iff_head?_eq_some]
@[simp] theorem getLast?_filter (p : α Bool) (l : List α) : (l.filter p).getLast? = l.reverse.find? p := by
@[simp] theorem getLast?_filter {p : α Bool} {l : List α} : (l.filter p).getLast? = l.reverse.find? p := by
rw [getLast?_eq_head?_reverse]
simp [ filter_reverse]
@[simp] theorem getLast_filter (p : α Bool) (l : List α) (h) :
@[simp] theorem getLast_filter {p : α Bool} {l : List α} (h) :
(l.filter p).getLast h = (l.reverse.find? p).get (by simp_all [Option.isSome_iff_ne_none]) := by
simp [getLast_eq_iff_getLast?_eq_some]
@[simp] theorem find?_filterMap (xs : List α) (f : α Option β) (p : β Bool) :
@[simp] theorem find?_filterMap {xs : List α} {f : α Option β} {p : β Bool} :
(xs.filterMap f).find? p = (xs.find? (fun a => (f a).any p)).bind f := by
induction xs with
| nil => simp
@@ -325,7 +325,7 @@ theorem get_find?_mem (xs : List α) (p : α → Bool) (h) : (xs.find? p).get h
· simp only [find?_cons]
split <;> simp_all
@[simp] theorem find?_map (f : β α) (l : List β) : find? p (l.map f) = (l.find? (p f)).map f := by
@[simp] theorem find?_map {f : β α} {l : List β} : find? p (l.map f) = (l.find? (p f)).map f := by
induction l with
| nil => simp
| cons x xs ih =>
@@ -339,7 +339,7 @@ theorem get_find?_mem (xs : List α) (p : α → Bool) (h) : (xs.find? p).get h
simp only [cons_append, find?]
by_cases h : p x <;> simp [h, ih]
@[simp] theorem find?_flatten (xss : List (List α)) (p : α Bool) :
@[simp] theorem find?_flatten {xss : List (List α)} {p : α Bool} :
xss.flatten.find? p = xss.findSome? (·.find? p) := by
induction xss with
| nil => simp
@@ -397,7 +397,7 @@ theorem find?_flatten_eq_some_iff {xs : List (List α)} {p : α → Bool} {a :
@[deprecated find?_flatten_eq_some_iff (since := "2025-02-03")]
abbrev find?_flatten_eq_some := @find?_flatten_eq_some_iff
@[simp] theorem find?_flatMap (xs : List α) (f : α List β) (p : β Bool) :
@[simp] theorem find?_flatMap {xs : List α} {f : α List β} {p : β Bool} :
(xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by
simp [flatMap_def, findSome?_map]; rfl
@@ -441,7 +441,7 @@ abbrev find?_replicate_eq_none := @find?_replicate_eq_none_iff
@[deprecated find?_replicate_eq_some_iff (since := "2025-02-03")]
abbrev find?_replicate_eq_some := @find?_replicate_eq_some_iff
@[simp] theorem get_find?_replicate (n : Nat) (a : α) (p : α Bool) (h) : ((replicate n a).find? p).get h = a := by
@[simp] theorem get_find?_replicate {n : Nat} {a : α} {p : α Bool} (h) : ((replicate n a).find? p).get h = a := by
cases n with
| zero => simp at h
| succ n => simp
@@ -476,8 +476,8 @@ theorem IsInfix.find?_eq_none {l₁ l₂ : List α} {p : α → Bool} (h : l₁
List.find? p l₂ = none List.find? p l₁ = none :=
h.sublist.find?_eq_none
theorem find?_pmap {P : α Prop} (f : (a : α) P a β) (xs : List α)
(H : (a : α), a xs P a) (p : β Bool) :
theorem find?_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs P a) {p : β Bool} :
(xs.pmap f H).find? p = (xs.attach.find? (fun a, m => p (f a (H a m)))).map fun a, m => f a (H a m) := by
simp only [pmap_eq_map_attach, find?_map]
rfl
@@ -516,7 +516,7 @@ private theorem findIdx?_go_eq {p : α → Bool} {xs : List α} {i : Nat} :
/-! ### findIdx -/
theorem findIdx_cons (p : α Bool) (b : α) (l : List α) :
theorem findIdx_cons {p : α Bool} {b : α} {l : List α} :
(b :: l).findIdx p = bif p b then 0 else (l.findIdx p) + 1 := by
cases H : p b with
| true => simp [H, findIdx, findIdx.go]
@@ -572,7 +572,7 @@ theorem findIdx_eq_length_of_false {p : α → Bool} {xs : List α} (h : ∀ x
rw [findIdx_eq_length]
exact h
theorem findIdx_le_length (p : α Bool) {xs : List α} : xs.findIdx p xs.length := by
theorem findIdx_le_length {p : α Bool} {xs : List α} : xs.findIdx p xs.length := by
by_cases e : x xs, p x
· exact Nat.le_of_lt (findIdx_lt_length_of_exists e)
· simp at e
@@ -589,7 +589,7 @@ theorem findIdx_lt_length {p : α → Bool} {xs : List α} :
/-- `p` does not hold for elements with indices less than `xs.findIdx p`. -/
theorem not_of_lt_findIdx {p : α Bool} {xs : List α} {i : Nat} (h : i < xs.findIdx p) :
p (xs[i]'(Nat.le_trans h (findIdx_le_length p))) = false := by
p (xs[i]'(Nat.le_trans h findIdx_le_length)) = false := by
revert i
induction xs with
| nil => intro i h; rw [findIdx_nil] at h; simp at h
@@ -638,7 +638,7 @@ theorem findIdx_eq {p : α → Bool} {xs : List α} {i : Nat} (h : i < xs.length
simp at h3
simp_all [not_of_lt_findIdx h3]
theorem findIdx_append (p : α Bool) (l₁ l₂ : List α) :
theorem findIdx_append {p : α Bool} {l₁ l₂ : List α} :
(l₁ ++ l₂).findIdx p =
if l₁.findIdx p < l₁.length then l₁.findIdx p else l₂.findIdx p + l₁.length := by
induction l₁ with
@@ -813,7 +813,7 @@ theorem of_findIdx?_eq_none {xs : List α} {p : α → Bool} (w : xs.findIdx? p
@[deprecated of_findIdx?_eq_none (since := "2025-02-02")]
abbrev findIdx?_of_eq_none := @of_findIdx?_eq_none
@[simp] theorem findIdx?_map (f : β α) (l : List β) : findIdx? p (l.map f) = l.findIdx? (p f) := by
@[simp] theorem findIdx?_map {f : β α} {l : List β} : findIdx? p (l.map f) = l.findIdx? (p f) := by
induction l with
| nil => simp
| cons x xs ih =>
@@ -1066,7 +1066,7 @@ theorem idxOf?_eq_map_finIdxOf?_val [BEq α] {xs : List α} {a : α} :
@[simp] theorem finIdxOf?_nil [BEq α] : ([] : List α).finIdxOf? a = none := rfl
@[simp] theorem finIdxOf?_cons [BEq α] (a : α) (xs : List α) :
@[simp] theorem finIdxOf?_cons [BEq α] {a : α} {xs : List α} :
(a :: xs).finIdxOf? b =
if a == b then some 0, by simp else (xs.finIdxOf? b).map (·.succ) := by
simp [finIdxOf?]
@@ -1092,7 +1092,7 @@ The lemmas below should be made consistent with those for `findIdx?` (and proved
@[simp] theorem idxOf?_nil [BEq α] : ([] : List α).idxOf? a = none := rfl
theorem idxOf?_cons [BEq α] (a : α) (xs : List α) (b : α) :
theorem idxOf?_cons [BEq α] {a : α} {xs : List α} {b : α} :
(a :: xs).idxOf? b = if a == b then some 0 else (xs.idxOf? b).map (· + 1) := by
simp [idxOf?]
@@ -1117,7 +1117,7 @@ variable [BEq α] [LawfulBEq α]
@[simp] theorem lookup_cons_self {k : α} : ((k,b) :: es).lookup k = some b := by
simp [lookup_cons]
theorem lookup_eq_findSome? (l : List (α × β)) (k : α) :
theorem lookup_eq_findSome? {l : List (α × β)} {k : α} :
l.lookup k = l.findSome? fun p => if k == p.1 then some p.2 else none := by
induction l with
| nil => rfl

File diff suppressed because it is too large Load Diff

View File

@@ -14,11 +14,11 @@ namespace List
/-! ### Lexicographic ordering -/
@[simp] theorem lex_lt [LT α] (l₁ l₂ : List α) : Lex (· < ·) l₁ l₂ l₁ < l₂ := Iff.rfl
@[simp] theorem not_lex_lt [LT α] (l₁ l₂ : List α) : ¬ Lex (· < ·) l₁ l₂ l₂ l₁ := Iff.rfl
@[simp] theorem lex_lt [LT α] {l₁ l₂ : List α} : Lex (· < ·) l₁ l₂ l₁ < l₂ := Iff.rfl
@[simp] theorem not_lex_lt [LT α] {l₁ l₂ : List α} : ¬ Lex (· < ·) l₁ l₂ l₂ l₁ := Iff.rfl
protected theorem not_lt_iff_ge [LT α] (l₁ l₂ : List α) : ¬ l₁ < l₂ l₂ l₁ := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] (l₁ l₂ : List α) :
protected theorem not_lt_iff_ge [LT α] {l₁ l₂ : List α} : ¬ l₁ < l₂ l₂ l₁ := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {l₁ l₂ : List α} :
¬ l₁ l₂ l₂ < l₁ :=
Decidable.not_not
@@ -49,7 +49,7 @@ instance ltIrrefl [LT α] [Std.Irrefl (· < · : αα → Prop)] : Std.Irre
· rintro rfl
exact not_lex_nil
@[simp] theorem le_nil [LT α] (l : List α) : l [] l = [] := not_nil_lex_iff
@[simp] theorem le_nil [LT α] {l : List α} : l [] l = [] := not_nil_lex_iff
-- This is named with a prime to avoid conflict with `lex [] (b :: bs) lt = true`.
-- Better naming for the `Lex` vs `lex` distinction would be welcome.

View File

@@ -490,9 +490,9 @@ theorem mapIdx_eq_mapIdx_iff {l : List α} :
cases l with
| nil => simp at h
| cons _ _ =>
simp only [ getElem_cons_length _ _ _ rfl]
simp only [ getElem_cons_length rfl]
simp only [mapIdx_cons]
simp only [ getElem_cons_length _ _ _ rfl]
simp only [ getElem_cons_length rfl]
simp only [ mapIdx_cons, getElem_mapIdx]
simp

View File

@@ -37,19 +37,19 @@ theorem min?_cons' [Min α] {xs : List α} : (x :: xs).min? = foldl min x xs :=
theorem isSome_min?_of_mem {l : List α} [Min α] {a : α} (h : a l) :
l.min?.isSome := by
cases l <;> simp_all [List.min?_cons']
cases l <;> simp_all [min?_cons']
theorem min?_eq_head? {α : Type u} [Min α] {l : List α}
(h : l.Pairwise (fun a b => min a b = a)) : l.min? = l.head? := by
cases l with
| nil => rfl
| cons x l =>
rw [List.head?_cons, List.min?_cons', Option.some.injEq]
rw [head?_cons, min?_cons', Option.some.injEq]
induction l generalizing x with
| nil => simp
| cons y l ih =>
have hx : min x y = x := List.rel_of_pairwise_cons h (List.mem_cons_self _ _)
rw [List.foldl_cons, ih _ (hx.symm h.sublist (by simp)), hx]
have hx : min x y = x := rel_of_pairwise_cons h mem_cons_self
rw [foldl_cons, ih _ (hx.symm h.sublist (by simp)), hx]
theorem min?_mem [Min α] (min_eq_or : a b : α, min a b = a min a b = b) :
{xs : List α} xs.min? = some a a xs := by
@@ -57,7 +57,7 @@ theorem min?_mem [Min α] (min_eq_or : ∀ a b : α, min a b = a min a b = b
match xs with
| nil => simp
| x :: xs =>
simp only [min?_cons', Option.some.injEq, List.mem_cons]
simp only [min?_cons', Option.some.injEq, mem_cons]
intro eq
induction xs generalizing x with
| nil =>
@@ -138,7 +138,7 @@ theorem max?_cons' [Max α] {xs : List α} : (x :: xs).max? = foldl max x xs :=
theorem isSome_max?_of_mem {l : List α} [Max α] {a : α} (h : a l) :
l.max?.isSome := by
cases l <;> simp_all [List.max?_cons']
cases l <;> simp_all [max?_cons']
theorem max?_mem [Max α] (min_eq_or : a b : α, max a b = a max a b = b) :
{xs : List α} xs.max? = some a a xs

View File

@@ -48,29 +48,29 @@ def mapM' [Monad m] (f : α → m β) : List α → m (List β)
mapM' f (a :: l) = return (( f a) :: ( l.mapM' f)) :=
rfl
theorem mapM'_eq_mapM [Monad m] [LawfulMonad m] (f : α m β) (l : List α) :
theorem mapM'_eq_mapM [Monad m] [LawfulMonad m] {f : α m β} {l : List α} :
mapM' f l = mapM f l := by simp [go, mapM] where
go : l acc, mapM.loop f l acc = return acc.reverse ++ ( mapM' f l)
| [], acc => by simp [mapM.loop, mapM']
| a::l, acc => by simp [go l, mapM.loop, mapM']
@[simp] theorem mapM_nil [Monad m] (f : α m β) : [].mapM f = pure [] := rfl
@[simp] theorem mapM_nil [Monad m] {f : α m β} : [].mapM f = pure [] := rfl
@[simp] theorem mapM_cons [Monad m] [LawfulMonad m] (f : α m β) :
@[simp] theorem mapM_cons [Monad m] [LawfulMonad m] {f : α m β} :
(a :: l).mapM f = (return ( f a) :: ( l.mapM f)) := by simp [ mapM'_eq_mapM, mapM']
@[simp] theorem mapM_pure [Monad m] [LawfulMonad m] (l : List α) (f : α β) :
@[simp] theorem mapM_pure [Monad m] [LawfulMonad m] {l : List α} {f : α β} :
l.mapM (m := m) (pure <| f ·) = pure (l.map f) := by
induction l <;> simp_all
@[simp] theorem mapM_id {l : List α} {f : α Id β} : l.mapM f = l.map f :=
mapM_pure _ _
mapM_pure
@[simp] theorem mapM_append [Monad m] [LawfulMonad m] (f : α m β) {l₁ l₂ : List α} :
@[simp] theorem mapM_append [Monad m] [LawfulMonad m] {f : α m β} {l₁ l₂ : List α} :
(l₁ ++ l₂).mapM f = (return ( l₁.mapM f) ++ ( l₂.mapM f)) := by induction l₁ <;> simp [*]
/-- Auxiliary lemma for `mapM_eq_reverse_foldlM_cons`. -/
theorem foldlM_cons_eq_append [Monad m] [LawfulMonad m] (f : α m β) (as : List α) (b : β) (bs : List β) :
theorem foldlM_cons_eq_append [Monad m] [LawfulMonad m] {f : α m β} {as : List α} {b : β} {bs : List β} :
(as.foldlM (init := b :: bs) fun acc a => return (( f a) :: acc)) =
(· ++ b :: bs) <$> as.foldlM (init := []) fun acc a => return (( f a) :: acc) := by
induction as generalizing b bs with
@@ -79,7 +79,7 @@ theorem foldlM_cons_eq_append [Monad m] [LawfulMonad m] (f : α → m β) (as :
simp only [bind_pure_comp] at ih
simp [ih, _root_.map_bind, Functor.map_map, Function.comp_def]
theorem mapM_eq_reverse_foldlM_cons [Monad m] [LawfulMonad m] (f : α m β) (l : List α) :
theorem mapM_eq_reverse_foldlM_cons [Monad m] [LawfulMonad m] {f : α m β} {l : List α} :
mapM f l = reverse <$> (l.foldlM (fun acc a => return (( f a) :: acc)) []) := by
rw [ mapM'_eq_mapM]
induction l with
@@ -92,10 +92,9 @@ theorem mapM_eq_reverse_foldlM_cons [Monad m] [LawfulMonad m] (f : α → m β)
/-! ### filterMapM -/
@[simp] theorem filterMapM_nil [Monad m] (f : α m (Option β)) : [].filterMapM f = pure [] := rfl
@[simp] theorem filterMapM_nil [Monad m] {f : α m (Option β)} : [].filterMapM f = pure [] := rfl
theorem filterMapM_loop_eq [Monad m] [LawfulMonad m]
(f : α m (Option β)) (l : List α) (acc : List β) :
theorem filterMapM_loop_eq [Monad m] [LawfulMonad m] {f : α m (Option β)} {l : List α} {acc : List β} :
filterMapM.loop f l acc = (acc.reverse ++ ·) <$> filterMapM.loop f l [] := by
induction l generalizing acc with
| nil => simp [filterMapM.loop]
@@ -105,10 +104,10 @@ theorem filterMapM_loop_eq [Monad m] [LawfulMonad m]
funext b?
split <;> rename_i b
· apply ih
· rw [ih, ih [b]]
· rw [ih, ih (acc := [b])]
simp
@[simp] theorem filterMapM_cons [Monad m] [LawfulMonad m] (f : α m (Option β)) :
@[simp] theorem filterMapM_cons [Monad m] [LawfulMonad m] {f : α m (Option β)} :
(a :: l).filterMapM f = do
match ( f a) with
| none => filterMapM f l
@@ -124,9 +123,9 @@ theorem filterMapM_loop_eq [Monad m] [LawfulMonad m]
/-! ### flatMapM -/
@[simp] theorem flatMapM_nil [Monad m] (f : α m (List β)) : [].flatMapM f = pure [] := rfl
@[simp] theorem flatMapM_nil [Monad m] {f : α m (List β)} : [].flatMapM f = pure [] := rfl
theorem flatMapM_loop_eq [Monad m] [LawfulMonad m] (f : α m (List β)) (l : List α) (acc : List (List β)) :
theorem flatMapM_loop_eq [Monad m] [LawfulMonad m] {f : α m (List β)} {l : List α} {acc : List (List β)} :
flatMapM.loop f l acc = (acc.reverse.flatten ++ ·) <$> flatMapM.loop f l [] := by
induction l generalizing acc with
| nil => simp [flatMapM.loop]
@@ -134,10 +133,10 @@ theorem flatMapM_loop_eq [Monad m] [LawfulMonad m] (f : α → m (List β)) (l :
simp only [flatMapM.loop, append_nil, _root_.map_bind]
congr
funext bs
rw [ih, ih [bs]]
rw [ih, ih (acc := [bs])]
simp
@[simp] theorem flatMapM_cons [Monad m] [LawfulMonad m] (f : α m (List β)) :
@[simp] theorem flatMapM_cons [Monad m] [LawfulMonad m] {f : α m (List β)} :
(a :: l).flatMapM f = do
let bs f a
return (bs ++ ( l.flatMapM f)) := by
@@ -149,15 +148,15 @@ theorem flatMapM_loop_eq [Monad m] [LawfulMonad m] (f : α → m (List β)) (l :
/-! ### foldlM and foldrM -/
theorem foldlM_map [Monad m] (f : β₁ β₂) (g : α β₂ m α) (l : List β₁) (init : α) :
theorem foldlM_map [Monad m] {f : β₁ β₂} {g : α β₂ m α} {l : List β₁} {init : α} :
(l.map f).foldlM g init = l.foldlM (fun x y => g x (f y)) init := by
induction l generalizing g init <;> simp [*]
theorem foldrM_map [Monad m] [LawfulMonad m] (f : β₁ β₂) (g : β₂ α m α) (l : List β₁)
(init : α) : (l.map f).foldrM g init = l.foldrM (fun x y => g (f x) y) init := by
theorem foldrM_map [Monad m] [LawfulMonad m] {f : β₁ β₂} {g : β₂ α m α} {l : List β₁} {init : α} :
(l.map f).foldrM g init = l.foldrM (fun x y => g (f x) y) init := by
induction l generalizing g init <;> simp [*]
theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α Option β) (g : γ β m γ) (l : List α) (init : γ) :
theorem foldlM_filterMap [Monad m] [LawfulMonad m] {f : α Option β} {g : γ β m γ} {l : List α} {init : γ} :
(l.filterMap f).foldlM g init =
l.foldlM (fun x y => match f y with | some b => g x b | none => pure x) init := by
induction l generalizing init with
@@ -166,7 +165,7 @@ theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g :
simp only [filterMap_cons, foldlM_cons]
cases f a <;> simp [ih]
theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α Option β) (g : β γ m γ) (l : List α) (init : γ) :
theorem foldrM_filterMap [Monad m] [LawfulMonad m] {f : α Option β} {g : β γ m γ} {l : List α} {init : γ} :
(l.filterMap f).foldrM g init =
l.foldrM (fun x y => match f x with | some b => g b y | none => pure y) init := by
induction l generalizing init with
@@ -175,7 +174,7 @@ theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g :
simp only [filterMap_cons, foldrM_cons]
cases f a <;> simp [ih]
theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α Bool) (g : β α m β) (l : List α) (init : β) :
theorem foldlM_filter [Monad m] [LawfulMonad m] {p : α Bool} {g : β α m β} {l : List α} {init : β} :
(l.filter p).foldlM g init =
l.foldlM (fun x y => if p y then g x y else pure x) init := by
induction l generalizing init with
@@ -184,7 +183,7 @@ theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : β → α
simp only [filter_cons, foldlM_cons]
split <;> simp [ih]
theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α Bool) (g : α β m β) (l : List α) (init : β) :
theorem foldrM_filter [Monad m] [LawfulMonad m] {p : α Bool} {g : α β m β} {l : List α} {init : β} :
(l.filter p).foldrM g init =
l.foldrM (fun x y => if p x then g x y else pure y) init := by
induction l generalizing init with
@@ -194,14 +193,14 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β
split <;> simp [ih]
@[simp] theorem foldlM_attachWith [Monad m]
(l : List α) {q : α Prop} (H : a, a l q a) {f : β { x // q x} m β} {b} :
{l : List α} {q : α Prop} (H : a, a l q a) {f : β { x // q x} m β} {b} :
(l.attachWith q H).foldlM f b = l.attach.foldlM (fun b a, h => f b a, H _ h) b := by
induction l generalizing b with
| nil => simp
| cons a l ih => simp [ih, foldlM_map]
@[simp] theorem foldrM_attachWith [Monad m] [LawfulMonad m]
(l : List α) {q : α Prop} (H : a, a l q a) {f : { x // q x} β m β} {b} :
{l : List α} {q : α Prop} (H : a, a l q a) {f : { x // q x} β m β} {b} :
(l.attachWith q H).foldrM f b = l.attach.foldrM (fun a acc => f a.1, H _ a.2 acc) b := by
induction l generalizing b with
| nil => simp
@@ -215,13 +214,13 @@ theorem forM_nil' [Monad m] : ([] : List α).forM f = (pure .unit : m PUnit) :=
@[deprecated forM_cons (since := "2025-01-31")]
theorem forM_cons' [Monad m] :
(a::as).forM f = (f a >>= fun _ => as.forM f : m PUnit) :=
List.forM_cons _ _ _
List.forM_cons
@[simp] theorem forM_append [Monad m] [LawfulMonad m] (l₁ l₂ : List α) (f : α m PUnit) :
@[simp] theorem forM_append [Monad m] [LawfulMonad m] {l₁ l₂ : List α} {f : α m PUnit} :
forM (l₁ ++ l₂) f = (do forM l₁ f; forM l₂ f) := by
induction l₁ <;> simp [*]
@[simp] theorem forM_map [Monad m] [LawfulMonad m] (l : List α) (g : α β) (f : β m PUnit) :
@[simp] theorem forM_map [Monad m] [LawfulMonad m] {l : List α} {g : α β} {f : β m PUnit} :
forM (l.map g) f = forM l (fun a => f (g a)) := by
induction l <;> simp [*]
@@ -246,7 +245,7 @@ theorem forIn'_loop_congr [Monad m] {as bs : List α}
@[simp] theorem forIn'_cons [Monad m] {a : α} {as : List α}
(f : (a' : α) a' a :: as β m (ForInStep β)) (b : β) :
forIn' (a::as) b f = f a (mem_cons_self a as) b >>=
forIn' (a::as) b f = f a mem_cons_self b >>=
fun | ForInStep.done b => pure b | ForInStep.yield b => forIn' as b fun a' m b => f a' (mem_cons_of_mem a m) b := by
simp only [forIn', List.forIn', forIn'.loop]
congr 1
@@ -294,7 +293,7 @@ We can express a for loop over a list as a fold,
in which whenever we reach `.done b` we keep that value through the rest of the fold.
-/
theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
(l : List α) (f : (a : α) a l β m (ForInStep β)) (init : β) :
{l : List α} (f : (a : α) a l β m (ForInStep β)) (init : β) :
forIn' l init f = ForInStep.value <$>
l.attach.foldlM (fun b a, m => match b with
| .yield b => f a m b
@@ -324,29 +323,29 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
/-- We can express a for loop over a list which always yields as a fold. -/
@[simp] theorem forIn'_yield_eq_foldlM [Monad m] [LawfulMonad m]
(l : List α) (f : (a : α) a l β m γ) (g : (a : α) a l β γ β) (init : β) :
{l : List α} (f : (a : α) a l β m γ) (g : (a : α) a l β γ β) (init : β) :
forIn' l init (fun a m b => (fun c => .yield (g a m b c)) <$> f a m b) =
l.attach.foldlM (fun b a, m => g a m b <$> f a m b) init := by
simp only [forIn'_eq_foldlM]
induction l.attach generalizing init <;> simp_all
@[simp] theorem forIn'_pure_yield_eq_foldl [Monad m] [LawfulMonad m]
(l : List α) (f : (a : α) a l β β) (init : β) :
{l : List α} (f : (a : α) a l β β) (init : β) :
forIn' l init (fun a m b => pure (.yield (f a m b))) =
pure (f := m) (l.attach.foldl (fun b a, h => f a h b) init) := by
simp only [forIn'_eq_foldlM]
induction l.attach generalizing init <;> simp_all
@[simp] theorem forIn'_yield_eq_foldl
(l : List α) (f : (a : α) a l β β) (init : β) :
{l : List α} (f : (a : α) a l β β) (init : β) :
forIn' (m := Id) l init (fun a m b => .yield (f a m b)) =
l.attach.foldl (fun b a, h => f a h b) init := by
simp only [forIn'_eq_foldlM]
induction l.attach generalizing init <;> simp_all
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
(l : List α) (g : α β) (f : (b : β) b l.map g γ m (ForInStep γ)) :
forIn' (l.map g) init f = forIn' l init fun a h y => f (g a) (mem_map_of_mem g h) y := by
{l : List α} (g : α β) (f : (b : β) b l.map g γ m (ForInStep γ)) :
forIn' (l.map g) init f = forIn' l init fun a h y => f (g a) (mem_map_of_mem h) y := by
induction l generalizing init <;> simp_all
/--
@@ -354,7 +353,7 @@ We can express a for loop over a list as a fold,
in which whenever we reach `.done b` we keep that value through the rest of the fold.
-/
theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
(f : α β m (ForInStep β)) (init : β) (l : List α) :
{l : List α} (f : α β m (ForInStep β)) (init : β) :
forIn l init f = ForInStep.value <$>
l.foldlM (fun b a => match b with
| .yield b => f a b
@@ -377,34 +376,34 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
/-- We can express a for loop over a list which always yields as a fold. -/
@[simp] theorem forIn_yield_eq_foldlM [Monad m] [LawfulMonad m]
(l : List α) (f : α β m γ) (g : α β γ β) (init : β) :
{l : List α} (f : α β m γ) (g : α β γ β) (init : β) :
forIn l init (fun a b => (fun c => .yield (g a b c)) <$> f a b) =
l.foldlM (fun b a => g a b <$> f a b) init := by
simp only [forIn_eq_foldlM]
induction l generalizing init <;> simp_all
@[simp] theorem forIn_pure_yield_eq_foldl [Monad m] [LawfulMonad m]
(l : List α) (f : α β β) (init : β) :
{l : List α} (f : α β β) (init : β) :
forIn l init (fun a b => pure (.yield (f a b))) =
pure (f := m) (l.foldl (fun b a => f a b) init) := by
simp only [forIn_eq_foldlM]
induction l generalizing init <;> simp_all
@[simp] theorem forIn_yield_eq_foldl
(l : List α) (f : α β β) (init : β) :
{l : List α} (f : α β β) (init : β) :
forIn (m := Id) l init (fun a b => .yield (f a b)) =
l.foldl (fun b a => f a b) init := by
simp only [forIn_eq_foldlM]
induction l generalizing init <;> simp_all
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
(l : List α) (g : α β) (f : β γ m (ForInStep γ)) :
{l : List α} {g : α β} {f : β γ m (ForInStep γ)} :
forIn (l.map g) init f = forIn l init fun a y => f (g a) y := by
induction l generalizing init <;> simp_all
/-! ### allM and anyM -/
theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] (p : α m Bool) (as : List α) :
theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] {p : α m Bool} {as : List α} :
allM p as = (! ·) <$> anyM ((! ·) <$> p ·) as := by
induction as with
| nil => simp
@@ -414,7 +413,7 @@ theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] (p : α → m Bool) (as :
funext b
split <;> simp_all
@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] (p : α Bool) (as : List α) :
@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] {p : α Bool} {as : List α} :
as.anyM (m := m) (pure <| p ·) = pure (as.any p) := by
induction as with
| nil => simp
@@ -422,7 +421,7 @@ theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] (p : α → m Bool) (as :
simp only [anyM, ih, pure_bind, all_cons]
split <;> simp_all
@[simp] theorem allM_pure [Monad m] [LawfulMonad m] (p : α Bool) (as : List α) :
@[simp] theorem allM_pure [Monad m] [LawfulMonad m] {p : α Bool} {as : List α} :
as.allM (m := m) (pure <| p ·) = pure (as.all p) := by
simp [allM_eq_not_anyM_not, all_eq_not_any_not]
@@ -441,11 +440,11 @@ and simplifies these to the function directly taking the value.
| nil => simp
| cons a l ih => simp [ih, hf]
@[wf_preprocess] theorem foldlM_wfParam [Monad m] (xs : List α) (f : β α m β) (init : β) :
@[wf_preprocess] theorem foldlM_wfParam [Monad m] {xs : List α} {f : β α m β} {init : β} :
(wfParam xs).foldlM f init = xs.attach.unattach.foldlM f init := by
simp [wfParam]
@[wf_preprocess] theorem foldlM_unattach [Monad m] (P : α Prop) (xs : List (Subtype P)) (f : β α m β) (init : β):
@[wf_preprocess] theorem foldlM_unattach [Monad m] {P : α Prop} {xs : List (Subtype P)} {f : β α m β} {init : β} :
xs.unattach.foldlM f init = xs.foldlM (init := init) fun b x, h =>
binderNameHint b f <| binderNameHint x (f b) <| binderNameHint h () <|
f b (wfParam x) := by
@@ -468,11 +467,11 @@ and simplifies these to the function directly taking the value.
funext b
simp [hf]
@[wf_preprocess] theorem foldrM_wfParam [Monad m] [LawfulMonad m] (xs : List α) (f : α β m β) (init : β) :
@[wf_preprocess] theorem foldrM_wfParam [Monad m] [LawfulMonad m] {xs : List α} {f : α β m β} {init : β} :
(wfParam xs).foldrM f init = xs.attach.unattach.foldrM f init := by
simp [wfParam]
@[wf_preprocess] theorem foldrM_unattach [Monad m] [LawfulMonad m] (P : α Prop) (xs : List (Subtype P)) (f : α β m β) (init : β) :
@[wf_preprocess] theorem foldrM_unattach [Monad m] [LawfulMonad m] {P : α Prop} {xs : List (Subtype P)} {f : α β m β} {init : β} :
xs.unattach.foldrM f init = xs.foldrM (init := init) fun x, h b =>
binderNameHint x f <| binderNameHint h () <| binderNameHint b (f x) <|
f (wfParam x) b := by
@@ -491,11 +490,11 @@ and simplifies these to the function directly taking the value.
| nil => simp
| cons a l ih => simp [ih, hf]
@[wf_preprocess] theorem mapM_wfParam [Monad m] [LawfulMonad m] (xs : List α) (f : α m β) :
@[wf_preprocess] theorem mapM_wfParam [Monad m] [LawfulMonad m] {xs : List α} {f : α m β} :
(wfParam xs).mapM f = xs.attach.unattach.mapM f := by
simp [wfParam]
@[wf_preprocess] theorem mapM_unattach [Monad m] [LawfulMonad m] (P : α Prop) (xs : List (Subtype P)) (f : α m β) :
@[wf_preprocess] theorem mapM_unattach [Monad m] [LawfulMonad m] {P : α Prop} {xs : List (Subtype P)} {f : α m β} :
xs.unattach.mapM f = xs.mapM fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]
@@ -509,12 +508,12 @@ and simplifies these to the function directly taking the value.
| cons a l ih => simp [ih, hf, filterMapM_cons]
@[wf_preprocess] theorem filterMapM_wfParam [Monad m] [LawfulMonad m]
(xs : List α) (f : α m (Option β)) :
{xs : List α} {f : α m (Option β)} :
(wfParam xs).filterMapM f = xs.attach.unattach.filterMapM f := by
simp [wfParam]
@[wf_preprocess] theorem filterMapM_unattach [Monad m] [LawfulMonad m]
(P : α Prop) (xs : List (Subtype P)) (f : α m (Option β)) :
{P : α Prop} {xs : List (Subtype P)} {f : α m (Option β)} :
xs.unattach.filterMapM f = xs.filterMapM fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]
@@ -528,12 +527,12 @@ and simplifies these to the function directly taking the value.
| cons a l ih => simp [ih, hf]
@[wf_preprocess] theorem flatMapM_wfParam [Monad m] [LawfulMonad m]
(xs : List α) (f : α m (List β)) :
{xs : List α} {f : α m (List β)} :
(wfParam xs).flatMapM f = xs.attach.unattach.flatMapM f := by
simp [wfParam]
@[wf_preprocess] theorem flatMapM_unattach [Monad m] [LawfulMonad m]
(P : α Prop) (xs : List (Subtype P)) (f : α m (List β)) :
{P : α Prop} {xs : List (Subtype P)} {f : α m (List β)} :
xs.unattach.flatMapM f = xs.flatMapM fun x, h =>
binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by
simp [wfParam]

View File

@@ -14,7 +14,7 @@ namespace List
/-! ### isEqv -/
theorem isEqv_eq_decide (as bs : List α) (r) :
theorem isEqv_eq_decide {as bs : List α} {r : α α Bool} :
isEqv as bs r = if h : as.length = bs.length then
decide ( (i : Nat) (h' : i < as.length), r (as[i]'(h h')) (bs[i]'(h h'))) else false := by
induction as generalizing bs with
@@ -29,7 +29,7 @@ theorem isEqv_eq_decide (as bs : List α) (r) :
/-! ### beq -/
theorem beq_eq_isEqv [BEq α] (as bs : List α) : as.beq bs = isEqv as bs (· == ·) := by
theorem beq_eq_isEqv [BEq α] {as bs : List α} : as.beq bs = isEqv as bs (· == ·) := by
induction as generalizing bs with
| nil =>
cases bs <;> simp
@@ -42,7 +42,7 @@ theorem beq_eq_isEqv [BEq α] (as bs : List α) : as.beq bs = isEqv as bs (· ==
Bool.decide_eq_true]
split <;> simp
theorem beq_eq_decide [BEq α] (as bs : List α) :
theorem beq_eq_decide [BEq α] {as bs : List α} :
(as == bs) = if h : as.length = bs.length then
decide ( (i : Nat) (h' : i < as.length), as[i] == bs[i]'(h h')) else false := by
simp [BEq.beq, beq_eq_isEqv, isEqv_eq_decide]

View File

@@ -24,7 +24,7 @@ namespace List
/-! ### dropLast -/
theorem tail_dropLast (l : List α) : tail (dropLast l) = dropLast (tail l) := by
theorem tail_dropLast {l : List α} : tail (dropLast l) = dropLast (tail l) := by
ext1
simp only [getElem?_tail, getElem?_dropLast, length_tail]
split <;> split
@@ -33,7 +33,7 @@ theorem tail_dropLast (l : List α) : tail (dropLast l) = dropLast (tail l) := b
· omega
· rfl
@[simp] theorem dropLast_reverse (l : List α) : l.reverse.dropLast = l.tail.reverse := by
@[simp] theorem dropLast_reverse {l : List α} : l.reverse.dropLast = l.tail.reverse := by
apply ext_getElem
· simp
· intro i h₁ h₂
@@ -47,13 +47,13 @@ theorem tail_dropLast (l : List α) : tail (dropLast l) = dropLast (tail l) := b
@[simp]
theorem length_filter_pos_iff {l : List α} {p : α Bool} :
0 < (filter p l).length x l, p x := by
simpa [length_eq_countP_add_countP p l, countP_eq_length_filter] using
simpa [length_eq_countP_add_countP, countP_eq_length_filter] using
countP_pos_iff (p := p)
@[simp]
theorem length_filter_lt_length_iff_exists {l} :
(filter p l).length < l.length x l, ¬p x := by
simp [length_eq_countP_add_countP p l, countP_eq_length_filter]
simp [length_eq_countP_add_countP p (l := l), countP_eq_length_filter]
/-! ### filterMap -/
@@ -95,14 +95,14 @@ theorem getElem_eq_getElem_reverse {l : List α} {i} (h : i < l.length) :
to the larger of `n` and `l.length` -/
-- We don't mark this as a `@[simp]` lemma since we allow `simp` to unfold `leftpad`,
-- so the left hand side simplifies directly to `n - l.length + l.length`.
theorem length_leftpad (n : Nat) (a : α) (l : List α) :
theorem length_leftpad {n : Nat} {a : α} {l : List α} :
(leftpad n a l).length = max n l.length := by
simp only [leftpad, length_append, length_replicate, Nat.sub_add_eq_max]
@[deprecated length_leftpad (since := "2025-02-24")]
abbrev leftpad_length := @length_leftpad
theorem length_rightpad (n : Nat) (a : α) (l : List α) :
theorem length_rightpad {n : Nat} {a : α} {l : List α} :
(rightpad n a l).length = max n l.length := by
simp [rightpad]
omega

View File

@@ -14,7 +14,7 @@ namespace List
open Nat
theorem countP_set (p : α Bool) (l : List α) (i : Nat) (a : α) (h : i < l.length) :
theorem countP_set {p : α Bool} {l : List α} {i : Nat} {a : α} (h : i < l.length) :
(l.set i a).countP p = l.countP p - (if p l[i] then 1 else 0) + (if p a then 1 else 0) := by
induction l generalizing i with
| nil => simp at h
@@ -23,11 +23,11 @@ theorem countP_set (p : α → Bool) (l : List α) (i : Nat) (a : α) (h : i < l
| zero => simp [countP_cons]
| succ i =>
simp [add_one_lt_add_one_iff] at h
simp [countP_cons, ih _ h]
have : (if p l[i] = true then 1 else 0) l.countP p := boole_getElem_le_countP p l i h
simp [countP_cons, ih h]
have : (if p l[i] = true then 1 else 0) l.countP p := boole_getElem_le_countP (p := p) h
omega
theorem count_set [BEq α] (a b : α) (l : List α) (i : Nat) (h : i < l.length) :
theorem count_set [BEq α] {a b : α} {l : List α} {i : Nat} (h : i < l.length) :
(l.set i a).count b = l.count b - (if l[i] == b then 1 else 0) + (if a == b then 1 else 0) := by
simp [count_eq_countP, countP_set, h]
@@ -64,7 +64,7 @@ theorem IsInfix.le_countP (s : l₁ <:+: l₂) : countP p l₂ - (l₂.length -
The number of elements satisfying a predicate in the tail of a list is
at least one less than the number of elements satisfying the predicate in the list.
-/
theorem le_countP_tail (l) : countP p l - 1 countP p l.tail := by
theorem le_countP_tail {l} : countP p l - 1 countP p l.tail := by
have := (tail_sublist l).le_countP p
simp only [length_tail] at this
omega
@@ -83,7 +83,7 @@ theorem IsSuffix.le_count (s : l₁ <:+ l₂) (a : α) : count a l₂ - (l₂.le
theorem IsInfix.le_count (s : l₁ <:+: l₂) (a : α) : count a l₂ - (l₂.length - l₁.length) count a l₁ :=
s.sublist.le_count _
theorem le_count_tail (a : α) (l) : count a l - 1 count a l.tail :=
le_countP_tail _
theorem le_count_tail {a : α} {l : List α} : count a l - 1 count a l.tail :=
le_countP_tail
end List

View File

@@ -12,7 +12,7 @@ set_option linter.indexVariables true -- Enforce naming conventions for index va
namespace List
theorem getElem?_eraseIdx (l : List α) (i : Nat) (j : Nat) :
theorem getElem?_eraseIdx {l : List α} {i : Nat} {j : Nat} :
(l.eraseIdx i)[j]? = if j < i then l[j]? else l[j + 1]? := by
rw [eraseIdx_eq_take_drop_succ, getElem?_append]
split <;> rename_i h
@@ -35,19 +35,19 @@ theorem getElem?_eraseIdx (l : List α) (i : Nat) (j : Nat) :
omega
· rw [getElem?_eq_none, getElem?_eq_none] <;> omega
theorem getElem?_eraseIdx_of_lt (l : List α) (i : Nat) (j : Nat) (h : j < i) :
theorem getElem?_eraseIdx_of_lt {l : List α} {i : Nat} {j : Nat} (h : j < i) :
(l.eraseIdx i)[j]? = l[j]? := by
rw [getElem?_eraseIdx]
simp [h]
theorem getElem?_eraseIdx_of_ge (l : List α) (i : Nat) (j : Nat) (h : i j) :
theorem getElem?_eraseIdx_of_ge {l : List α} {i : Nat} {j : Nat} (h : i j) :
(l.eraseIdx i)[j]? = l[j + 1]? := by
rw [getElem?_eraseIdx]
simp only [dite_eq_ite, ite_eq_right_iff]
intro h'
omega
theorem getElem_eraseIdx (l : List α) (i : Nat) (j : Nat) (h : j < (l.eraseIdx i).length) :
theorem getElem_eraseIdx {l : List α} {i : Nat} {j : Nat} (h : j < (l.eraseIdx i).length) :
(l.eraseIdx i)[j] = if h' : j < i then
l[j]'(by have := length_eraseIdx_le l i; omega)
else
@@ -56,19 +56,19 @@ theorem getElem_eraseIdx (l : List α) (i : Nat) (j : Nat) (h : j < (l.eraseIdx
rw [ getElem?_eq_getElem, getElem?_eraseIdx]
split <;> simp
theorem getElem_eraseIdx_of_lt (l : List α) (i : Nat) (j : Nat) (h : j < (l.eraseIdx i).length) (h' : j < i) :
theorem getElem_eraseIdx_of_lt {l : List α} {i : Nat} {j : Nat} (h : j < (l.eraseIdx i).length) (h' : j < i) :
(l.eraseIdx i)[j] = l[j]'(by have := length_eraseIdx_le l i; omega) := by
rw [getElem_eraseIdx]
simp only [dite_eq_left_iff, Nat.not_lt]
intro h'
omega
theorem getElem_eraseIdx_of_ge (l : List α) (i : Nat) (j : Nat) (h : j < (l.eraseIdx i).length) (h' : i j) :
theorem getElem_eraseIdx_of_ge {l : List α} {i : Nat} {j : Nat} (h : j < (l.eraseIdx i).length) (h' : i j) :
(l.eraseIdx i)[j] = l[j + 1]'(by rw [length_eraseIdx] at h; split at h <;> omega) := by
rw [getElem_eraseIdx, dif_neg]
omega
theorem eraseIdx_eq_dropLast (l : List α) (i : Nat) (h : i + 1 = l.length) :
theorem eraseIdx_eq_dropLast {l : List α} {i : Nat} (h : i + 1 = l.length) :
l.eraseIdx i = l.dropLast := by
simp [eraseIdx_eq_take_drop_succ, h]
rw [take_eq_dropLast h]
@@ -141,7 +141,7 @@ theorem eraseIdx_set_gt {l : List α} {i : Nat} {j : Nat} {a : α} (h : i < j) :
· have t : ¬ n < i := by omega
simp [t]
@[simp] theorem eraseIdx_length_sub_one (l : List α) :
@[simp] theorem eraseIdx_length_sub_one {l : List α} :
(l.eraseIdx (l.length - 1)) = l.dropLast := by
apply ext_getElem
· simp [length_eraseIdx]

View File

@@ -29,19 +29,19 @@ section InsertIdx
variable {a : α}
@[simp]
theorem insertIdx_zero (xs : List α) (x : α) : xs.insertIdx 0 x = x :: xs :=
theorem insertIdx_zero {xs : List α} {x : α} : xs.insertIdx 0 x = x :: xs :=
rfl
@[simp]
theorem insertIdx_succ_nil (n : Nat) (a : α) : ([] : List α).insertIdx (n + 1) a = [] :=
theorem insertIdx_succ_nil {n : Nat} {a : α} : ([] : List α).insertIdx (n + 1) a = [] :=
rfl
@[simp]
theorem insertIdx_succ_cons (xs : List α) (hd x : α) (i : Nat) :
theorem insertIdx_succ_cons {xs : List α} {hd x : α} {i : Nat} :
(hd :: xs).insertIdx (i + 1) x = hd :: xs.insertIdx i x :=
rfl
theorem length_insertIdx : i (as : List α), (as.insertIdx i a).length = if i as.length then as.length + 1 else as.length
theorem length_insertIdx : {i} {as : List α}, (as.insertIdx i a).length = if i as.length then as.length + 1 else as.length
| 0, _ => by simp
| n + 1, [] => by simp
| n + 1, a :: as => by
@@ -55,37 +55,37 @@ theorem length_insertIdx_of_length_lt (h : length as < i) : (as.insertIdx i a).l
simp [length_insertIdx, h]
@[simp]
theorem eraseIdx_insertIdx (i : Nat) (l : List α) : (l.insertIdx i a).eraseIdx i = l := by
theorem eraseIdx_insertIdx {i : Nat} {l : List α} : (l.insertIdx i a).eraseIdx i = l := by
rw [eraseIdx_eq_modifyTailIdx, insertIdx, modifyTailIdx_modifyTailIdx_self]
exact modifyTailIdx_id _ _
theorem insertIdx_eraseIdx_of_ge :
i m as,
{i m as},
i < length as i m (as.eraseIdx i).insertIdx m a = (as.insertIdx (m + 1) a).eraseIdx i
| 0, 0, [], has, _ => (Nat.lt_irrefl _ has).elim
| 0, 0, _ :: as, _, _ => by simp [eraseIdx, insertIdx]
| 0, _ + 1, _ :: _, _, _ => rfl
| n + 1, m + 1, a :: as, has, hmn =>
congrArg (cons a) <|
insertIdx_eraseIdx_of_ge n m as (Nat.lt_of_succ_lt_succ has) (Nat.le_of_succ_le_succ hmn)
insertIdx_eraseIdx_of_ge (Nat.lt_of_succ_lt_succ has) (Nat.le_of_succ_le_succ hmn)
theorem insertIdx_eraseIdx_of_le :
i j as,
{i j as},
i < length as j i (as.eraseIdx i).insertIdx j a = (as.insertIdx j a).eraseIdx (i + 1)
| _, 0, _ :: _, _, _ => rfl
| n + 1, m + 1, a :: as, has, hmn =>
| _ + 1, _ + 1, a :: _, has, hmn =>
congrArg (cons a) <|
insertIdx_eraseIdx_of_le n m as (Nat.lt_of_succ_lt_succ has) (Nat.le_of_succ_le_succ hmn)
insertIdx_eraseIdx_of_le (Nat.lt_of_succ_lt_succ has) (Nat.le_of_succ_le_succ hmn)
theorem insertIdx_comm (a b : α) :
(i j : Nat) (l : List α) (_ : i j) (_ : j length l),
{i j : Nat} {l : List α} (_ : i j) (_ : j length l),
(l.insertIdx i a).insertIdx (j + 1) b = (l.insertIdx j b).insertIdx i a
| 0, j, l => by simp [insertIdx]
| _ + 1, 0, _ => fun h => (Nat.not_lt_zero _ h).elim
| i + 1, j + 1, [] => by simp
| i + 1, j + 1, c :: l => fun h₀ h₁ => by
simp only [insertIdx_succ_cons, cons.injEq, true_and]
exact insertIdx_comm a b i j l (Nat.le_of_succ_le_succ h₀) (Nat.le_of_succ_le_succ h₁)
exact insertIdx_comm a b (Nat.le_of_succ_le_succ h₀) (Nat.le_of_succ_le_succ h₁)
theorem mem_insertIdx {a b : α} :
{i : Nat} {l : List α} (_ : i l.length), a l.insertIdx i b a = b a l
@@ -95,7 +95,7 @@ theorem mem_insertIdx {a b : α} :
rw [List.insertIdx_succ_cons, mem_cons, mem_insertIdx (Nat.le_of_succ_le_succ h),
or_assoc, @or_comm (a = a'), or_assoc, mem_cons]
theorem insertIdx_of_length_lt (l : List α) (x : α) (i : Nat) (h : l.length < i) :
theorem insertIdx_of_length_lt {l : List α} {x : α} {i : Nat} (h : l.length < i) :
l.insertIdx i x = l := by
induction l generalizing i with
| nil =>
@@ -106,20 +106,20 @@ theorem insertIdx_of_length_lt (l : List α) (x : α) (i : Nat) (h : l.length <
cases i
· simp at h
· simp only [Nat.succ_lt_succ_iff, length] at h
simpa using ih _ h
simpa using ih h
@[simp]
theorem insertIdx_length_self (l : List α) (x : α) : l.insertIdx l.length x = l ++ [x] := by
theorem insertIdx_length_self {l : List α} {x : α} : l.insertIdx l.length x = l ++ [x] := by
induction l with
| nil => simp
| cons x l ih => simpa using ih
theorem length_le_length_insertIdx (l : List α) (x : α) (i : Nat) :
theorem length_le_length_insertIdx {l : List α} {x : α} {i : Nat} :
l.length (l.insertIdx i x).length := by
simp only [length_insertIdx]
split <;> simp
theorem length_insertIdx_le_succ (l : List α) (x : α) (i : Nat) :
theorem length_insertIdx_le_succ {l : List α} {x : α} {i : Nat} :
(l.insertIdx i x).length l.length + 1 := by
simp only [length_insertIdx]
split <;> simp

View File

@@ -47,7 +47,7 @@ theorem set_set_perm {as : List α} {i j : Nat} (h₁ : i < as.length) (h₂ : j
subst t
exact set_set_perm' _ _ (by omega)
else
rw [set_comm _ _ _ (by omega)]
rw [set_comm _ _ (by omega)]
let i' := i - j
have t : i = j + i' := by omega
generalize i' = i' at t

View File

@@ -30,7 +30,7 @@ open Nat
fun i, h, e => e Nat.le_add_right .., Nat.add_lt_add_left h _,
fun h₁, h₂ => m - s, Nat.sub_lt_left_of_lt_add h₁ h₂, (Nat.add_sub_cancel' h₁).symm
theorem getLast?_range' (n : Nat) : (range' s n).getLast? = if n = 0 then none else some (s + n - 1) := by
theorem getLast?_range' {n : Nat} : (range' s n).getLast? = if n = 0 then none else some (s + n - 1) := by
induction n generalizing s with
| zero => simp
| succ n ih =>
@@ -42,12 +42,12 @@ theorem getLast?_range' (n : Nat) : (range' s n).getLast? = if n = 0 then none e
simp
omega
@[simp] theorem getLast_range' (n : Nat) (h) : (range' s n).getLast h = s + n - 1 := by
@[simp] theorem getLast_range' {n : Nat} (h) : (range' s n).getLast h = s + n - 1 := by
cases n with
| zero => simp at h
| succ n => simp [getLast?_range', getLast_eq_iff_getLast?_eq_some]
theorem pairwise_lt_range' s n (step := 1) (pos : 0 < step := by simp) :
theorem pairwise_lt_range' {s n} (step := 1) (pos : 0 < step := by simp) :
Pairwise (· < ·) (range' s n step) :=
match s, n, step, pos with
| _, 0, _, _ => Pairwise.nil
@@ -57,9 +57,9 @@ theorem pairwise_lt_range' s n (step := 1) (pos : 0 < step := by simp) :
· intros n m
rw [mem_range'] at m
omega
· exact pairwise_lt_range' (s + step) n step pos
· exact pairwise_lt_range' (s := s + step) step pos
theorem pairwise_le_range' s n (step := 1) :
theorem pairwise_le_range' {s n} (step := 1) :
Pairwise (· ·) (range' s n step) :=
match s, n, step with
| _, 0, _ => Pairwise.nil
@@ -69,12 +69,12 @@ theorem pairwise_le_range' s n (step := 1) :
· intros n m
rw [mem_range'] at m
omega
· exact pairwise_le_range' (s + step) n step
· exact pairwise_le_range' (s := s + step) step
theorem nodup_range' (s n : Nat) (step := 1) (h : 0 < step := by simp) : Nodup (range' s n step) :=
(pairwise_lt_range' s n step h).imp Nat.ne_of_lt
theorem nodup_range' {s n : Nat} (step := 1) (h : 0 < step := by simp) : Nodup (range' s n step) :=
(pairwise_lt_range' step h).imp Nat.ne_of_lt
theorem map_sub_range' (a s n : Nat) (h : a s) :
theorem map_sub_range' {a s n : Nat} (h : a s) :
map (· - a) (range' s n step) = range' (s - a) n step := by
conv => lhs; rw [ Nat.add_sub_cancel' h]
rw [ map_add_range', map_map, (?_ : __ = _), map_id]
@@ -159,7 +159,7 @@ theorem erase_range' :
/-! ### range -/
theorem reverse_range' : s n : Nat, reverse (range' s n) = map (s + n - 1 - ·) (range n)
theorem reverse_range' : {s n : Nat}, reverse (range' s n) = map (s + n - 1 - ·) (range n)
| _, 0 => rfl
| s, n + 1 => by
rw [range'_1_concat, reverse_append, range_succ_eq_map,
@@ -172,20 +172,20 @@ theorem mem_range {m n : Nat} : m ∈ range n ↔ m < n := by
theorem not_mem_range_self {n : Nat} : n range n := by simp
theorem self_mem_range_succ (n : Nat) : n range (n + 1) := by simp
theorem self_mem_range_succ {n : Nat} : n range (n + 1) := by simp
theorem pairwise_lt_range (n : Nat) : Pairwise (· < ·) (range n) := by
theorem pairwise_lt_range {n : Nat} : Pairwise (· < ·) (range n) := by
simp +decide only [range_eq_range', pairwise_lt_range']
theorem pairwise_le_range (n : Nat) : Pairwise (· ·) (range n) :=
Pairwise.imp Nat.le_of_lt (pairwise_lt_range _)
theorem pairwise_le_range {n : Nat} : Pairwise (· ·) (range n) :=
Pairwise.imp Nat.le_of_lt pairwise_lt_range
@[simp] theorem take_range (i n : Nat) : take i (range n) = range (min i n) := by
@[simp] theorem take_range {i n : Nat} : take i (range n) = range (min i n) := by
apply List.ext_getElem
· simp
· simp +contextual [getElem_take, Nat.lt_min]
theorem nodup_range (n : Nat) : Nodup (range n) := by
theorem nodup_range {n : Nat} : Nodup (range n) := by
simp +decide only [range_eq_range', nodup_range']
@[simp] theorem find?_range_eq_some {n : Nat} {i : Nat} {p : Nat Bool} :
@@ -263,7 +263,7 @@ theorem iota_eq_append_iff : iota n = xs ++ ys ↔ ∃ k, k ≤ n ∧ xs = (rang
@[deprecated "Use `(List.range' 1 n).reverse` instead of `iota n`." (since := "2025-01-20")]
theorem pairwise_gt_iota (n : Nat) : Pairwise (· > ·) (iota n) := by
simpa only [iota_eq_reverse_range', pairwise_reverse] using pairwise_lt_range' 1 n
simpa only [iota_eq_reverse_range', pairwise_reverse] using pairwise_lt_range'
@[deprecated "Use `(List.range' 1 n).reverse` instead of `iota n`." (since := "2025-01-20")]
theorem nodup_iota (n : Nat) : Nodup (iota n) :=
@@ -348,14 +348,14 @@ end
/-! ### zipIdx -/
@[simp]
theorem zipIdx_singleton (x : α) (k : Nat) : zipIdx [x] k = [(x, k)] :=
theorem zipIdx_singleton {x : α} {k : Nat} : zipIdx [x] k = [(x, k)] :=
rfl
@[simp] theorem head?_zipIdx (l : List α) (k : Nat) :
@[simp] theorem head?_zipIdx {l : List α} {k : Nat} :
(zipIdx l k).head? = l.head?.map fun a => (a, k) := by
simp [head?_eq_getElem?]
@[simp] theorem getLast?_zipIdx (l : List α) (k : Nat) :
@[simp] theorem getLast?_zipIdx {l : List α} {k : Nat} :
(zipIdx l k).getLast? = l.getLast?.map fun a => (a, k + l.length - 1) := by
simp [getLast?_eq_getElem?]
cases l <;> simp; omega
@@ -401,12 +401,12 @@ theorem snd_lt_add_of_mem_zipIdx {x : α × Nat} {l : List α} {k : Nat} (h : x
theorem snd_lt_of_mem_zipIdx {x : α × Nat} {l : List α} {k : Nat} (h : x l.zipIdx k) : x.2 < l.length + k := by
simpa [Nat.add_comm] using snd_lt_add_of_mem_zipIdx h
theorem map_zipIdx (f : α β) (l : List α) (k : Nat) :
theorem map_zipIdx {f : α β} {l : List α} {k : Nat} :
map (Prod.map f id) (zipIdx l k) = zipIdx (l.map f) k := by
induction l generalizing k <;> simp_all
theorem fst_mem_of_mem_zipIdx {x : α × Nat} {l : List α} {k : Nat} (h : x zipIdx l k) : x.1 l :=
zipIdx_map_fst k l mem_map_of_mem _ h
zipIdx_map_fst k l mem_map_of_mem h
theorem fst_eq_of_mem_zipIdx {x : α × Nat} {l : List α} {k : Nat} (h : x zipIdx l k) :
x.1 = l[x.2 - k]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) := by
@@ -432,7 +432,7 @@ theorem mem_zipIdx' {x : α} {i : Nat} {xs : List α} (h : (x, i) ∈ xs.zipIdx)
i < xs.length x = xs[i]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) :=
by simpa using snd_lt_add_of_mem_zipIdx h, fst_eq_of_mem_zipIdx h
theorem zipIdx_map (l : List α) (k : Nat) (f : α β) :
theorem zipIdx_map {l : List α} {k : Nat} {f : α β} :
zipIdx (l.map f) k = (zipIdx l k).map (Prod.map f id) := by
induction l with
| nil => rfl
@@ -440,7 +440,7 @@ theorem zipIdx_map (l : List α) (k : Nat) (f : α → β) :
rw [map_cons, zipIdx_cons', zipIdx_cons', map_cons, map_map, IH, map_map]
rfl
theorem zipIdx_append (xs ys : List α) (k : Nat) :
theorem zipIdx_append {xs ys : List α} {k : Nat} :
zipIdx (xs ++ ys) k = zipIdx xs k ++ zipIdx ys (k + xs.length) := by
induction xs generalizing ys k with
| nil => simp
@@ -532,7 +532,7 @@ theorem map_enumFrom (f : α → β) (n : Nat) (l : List α) :
@[deprecated fst_mem_of_mem_zipIdx (since := "2025-01-21")]
theorem snd_mem_of_mem_enumFrom {x : Nat × α} {n : Nat} {l : List α} (h : x enumFrom n l) : x.2 l :=
enumFrom_map_snd n l mem_map_of_mem _ h
enumFrom_map_snd n l mem_map_of_mem h
@[deprecated fst_eq_of_mem_zipIdx (since := "2025-01-21")]
theorem snd_eq_of_mem_enumFrom {x : Nat × α} {n : Nat} {l : List α} (h : x enumFrom n l) :

View File

@@ -25,7 +25,7 @@ open Nat
/-! ### take -/
@[simp] theorem length_take : (i : Nat) (l : List α), length (take i l) = min i (length l)
@[simp] theorem length_take : {i : Nat} {l : List α}, (take i l).length = min i l.length
| 0, l => by simp [Nat.zero_min]
| succ n, [] => by simp [Nat.min_zero]
| succ n, _ :: l => by simp [Nat.succ_min_succ, length_take]
@@ -39,16 +39,16 @@ theorem length_take_of_le (h : i ≤ length l) : length (take i l) = i := by sim
/-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of
length `> i`. Version designed to rewrite from the big list to the small list. -/
theorem getElem_take' (xs : List α) {i j : Nat} (hi : i < xs.length) (hj : i < j) :
theorem getElem_take' {xs : List α} {i j : Nat} (hi : i < xs.length) (hj : i < j) :
xs[i] = (xs.take j)[i]'(length_take .. Nat.lt_min.mpr hj, hi) :=
getElem_of_eq (take_append_drop j xs).symm _ getElem_append_left ..
/-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of
length `> i`. Version designed to rewrite from the small list to the big list. -/
@[simp] theorem getElem_take (xs : List α) {j i : Nat} {h : i < (xs.take j).length} :
@[simp] theorem getElem_take {xs : List α} {j i : Nat} {h : i < (xs.take j).length} :
(xs.take j)[i] =
xs[i]'(Nat.lt_of_lt_of_le h (length_take_le' _ _)) := by
rw [length_take, Nat.lt_min] at h; rw [getElem_take' xs _ h.1]
rw [length_take, Nat.lt_min] at h; rw [getElem_take' (xs := xs) _ h.1]
theorem getElem?_take_eq_none {l : List α} {i j : Nat} (h : i j) :
(l.take i)[j]? = none :=
@@ -97,14 +97,14 @@ theorem getLast_take {l : List α} (h : l.take i ≠ []) :
· rw [getElem?_eq_none (by omega), getLast_eq_getElem]
simp
theorem take_take : (i j) (l : List α), take i (take j l) = take (min i j) l
theorem take_take : {i j} {l : List α}, take i (take j l) = take (min i j) l
| n, 0, l => by rw [Nat.min_zero, take_zero, take_nil]
| 0, m, l => by rw [Nat.zero_min, take_zero, take_zero]
| succ n, succ m, nil => by simp only [take_nil]
| succ n, succ m, a :: l => by
simp only [take, succ_min_succ, take_take n m l]
simp only [take, succ_min_succ, take_take]
theorem take_set_of_le (a : α) {i j : Nat} (l : List α) (h : j i) :
theorem take_set_of_le {a : α} {i j : Nat} {l : List α} (h : j i) :
(l.set i a).take j = l.take j :=
List.ext_getElem? fun i => by
rw [getElem?_take, getElem?_take]
@@ -115,12 +115,12 @@ theorem take_set_of_le (a : α) {i j : Nat} (l : List α) (h : j ≤ i) :
@[deprecated take_set_of_le (since := "2025-02-04")]
abbrev take_set_of_lt := @take_set_of_le
@[simp] theorem take_replicate (a : α) : i n : Nat, take i (replicate n a) = replicate (min i n) a
@[simp] theorem take_replicate {a : α} : {i n : Nat}, take i (replicate n a) = replicate (min i n) a
| n, 0 => by simp [Nat.min_zero]
| 0, m => by simp [Nat.zero_min]
| succ n, succ m => by simp [replicate_succ, succ_min_succ, take_replicate]
@[simp] theorem drop_replicate (a : α) : i n : Nat, drop i (replicate n a) = replicate (n - i) a
@[simp] theorem drop_replicate {a : α} : {i n : Nat}, drop i (replicate n a) = replicate (n - i) a
| n, 0 => by simp
| 0, m => by simp
| succ n, succ m => by simp [replicate_succ, succ_sub_succ, drop_replicate]
@@ -160,7 +160,7 @@ theorem take_eq_take_iff :
@[deprecated take_eq_take_iff (since := "2025-02-16")]
abbrev take_eq_take := @take_eq_take_iff
theorem take_add (l : List α) (i j : Nat) : l.take (i + j) = l.take i ++ (l.drop i).take j := by
theorem take_add {l : List α} {i j : Nat} : l.take (i + j) = l.take i ++ (l.drop i).take j := by
suffices take (i + j) (take i l ++ drop i l) = take i l ++ take j (drop i l) by
rw [take_append_drop] at this
assumption
@@ -198,22 +198,22 @@ theorem take_eq_dropLast {l : List α} {i : Nat} (h : i + 1 = l.length) :
rw [ih]
simpa using h
theorem take_prefix_take_left (l : List α) {i j : Nat} (h : i j) : take i l <+: take j l := by
theorem take_prefix_take_left {l : List α} {i j : Nat} (h : i j) : take i l <+: take j l := by
rw [isPrefix_iff]
intro i w
rw [getElem?_take_of_lt, getElem_take, getElem?_eq_getElem]
simp only [length_take] at w
exact Nat.lt_of_lt_of_le (Nat.lt_of_lt_of_le w (Nat.min_le_left _ _)) h
theorem take_sublist_take_left (l : List α) {i j : Nat} (h : i j) : take i l <+ take j l :=
(take_prefix_take_left l h).sublist
theorem take_sublist_take_left {l : List α} {i j : Nat} (h : i j) : take i l <+ take j l :=
(take_prefix_take_left h).sublist
theorem take_subset_take_left (l : List α) {i j : Nat} (h : i j) : take i l take j l :=
(take_sublist_take_left l h).subset
(take_sublist_take_left h).subset
/-! ### drop -/
theorem lt_length_drop (xs : List α) {i j : Nat} (h : i + j < xs.length) : j < (xs.drop i).length := by
theorem lt_length_drop {xs : List α} {i j : Nat} (h : i + j < xs.length) : j < (xs.drop i).length := by
have A : i < xs.length := Nat.lt_of_le_of_lt (Nat.le.intro rfl) h
rw [(take_append_drop i xs).symm] at h
simpa only [Nat.le_of_lt A, Nat.min_eq_left, Nat.add_lt_add_iff_left, length_take,
@@ -221,8 +221,8 @@ theorem lt_length_drop (xs : List α) {i j : Nat} (h : i + j < xs.length) : j <
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
theorem getElem_drop' (xs : List α) {i j : Nat} (h : i + j < xs.length) :
xs[i + j] = (xs.drop i)[j]'(lt_length_drop xs h) := by
theorem getElem_drop' {xs : List α} {i j : Nat} (h : i + j < xs.length) :
xs[i + j] = (xs.drop i)[j]'(lt_length_drop h) := by
have : i xs.length := Nat.le_trans (Nat.le_add_right _ _) (Nat.le_of_lt h)
rw [getElem_of_eq (take_append_drop i xs).symm h, getElem_append_right]
· simp [Nat.min_eq_left this, Nat.add_sub_cancel_left]
@@ -230,14 +230,14 @@ theorem getElem_drop' (xs : List α) {i j : Nat} (h : i + j < xs.length) :
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the small list to the big list. -/
@[simp] theorem getElem_drop (xs : List α) {i : Nat} {j : Nat} {h : j < (xs.drop i).length} :
@[simp] theorem getElem_drop {xs : List α} {i : Nat} {j : Nat} {h : j < (xs.drop i).length} :
(xs.drop i)[j] = xs[i + j]'(by
rw [Nat.add_comm]
exact Nat.add_lt_of_lt_sub (length_drop i xs h)) := by
exact Nat.add_lt_of_lt_sub (length_drop h)) := by
rw [getElem_drop']
@[simp]
theorem getElem?_drop (xs : List α) (i j : Nat) : (xs.drop i)[j]? = xs[i + j]? := by
theorem getElem?_drop {xs : List α} {i j : Nat} : (xs.drop i)[j]? = xs[i + j]? := by
ext
simp only [getElem?_eq_some_iff, getElem_drop, Option.mem_def]
constructor <;> intro h, ha
@@ -267,7 +267,7 @@ theorem mem_drop_iff_getElem {l : List α} {a : α} :
· rintro i, hm, rfl
refine i, by simp; omega, by rw [getElem_drop]
@[simp] theorem head?_drop (l : List α) (i : Nat) :
@[simp] theorem head?_drop {l : List α} {i : Nat} :
(l.drop i).head? = l[i]? := by
rw [head?_eq_getElem?, getElem?_drop, Nat.add_zero]
@@ -327,7 +327,7 @@ theorem drop_append {l₁ l₂ : List α} (i : Nat) : drop (l₁.length + i) (l
rw [drop_append_eq_append_drop, drop_eq_nil_of_le] <;>
simp [Nat.add_sub_cancel_left, Nat.le_add_right]
theorem set_eq_take_append_cons_drop (l : List α) (i : Nat) (a : α) :
theorem set_eq_take_append_cons_drop {l : List α} {i : Nat} {a : α} :
l.set i a = if i < l.length then l.take i ++ a :: l.drop (i + 1) else l := by
split <;> rename_i h
· ext1 j
@@ -354,16 +354,15 @@ theorem set_eq_take_append_cons_drop (l : List α) (i : Nat) (a : α) :
· rw [set_eq_of_length_le]
omega
theorem drop_set_of_lt (a : α) {i j : Nat} (l : List α)
(hnm : i < j) : drop j (l.set i a) = l.drop j :=
theorem drop_set_of_lt {a : α} {i j : Nat} {l : List α} (hnm : i < j) : drop j (l.set i a) = l.drop j :=
ext_getElem? fun k => by simpa only [getElem?_drop] using getElem?_set_ne (by omega)
theorem drop_take : (i j : Nat) (l : List α), drop i (take j l) = take (j - i) (drop i l)
theorem drop_take : {i j : Nat} {l : List α}, drop i (take j l) = take (j - i) (drop i l)
| 0, _, _ => by simp
| _, 0, _ => by simp
| _, _, [] => by simp
| i+1, j+1, h :: t => by
simp [take_succ_cons, drop_succ_cons, drop_take i j t]
simp [take_succ_cons, drop_succ_cons, drop_take]
congr 1
omega
@@ -515,7 +514,7 @@ theorem dropWhile_eq_drop_findIdx_not {xs : List α} {p : α → Bool} :
/-! ### rotateLeft -/
@[simp] theorem rotateLeft_replicate (n) (a : α) : rotateLeft (replicate m a) n = replicate m a := by
@[simp] theorem rotateLeft_replicate {n} {a : α} : rotateLeft (replicate m a) n = replicate m a := by
cases n with
| zero => simp
| succ n =>
@@ -528,7 +527,7 @@ theorem dropWhile_eq_drop_findIdx_not {xs : List α} {p : α → Bool} :
/-! ### rotateRight -/
@[simp] theorem rotateRight_replicate (n) (a : α) : rotateRight (replicate m a) n = replicate m a := by
@[simp] theorem rotateRight_replicate {n} {a : α} : rotateRight (replicate m a) n = replicate m a := by
cases n with
| zero => simp
| succ n =>
@@ -541,7 +540,7 @@ theorem dropWhile_eq_drop_findIdx_not {xs : List α} {p : α → Bool} :
/-! ### zipWith -/
@[simp] theorem length_zipWith (f : α β γ) (l₁ l₂) :
@[simp] theorem length_zipWith {f : α β γ} {l₁ : List α} {l₂ : List β} :
length (zipWith f l₁ l₂) = min (length l₁) (length l₂) := by
induction l₁ generalizing l₂ <;> cases l₂ <;>
simp_all [succ_min_succ, Nat.zero_min, Nat.min_zero]
@@ -563,11 +562,11 @@ theorem getElem_zipWith {f : α → β → γ} {l : List α} {l' : List β}
l[i]'(lt_length_left_of_zipWith h), l'[i]'(lt_length_right_of_zipWith h),
by rw [getElem?_eq_getElem], by rw [getElem?_eq_getElem]; exact rfl, rfl
theorem zipWith_eq_zipWith_take_min : (l₁ : List α) (l₂ : List β),
theorem zipWith_eq_zipWith_take_min : {l₁ : List α} {l₂ : List β},
zipWith f l₁ l₂ = zipWith f (l₁.take (min l₁.length l₂.length)) (l₂.take (min l₁.length l₂.length))
| [], _ => by simp
| _, [] => by simp
| a :: l₁, b :: l₂ => by simp [succ_min_succ, zipWith_eq_zipWith_take_min l₁ l₂]
| a :: l₁, b :: l₂ => by simp [succ_min_succ, zipWith_eq_zipWith_take_min (l₁ := l₁) (l₂ := l₂)]
theorem reverse_zipWith (h : l.length = l'.length) :
(zipWith f l l').reverse = zipWith f l.reverse l'.reverse := by
@@ -579,7 +578,7 @@ theorem reverse_zipWith (h : l.length = l'.length) :
| cons hd' tl' =>
simp only [Nat.add_right_cancel_iff, length] at h
have : tl.reverse.length = tl'.reverse.length := by simp [h]
simp [hl h, zipWith_append _ _ _ _ _ this]
simp [hl h, zipWith_append this]
@[simp] theorem zipWith_replicate {a : α} {b : β} {m n : Nat} :
zipWith f (replicate m a) (replicate n b) = replicate (min m n) (f a b) := by
@@ -588,7 +587,7 @@ theorem reverse_zipWith (h : l.length = l'.length) :
/-! ### zip -/
@[simp] theorem length_zip (l₁ : List α) (l₂ : List β) :
@[simp] theorem length_zip {l₁ : List α} {l₂ : List β} :
length (zip l₁ l₂) = min (length l₁) (length l₂) := by
simp [zip]
@@ -606,11 +605,11 @@ theorem getElem_zip {l : List α} {l' : List β} {i : Nat} {h : i < (zip l l').l
(l[i]'(lt_length_left_of_zip h), l'[i]'(lt_length_right_of_zip h)) :=
getElem_zipWith (h := h)
theorem zip_eq_zip_take_min : (l₁ : List α) (l₂ : List β),
theorem zip_eq_zip_take_min : {l₁ : List α} {l₂ : List β},
zip l₁ l₂ = zip (l₁.take (min l₁.length l₂.length)) (l₂.take (min l₁.length l₂.length))
| [], _ => by simp
| _, [] => by simp
| a :: l₁, b :: l₂ => by simp [succ_min_succ, zip_eq_zip_take_min l₁ l₂]
| a :: l₁, b :: l₂ => by simp [succ_min_succ, zip_eq_zip_take_min (l₁ := l₁) (l₂ := l₂)]
@[simp] theorem zip_replicate {a : α} {b : β} {m n : Nat} :
zip (replicate m a) (replicate n b) = replicate (min m n) (a, b) := by

View File

@@ -26,14 +26,14 @@ Examples:
def ofFn {n} (f : Fin n α) : List α := Fin.foldr n (f · :: ·) []
@[simp]
theorem length_ofFn (f : Fin n α) : (ofFn f).length = n := by
theorem length_ofFn {f : Fin n α} : (ofFn f).length = n := by
simp only [ofFn]
induction n with
| zero => simp
| succ n ih => simp [Fin.foldr_succ, ih]
@[simp]
protected theorem getElem_ofFn (f : Fin n α) (i : Nat) (h : i < (ofFn f).length) :
protected theorem getElem_ofFn {f : Fin n α} (h : i < (ofFn f).length) :
(ofFn f)[i] = f i, by simp_all := by
simp only [ofFn]
induction n generalizing i with
@@ -47,7 +47,7 @@ protected theorem getElem_ofFn (f : Fin n → α) (i : Nat) (h : i < (ofFn f).le
simp_all
@[simp]
protected theorem getElem?_ofFn (f : Fin n α) (i) : (ofFn f)[i]? = if h : i < n then some (f i, h) else none :=
protected theorem getElem?_ofFn {f : Fin n α} : (ofFn f)[i]? = if h : i < n then some (f i, h) else none :=
if h : i < (ofFn f).length
then by
rw [getElem?_eq_getElem h, List.getElem_ofFn]
@@ -58,11 +58,11 @@ protected theorem getElem?_ofFn (f : Fin n → α) (i) : (ofFn f)[i]? = if h : i
/-- `ofFn` on an empty domain is the empty list. -/
@[simp]
theorem ofFn_zero (f : Fin 0 α) : ofFn f = [] :=
theorem ofFn_zero {f : Fin 0 α} : ofFn f = [] :=
ext_get (by simp) (fun i hi₁ hi₂ => by contradiction)
@[simp]
theorem ofFn_succ {n} (f : Fin (n + 1) α) : ofFn f = f 0 :: ofFn fun i => f i.succ :=
theorem ofFn_succ {n} {f : Fin (n + 1) α} : ofFn f = f 0 :: ofFn fun i => f i.succ :=
ext_get (by simp) (fun i hi₁ hi₂ => by
cases i
· simp
@@ -73,7 +73,7 @@ theorem ofFn_eq_nil_iff {f : Fin n → α} : ofFn f = [] ↔ n = 0 := by
cases n <;> simp only [ofFn_zero, ofFn_succ, eq_self_iff_true, Nat.succ_ne_zero, reduceCtorEq]
@[simp 500]
theorem mem_ofFn {n} (f : Fin n α) (a : α) : a ofFn f i, f i = a := by
theorem mem_ofFn {n} {f : Fin n α} {a : α} : a ofFn f i, f i = a := by
constructor
· intro w
obtain i, h, rfl := getElem_of_mem w
@@ -81,12 +81,12 @@ theorem mem_ofFn {n} (f : Fin n → α) (a : α) : a ∈ ofFn f ↔ ∃ i, f i =
· rintro i, rfl
apply mem_of_getElem (i := i) <;> simp
theorem head_ofFn {n} (f : Fin n α) (h : ofFn f []) :
theorem head_ofFn {n} {f : Fin n α} (h : ofFn f []) :
(ofFn f).head h = f 0, Nat.pos_of_ne_zero (mt ofFn_eq_nil_iff.2 h) := by
rw [ getElem_zero (length_ofFn _ Nat.pos_of_ne_zero (mt ofFn_eq_nil_iff.2 h)),
rw [ getElem_zero (length_ofFn Nat.pos_of_ne_zero (mt ofFn_eq_nil_iff.2 h)),
List.getElem_ofFn]
theorem getLast_ofFn {n} (f : Fin n α) (h : ofFn f []) :
theorem getLast_ofFn {n} {f : Fin n α} (h : ofFn f []) :
(ofFn f).getLast h = f n - 1, Nat.sub_one_lt (mt ofFn_eq_nil_iff.2 h) := by
simp [getLast_eq_getElem, length_ofFn, List.getElem_ofFn]

View File

@@ -38,7 +38,8 @@ theorem rel_of_pairwise_cons (p : (a :: l).Pairwise R) : ∀ {a'}, a' ∈ l →
theorem Pairwise.of_cons (p : (a :: l).Pairwise R) : Pairwise R l :=
(pairwise_cons.1 p).2
theorem Pairwise.tail : {l : List α} (_p : Pairwise R l), Pairwise R l.tail
set_option linter.unusedVariables false in
theorem Pairwise.tail : {l : List α} (h : Pairwise R l), Pairwise R l.tail
| [], h => h
| _ :: _, h => h.of_cons
@@ -93,7 +94,7 @@ theorem Pairwise.forall_of_forall_of_flip (h₁ : ∀ x ∈ l, R x x) (h₂ : Pa
rw [pairwise_cons] at h₂ h₃
simp only [mem_cons]
rintro x (rfl | hx) y (rfl | hy)
· exact h₁ _ (l.mem_cons_self _)
· exact h₁ _ l.mem_cons_self
· exact h₂.1 _ hy
· exact h₃.1 _ hx
· exact ih (fun x hx => h₁ _ <| mem_cons_of_mem _ hx) h₂.2 h₃.2 hx hy
@@ -143,7 +144,7 @@ theorem pairwise_filter {p : α → Prop} [DecidablePred p] {l : List α} :
simp
theorem Pairwise.filter (p : α Bool) : Pairwise R l Pairwise R (filter p l) :=
Pairwise.sublist (filter_sublist _)
Pairwise.sublist filter_sublist
theorem pairwise_append {l₁ l₂ : List α} :
(l₁ ++ l₂).Pairwise R l₁.Pairwise R l₂.Pairwise R a l₁, b l₂, R a b := by

View File

@@ -191,7 +191,7 @@ theorem Perm.filterMap (f : α → Option β) {l₁ l₂ : List α} (p : l₁ ~
| trans _p₁ _p₂ IH₁ IH₂ => exact IH₁.trans IH₂
theorem Perm.map (f : α β) {l₁ l₂ : List α} (p : l₁ ~ l₂) : map f l₁ ~ map f l₂ :=
filterMap_eq_map f p.filterMap _
filterMap_eq_map p.filterMap _
theorem Perm.pmap {p : α Prop} (f : a, p a β) {l₁ l₂ : List α} (p : l₁ ~ l₂) {H₁ H₂} :
pmap f l₁ H₁ ~ pmap f l₂ H₂ := by
@@ -384,7 +384,7 @@ theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.erase
theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : List α} :
a :: l₁ ~ l₂ a l₂ l₁ ~ l₂.erase a := by
refine fun h => ?_, fun m, h => (h.cons a).trans (perm_cons_erase m).symm
have : a l₂ := h.subset (mem_cons_self a l₁)
have : a l₂ := h.subset mem_cons_self
exact this, (h.trans <| perm_cons_erase this).cons_inv
theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ a, count a l₁ = count a l₂ := by
@@ -435,7 +435,7 @@ theorem Perm.pairwise_iff {R : αα → Prop} (S : ∀ {x y}, R x y → R y
induction d generalizing l₂ with
| nil => rw [ p.nil_eq]; constructor
| cons h _ IH =>
have : _ l₂ := p.subset (mem_cons_self _ _)
have : _ l₂ := p.subset mem_cons_self
obtain s₂, t₂, rfl := append_of_mem this
have p' := (p.trans perm_middle).cons_inv
refine (pairwise_middle S).2 (pairwise_cons.2 fun b m => ?_, IH p')
@@ -458,8 +458,8 @@ theorem Perm.eq_of_sorted : ∀ {l₁ l₂ : List α}
| [], b :: l₂, _, _, _, h => by simp_all
| a :: l₁, [], _, _, _, h => by simp_all
| a :: l₁, b :: l₂, w, h₁, h₂, h => by
have am : a b :: l₂ := h.subset (mem_cons_self _ _)
have bm : b a :: l₁ := h.symm.subset (mem_cons_self _ _)
have am : a b :: l₂ := h.subset mem_cons_self
have bm : b a :: l₁ := h.symm.subset mem_cons_self
have ab : a = b := by
simp only [mem_cons] at am
rcases am with rfl | am
@@ -467,7 +467,7 @@ theorem Perm.eq_of_sorted : ∀ {l₁ l₂ : List α}
· simp only [mem_cons] at bm
rcases bm with rfl | bm
· rfl
· exact w _ _ (mem_cons_self _ _) (mem_cons_self _ _)
· exact w _ _ mem_cons_self mem_cons_self
(rel_of_pairwise_cons h₁ bm) (rel_of_pairwise_cons h₂ am)
subst ab
simp only [perm_cons] at h

View File

@@ -25,12 +25,12 @@ open Nat
/-! ### range' -/
theorem range'_succ (s n step) : range' s (n + 1) step = s :: range' (s + step) n step := by
theorem range'_succ {s n step} : range' s (n + 1) step = s :: range' (s + step) n step := by
simp [range', Nat.add_succ, Nat.mul_succ]
@[simp] theorem length_range' (s step) : n : Nat, length (range' s n step) = n
@[simp] theorem length_range' {s step} : {n : Nat}, length (range' s n step) = n
| 0 => rfl
| _ + 1 => congrArg succ (length_range' _ _ _)
| _ + 1 => congrArg succ length_range'
@[simp] theorem range'_eq_nil_iff : range' s n step = [] n = 0 := by
rw [ length_eq_zero_iff, length_range']
@@ -47,7 +47,7 @@ theorem range'_ne_nil_iff (s : Nat) {n step : Nat} : range' s n step ≠ [] ↔
@[simp] theorem range'_one {s step : Nat} : range' s 1 step = [s] := rfl
@[simp] theorem tail_range' (n : Nat) : (range' s n step).tail = range' (s + step) (n - 1) step := by
@[simp] theorem tail_range' : (range' s n step).tail = range' (s + step) (n - 1) step := by
cases n with
| zero => simp
| succ n => simp [range'_succ]
@@ -65,7 +65,7 @@ theorem range'_ne_nil_iff (s : Nat) {n step : Nat} : range' s n step ≠ [] ↔
simp_all
· rintro rfl, rfl | rfl <;> simp
theorem mem_range' : {n}, m range' s n step i < n, m = s + step * i
theorem mem_range' : {n}, m range' s n step i < n, m = s + step * i
| 0 => by simp [range', Nat.not_lt_zero]
| n + 1 => by
have h (i) : i n i = 0 j, i = succ j j < n := by
@@ -73,42 +73,42 @@ theorem mem_range' : ∀{n}, m ∈ range' s n step ↔ ∃ i < n, m = s + step *
simp [range', mem_range', Nat.lt_succ, h]; simp only [ exists_and_right, and_assoc]
rw [exists_comm]; simp [Nat.mul_succ, Nat.add_assoc, Nat.add_comm]
theorem getElem?_range' (s step) :
theorem getElem?_range' {s step} :
{i n : Nat}, i < n (range' s n step)[i]? = some (s + step * i)
| 0, n + 1, _ => by simp [range'_succ]
| m + 1, n + 1, h => by
simp only [range'_succ, getElem?_cons_succ]
exact (getElem?_range' (s + step) step (by exact succ_lt_succ_iff.mp h)).trans <| by
exact (getElem?_range' (s := s + step) (by exact succ_lt_succ_iff.mp h)).trans <| by
simp [Nat.mul_succ, Nat.add_assoc, Nat.add_comm]
@[simp] theorem getElem_range' {n m step} (i) (H : i < (range' n m step).length) :
@[simp] theorem getElem_range' {n m step} {i} (H : i < (range' n m step).length) :
(range' n m step)[i] = n + step * i :=
(getElem?_eq_some_iff.1 <| getElem?_range' n step (by simpa using H)).2
(getElem?_eq_some_iff.1 <| getElem?_range' (by simpa using H)).2
theorem head?_range' (n : Nat) : (range' s n).head? = if n = 0 then none else some s := by
theorem head?_range' : (range' s n).head? = if n = 0 then none else some s := by
induction n <;> simp_all [range'_succ, head?_append]
@[simp] theorem head_range' (n : Nat) (h) : (range' s n).head h = s := by
@[simp] theorem head_range' (h) : (range' s n).head h = s := by
repeat simp_all [head?_range', head_eq_iff_head?_eq_some]
theorem map_add_range' (a) : s n step, map (a + ·) (range' s n step) = range' (a + s) n step
theorem map_add_range' {a} : s n step, map (a + ·) (range' s n step) = range' (a + s) n step
| _, 0, _ => rfl
| s, n + 1, step => by simp [range', map_add_range' _ (s + step) n step, Nat.add_assoc]
| s, n + 1, step => by simp [range', map_add_range' (s + step), Nat.add_assoc]
theorem range'_succ_left : range' (s + 1) n step = (range' s n step).map (· + 1) := by
apply ext_getElem
· simp
· simp [Nat.add_right_comm]
theorem range'_append : s m n step : Nat,
theorem range'_append : {s m n step : Nat},
range' s m step ++ range' (s + step * m) n step = range' s (m + n) step
| _, 0, _, _ => by simp
| s, m + 1, n, step => by
simpa [range', Nat.mul_succ, Nat.add_assoc, Nat.add_comm]
using range'_append (s + step) m n step
using range'_append (s := s + step)
@[simp] theorem range'_append_1 (s m n : Nat) :
range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append s m n 1
@[simp] theorem range'_append_1 {s m n : Nat} :
range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append (step := 1)
theorem range'_sublist_right {s m n : Nat} : range' s m step <+ range' s n step m n :=
fun h => by simpa only [length_range'] using h.length_le,
@@ -123,10 +123,10 @@ theorem range'_subset_right {s m n : Nat} (step0 : 0 < step) :
theorem range'_subset_right_1 {s m n : Nat} : range' s m range' s n m n :=
range'_subset_right (by decide)
theorem range'_concat (s n : Nat) : range' s (n + 1) step = range' s n step ++ [s + step * n] := by
exact (range'_append s n 1 step).symm
theorem range'_concat {s n : Nat} : range' s (n + 1) step = range' s n step ++ [s + step * n] := by
exact range'_append.symm
theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ [s + n] := by
theorem range'_1_concat {s n : Nat} : range' s (n + 1) = range' s n ++ [s + n] := by
simp [range'_concat]
theorem range'_eq_cons_iff : range' s n = a :: xs s = a 0 < n xs = range' (a + 1) (n - 1) := by
@@ -140,27 +140,27 @@ theorem range'_eq_cons_iff : range' s n = a :: xs ↔ s = a ∧ 0 < n ∧ xs = r
/-! ### range -/
theorem range_loop_range' : s n : Nat, range.loop s (range' s n) = range' 0 (n + s)
theorem range_loop_range' : s n, range.loop s (range' s n) = range' 0 (n + s)
| 0, _ => rfl
| s + 1, n => by rw [ Nat.add_assoc, Nat.add_right_comm n s 1]; exact range_loop_range' s (n + 1)
theorem range_eq_range' (n : Nat) : range n = range' 0 n :=
theorem range_eq_range' {n : Nat} : range n = range' 0 n :=
(range_loop_range' n 0).trans <| by rw [Nat.zero_add]
theorem getElem?_range {i n : Nat} (h : i < n) : (range n)[i]? = some i := by
simp [range_eq_range', getElem?_range' _ _ h]
simp [range_eq_range', getElem?_range' h]
@[simp] theorem getElem_range {n : Nat} (j) (h : j < (range n).length) : (range n)[j] = j := by
@[simp] theorem getElem_range (h : j < (range n).length) : (range n)[j] = j := by
simp [range_eq_range']
theorem range_succ_eq_map (n : Nat) : range (n + 1) = 0 :: map succ (range n) := by
theorem range_succ_eq_map {n : Nat} : range (n + 1) = 0 :: map succ (range n) := by
rw [range_eq_range', range_eq_range', range', Nat.add_comm, map_add_range']
congr; exact funext (Nat.add_comm 1)
theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) := by
theorem range'_eq_map_range {s n : Nat} : range' s n = map (s + ·) (range n) := by
rw [range_eq_range', map_add_range']; rfl
@[simp] theorem length_range (n : Nat) : length (range n) = n := by
@[simp] theorem length_range {n : Nat} : (range n).length = n := by
simp only [range_eq_range', length_range']
@[simp] theorem range_eq_nil {n : Nat} : range n = [] n = 0 := by
@@ -169,7 +169,7 @@ theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) :=
theorem range_ne_nil {n : Nat} : range n [] n 0 := by
cases n <;> simp
@[simp] theorem tail_range (n : Nat) : (range n).tail = range' 1 (n - 1) := by
@[simp] theorem tail_range : (range n).tail = range' 1 (n - 1) := by
rw [range_eq_range', tail_range']
@[simp]
@@ -180,33 +180,33 @@ theorem range_sublist {m n : Nat} : range m <+ range n ↔ m ≤ n := by
theorem range_subset {m n : Nat} : range m range n m n := by
simp only [range_eq_range', range'_subset_right, lt_succ_self]
theorem range_succ (n : Nat) : range (succ n) = range n ++ [n] := by
theorem range_succ {n : Nat} : range (succ n) = range n ++ [n] := by
simp only [range_eq_range', range'_1_concat, Nat.zero_add]
theorem range_add (n m : Nat) : range (n + m) = range n ++ (range m).map (n + ·) := by
theorem range_add {n m : Nat} : range (n + m) = range n ++ (range m).map (n + ·) := by
rw [ range'_eq_map_range]
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 n m).symm
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 (s := 0)).symm
theorem head?_range (n : Nat) : (range n).head? = if n = 0 then none else some 0 := by
theorem head?_range {n : Nat} : (range n).head? = if n = 0 then none else some 0 := by
induction n with
| zero => simp
| succ n ih =>
simp only [range_succ, head?_append, ih]
split <;> simp_all
@[simp] theorem head_range (n : Nat) (h) : (range n).head h = 0 := by
@[simp] theorem head_range {n : Nat} (h) : (range n).head h = 0 := by
cases n with
| zero => simp at h
| succ n => simp [head?_range, head_eq_iff_head?_eq_some]
theorem getLast?_range (n : Nat) : (range n).getLast? = if n = 0 then none else some (n - 1) := by
theorem getLast?_range {n : Nat} : (range n).getLast? = if n = 0 then none else some (n - 1) := by
induction n with
| zero => simp
| succ n ih =>
simp only [range_succ, getLast?_append, ih]
split <;> simp_all
@[simp] theorem getLast_range (n : Nat) (h) : (range n).getLast h = n - 1 := by
@[simp] theorem getLast_range {n : Nat} (h) : (range n).getLast h = n - 1 := by
cases n with
| zero => simp at h
| succ n => simp [getLast?_range, getLast_eq_iff_getLast?_eq_some]
@@ -223,15 +223,15 @@ theorem zipIdx_eq_nil_iff {l : List α} {i : Nat} : List.zipIdx l i = [] ↔ l =
@[simp]
theorem getElem?_zipIdx :
(l : List α) i j, (zipIdx l i)[j]? = l[j]?.map fun a => (a, i + j)
{l : List α} {i j}, (zipIdx l i)[j]? = l[j]?.map fun a => (a, i + j)
| [], _, _ => rfl
| _ :: _, _, 0 => by simp
| _ :: l, n, m + 1 => by
simp only [zipIdx_cons, getElem?_cons_succ]
exact (getElem?_zipIdx l (n + 1) m).trans <| by rw [Nat.add_right_comm]; rfl
exact getElem?_zipIdx.trans <| by rw [Nat.add_right_comm]; rfl
@[simp]
theorem getElem_zipIdx (l : List α) (j) (i : Nat) (h : i < (l.zipIdx j).length) :
theorem getElem_zipIdx {l : List α} (h : i < (l.zipIdx j).length) :
(l.zipIdx j)[i] = (l[i]'(by simpa [length_zipIdx] using h), j + i) := by
simp only [length_zipIdx] at h
rw [getElem_eq_getElem?_get]
@@ -239,53 +239,55 @@ theorem getElem_zipIdx (l : List α) (j) (i : Nat) (h : i < (l.zipIdx j).length)
simp
@[simp]
theorem tail_zipIdx (l : List α) (i : Nat) : (zipIdx l i).tail = zipIdx l.tail (i + 1) := by
theorem tail_zipIdx {l : List α} {i : Nat} : (zipIdx l i).tail = zipIdx l.tail (i + 1) := by
induction l generalizing i with
| nil => simp
| cons _ l ih => simp [ih, zipIdx_cons]
theorem map_snd_add_zipIdx_eq_zipIdx (l : List α) (n k : Nat) :
theorem map_snd_add_zipIdx_eq_zipIdx {l : List α} {n k : Nat} :
map (Prod.map id (· + n)) (zipIdx l k) = zipIdx l (n + k) :=
ext_getElem? fun i by simp [(· ·), Nat.add_comm, Nat.add_left_comm]; rfl
theorem zipIdx_cons' (i : Nat) (x : α) (xs : List α) :
theorem zipIdx_cons' {i : Nat} {x : α} {xs : List α} :
zipIdx (x :: xs) i = (x, i) :: (zipIdx xs i).map (Prod.map id (· + 1)) := by
rw [zipIdx_cons, Nat.add_comm, map_snd_add_zipIdx_eq_zipIdx]
-- Arguments are explicit for parity with `zipIdx_map_fst`.
@[simp]
theorem zipIdx_map_snd (i) :
theorem zipIdx_map_snd (i : Nat) :
(l : List α), map Prod.snd (zipIdx l i) = range' i l.length
| [] => rfl
| _ :: _ => congrArg (cons _) (zipIdx_map_snd _ _)
| _ :: _ => congrArg (cons _) (zipIdx_map_snd ..)
-- Arguments are explicit so we can rewrite from right to left.
@[simp]
theorem zipIdx_map_fst : (i) (l : List α), map Prod.fst (zipIdx l i) = l
theorem zipIdx_map_fst : i (l : List α), map Prod.fst (zipIdx l i) = l
| _, [] => rfl
| _, _ :: _ => congrArg (cons _) (zipIdx_map_fst _ _)
| _, _ :: _ => congrArg (cons _) (zipIdx_map_fst ..)
theorem zipIdx_eq_zip_range' (l : List α) {i : Nat} : l.zipIdx i = l.zip (range' i l.length) :=
zip_of_prod (zipIdx_map_fst _ _) (zipIdx_map_snd _ _)
theorem zipIdx_eq_zip_range' {l : List α} {i : Nat} : l.zipIdx i = l.zip (range' i l.length) :=
zip_of_prod (zipIdx_map_fst ..) (zipIdx_map_snd ..)
@[simp]
theorem unzip_zipIdx_eq_prod (l : List α) {i : Nat} :
theorem unzip_zipIdx_eq_prod {l : List α} {i : Nat} :
(l.zipIdx i).unzip = (l, range' i l.length) := by
simp only [zipIdx_eq_zip_range', unzip_zip, length_range']
/-- Replace `zipIdx` with a starting index `n+1` with `zipIdx` starting from `n`,
followed by a `map` increasing the indices by one. -/
theorem zipIdx_succ (l : List α) (i : Nat) :
theorem zipIdx_succ {l : List α} {i : Nat} :
l.zipIdx (i + 1) = (l.zipIdx i).map (fun a, i => (a, i + 1)) := by
induction l generalizing i with
| nil => rfl
| cons _ _ ih => simp only [zipIdx_cons, ih (i + 1), map_cons]
| cons _ _ ih => simp only [zipIdx_cons, ih, map_cons]
/-- Replace `zipIdx` with a starting index with `zipIdx` starting from 0,
followed by a `map` increasing the indices. -/
theorem zipIdx_eq_map_add (l : List α) (i : Nat) :
theorem zipIdx_eq_map_add {l : List α} {i : Nat} :
l.zipIdx i = l.zipIdx.map (fun a, j => (a, i + j)) := by
induction l generalizing i with
| nil => rfl
| cons _ _ ih => simp [ih (i+1), zipIdx_succ, Nat.add_assoc, Nat.add_comm 1]
| cons _ _ ih => simp [ih (i := i + 1), zipIdx_succ, Nat.add_assoc, Nat.add_comm 1]
/-! ### enumFrom -/

View File

@@ -243,7 +243,7 @@ theorem merge_of_le : ∀ {xs ys : List α} (_ : ∀ a b, a ∈ xs → b ∈ ys
rw [if_pos, merge_of_le]
· intro a b ma mb
exact h a b (mem_cons_of_mem _ ma) mb
· exact h x y (mem_cons_self _ _) (mem_cons_self _ _)
· exact h x y mem_cons_self mem_cons_self
variable (le) in
theorem merge_perm_append : {xs ys : List α}, merge xs ys le ~ xs ++ ys
@@ -367,9 +367,9 @@ theorem mergeSort_cons {le : αα → Bool}
b, b l₁ !le a b := by
rw [ mergeSort_zipIdx]
rw [zipIdx_cons]
have nd : Nodup ((a :: l).zipIdx.map (·.2)) := by rw [zipIdx_map_snd]; exact nodup_range' _ _
have nd : Nodup ((a :: l).zipIdx.map (·.2)) := by rw [zipIdx_map_snd]; exact nodup_range' _
have m₁ : (a, 0) mergeSort ((a :: l).zipIdx) (zipIdxLE le) :=
mem_mergeSort.mpr (mem_cons_self _ _)
mem_mergeSort.mpr mem_cons_self
obtain l₁, l₂, h := append_of_mem m₁
have s := sorted_mergeSort (zipIdxLE_trans trans) (zipIdxLE_total total) ((a :: l).zipIdx)
rw [h] at s
@@ -408,9 +408,9 @@ theorem mergeSort_cons {le : αα → Bool}
have nd' := nd.perm p.symm
rw [map_append] at nd'
have j0 := nd'.rel_of_mem_append
(mem_map_of_mem (·.2) m) (mem_map_of_mem _ (mem_cons_self _ _))
(mem_map_of_mem m) (mem_map_of_mem mem_cons_self)
simp only [ne_eq] at j0
have r := s.rel_of_mem_append m (mem_cons_self _ _)
have r := s.rel_of_mem_append m mem_cons_self
simp_all [zipIdxLE]
/--

View File

@@ -256,10 +256,10 @@ protected theorem Sublist.filter (p : α → Bool) {l₁ l₂} (s : l₁ <+ l₂
rw [ filterMap_eq_filter]; apply s.filterMap
theorem head_filter_mem (xs : List α) (p : α Bool) (h) : (xs.filter p).head h xs :=
(filter_sublist xs).head_mem h
filter_sublist.head_mem h
theorem getLast_filter_mem (xs : List α) (p : α Bool) (h) : (xs.filter p).getLast h xs :=
(filter_sublist xs).getLast_mem h
filter_sublist.getLast_mem h
theorem sublist_filterMap_iff {l₁ : List β} {f : α Option β} :
l₁ <+ l₂.filterMap f l', l' <+ l₂ l₁ = l'.filterMap f := by
@@ -991,10 +991,10 @@ theorem drop_subset_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l
(drop_sublist_drop_left l h).subset
theorem takeWhile_prefix (p : α Bool) : l.takeWhile p <+: l :=
l.dropWhile p, takeWhile_append_dropWhile p l
l.dropWhile p, takeWhile_append_dropWhile
theorem dropWhile_suffix (p : α Bool) : l.dropWhile p <:+ l :=
l.takeWhile p, takeWhile_append_dropWhile p l
l.takeWhile p, takeWhile_append_dropWhile
theorem takeWhile_sublist (p : α Bool) : l.takeWhile p <+ l :=
(takeWhile_prefix p).sublist

View File

@@ -23,28 +23,29 @@ Further results on `List.take` and `List.drop`, which rely on stronger automatio
are given in `Init.Data.List.TakeDrop`.
-/
theorem take_cons {l : List α} (h : 0 < i) : take i (a :: l) = a :: take (i - 1) l := by
theorem take_cons {l : List α} (h : 0 < i) : (a :: l).take i = a :: l.take (i - 1) := by
cases i with
| zero => exact absurd h (Nat.lt_irrefl _)
| succ i => rfl
@[simp]
theorem drop_one : l : List α, drop 1 l = tail l
theorem drop_one : {l : List α}, l.drop 1 = l.tail
| [] | _ :: _ => rfl
@[simp] theorem take_append_drop : (i : Nat) (l : List α), take i l ++ drop i l = l
-- Arguments are explicit so we can rewrite from right to left.
@[simp] theorem take_append_drop : (i : Nat) (l : List α), l.take i ++ l.drop i = l
| 0, _ => rfl
| _+1, [] => rfl
| i+1, x :: xs => congrArg (cons x) <| take_append_drop i xs
| _ + 1, [] => rfl
| _ + 1, x :: _ => congrArg (cons x) (take_append_drop ..)
@[simp] theorem length_drop : (i : Nat) (l : List α), length (drop i l) = length l - i
@[simp] theorem length_drop : {i : Nat} {l : List α}, (drop i l).length = l.length - i
| 0, _ => rfl
| succ i, [] => Eq.symm (Nat.zero_sub (succ i))
| succ i, x :: l => calc
length (drop (succ i) (x :: l)) = length l - i := length_drop i l
length (drop (i + 1) (x :: l)) = length l - i := length_drop (i := i) (l := l)
_ = succ (length l) - succ i := (Nat.succ_sub_succ_eq_sub (length l) i).symm
theorem drop_of_length_le {l : List α} (h : l.length i) : drop i l = [] :=
theorem drop_of_length_le {l : List α} (h : l.length i) : l.drop i = [] :=
length_eq_zero_iff.1 (length_drop .. Nat.sub_eq_zero_of_le h)
theorem length_lt_of_drop_ne_nil {l : List α} {i} (h : drop i l []) : i < l.length :=
@@ -57,18 +58,18 @@ theorem take_of_length_le {l : List α} (h : l.length ≤ i) : take i l = l := b
theorem lt_length_of_take_ne_self {l : List α} {i} (h : l.take i l) : i < l.length :=
gt_of_not_le (mt take_of_length_le h)
@[simp] theorem drop_length (l : List α) : drop l.length l = [] := drop_of_length_le (Nat.le_refl _)
@[simp] theorem drop_length {l : List α} : l.drop l.length = [] := drop_of_length_le (Nat.le_refl _)
@[simp] theorem take_length (l : List α) : take l.length l = l := take_of_length_le (Nat.le_refl _)
@[simp] theorem take_length {l : List α} : l.take l.length = l := take_of_length_le (Nat.le_refl _)
@[simp]
theorem getElem_cons_drop : (l : List α) (i : Nat) (h : i < l.length),
theorem getElem_cons_drop : {l : List α} {i : Nat} (h : i < l.length),
l[i] :: drop (i + 1) l = drop i l
| _::_, 0, _ => rfl
| _::_, i+1, h => getElem_cons_drop _ i (Nat.add_one_lt_add_one_iff.mp h)
| _::_, _+1, h => getElem_cons_drop (Nat.add_one_lt_add_one_iff.mp h)
theorem drop_eq_getElem_cons {i} {l : List α} (h : i < l.length) : drop i l = l[i] :: drop (i + 1) l :=
(getElem_cons_drop _ i h).symm
(getElem_cons_drop h).symm
@[simp]
theorem getElem?_take_of_lt {l : List α} {i j : Nat} (h : i < j) : (l.take j)[i]? = l[i]? := by
@@ -85,25 +86,25 @@ theorem getElem?_take_of_lt {l : List α} {i j : Nat} (h : i < j) : (l.take j)[i
theorem getElem?_take_of_succ {l : List α} {i : Nat} : (l.take (i + 1))[i]? = l[i]? := by simp
@[simp] theorem drop_drop (i : Nat) : (j) (l : List α), drop i (drop j l) = drop (j + i) l
@[simp] theorem drop_drop {i : Nat} : {j} {l : List α}, drop i (drop j l) = drop (j + i) l
| j, [] => by simp
| 0, l => by simp
| j + 1, a :: l =>
calc
drop i (drop (j + 1) (a :: l)) = drop i (drop j l) := rfl
_ = drop (j + i) l := drop_drop i j l
_ = drop (j + i) l := drop_drop
_ = drop ((j + 1) + i) (a :: l) := by rw [Nat.add_right_comm]; rfl
theorem drop_add_one_eq_tail_drop (l : List α) : l.drop (i + 1) = (l.drop i).tail := by
theorem drop_add_one_eq_tail_drop {l : List α} : l.drop (i + 1) = (l.drop i).tail := by
rw [ drop_drop, drop_one]
theorem take_drop : (i j : Nat) (l : List α), take i (drop j l) = drop j (take (j + i) l)
theorem take_drop : {i j : Nat} {l : List α}, take i (drop j l) = drop j (take (j + i) l)
| _, 0, _ => by simp
| _, _, [] => by simp
| _, _+1, _ :: _ => by simpa [Nat.succ_add, take_succ_cons, drop_succ_cons] using take_drop ..
@[simp]
theorem tail_drop (l : List α) (i : Nat) : (l.drop i).tail = l.drop (i + 1) := by
theorem tail_drop {l : List α} {i : Nat} : (l.drop i).tail = l.drop (i + 1) := by
induction l generalizing i with
| nil => simp
| cons hd tl hl =>
@@ -112,7 +113,7 @@ theorem tail_drop (l : List α) (i : Nat) : (l.drop i).tail = l.drop (i + 1) :=
· simp [hl]
@[simp]
theorem drop_tail (l : List α) (i : Nat) : l.tail.drop i = l.drop (i + 1) := by
theorem drop_tail {l : List α} {i : Nat} : l.tail.drop i = l.drop (i + 1) := by
rw [Nat.add_comm, drop_drop, drop_one]
@[simp]
@@ -177,18 +178,20 @@ theorem set_drop {l : List α} {i j : Nat} {a : α} :
rw [drop_set, if_neg, add_sub_self_left]
exact (Nat.not_lt).2 (le_add_right ..)
theorem take_concat_get (l : List α) (i : Nat) (h : i < l.length) :
theorem take_concat_get {l : List α} {i : Nat} (h : i < l.length) :
(l.take i).concat l[i] = l.take (i+1) :=
Eq.symm <| (append_left_inj _).1 <| (take_append_drop (i+1) l).trans <| by
rw [concat_eq_append, append_assoc, singleton_append, getElem_cons_drop_succ_eq_drop, take_append_drop]
@[simp] theorem take_append_getElem (l : List α) (i : Nat) (h : i < l.length) :
@[simp] theorem take_append_getElem {l : List α} {i : Nat} (h : i < l.length) :
(l.take i) ++ [l[i]] = l.take (i+1) := by
simpa using take_concat_get l i h
simpa using take_concat_get h
theorem take_succ_eq_append_getElem {i} {l : List α} (h : i < l.length) : l.take (i + 1) = l.take i ++ [l[i]] :=
(take_append_getElem _ _ h).symm
(take_append_getElem h).symm
-- The argument `l : List α` is explicit
-- as `h` may be produced by a tactic that does not determine `l`.
@[simp] theorem take_append_getLast (l : List α) (h : l []) :
(l.take (l.length - 1)) ++ [l.getLast h] = l := by
rw [getLast_eq_getElem]
@@ -203,17 +206,17 @@ theorem take_succ_eq_append_getElem {i} {l : List α} (h : i < l.length) : l.tak
| x :: xs =>
simpa using take_append_getLast (x :: xs) (by simp)
theorem drop_left : l₁ l₂ : List α, drop (length l₁) (l₁ ++ l₂) = l₂
theorem drop_left : {l₁ l₂ : List α}, drop (length l₁) (l₁ ++ l₂) = l₂
| [], _ => rfl
| _ :: l₁, l₂ => drop_left l₁ l₂
| _ :: l₁, _ => drop_left (l₁ := l₁)
@[simp]
theorem drop_left' {l₁ l₂ : List α} {i} (h : length l₁ = i) : drop i (l₁ ++ l₂) = l₂ := by
rw [ h]; apply drop_left
theorem take_left : l₁ l₂ : List α, take (length l₁) (l₁ ++ l₂) = l₁
theorem take_left : {l₁ l₂ : List α}, take (length l₁) (l₁ ++ l₂) = l₁
| [], _ => rfl
| a :: l₁, l₂ => congrArg (cons a) (take_left l₁ l₂)
| a :: _, _ => congrArg (cons a) take_left
@[simp]
theorem take_left' {l₁ l₂ : List α} {i} (h : length l₁ = i) : take i (l₁ ++ l₂) = l₁ := by
@@ -228,29 +231,29 @@ theorem take_succ {l : List α} {i : Nat} : l.take (i + 1) = l.take i ++ l[i]?.t
· simp only [take, Option.toList, getElem?_cons_zero, nil_append]
· simp only [take, hl, getElem?_cons_succ, cons_append]
theorem dropLast_eq_take (l : List α) : l.dropLast = l.take (l.length - 1) := by
theorem dropLast_eq_take {l : List α} : l.dropLast = l.take (l.length - 1) := by
cases l with
| nil => simp [dropLast]
| cons x l =>
induction l generalizing x <;> simp_all [dropLast]
@[simp] theorem map_take (f : α β) :
(l : List α) (i : Nat), (l.take i).map f = (l.map f).take i
@[simp] theorem map_take {f : α β} :
{l : List α} {i : Nat}, (l.take i).map f = (l.map f).take i
| [], i => by simp
| _, 0 => by simp
| _ :: tl, n + 1 => by dsimp; rw [map_take f tl n]
| _ :: tl, n + 1 => by dsimp; rw [map_take]
@[simp] theorem map_drop (f : α β) :
(l : List α) (i : Nat), (l.drop i).map f = (l.map f).drop i
@[simp] theorem map_drop {f : α β} :
{l : List α} {i : Nat}, (l.drop i).map f = (l.map f).drop i
| [], i => by simp
| l, 0 => by simp
| _ :: tl, n + 1 => by
dsimp
rw [map_drop f tl]
rw [map_drop]
/-! ### takeWhile and dropWhile -/
theorem takeWhile_cons (p : α Bool) (a : α) (l : List α) :
theorem takeWhile_cons {p : α Bool} {a : α} {l : List α} :
(a :: l).takeWhile p = if p a then a :: l.takeWhile p else [] := by
simp only [takeWhile]
by_cases h: p a <;> simp [h]
@@ -275,14 +278,14 @@ theorem dropWhile_cons :
(a :: l).dropWhile p = a :: l := by
simp [dropWhile_cons, h]
theorem head?_takeWhile (p : α Bool) (l : List α) : (l.takeWhile p).head? = l.head?.filter p := by
theorem head?_takeWhile {p : α Bool} {l : List α} : (l.takeWhile p).head? = l.head?.filter p := by
cases l with
| nil => rfl
| cons x xs =>
simp only [takeWhile_cons, head?_cons, Option.filter_some]
split <;> simp
theorem head_takeWhile (p : α Bool) (l : List α) (w) :
theorem head_takeWhile {p : α Bool} {l : List α} (w) :
(l.takeWhile p).head w = l.head (by rintro rfl; simp_all) := by
cases l with
| nil => rfl
@@ -299,11 +302,12 @@ theorem head?_dropWhile_not (p : α → Bool) (l : List α) :
simp only [dropWhile_cons]
split <;> rename_i h <;> split at h <;> simp_all
theorem head_dropWhile_not (p : α Bool) (l : List α) (w) :
-- The argument `p` is explicit, as otherwise the head of the left hand side may be a metavariable.
theorem head_dropWhile_not (p : α Bool) {l : List α} (w) :
p ((l.dropWhile p).head w) = false := by
simpa [head?_eq_head, w] using head?_dropWhile_not p l
theorem takeWhile_map (f : α β) (p : β Bool) (l : List α) :
theorem takeWhile_map {f : α β} {p : β Bool} {l : List α} :
(l.map f).takeWhile p = (l.takeWhile (p f)).map f := by
induction l with
| nil => rfl
@@ -311,7 +315,7 @@ theorem takeWhile_map (f : α → β) (p : β → Bool) (l : List α) :
simp only [map_cons, takeWhile_cons]
split <;> simp_all
theorem dropWhile_map (f : α β) (p : β Bool) (l : List α) :
theorem dropWhile_map {f : α β} {p : β Bool} {l : List α} :
(l.map f).dropWhile p = (l.dropWhile (p f)).map f := by
induction l with
| nil => rfl
@@ -319,7 +323,7 @@ theorem dropWhile_map (f : α → β) (p : β → Bool) (l : List α) :
simp only [map_cons, dropWhile_cons]
split <;> simp_all
theorem takeWhile_filterMap (f : α Option β) (p : β Bool) (l : List α) :
theorem takeWhile_filterMap {f : α Option β} {p : β Bool} {l : List α} :
(l.filterMap f).takeWhile p = (l.takeWhile fun a => (f a).all p).filterMap f := by
induction l with
| nil => rfl
@@ -331,7 +335,7 @@ theorem takeWhile_filterMap (f : α → Option β) (p : β → Bool) (l : List
· simp [takeWhile_cons, h, ih]
split <;> simp_all [filterMap_cons]
theorem dropWhile_filterMap (f : α Option β) (p : β Bool) (l : List α) :
theorem dropWhile_filterMap {f : α Option β} {p : β Bool} {l : List α} :
(l.filterMap f).dropWhile p = (l.dropWhile fun a => (f a).all p).filterMap f := by
induction l with
| nil => rfl
@@ -343,18 +347,18 @@ theorem dropWhile_filterMap (f : α → Option β) (p : β → Bool) (l : List
· simp [dropWhile_cons, h, ih]
split <;> simp_all [filterMap_cons]
theorem takeWhile_filter (p q : α Bool) (l : List α) :
theorem takeWhile_filter {p q : α Bool} {l : List α} :
(l.filter p).takeWhile q = (l.takeWhile fun a => !p a || q a).filter p := by
simp [ filterMap_eq_filter, takeWhile_filterMap]
theorem dropWhile_filter (p q : α Bool) (l : List α) :
theorem dropWhile_filter {p q : α Bool} {l : List α} :
(l.filter p).dropWhile q = (l.dropWhile fun a => !p a || q a).filter p := by
simp [ filterMap_eq_filter, dropWhile_filterMap]
@[simp] theorem takeWhile_append_dropWhile (p : α Bool) :
(l : List α), takeWhile p l ++ dropWhile p l = l
@[simp] theorem takeWhile_append_dropWhile {p : α Bool} :
{l : List α}, takeWhile p l ++ dropWhile p l = l
| [] => rfl
| x :: xs => by simp [takeWhile, dropWhile]; cases p x <;> simp [takeWhile_append_dropWhile p xs]
| x :: xs => by simp [takeWhile, dropWhile]; cases p x <;> simp [takeWhile_append_dropWhile]
theorem takeWhile_append {xs ys : List α} :
(xs ++ ys).takeWhile p =
@@ -389,7 +393,7 @@ theorem dropWhile_append {xs ys : List α} :
| nil => simp
| cons x xs ih => simp_all [dropWhile_cons]
@[simp] theorem takeWhile_replicate_eq_filter (p : α Bool) :
@[simp] theorem takeWhile_replicate_eq_filter {p : α Bool} :
(replicate n a).takeWhile p = (replicate n a).filter p := by
induction n with
| zero => simp
@@ -397,11 +401,11 @@ theorem dropWhile_append {xs ys : List α} :
simp only [replicate_succ, takeWhile_cons]
split <;> simp_all
theorem takeWhile_replicate (p : α Bool) :
theorem takeWhile_replicate {p : α Bool} :
(replicate n a).takeWhile p = if p a then replicate n a else [] := by
rw [takeWhile_replicate_eq_filter, filter_replicate]
@[simp] theorem dropWhile_replicate_eq_filter_not (p : α Bool) :
@[simp] theorem dropWhile_replicate_eq_filter_not {p : α Bool} :
(replicate n a).dropWhile p = (replicate n a).filter (fun a => !p a) := by
induction n with
| zero => simp
@@ -409,12 +413,12 @@ theorem takeWhile_replicate (p : α → Bool) :
simp only [replicate_succ, dropWhile_cons]
split <;> simp_all
theorem dropWhile_replicate (p : α Bool) :
theorem dropWhile_replicate {p : α Bool} :
(replicate n a).dropWhile p = if p a then [] else replicate n a := by
simp only [dropWhile_replicate_eq_filter_not, filter_replicate]
split <;> simp_all
theorem take_takeWhile {l : List α} (p : α Bool) i :
theorem take_takeWhile {l : List α} {p : α Bool} :
(l.takeWhile p).take i = (l.take i).takeWhile p := by
induction l generalizing i with
| nil => simp
@@ -446,13 +450,13 @@ theorem replace_takeWhile [BEq α] [LawfulBEq α] {l : List α} {p : α → Bool
/-! ### splitAt -/
@[simp] theorem splitAt_eq (i : Nat) (l : List α) : splitAt i l = (l.take i, l.drop i) := by
@[simp] theorem splitAt_eq {i : Nat} {l : List α} : splitAt i l = (l.take i, l.drop i) := by
rw [splitAt, splitAt_go, reverse_nil, nil_append]
split <;> simp_all [take_of_length_le, drop_of_length_le]
/-! ### rotateLeft -/
@[simp] theorem rotateLeft_zero (l : List α) : rotateLeft l 0 = l := by
@[simp] theorem rotateLeft_zero {l : List α} : rotateLeft l 0 = l := by
simp [rotateLeft]
-- TODO Batteries defines its own `getElem?_rotate`, which we need to adapt.
@@ -460,7 +464,7 @@ theorem replace_takeWhile [BEq α] [LawfulBEq α] {l : List α} {p : α → Bool
/-! ### rotateRight -/
@[simp] theorem rotateRight_zero (l : List α) : rotateRight l 0 = l := by
@[simp] theorem rotateRight_zero {l : List α} : rotateRight l 0 = l := by
simp [rotateRight]
-- TODO Batteries defines its own `getElem?_rotate`, which we need to adapt.

View File

@@ -619,15 +619,15 @@ private theorem insertIdx_loop_toArray (i : Nat) (l : List α) (j : Nat) (hj : j
simp only [append_assoc, cons_append]
rw [insertIdx_loop_toArray _ _ _ _ (by omega)]
simp only [swap_toArray, w, append_assoc, cons_append, mk.injEq]
rw [take_set_of_le _ _ (by omega), drop_eq_getElem_cons (i := j) (by simpa), getElem_set_self,
drop_set_of_lt _ _ (by omega), drop_set_of_lt _ _ (by omega), getElem_set_ne (by omega),
getElem_set_self, take_set_of_le (j := j - 1) _ _ (by omega),
take_set_of_le (j := j - 1) _ _ (by omega), take_eq_append_getElem_of_pos (by omega) hj,
rw [take_set_of_le (by omega), drop_eq_getElem_cons (i := j) (by simpa), getElem_set_self,
drop_set_of_lt (by omega), drop_set_of_lt (by omega), getElem_set_ne (by omega),
getElem_set_self, take_set_of_le (j := j - 1) (by omega),
take_set_of_le (j := j - 1) (by omega), take_eq_append_getElem_of_pos (by omega) hj,
drop_append_of_le_length (by simp; omega)]
simp only [append_assoc, cons_append, nil_append, append_cancel_right_eq]
cases i with
| zero => simp
| succ i => rw [take_set_of_le _ _ (by omega)]
| succ i => rw [take_set_of_le (by omega)]
· simp only [Nat.not_lt] at h'
have : i = j := by omega
subst this

View File

@@ -22,21 +22,21 @@ open Nat
/-! ### zipWith -/
theorem zipWith_comm (f : α β γ) :
(as : List α) (bs : List β), zipWith f as bs = zipWith (fun b a => f a b) bs as
theorem zipWith_comm {f : α β γ} :
{as : List α} {bs : List β}, zipWith f as bs = zipWith (fun b a => f a b) bs as
| [], _ => List.zipWith_nil_right.symm
| _ :: _, [] => rfl
| _ :: as, _ :: bs => congrArg _ (zipWith_comm f as bs)
| _ :: _, _ :: _ => congrArg _ zipWith_comm
theorem zipWith_comm_of_comm (f : α α β) (comm : x y : α, f x y = f y x) (l l' : List α) :
theorem zipWith_comm_of_comm {f : α α β} (comm : x y : α, f x y = f y x) {l l' : List α} :
zipWith f l l' = zipWith f l' l := by
rw [zipWith_comm]
simp only [comm]
@[simp]
theorem zipWith_self (f : α α δ) : l : List α, zipWith f l l = l.map fun a => f a a
theorem zipWith_self {f : α α δ} : {l : List α}, zipWith f l l = l.map fun a => f a a
| [] => rfl
| _ :: xs => congrArg _ (zipWith_self f xs)
| _ :: _ => congrArg _ zipWith_self
@[deprecated zipWith_self (since := "2025-01-29")] abbrev zipWith_same := @zipWith_self
@@ -92,23 +92,23 @@ theorem head_zipWith {f : α → β → γ} (h):
rw [ head?_eq_head, head?_zipWith, head?_eq_head, head?_eq_head]
@[simp]
theorem zipWith_map {μ} (f : γ δ μ) (g : α γ) (h : β δ) (l₁ : List α) (l₂ : List β) :
theorem zipWith_map {μ} {f : γ δ μ} {g : α γ} {h : β δ} {l₁ : List α} {l₂ : List β} :
zipWith f (l₁.map g) (l₂.map h) = zipWith (fun a b => f (g a) (h b)) l₁ l₂ := by
induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all
theorem zipWith_map_left (l₁ : List α) (l₂ : List β) (f : α α') (g : α' β γ) :
theorem zipWith_map_left {l₁ : List α} {l₂ : List β} {f : α α'} {g : α' β γ} :
zipWith g (l₁.map f) l₂ = zipWith (fun a b => g (f a) b) l₁ l₂ := by
induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all
theorem zipWith_map_right (l₁ : List α) (l₂ : List β) (f : β β') (g : α β' γ) :
theorem zipWith_map_right {l₁ : List α} {l₂ : List β} {f : β β'} {g : α β' γ} :
zipWith g l₁ (l₂.map f) = zipWith (fun a b => g a (f b)) l₁ l₂ := by
induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all
theorem zipWith_foldr_eq_zip_foldr {f : α β γ} (i : δ):
theorem zipWith_foldr_eq_zip_foldr {f : α β γ} {i : δ} {g : γ δ δ} :
(zipWith f l₁ l₂).foldr g i = (zip l₁ l₂).foldr (fun p r => g (f p.1 p.2) r) i := by
induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all
theorem zipWith_foldl_eq_zip_foldl {f : α β γ} (i : δ):
theorem zipWith_foldl_eq_zip_foldl {f : α β γ} {i : δ} {g : δ γ δ} :
(zipWith f l₁ l₂).foldl g i = (zip l₁ l₂).foldl (fun r p => g r (f p.1 p.2)) i := by
induction l₁ generalizing i l₂ <;> cases l₂ <;> simp_all
@@ -116,7 +116,7 @@ theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} (i : δ):
theorem zipWith_eq_nil_iff {f : α β γ} {l l'} : zipWith f l l' = [] l = [] l' = [] := by
cases l <;> cases l' <;> simp
theorem map_zipWith {δ : Type _} (f : α β) (g : γ δ α) (l : List γ) (l' : List δ) :
theorem map_zipWith {δ : Type _} {f : α β} {g : γ δ α} {l : List γ} {l' : List δ} :
map f (zipWith g l l') = zipWith (fun x y => f (g x y)) l l' := by
induction l generalizing l' with
| nil => simp
@@ -149,7 +149,7 @@ theorem drop_zipWith : (zipWith f l l').drop i = zipWith f (l.drop i) (l'.drop i
theorem tail_zipWith : (zipWith f l l').tail = zipWith f l.tail l'.tail := by
rw [ drop_one]; simp [drop_zipWith]
theorem zipWith_append (f : α β γ) (l₁ l₁' : List α) (l₂ l₂' : List β)
theorem zipWith_append {f : α β γ} {l₁ l₁' : List α} {l₂ l₂' : List β}
(h : l₁.length = l₂.length) :
zipWith f (l₁ ++ l₁') (l₂ ++ l₂') = zipWith f l₁ l₂ ++ zipWith f l₁' l₂' := by
induction l₁ generalizing l₂ with
@@ -161,7 +161,7 @@ theorem zipWith_append (f : α → β → γ) (l₁ l₁' : List α) (l₂ l₂'
| nil => simp at h
| cons _ _ =>
simp only [length_cons, Nat.succ.injEq] at h
simp [ih _ h]
simp [ih h]
theorem zipWith_eq_cons_iff {f : α β γ} {l₁ : List α} {l₂ : List β} :
zipWith f l₁ l₂ = g :: l
@@ -229,7 +229,7 @@ theorem zipWith_eq_append_iff {f : α → β → γ} {l₁ : List α} {l₂ : Li
| zero => rfl
| succ n ih => simp [replicate_succ, ih]
theorem map_uncurry_zip_eq_zipWith (f : α β γ) (l : List α) (l' : List β) :
theorem map_uncurry_zip_eq_zipWith {f : α β γ} {l : List α} {l' : List β} :
map (Function.uncurry f) (l.zip l') = zipWith f l l' := by
rw [zip]
induction l generalizing l' with
@@ -237,7 +237,7 @@ theorem map_uncurry_zip_eq_zipWith (f : α → β → γ) (l : List α) (l' : Li
| cons hl tl ih =>
cases l' <;> simp [ih]
theorem map_zip_eq_zipWith (f : α × β γ) (l : List α) (l' : List β) :
theorem map_zip_eq_zipWith {f : α × β γ} {l : List α} {l' : List β} :
map f (l.zip l') = zipWith (Function.curry f) l l' := by
rw [zip]
induction l generalizing l' with
@@ -247,24 +247,24 @@ theorem map_zip_eq_zipWith (f : α × β → γ) (l : List α) (l' : List β) :
/-! ### zip -/
theorem zip_eq_zipWith : (l₁ : List α) (l₂ : List β), zip l₁ l₂ = zipWith Prod.mk l₁ l₂
theorem zip_eq_zipWith : {l₁ : List α} {l₂ : List β}, zip l₁ l₂ = zipWith Prod.mk l₁ l₂
| [], _ => rfl
| _, [] => rfl
| a :: l₁, b :: l₂ => by simp [zip_cons_cons, zip_eq_zipWith l₁ l₂]
| a :: l₁, b :: l₂ => by simp [zip_cons_cons, zip_eq_zipWith (l₁ := l₁)]
theorem zip_map (f : α γ) (g : β δ) :
(l₁ : List α) (l₂ : List β), zip (l₁.map f) (l₂.map g) = (zip l₁ l₂).map (Prod.map f g)
theorem zip_map {f : α γ} {g : β δ} :
{l₁ : List α} {l₂ : List β}, zip (l₁.map f) (l₂.map g) = (zip l₁ l₂).map (Prod.map f g)
| [], _ => rfl
| _, [] => by simp only [map, zip_nil_right]
| _ :: _, _ :: _ => by simp only [map, zip_cons_cons, zip_map, Prod.map]
theorem zip_map_left (f : α γ) (l₁ : List α) (l₂ : List β) :
theorem zip_map_left {f : α γ} {l₁ : List α} {l₂ : List β} :
zip (l₁.map f) l₂ = (zip l₁ l₂).map (Prod.map f id) := by rw [ zip_map, map_id]
theorem zip_map_right (f : β γ) (l₁ : List α) (l₂ : List β) :
theorem zip_map_right {f : β γ} {l₁ : List α} {l₂ : List β} :
zip l₁ (l₂.map f) = (zip l₁ l₂).map (Prod.map id f) := by rw [ zip_map, map_id]
@[simp] theorem tail_zip (l₁ : List α) (l₂ : List β) :
@[simp] theorem tail_zip {l₁ : List α} {l₂ : List β} :
(zip l₁ l₂).tail = zip l₁.tail l₂.tail := by
cases l₁ <;> cases l₂ <;> simp
@@ -276,8 +276,8 @@ theorem zip_append :
| _ :: _, _, _ :: _, _, h => by
simp only [cons_append, zip_cons_cons, zip_append (Nat.succ.inj h)]
theorem zip_map' (f : α β) (g : α γ) :
l : List α, zip (l.map f) (l.map g) = l.map fun a => (f a, g a)
theorem zip_map' {f : α β} {g : α γ} :
{l : List α}, zip (l.map f) (l.map g) = l.map fun a => (f a, g a)
| [] => rfl
| a :: l => by simp only [map, zip_cons_cons, zip_map']
@@ -290,16 +290,16 @@ theorem of_mem_zip {a b} : ∀ {l₁ : List α} {l₂ : List β}, (a, b) ∈ zip
exact Mem.tail _ this.1, Mem.tail _ this.2
theorem map_fst_zip :
(l₁ : List α) (l₂ : List β), l₁.length l₂.length map Prod.fst (zip l₁ l₂) = l₁
{l₁ : List α} {l₂ : List β}, l₁.length l₂.length map Prod.fst (zip l₁ l₂) = l₁
| [], _, _ => rfl
| _ :: as, _ :: bs, h => by
simp [Nat.succ_le_succ_iff] at h
show _ :: map Prod.fst (zip as bs) = _ :: as
rw [map_fst_zip as bs h]
rw [map_fst_zip (l₁ := as) h]
| _ :: _, [], h => by simp at h
theorem map_snd_zip :
(l₁ : List α) (l₂ : List β), l₂.length l₁.length map Prod.snd (zip l₁ l₂) = l₂
{l₁ : List α} {l₂ : List β}, l₂.length l₁.length map Prod.snd (zip l₁ l₂) = l₂
| _, [], _ => by
rw [zip_nil_right]
rfl
@@ -307,15 +307,15 @@ theorem map_snd_zip :
| a :: as, b :: bs, h => by
simp [Nat.succ_le_succ_iff] at h
show _ :: map Prod.snd (zip as bs) = _ :: bs
rw [map_snd_zip as bs h]
rw [map_snd_zip (l₂ := bs) h]
theorem map_prod_left_eq_zip {l : List α} (f : α β) :
theorem map_prod_left_eq_zip {l : List α} {f : α β} :
(l.map fun x => (x, f x)) = l.zip (l.map f) := by
rw [ zip_map']
congr
simp
theorem map_prod_right_eq_zip {l : List α} (f : α β) :
theorem map_prod_right_eq_zip {l : List α} {f : α β} :
(l.map fun x => (f x, x)) = (l.map f).zip l := by
rw [ zip_map']
congr
@@ -379,19 +379,19 @@ theorem head?_zipWithAll {f : Option α → Option β → γ} :
(zipWithAll f as bs).tail = zipWithAll f as.tail bs.tail := by
cases as <;> cases bs <;> simp
theorem zipWithAll_map {μ} (f : Option γ Option δ μ) (g : α γ) (h : β δ) (l₁ : List α) (l₂ : List β) :
theorem zipWithAll_map {μ} {f : Option γ Option δ μ} {g : α γ} {h : β δ} {l₁ : List α} {l₂ : List β} :
zipWithAll f (l₁.map g) (l₂.map h) = zipWithAll (fun a b => f (g <$> a) (h <$> b)) l₁ l₂ := by
induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all
theorem zipWithAll_map_left (l₁ : List α) (l₂ : List β) (f : α α') (g : Option α' Option β γ) :
theorem zipWithAll_map_left {l₁ : List α} {l₂ : List β} {f : α α'} {g : Option α' Option β γ} :
zipWithAll g (l₁.map f) l₂ = zipWithAll (fun a b => g (f <$> a) b) l₁ l₂ := by
induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all
theorem zipWithAll_map_right (l₁ : List α) (l₂ : List β) (f : β β') (g : Option α Option β' γ) :
theorem zipWithAll_map_right {l₁ : List α} {l₂ : List β} {f : β β'} {g : Option α Option β' γ} :
zipWithAll g l₁ (l₂.map f) = zipWithAll (fun a b => g a (f <$> b)) l₁ l₂ := by
induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all
theorem map_zipWithAll {δ : Type _} (f : α β) (g : Option γ Option δ α) (l : List γ) (l' : List δ) :
theorem map_zipWithAll {δ : Type _} {f : α β} {g : Option γ Option δ α} {l : List γ} {l' : List δ} :
map f (zipWithAll g l l') = zipWithAll (fun x y => f (g x y)) l l' := by
induction l generalizing l' with
| nil => simp
@@ -412,10 +412,11 @@ theorem map_zipWithAll {δ : Type _} (f : α → β) (g : Option γ → Option
@[simp] theorem unzip_snd : (unzip l).snd = l.map Prod.snd := by
induction l <;> simp_all
theorem unzip_eq_map : l : List (α × β), unzip l = (l.map Prod.fst, l.map Prod.snd)
theorem unzip_eq_map : {l : List (α × β)}, unzip l = (l.map Prod.fst, l.map Prod.snd)
| [] => rfl
| (a, b) :: l => by simp only [unzip_cons, map_cons, unzip_eq_map l]
| (a, b) :: l => by simp only [unzip_cons, map_cons, unzip_eq_map (l := l)]
-- The argument `l` is explicit so we can rewrite from right to left.
theorem zip_unzip : l : List (α × β), zip (unzip l).1 (unzip l).2 = l
| [] => rfl
| (a, b) :: l => by simp only [unzip_cons, zip_cons_cons, zip_unzip l]

View File

@@ -89,9 +89,9 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep
intro a m h₁ h₂
congr
@[simp] theorem pmap_empty {P : α Prop} (f : a, P a β) : pmap f #v[] (by simp) = #v[] := rfl
@[simp] theorem pmap_empty {P : α Prop} {f : a, P a β} : pmap f #v[] (by simp) = #v[] := rfl
@[simp] theorem pmap_push {P : α Prop} (f : a, P a β) (a : α) (xs : Vector α n) (h : b xs.push a, P b) :
@[simp] theorem pmap_push {P : α Prop} {f : a, P a β} {a : α} {xs : Vector α n} {h : b xs.push a, P b} :
pmap f (xs.push a) h =
(pmap f xs (fun a m => by simp at h; exact h a (.inl m))).push (f a (h a (by simp))) := by
simp [pmap]
@@ -101,7 +101,7 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep
@[simp] theorem attachWith_empty {P : α Prop} (H : x #v[], P x) : (#v[] : Vector α 0).attachWith P H = #v[] := rfl
@[simp]
theorem pmap_eq_map (p : α Prop) (f : α β) (xs : Vector α n) (H) :
theorem pmap_eq_map {p : α Prop} {f : α β} {xs : Vector α n} (H) :
@pmap _ _ _ p (fun a _ => f a) xs H = map f xs := by
cases xs; simp
@@ -112,13 +112,13 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a,
apply Array.pmap_congr_left
simpa using h
theorem map_pmap {p : α Prop} (g : β γ) (f : a, p a β) (xs : Vector α n) (H) :
theorem map_pmap {p : α Prop} {g : β γ} {f : a, p a β} {xs : Vector α n} (H) :
map g (pmap f xs H) = pmap (fun a h => g (f a h)) xs H := by
rcases xs with xs, rfl
simp [Array.map_pmap]
theorem pmap_map {p : β Prop} (g : b, p b γ) (f : α β) (xs : Vector α n) (H) :
pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem _ h) := by
theorem pmap_map {p : β Prop} {g : b, p b γ} {f : α β} {xs : Vector α n} (H) :
pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem h) := by
rcases xs with xs, rfl
simp [Array.pmap_map]
@@ -144,7 +144,7 @@ theorem attachWith_congr {xs ys : Vector α n} (w : xs = ys) {P : α → Prop} {
rcases xs with xs, rfl
simp
theorem pmap_eq_map_attach {p : α Prop} (f : a, p a β) (xs : Vector α n) (H) :
theorem pmap_eq_map_attach {p : α Prop} {f : a, p a β} {xs : Vector α n} (H) :
pmap f xs H = xs.attach.map fun x => f x.1 (H _ x.2) := by
rcases xs with xs, rfl
simp only [pmap_mk, Array.pmap_eq_map_attach, attach_mk, map_mk, eq_mk]
@@ -152,7 +152,7 @@ theorem pmap_eq_map_attach {p : α → Prop} (f : ∀ a, p a → β) (xs : Vecto
ext i hi₁ hi₂ <;> simp
@[simp]
theorem pmap_eq_attachWith {p q : α Prop} (f : a, p a q a) (xs : Vector α n) (H) :
theorem pmap_eq_attachWith {p q : α Prop} {f : a, p a q a} {xs : Vector α n} (H) :
pmap (fun a h => a, f a h) xs H = xs.attachWith q (fun x h => f x (H x h)) := by
rcases xs with xs, rfl
simp
@@ -165,11 +165,12 @@ theorem attach_map_val (xs : Vector α n) (f : α → β) :
@[deprecated attach_map_val (since := "2025-02-17")]
abbrev attach_map_coe := @attach_map_val
-- The argument `xs : Vector α n` is explicit to allow rewriting from right to left.
theorem attach_map_subtype_val (xs : Vector α n) : xs.attach.map Subtype.val = xs := by
rcases xs with xs, rfl
simp
theorem attachWith_map_val {p : α Prop} (f : α β) (xs : Vector α n) (H : a xs, p a) :
theorem attachWith_map_val {p : α Prop} {f : α β} {xs : Vector α n} (H : a xs, p a) :
((xs.attachWith p H).map fun (i : { i // p i}) => f i) = xs.map f := by
rcases xs with xs, rfl
simp
@@ -177,7 +178,7 @@ theorem attachWith_map_val {p : α → Prop} (f : α → β) (xs : Vector α n)
@[deprecated attachWith_map_val (since := "2025-02-17")]
abbrev attachWith_map_coe := @attachWith_map_val
theorem attachWith_map_subtype_val {p : α Prop} (xs : Vector α n) (H : a xs, p a) :
theorem attachWith_map_subtype_val {p : α Prop} {xs : Vector α n} (H : a xs, p a) :
(xs.attachWith p H).map Subtype.val = xs := by
rcases xs with xs, rfl
simp
@@ -190,7 +191,7 @@ theorem mem_attach (xs : Vector α n) : ∀ x, x ∈ xs.attach
exact m
@[simp]
theorem mem_attachWith (xs : Vector α n) {q : α Prop} (H) (x : {x // q x}) :
theorem mem_attachWith {xs : Vector α n} {q : α Prop} (H) (x : {x // q x}) :
x xs.attachWith q H x.1 xs := by
rcases xs with xs, rfl
simp
@@ -211,11 +212,12 @@ theorem pmap_eq_self {xs : Vector α n} {p : α → Prop} {hp : ∀ (a : α), a
simp [Array.pmap_eq_self]
@[simp]
theorem getElem?_pmap {p : α Prop} (f : a, p a β) {xs : Vector α n} (h : a xs, p a) (i : Nat) :
theorem getElem?_pmap {p : α Prop} {f : a, p a β} {xs : Vector α n} (h : a xs, p a) (i : Nat) :
(pmap f xs h)[i]? = Option.pmap f xs[i]? fun x H => h x (mem_of_getElem? H) := by
rcases xs with xs, rfl
simp
-- The argument `f` is explicit to allow rewriting from right to left.
@[simp]
theorem getElem_pmap {p : α Prop} (f : a, p a β) {xs : Vector α n} (h : a xs, p a) {i : Nat}
(hn : i < n) :
@@ -244,26 +246,26 @@ theorem getElem_attach {xs : Vector α n} {i : Nat} (h : i < n) :
xs.attach[i] = xs[i]'(by simpa using h), getElem_mem (by simpa using h) :=
getElem_attachWith h
@[simp] theorem pmap_attach (xs : Vector α n) {p : {x // x xs} Prop} (f : a, p a β) (H) :
@[simp] theorem pmap_attach {xs : Vector α n} {p : {x // x xs} Prop} {f : a, p a β} (H) :
pmap f xs.attach H =
xs.pmap (P := fun a => h : a xs, p a, h)
(fun a h => f a, h.1 h.2) (fun a h => h, H a, h (by simp)) := by
rcases xs with xs, rfl
ext <;> simp
@[simp] theorem pmap_attachWith (xs : Vector α n) {p : {x // q x} Prop} (f : a, p a β) (H₁ H₂) :
@[simp] theorem pmap_attachWith {xs : Vector α n} {p : {x // q x} Prop} {f : a, p a β} (H₁ H₂) :
pmap f (xs.attachWith q H₁) H₂ =
xs.pmap (P := fun a => h : q a, p a, h)
(fun a h => f a, h.1 h.2) (fun a h => H₁ _ h, H₂ a, H₁ _ h (by simpa)) := by
ext <;> simp
theorem foldl_pmap (xs : Vector α n) {P : α Prop} (f : (a : α) P a β)
(H : (a : α), a xs P a) (g : γ β γ) (x : γ) :
theorem foldl_pmap {xs : Vector α n} {P : α Prop} {f : (a : α) P a β}
(H : (a : α), a xs P a) (g : γ β γ) (x : γ) :
(xs.pmap f H).foldl g x = xs.attach.foldl (fun acc a => g acc (f a.1 (H _ a.2))) x := by
rw [pmap_eq_map_attach, foldl_map]
theorem foldr_pmap (xs : Vector α n) {P : α Prop} (f : (a : α) P a β)
(H : (a : α), a xs P a) (g : β γ γ) (x : γ) :
theorem foldr_pmap {xs : Vector α n} {P : α Prop} {f : (a : α) P a β}
(H : (a : α), a xs P a) (g : β γ γ) (x : γ) :
(xs.pmap f H).foldr g x = xs.attach.foldr (fun a acc => g (f a.1 (H _ a.2)) acc) x := by
rw [pmap_eq_map_attach, foldr_map]
@@ -277,7 +279,7 @@ Unfortunately this can't be applied by `simp` because of the higher order unific
and even when rewriting we need to specify the function explicitly.
See however `foldl_subtype` below.
-/
theorem foldl_attach (xs : Vector α n) (f : β α β) (b : β) :
theorem foldl_attach {xs : Vector α n} {f : β α β} {b : β} :
xs.attach.foldl (fun acc t => f acc t.1) b = xs.foldl f b := by
rcases xs with xs, rfl
simp [Array.foldl_attach]
@@ -292,37 +294,37 @@ Unfortunately this can't be applied by `simp` because of the higher order unific
and even when rewriting we need to specify the function explicitly.
See however `foldr_subtype` below.
-/
theorem foldr_attach (xs : Vector α n) (f : α β β) (b : β) :
theorem foldr_attach {xs : Vector α n} {f : α β β} {b : β} :
xs.attach.foldr (fun t acc => f t.1 acc) b = xs.foldr f b := by
rcases xs with xs, rfl
simp [Array.foldr_attach]
theorem attach_map {xs : Vector α n} (f : α β) :
(xs.map f).attach = xs.attach.map (fun x, h => f x, mem_map_of_mem f h) := by
theorem attach_map {xs : Vector α n} {f : α β} :
(xs.map f).attach = xs.attach.map (fun x, h => f x, mem_map_of_mem h) := by
cases xs
ext <;> simp
theorem attachWith_map {xs : Vector α n} (f : α β) {P : β Prop} {H : (b : β), b xs.map f P b} :
(xs.map f).attachWith P H = (xs.attachWith (P f) (fun _ h => H _ (mem_map_of_mem f h))).map
theorem attachWith_map {xs : Vector α n} {f : α β} {P : β Prop} (H : (b : β), b xs.map f P b) :
(xs.map f).attachWith P H = (xs.attachWith (P f) (fun _ h => H _ (mem_map_of_mem h))).map
fun x, h => f x, h := by
rcases xs with xs, rfl
simp [Array.attachWith_map]
@[simp] theorem map_attachWith {xs : Vector α n} {P : α Prop} {H : (a : α), a xs P a}
(f : { x // P x } β) :
{f : { x // P x } β} :
(xs.attachWith P H).map f = xs.attach.map fun x, h => f x, H _ h := by
rcases xs with xs, rfl
simp [Array.map_attachWith]
theorem map_attachWith_eq_pmap {xs : Vector α n} {P : α Prop} {H : (a : α), a xs P a}
(f : { x // P x } β) :
{f : { x // P x } β} :
(xs.attachWith P H).map f =
xs.pmap (fun a (h : a xs P a) => f a, H _ h.1) (fun a h => h, H a h) := by
rcases xs with xs, rfl
ext <;> simp
/-- See also `pmap_eq_map_attach` for writing `pmap` in terms of `map` and `attach`. -/
theorem map_attach_eq_pmap {xs : Vector α n} (f : { x // x xs } β) :
theorem map_attach_eq_pmap {xs : Vector α n} {f : { x // x xs } β} :
xs.attach.map f = xs.pmap (fun a h => f a, h) (fun _ => id) := by
rcases xs with xs, rfl
ext <;> simp
@@ -330,14 +332,14 @@ theorem map_attach_eq_pmap {xs : Vector α n} (f : { x // x ∈ xs } → β) :
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
abbrev map_attach := @map_attach_eq_pmap
theorem pmap_pmap {p : α Prop} {q : β Prop} (g : a, p a β) (f : b, q b γ) (xs : Vector α n) (H₁ H₂) :
theorem pmap_pmap {p : α Prop} {q : β Prop} {g : a, p a β} {f : b, q b γ} {xs : Vector α n} (H₁ H₂) :
pmap f (pmap g xs H₁) H₂ =
pmap (α := { x // x xs }) (fun a h => f (g a h) (H₂ (g a h) (mem_pmap_of_mem a.2))) xs.attach
(fun a _ => H₁ a a.2) := by
rcases xs with xs, rfl
ext <;> simp
@[simp] theorem pmap_append {p : ι Prop} (f : a : ι, p a α) (xs : Vector ι n) (ys : Vector ι m)
@[simp] theorem pmap_append {p : ι Prop} {f : a : ι, p a α} {xs : Vector ι n} {ys : Vector ι m}
(h : a xs ++ ys, p a) :
(xs ++ ys).pmap f h =
(xs.pmap f fun a ha => h a (mem_append_left ys ha)) ++
@@ -346,13 +348,13 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f
cases ys
simp
theorem pmap_append' {p : α Prop} (f : a : α, p a β) (xs : Vector α n) (ys : Vector α m)
theorem pmap_append' {p : α Prop} {f : a : α, p a β} {xs : Vector α n} {ys : Vector α m}
(h₁ : a xs, p a) (h₂ : a ys, p a) :
((xs ++ ys).pmap f fun a ha => (mem_append.1 ha).elim (h₁ a) (h₂ a)) =
xs.pmap f h₁ ++ ys.pmap f h₂ :=
pmap_append f xs ys _
pmap_append _
@[simp] theorem attach_append (xs : Vector α n) (ys : Vector α m) :
@[simp] theorem attach_append {xs : Vector α n} {ys : Vector α m} :
(xs ++ ys).attach = xs.attach.map (fun x, h => (x, mem_append_left ys h : { x // x xs ++ ys })) ++
ys.attach.map (fun y, h => (y, mem_append_right xs h : { y // y xs ++ ys })) := by
rcases xs with xs, rfl
@@ -365,12 +367,12 @@ theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (xs : Vector
ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by
simp [attachWith, attach_append, map_pmap, pmap_append]
@[simp] theorem pmap_reverse {P : α Prop} (f : (a : α) P a β) (xs : Vector α n)
@[simp] theorem pmap_reverse {P : α Prop} {f : (a : α) P a β} {xs : Vector α n}
(H : (a : α), a xs.reverse P a) :
xs.reverse.pmap f H = (xs.pmap f (fun a h => H a (by simpa using h))).reverse := by
induction xs <;> simp_all
theorem reverse_pmap {P : α Prop} (f : (a : α) P a β) (xs : Vector α n)
theorem reverse_pmap {P : α Prop} {f : (a : α) P a β} {xs : Vector α n}
(H : (a : α), a xs P a) :
(xs.pmap f H).reverse = xs.reverse.pmap f (fun a h => H a (by simpa using h)) := by
rw [pmap_reverse]
@@ -388,18 +390,18 @@ theorem reverse_attachWith {P : α → Prop} {xs : Vector α n}
cases xs
simp
@[simp] theorem attach_reverse (xs : Vector α n) :
@[simp] theorem attach_reverse {xs : Vector α n} :
xs.reverse.attach = xs.attach.reverse.map fun x, h => x, by simpa using h := by
cases xs
rw [attach_congr (reverse_mk ..)]
simp [Array.map_attachWith]
theorem reverse_attach (xs : Vector α n) :
theorem reverse_attach {xs : Vector α n} :
xs.attach.reverse = xs.reverse.attach.map fun x, h => x, by simpa using h := by
cases xs
simp [Array.map_attach_eq_pmap]
@[simp] theorem back?_pmap {P : α Prop} (f : (a : α) P a β) (xs : Vector α n)
@[simp] theorem back?_pmap {P : α Prop} {f : (a : α) P a β} {xs : Vector α n}
(H : (a : α), a xs P a) :
(xs.pmap f H).back? = xs.attach.back?.map fun a, m => f a (H a m) := by
cases xs
@@ -418,30 +420,30 @@ theorem back?_attach {xs : Vector α n} :
simp
@[simp]
theorem countP_attach (xs : Vector α n) (p : α Bool) :
theorem countP_attach {xs : Vector α n} {p : α Bool} :
xs.attach.countP (fun a : {x // x xs} => p a) = xs.countP p := by
cases xs
simp [Function.comp_def]
@[simp]
theorem countP_attachWith {p : α Prop} (xs : Vector α n) (H : a xs, p a) (q : α Bool) :
theorem countP_attachWith {p : α Prop} {q : α Bool} {xs : Vector α n} {H : a xs, p a} :
(xs.attachWith p H).countP (fun a : {x // p x} => q a) = xs.countP q := by
cases xs
simp
@[simp]
theorem count_attach [DecidableEq α] (xs : Vector α n) (a : {x // x xs}) :
theorem count_attach [DecidableEq α] {xs : Vector α n} {a : {x // x xs}} :
xs.attach.count a = xs.count a := by
rcases xs with xs, rfl
simp
@[simp]
theorem count_attachWith [DecidableEq α] {p : α Prop} (xs : Vector α n) (H : a xs, p a) (a : {x // p x}) :
theorem count_attachWith [DecidableEq α] {p : α Prop} {xs : Vector α n} (H : a xs, p a) {a : {x // p x}} :
(xs.attachWith p H).count a = xs.count a := by
cases xs
simp
@[simp] theorem countP_pmap {p : α Prop} (g : a, p a β) (f : β Bool) (xs : Vector α n) (H₁) :
@[simp] theorem countP_pmap {p : α Prop} {g : a, p a β} {f : β Bool} {xs : Vector α n} (H₁) :
(xs.pmap g H₁).countP f =
xs.attach.countP (fun a, m => f (g a (H₁ a m))) := by
rcases xs with xs, rfl

View File

@@ -21,26 +21,26 @@ open Nat
/-! ### countP -/
section countP
variable (p q : α Bool)
variable {p q : α Bool}
@[simp] theorem countP_empty : countP p #v[] = 0 := rfl
@[simp] theorem countP_push_of_pos (xs : Vector α n) (pa : p a) : countP p (xs.push a) = countP p xs + 1 := by
@[simp] theorem countP_push_of_pos {xs : Vector α n} (pa : p a) : countP p (xs.push a) = countP p xs + 1 := by
rcases xs with xs, rfl
simp_all
@[simp] theorem countP_push_of_neg (xs : Vector α n) (pa : ¬p a) : countP p (xs.push a) = countP p xs := by
@[simp] theorem countP_push_of_neg {xs : Vector α n} (pa : ¬p a) : countP p (xs.push a) = countP p xs := by
rcases xs with xs, rfl
simp_all
theorem countP_push (a : α) (xs : Vector α n) : countP p (xs.push a) = countP p xs + if p a then 1 else 0 := by
theorem countP_push {a : α} {xs : Vector α n} : countP p (xs.push a) = countP p xs + if p a then 1 else 0 := by
rcases xs with xs, rfl
simp [Array.countP_push]
@[simp] theorem countP_singleton (a : α) : countP p #v[a] = if p a then 1 else 0 := by
@[simp] theorem countP_singleton {a : α} : countP p #v[a] = if p a then 1 else 0 := by
simp [countP_push]
theorem size_eq_countP_add_countP (xs : Vector α n) : n = countP p xs + countP (fun a => ¬p a) xs := by
theorem size_eq_countP_add_countP {xs : Vector α n} : n = countP p xs + countP (fun a => ¬p a) xs := by
rcases xs with xs, rfl
simp [List.length_eq_countP_add_countP (p := p)]
@@ -48,7 +48,7 @@ theorem countP_le_size {xs : Vector α n} : countP p xs ≤ n := by
rcases xs with xs, rfl
simp [Array.countP_le_size (p := p)]
@[simp] theorem countP_append (xs : Vector α n) (ys : Vector α m) : countP p (xs ++ ys) = countP p xs + countP p ys := by
@[simp] theorem countP_append {xs : Vector α n} {ys : Vector α m} : countP p (xs ++ ys) = countP p xs + countP p ys := by
cases xs
cases ys
simp
@@ -72,20 +72,19 @@ theorem countP_le_size {xs : Vector α n} : countP p xs ≤ n := by
rcases xs with xs, rfl
simp
theorem countP_replicate (p : α Bool) (a : α) (n : Nat) :
countP p (replicate n a) = if p a then n else 0 := by
theorem countP_replicate {a : α} {n : Nat} : countP p (replicate n a) = if p a then n else 0 := by
simp only [replicate_eq_mk_replicate, countP_cast, countP_mk]
simp [Array.countP_replicate]
@[deprecated countP_replicate (since := "2025-03-18")]
abbrev countP_mkVector := @countP_replicate
theorem boole_getElem_le_countP (p : α Bool) (xs : Vector α n) (i : Nat) (h : i < n) :
theorem boole_getElem_le_countP {p : α Bool} {xs : Vector α n} (h : i < n) :
(if p xs[i] then 1 else 0) xs.countP p := by
rcases xs with xs, rfl
simp [Array.boole_getElem_le_countP]
theorem countP_set (p : α Bool) (xs : Vector α n) (i : Nat) (a : α) (h : i < n) :
theorem countP_set {p : α Bool} {xs : Vector α n} {a : α} (h : i < n) :
(xs.set i a).countP p = xs.countP p - (if p xs[i] then 1 else 0) + (if p a then 1 else 0) := by
rcases xs with xs, rfl
simp [Array.countP_set, h]
@@ -99,28 +98,25 @@ theorem countP_set (p : α → Bool) (xs : Vector α n) (i : Nat) (a : α) (h :
funext xs
simp
@[simp] theorem countP_map (p : β Bool) (f : α β) (xs : Vector α n) :
@[simp] theorem countP_map {p : β Bool} {f : α β} {xs : Vector α n} :
countP p (map f xs) = countP (p f) xs := by
rcases xs with xs, rfl
simp
set_option linter.listVariables false in -- This can probably be removed later.
@[simp] theorem countP_flatten (xss : Vector (Vector α m) n) :
@[simp] theorem countP_flatten {xss : Vector (Vector α m) n} :
countP p xss.flatten = (xss.map (countP p)).sum := by
rcases xss with xss, rfl
simp [Function.comp_def]
theorem countP_flatMap (p : β Bool) (xs : Vector α n) (f : α Vector β m) :
theorem countP_flatMap {p : β Bool} {xs : Vector α n} {f : α Vector β m} :
countP p (xs.flatMap f) = (map (countP p f) xs).sum := by
rcases xs with xs, rfl
simp [Array.countP_flatMap, Function.comp_def]
@[simp] theorem countP_reverse (xs : Vector α n) : countP p xs.reverse = countP p xs := by
@[simp] theorem countP_reverse {xs : Vector α n} : countP p xs.reverse = countP p xs := by
rcases xs with xs, rfl
simp
variable {p q}
theorem countP_mono_left (h : x xs, p x q x) : countP p xs countP q xs := by
rcases xs with xs, rfl
simpa using Array.countP_mono_left (by simpa using h)
@@ -137,67 +133,66 @@ section count
variable [BEq α]
@[simp] theorem count_empty (a : α) : count a #v[] = 0 := rfl
@[simp] theorem count_empty {a : α} : count a #v[] = 0 := rfl
theorem count_push (a b : α) (xs : Vector α n) :
theorem count_push {a b : α} {xs : Vector α n} :
count a (xs.push b) = count a xs + if b == a then 1 else 0 := by
rcases xs with xs, rfl
simp [Array.count_push]
theorem count_eq_countP (a : α) (xs : Vector α n) : count a xs = countP (· == a) xs := rfl
theorem count_eq_countP {a : α} {xs : Vector α n} : count a xs = countP (· == a) xs := rfl
theorem count_eq_countP' {a : α} : count (n := n) a = countP (· == a) := by
funext xs
apply count_eq_countP
theorem count_le_size (a : α) (xs : Vector α n) : count a xs n := countP_le_size _
theorem count_le_size {a : α} {xs : Vector α n} : count a xs n := countP_le_size
theorem count_le_count_push (a b : α) (xs : Vector α n) : count a xs count a (xs.push b) := by
theorem count_le_count_push {a b : α} {xs : Vector α n} : count a xs count a (xs.push b) := by
rcases xs with xs, rfl
simp [Array.count_push]
@[simp] theorem count_singleton (a b : α) : count a #v[b] = if b == a then 1 else 0 := by
@[simp] theorem count_singleton {a b : α} : count a #v[b] = if b == a then 1 else 0 := by
simp [count_eq_countP]
@[simp] theorem count_append (a : α) (xs : Vector α n) (ys : Vector α m) :
@[simp] theorem count_append {a : α} {xs : Vector α n} {ys : Vector α m} :
count a (xs ++ ys) = count a xs + count a ys :=
countP_append ..
set_option linter.listVariables false in -- This can probably be removed later.
@[simp] theorem count_flatten (a : α) (xss : Vector (Vector α m) n) :
@[simp] theorem count_flatten {a : α} {xss : Vector (Vector α m) n} :
count a xss.flatten = (xss.map (count a)).sum := by
rcases xss with xss, rfl
simp [Array.count_flatten, Function.comp_def]
@[simp] theorem count_reverse (a : α) (xs : Vector α n) : count a xs.reverse = count a xs := by
@[simp] theorem count_reverse {a : α} {xs : Vector α n} : count a xs.reverse = count a xs := by
rcases xs with xs, rfl
simp
theorem boole_getElem_le_count (a : α) (xs : Vector α n) (i : Nat) (h : i < n) :
theorem boole_getElem_le_count {a : α} {xs : Vector α n} (h : i < n) :
(if xs[i] == a then 1 else 0) xs.count a := by
rcases xs with xs, rfl
simp [Array.boole_getElem_le_count, h]
theorem count_set (a b : α) (xs : Vector α n) (i : Nat) (h : i < n) :
theorem count_set {a b : α} {xs : Vector α n} (h : i < n) :
(xs.set i a).count b = xs.count b - (if xs[i] == b then 1 else 0) + (if a == b then 1 else 0) := by
rcases xs with xs, rfl
simp [Array.count_set, h]
@[simp] theorem count_cast (xs : Vector α n) : (xs.cast h).count a = xs.count a := by
@[simp] theorem count_cast {xs : Vector α n} : (xs.cast h).count a = xs.count a := by
rcases xs with xs, rfl
simp
variable [LawfulBEq α]
@[simp] theorem count_push_self (a : α) (xs : Vector α n) : count a (xs.push a) = count a xs + 1 := by
@[simp] theorem count_push_self {a : α} {xs : Vector α n} : count a (xs.push a) = count a xs + 1 := by
rcases xs with xs, rfl
simp [Array.count_push_self]
@[simp] theorem count_push_of_ne (h : b a) (xs : Vector α n) : count a (xs.push b) = count a xs := by
@[simp] theorem count_push_of_ne {xs : Vector α n} (h : b a) : count a (xs.push b) = count a xs := by
rcases xs with xs, rfl
simp [Array.count_push_of_ne, h]
theorem count_singleton_self (a : α) : count a #v[a] = 1 := by simp
theorem count_singleton_self {a : α} : count a #v[a] = 1 := by simp
@[simp]
theorem count_pos_iff {a : α} {xs : Vector α n} : 0 < count a xs a xs := by
@@ -220,26 +215,26 @@ theorem count_eq_size {xs : Vector α n} : count a xs = xs.size ↔ ∀ b ∈ xs
rcases xs with xs, rfl
simp [Array.count_eq_size]
@[simp] theorem count_replicate_self (a : α) (n : Nat) : count a (replicate n a) = n := by
@[simp] theorem count_replicate_self {a : α} {n : Nat} : count a (replicate n a) = n := by
simp only [replicate_eq_mk_replicate, count_cast, count_mk]
simp
@[deprecated count_replicate_self (since := "2025-03-18")]
abbrev count_mkVector_self := @count_replicate_self
theorem count_replicate (a b : α) (n : Nat) : count a (replicate n b) = if b == a then n else 0 := by
theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by
simp only [replicate_eq_mk_replicate, count_cast, count_mk]
simp [Array.count_replicate]
@[deprecated count_replicate (since := "2025-03-18")]
abbrev count_mkVector := @count_replicate
theorem count_le_count_map [DecidableEq β] (xs : Vector α n) (f : α β) (x : α) :
theorem count_le_count_map [DecidableEq β] {xs : Vector α n} {f : α β} {x : α} :
count x xs count (f x) (map f xs) := by
rcases xs with xs, rfl
simp [Array.count_le_count_map]
theorem count_flatMap {α} [BEq β] (xs : Vector α n) (f : α Vector β m) (x : β) :
theorem count_flatMap {α} [BEq β] {xs : Vector α n} {f : α Vector β m} {x : β} :
count x (xs.flatMap f) = (map (count x f) xs).sum := by
rcases xs with xs, rfl
simp [Array.count_flatMap, Function.comp_def]

View File

@@ -20,29 +20,29 @@ open Nat
/-! ### eraseIdx -/
theorem eraseIdx_eq_take_drop_succ (xs : Vector α n) (i : Nat) (h) :
theorem eraseIdx_eq_take_drop_succ {xs : Vector α n} {i : Nat} (h) :
xs.eraseIdx i = (xs.take i ++ xs.drop (i + 1)).cast (by omega) := by
rcases xs with xs, rfl
simp [Array.eraseIdx_eq_take_drop_succ, *]
theorem getElem?_eraseIdx (xs : Vector α n) (i : Nat) (h : i < n) (j : Nat) :
theorem getElem?_eraseIdx {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} :
(xs.eraseIdx i)[j]? = if j < i then xs[j]? else xs[j + 1]? := by
rcases xs with xs, rfl
simp [Array.getElem?_eraseIdx]
theorem getElem?_eraseIdx_of_lt (xs : Vector α n) (i : Nat) (h : i < n) (j : Nat) (h' : j < i) :
theorem getElem?_eraseIdx_of_lt {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} (h' : j < i) :
(xs.eraseIdx i)[j]? = xs[j]? := by
rw [getElem?_eraseIdx]
simp [h']
theorem getElem?_eraseIdx_of_ge (xs : Vector α n) (i : Nat) (h : i < n) (j : Nat) (h' : i j) :
theorem getElem?_eraseIdx_of_ge {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} (h' : i j) :
(xs.eraseIdx i)[j]? = xs[j + 1]? := by
rw [getElem?_eraseIdx]
simp only [dite_eq_ite, ite_eq_right_iff]
intro h'
omega
theorem getElem_eraseIdx (xs : Vector α n) (i : Nat) (h : i < n) (j : Nat) (h' : j < n - 1) :
theorem getElem_eraseIdx {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} (h' : j < n - 1) :
(xs.eraseIdx i)[j] = if h'' : j < i then xs[j] else xs[j + 1] := by
apply Option.some.inj
rw [ getElem?_eq_getElem, getElem?_eraseIdx]
@@ -85,12 +85,12 @@ theorem mem_eraseIdx_iff_getElem? {x : α} {xs : Vector α n} {k} {h} : x ∈ xs
rcases xs with xs
simp [Array.mem_eraseIdx_iff_getElem?, *]
theorem getElem_eraseIdx_of_lt (xs : Vector α n) (i : Nat) (w : i < n) (j : Nat) (h : j < n - 1) (h' : j < i) :
theorem getElem_eraseIdx_of_lt {xs : Vector α n} {i : Nat} (w : i < n) {j : Nat} (h : j < n - 1) (h' : j < i) :
(xs.eraseIdx i)[j] = xs[j] := by
rcases xs with xs
simp [Array.getElem_eraseIdx_of_lt, *]
theorem getElem_eraseIdx_of_ge (xs : Vector α n) (i : Nat) (w : i < n) (j : Nat) (h : j < n - 1) (h' : i j) :
theorem getElem_eraseIdx_of_ge {xs : Vector α n} {i : Nat} (w : i < n) {j : Nat} (h : j < n - 1) (h' : i j) :
(xs.eraseIdx i)[j] = xs[j + 1] := by
rcases xs with xs
simp [Array.getElem_eraseIdx_of_ge, *]

View File

@@ -15,20 +15,20 @@ namespace Vector
/-- `finRange n` is the vector of all elements of `Fin n` in order. -/
protected def finRange (n : Nat) : Vector (Fin n) n := ofFn fun i => i
@[simp] theorem getElem_finRange (i : Nat) (h : i < n) :
@[simp] theorem getElem_finRange {i : Nat} (h : i < n) :
(Vector.finRange n)[i] = i, h := by
simp [Vector.finRange]
@[simp] theorem finRange_zero : Vector.finRange 0 = #v[] := by simp [Vector.finRange]
theorem finRange_succ (n) : Vector.finRange (n+1) =
theorem finRange_succ {n} : Vector.finRange (n+1) =
(#v[(0 : Fin (n+1))] ++ (Vector.finRange n).map Fin.succ).cast (by omega) := by
ext i h
· simp [getElem_append]
split <;>
· simp; omega
theorem finRange_succ_last (n) :
theorem finRange_succ_last {n} :
Vector.finRange (n+1) = (Vector.finRange n).map Fin.castSucc ++ #v[Fin.last n] := by
ext i h
· simp [getElem_push]
@@ -37,7 +37,7 @@ theorem finRange_succ_last (n) :
· simp_all
omega
theorem finRange_reverse (n) : (Vector.finRange n).reverse = (Vector.finRange n).map Fin.rev := by
theorem finRange_reverse {n} : (Vector.finRange n).reverse = (Vector.finRange n).map Fin.rev := by
ext i h
simp
omega

View File

@@ -24,11 +24,11 @@ open Nat
/-! ### findSome? -/
@[simp] theorem findSomeRev?_push_of_isSome (xs : Vector α n) (h : (f a).isSome) : (xs.push a).findSomeRev? f = f a := by
@[simp] theorem findSomeRev?_push_of_isSome {xs : Vector α n} {h : (f a).isSome} : (xs.push a).findSomeRev? f = f a := by
rcases xs with xs, rfl
simp only [push_mk, findSomeRev?_mk, Array.findSomeRev?_push_of_isSome, h]
@[simp] theorem findSomeRev?_push_of_isNone (xs : Vector α n) (h : (f a).isNone) : (xs.push a).findSomeRev? f = xs.findSomeRev? f := by
@[simp] theorem findSomeRev?_push_of_isNone {xs : Vector α n} {h : (f a).isNone} : (xs.push a).findSomeRev? f = xs.findSomeRev? f := by
rcases xs with xs, rfl
simp only [push_mk, findSomeRev?_mk, Array.findSomeRev?_push_of_isNone, h]
@@ -60,25 +60,25 @@ theorem findSome?_eq_some_iff {f : α → Option β} {xs : Vector α n} {b : β}
· rintro k₁, k₂, h, ys, a, zs, w, h₁, h₂
exact ys.toArray, a, zs.toArray, by simp [w], h₁, by simpa using h₂
@[simp] theorem findSome?_guard (xs : Vector α n) : findSome? (Option.guard fun x => p x) xs = find? p xs := by
@[simp] theorem findSome?_guard {xs : Vector α n} : findSome? (Option.guard fun x => p x) xs = find? p xs := by
rcases xs with xs, rfl
simp
theorem find?_eq_findSome?_guard (xs : Vector α n) : find? p xs = findSome? (Option.guard fun x => p x) xs :=
(findSome?_guard xs).symm
theorem find?_eq_findSome?_guard {xs : Vector α n} : find? p xs = findSome? (Option.guard fun x => p x) xs :=
findSome?_guard.symm
@[simp] theorem map_findSome? (f : α Option β) (g : β γ) (xs : Vector α n) :
@[simp] theorem map_findSome? {f : α Option β} {g : β γ} {xs : Vector α n} :
(xs.findSome? f).map g = xs.findSome? (Option.map g f) := by
cases xs; simp
theorem findSome?_map (f : β γ) (xs : Vector β n) : findSome? p (xs.map f) = xs.findSome? (p f) := by
theorem findSome?_map {f : β γ} {xs : Vector β n} : findSome? p (xs.map f) = xs.findSome? (p f) := by
rcases xs with xs, rfl
simp [Array.findSome?_map]
theorem findSome?_append {xs : Vector α n₁} {ys : Vector α n₂} : (xs ++ ys).findSome? f = (xs.findSome? f).or (ys.findSome? f) := by
cases xs; cases ys; simp [Array.findSome?_append]
theorem getElem?_zero_flatten (xss : Vector (Vector α m) n) :
theorem getElem?_zero_flatten {xss : Vector (Vector α m) n} :
(flatten xss)[0]? = xss.findSome? fun xs => xs[0]? := by
cases xss using vector₂_induction
simp [Array.getElem?_zero_flatten, Array.findSome?_map, Function.comp_def]
@@ -96,7 +96,7 @@ theorem getElem_zero_flatten.proof {xss : Vector (Vector α m) n} (h : 0 < n * m
theorem getElem_zero_flatten {xss : Vector (Vector α m) n} (h : 0 < n * m) :
(flatten xss)[0] = (xss.findSome? fun xs => xs[0]?).get (getElem_zero_flatten.proof h) := by
have t := getElem?_zero_flatten xss
have t := getElem?_zero_flatten (xss := xss)
simp [getElem?_eq_getElem, h] at t
simp [ t]
@@ -130,15 +130,15 @@ abbrev findSome?_mkVector_of_isNone := @findSome?_replicate_of_isNone
/-! ### find? -/
@[simp] theorem find?_singleton (a : α) (p : α Bool) :
@[simp] theorem find?_singleton {a : α} {p : α Bool} :
#v[a].find? p = if p a then some a else none := by
simp
@[simp] theorem findRev?_push_of_pos (xs : Vector α n) (h : p a) :
@[simp] theorem findRev?_push_of_pos {xs : Vector α n} (h : p a) :
findRev? p (xs.push a) = some a := by
cases xs; simp [h]
@[simp] theorem findRev?_cons_of_neg (xs : Vector α n) (h : ¬p a) :
@[simp] theorem findRev?_cons_of_neg {xs : Vector α n} (h : ¬p a) :
findRev? p (xs.push a) = findRev? p xs := by
cases xs; simp [h]
@@ -184,17 +184,17 @@ theorem get_find?_mem {xs : Vector α n} (h) : (xs.find? p).get h ∈ xs := by
(xs.filter p).find? q = xs.find? (fun a => p a q a) := by
cases xs; simp
@[simp] theorem getElem?_zero_filter (p : α Bool) (xs : Vector α n) :
@[simp] theorem getElem?_zero_filter {p : α Bool} {xs : Vector α n} :
(xs.filter p)[0]? = xs.find? p := by
cases xs; simp [ List.head?_eq_getElem?]
@[simp] theorem getElem_zero_filter (p : α Bool) (xs : Vector α n) (h) :
@[simp] theorem getElem_zero_filter {p : α Bool} {xs : Vector α n} (h) :
(xs.filter p)[0] =
(xs.find? p).get (by cases xs; simpa [ Array.countP_eq_size_filter] using h) := by
cases xs
simp [List.getElem_zero_eq_head]
@[simp] theorem find?_map (f : β α) (xs : Vector β n) :
@[simp] theorem find?_map {f : β α} {xs : Vector β n} :
find? p (xs.map f) = (xs.find? (p f)).map f := by
cases xs; simp
@@ -204,7 +204,7 @@ theorem get_find?_mem {xs : Vector α n} (h) : (xs.find? p).get h ∈ xs := by
cases ys
simp
@[simp] theorem find?_flatten (xs : Vector (Vector α m) n) (p : α Bool) :
@[simp] theorem find?_flatten {xs : Vector (Vector α m) n} {p : α Bool} :
xs.flatten.find? p = xs.findSome? (·.find? p) := by
cases xs using vector₂_induction
simp [Array.findSome?_map, Function.comp_def]
@@ -213,7 +213,7 @@ theorem find?_flatten_eq_none_iff {xs : Vector (Vector α m) n} {p : α → Bool
xs.flatten.find? p = none ys xs, x ys, !p x := by
simp
@[simp] theorem find?_flatMap (xs : Vector α n) (f : α Vector β m) (p : β Bool) :
@[simp] theorem find?_flatMap {xs : Vector α n} {f : α Vector β m} {p : β Bool} :
(xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by
cases xs
simp [Array.find?_flatMap, Array.flatMap_toArray]
@@ -266,7 +266,7 @@ abbrev find?_mkVector_eq_none_iff := @find?_replicate_eq_none_iff
@[deprecated find?_replicate_eq_some_iff (since := "2025-03-18")]
abbrev find?_mkVector_eq_some_iff := @find?_replicate_eq_some_iff
@[simp] theorem get_find?_replicate (n : Nat) (a : α) (p : α Bool) (h) :
@[simp] theorem get_find?_replicate {n : Nat} {a : α} {p : α Bool} (h) :
((replicate n a).find? p).get h = a := by
simp only [replicate_eq_mk_replicate, find?_mk]
simp
@@ -274,8 +274,8 @@ abbrev find?_mkVector_eq_some_iff := @find?_replicate_eq_some_iff
@[deprecated get_find?_replicate (since := "2025-03-18")]
abbrev get_find?_mkVector := @get_find?_replicate
theorem find?_pmap {P : α Prop} (f : (a : α) P a β) (xs : Vector α n)
(H : (a : α), a xs P a) (p : β Bool) :
theorem find?_pmap {P : α Prop} {f : (a : α) P a β} {xs : Vector α n}
(H : (a : α), a xs P a) {p : β Bool} :
(xs.pmap f H).find? p = (xs.attach.find? (fun a, m => p (f a (H a m)))).map fun a, m => f a (H a m) := by
simp only [pmap_eq_map_attach, find?_map]
rfl

View File

@@ -29,11 +29,11 @@ section InsertIdx
variable {a : α}
@[simp]
theorem insertIdx_zero (xs : Vector α n) (x : α) : xs.insertIdx 0 x = (#v[x] ++ xs).cast (by omega) := by
theorem insertIdx_zero {xs : Vector α n} {x : α} : xs.insertIdx 0 x = (#v[x] ++ xs).cast (by omega) := by
cases xs
simp
theorem eraseIdx_insertIdx (i : Nat) (xs : Vector α n) (h : i n) :
theorem eraseIdx_insertIdx {i : Nat} {xs : Vector α n} {h : i n} :
(xs.insertIdx i a).eraseIdx i = xs := by
rcases xs with xs, rfl
simp_all [Array.eraseIdx_insertIdx]
@@ -52,11 +52,11 @@ theorem insertIdx_eraseIdx_of_le {xs : Vector α n}
rcases xs with as, rfl
simpa using Array.insertIdx_eraseIdx_of_le (by simpa) (by simpa) (by simpa)
theorem insertIdx_comm (a b : α) (i j : Nat) (xs : Vector α n) (_ : i j) (_ : j n) :
theorem insertIdx_comm (a b : α) {i j : Nat} {xs : Vector α n} (_ : i j) (_ : j n) :
(xs.insertIdx i a).insertIdx (j + 1) b =
(xs.insertIdx j b).insertIdx i a := by
rcases xs with as, rfl
simpa using Array.insertIdx_comm a b i j _ (by simpa) (by simpa)
simpa using Array.insertIdx_comm a b (by simpa) (by simpa)
theorem mem_insertIdx {xs : Vector α n} {h : i n} : a xs.insertIdx i b h a = b a xs := by
rcases xs with as, rfl
@@ -64,7 +64,7 @@ theorem mem_insertIdx {xs : Vector α n} {h : i ≤ n} : a ∈ xs.insertIdx i b
set_option linter.indexVariables false in
@[simp]
theorem insertIdx_size_self (xs : Vector α n) (x : α) : xs.insertIdx n x = xs.push x := by
theorem insertIdx_size_self {xs : Vector α n} {x : α} : xs.insertIdx n x = xs.push x := by
rcases xs with as, rfl
simp

File diff suppressed because it is too large Load Diff

View File

@@ -16,14 +16,14 @@ namespace Vector
/-! ### Lexicographic ordering -/
@[simp] theorem lt_toArray [LT α] (xs ys : Vector α n) : xs.toArray < ys.toArray xs < ys := Iff.rfl
@[simp] theorem le_toArray [LT α] (xs ys : Vector α n) : xs.toArray ys.toArray xs ys := Iff.rfl
@[simp] theorem lt_toArray [LT α] {xs ys : Vector α n} : xs.toArray < ys.toArray xs < ys := Iff.rfl
@[simp] theorem le_toArray [LT α] {xs ys : Vector α n} : xs.toArray ys.toArray xs ys := Iff.rfl
@[simp] theorem lt_toList [LT α] (xs ys : Vector α n) : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp] theorem le_toList [LT α] (xs ys : Vector α n) : xs.toList ys.toList xs ys := Iff.rfl
@[simp] theorem lt_toList [LT α] {xs ys : Vector α n} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp] theorem le_toList [LT α] {xs ys : Vector α n} : xs.toList ys.toList xs ys := Iff.rfl
protected theorem not_lt_iff_ge [LT α] (xs ys : Vector α n) : ¬ xs < ys ys xs := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] (xs ys : Vector α n) :
protected theorem not_lt_iff_ge [LT α] {xs ys : Vector α n} : ¬ xs < ys ys xs := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Vector α n} :
¬ xs ys ys < xs :=
Decidable.not_not
@@ -33,18 +33,18 @@ protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] (xs ys
@[simp] theorem mk_le_mk [LT α] :
Vector.mk (α := α) (n := n) data₁ size₁ Vector.mk data₂ size₂ data₁ data₂ := Iff.rfl
@[simp] theorem mk_lex_mk [BEq α] (lt : α α Bool) {xs ys : Array α} {n₁ : xs.size = n} {n₂ : ys.size = n} :
@[simp] theorem mk_lex_mk [BEq α] {lt : α α Bool} {xs ys : Array α} {n₁ : xs.size = n} {n₂ : ys.size = n} :
(Vector.mk xs n₁).lex (Vector.mk ys n₂) lt = xs.lex ys lt := by
simp [Vector.lex, Array.lex, n₁, n₂]
rfl
@[simp] theorem lex_toArray [BEq α] (lt : α α Bool) (xs ys : Vector α n) :
@[simp] theorem lex_toArray [BEq α] {lt : α α Bool} {xs ys : Vector α n} :
xs.toArray.lex ys.toArray lt = xs.lex ys lt := by
cases xs
cases ys
simp
@[simp] theorem lex_toList [BEq α] (lt : α α Bool) (xs ys : Vector α n) :
@[simp] theorem lex_toList [BEq α] {lt : α α Bool} {xs ys : Vector α n} :
xs.toList.lex ys.toList lt = xs.lex ys lt := by
rcases xs with xs, n₁
rcases ys with ys, n₂
@@ -68,7 +68,7 @@ instance ltIrrefl [LT α] [Std.Irrefl (· < · : αα → Prop)] : Std.Irre
@[simp] theorem not_lt_empty [LT α] (xs : Vector α 0) : ¬ xs < #v[] := Array.not_lt_empty xs.toArray
@[simp] theorem empty_le [LT α] (xs : Vector α 0) : #v[] xs := Array.empty_le xs.toArray
@[simp] theorem le_empty [LT α] (xs : Vector α 0) : xs #v[] xs = #v[] := by
@[simp] theorem le_empty [LT α] {xs : Vector α 0} : xs #v[] xs = #v[] := by
cases xs
simp

View File

@@ -15,13 +15,13 @@ namespace Vector
/-! ### mapFinIdx -/
@[simp] theorem getElem_mapFinIdx (xs : Vector α n) (f : (i : Nat) α (h : i < n) β) (i : Nat)
@[simp] theorem getElem_mapFinIdx {xs : Vector α n} {f : (i : Nat) α (h : i < n) β} {i : Nat}
(h : i < n) :
(xs.mapFinIdx f)[i] = f i xs[i] h := by
rcases xs with xs, rfl
simp
@[simp] theorem getElem?_mapFinIdx (xs : Vector α n) (f : (i : Nat) α (h : i < n) β) (i : Nat) :
@[simp] theorem getElem?_mapFinIdx {xs : Vector α n} {f : (i : Nat) α (h : i < n) β} {i : Nat} :
(xs.mapFinIdx f)[i]? =
xs[i]?.pbind fun b h => f i b (getElem?_eq_some_iff.1 h).1 := by
simp only [getElem?_def, getElem_mapFinIdx]
@@ -29,12 +29,12 @@ namespace Vector
/-! ### mapIdx -/
@[simp] theorem getElem_mapIdx (f : Nat α β) (xs : Vector α n) (i : Nat) (h : i < n) :
@[simp] theorem getElem_mapIdx {f : Nat α β} {xs : Vector α n} {i : Nat} (h : i < n) :
(xs.mapIdx f)[i] = f i (xs[i]'(by simp_all)) := by
rcases xs with xs, rfl
simp
@[simp] theorem getElem?_mapIdx (f : Nat α β) (xs : Vector α n) (i : Nat) :
@[simp] theorem getElem?_mapIdx {f : Nat α β} {xs : Vector α n} {i : Nat} :
(xs.mapIdx f)[i]? = xs[i]?.map (f i) := by
rcases xs with xs, rfl
simp
@@ -43,11 +43,11 @@ end Vector
namespace Array
@[simp] theorem mapFinIdx_toVector (xs : Array α) (f : (i : Nat) α (h : i < xs.size) β) :
@[simp] theorem mapFinIdx_toVector {xs : Array α} {f : (i : Nat) α (h : i < xs.size) β} :
xs.toVector.mapFinIdx f = (xs.mapFinIdx f).toVector.cast (by simp) := by
ext <;> simp
@[simp] theorem mapIdx_toVector (f : Nat α β) (xs : Array α) :
@[simp] theorem mapIdx_toVector {f : Nat α β} {xs : Array α} :
xs.toVector.mapIdx f = (xs.mapIdx f).toVector.cast (by simp) := by
ext <;> simp
@@ -57,12 +57,12 @@ namespace Vector
/-! ### zipIdx -/
@[simp] theorem toList_zipIdx (xs : Vector α n) (k : Nat := 0) :
@[simp] theorem toList_zipIdx {xs : Vector α n} (k : Nat := 0) :
(xs.zipIdx k).toList = xs.toList.zipIdx k := by
rcases xs with xs, rfl
simp
@[simp] theorem getElem_zipIdx (xs : Vector α n) (i : Nat) (h : i < n) :
@[simp] theorem getElem_zipIdx {xs : Vector α n} {i : Nat} {h : i < n} :
(xs.zipIdx k)[i] = (xs[i]'(by simp_all), k + i) := by
rcases xs with xs, rfl
simp
@@ -366,8 +366,8 @@ abbrev mapIdx_eq_mkVector_iff := @mapIdx_eq_replicate_iff
rcases xs with xs, rfl
simp [Array.mapIdx_reverse]
theorem toArray_mapFinIdxM [Monad m] [LawfulMonad m]
(xs : Vector α n) (f : (i : Nat) α (h : i < n) m β) :
theorem toArray_mapFinIdxM [Monad m] [LawfulMonad m] {xs : Vector α n}
{f : (i : Nat) α (h : i < n) m β} :
toArray <$> xs.mapFinIdxM f = xs.toArray.mapFinIdxM
(fun i x h => f i x (size_toArray xs h)) := by
let rec go (i j : Nat) (inv : i + j = n) (bs : Vector β (n - i)) :
@@ -383,8 +383,9 @@ theorem toArray_mapFinIdxM [Monad m] [LawfulMonad m]
simp only [mapFinIdxM, Array.mapFinIdxM, size_toArray]
exact go _ _ _ _
theorem toArray_mapIdxM [Monad m] [LawfulMonad m] (xs : Vector α n) (f : Nat α m β) :
theorem toArray_mapIdxM [Monad m] [LawfulMonad m] {xs : Vector α n}
{f : Nat α m β} :
toArray <$> xs.mapIdxM f = xs.toArray.mapIdxM f := by
exact toArray_mapFinIdxM _ _
exact toArray_mapFinIdxM
end Vector

View File

@@ -41,14 +41,14 @@ theorem mapM_pure [Monad m] [LawfulMonad m] {xs : Vector α n} (f : α → β) :
subst w
simp
@[simp] theorem mapM_mk_empty [Monad m] (f : α m β) :
@[simp] theorem mapM_mk_empty [Monad m] {f : α m β} :
(mk #[] rfl).mapM f = pure #v[] := by
unfold mapM
unfold mapM.go
simp
@[simp] theorem mapM_append [Monad m] [LawfulMonad m]
(f : α m β) {xs : Vector α n} {ys : Vector α n'} :
{f : α m β} {xs : Vector α n} {ys : Vector α n'} :
(xs ++ ys).mapM f = (return ( xs.mapM f) ++ ( ys.mapM f)) := by
apply map_toArray_inj.mp
suffices toArray <$> (xs ++ ys).mapM f = (return ( toArray <$> xs.mapM f) ++ ( toArray <$> ys.mapM f)) by
@@ -58,50 +58,50 @@ theorem mapM_pure [Monad m] [LawfulMonad m] {xs : Vector α n} (f : α → β) :
/-! ### foldlM and foldrM -/
theorem foldlM_map [Monad m] (f : β₁ β₂) (g : α β₂ m α) (xs : Vector β₁ n) (init : α) :
theorem foldlM_map [Monad m] {f : β₁ β₂} {g : α β₂ m α} {xs : Vector β₁ n} {init : α} :
(xs.map f).foldlM g init = xs.foldlM (fun x y => g x (f y)) init := by
rcases xs with xs, rfl
simp [Array.foldlM_map]
theorem foldrM_map [Monad m] [LawfulMonad m] (f : β₁ β₂) (g : β₂ α m α) (xs : Vector β₁ n)
(init : α) : (xs.map f).foldrM g init = xs.foldrM (fun x y => g (f x) y) init := by
theorem foldrM_map [Monad m] [LawfulMonad m] {f : β₁ β₂} {g : β₂ α m α} {xs : Vector β₁ n} {init : α} :
(xs.map f).foldrM g init = xs.foldrM (fun x y => g (f x) y) init := by
rcases xs with xs, rfl
simp [Array.foldrM_map]
theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α Option β) (g : γ β m γ) (xs : Vector α n) (init : γ) :
theorem foldlM_filterMap [Monad m] [LawfulMonad m] {f : α Option β} {g : γ β m γ} {xs : Vector α n} {init : γ} :
(xs.filterMap f).foldlM g init =
xs.foldlM (fun x y => match f y with | some b => g x b | none => pure x) init := by
rcases xs with xs, rfl
simp [Array.foldlM_filterMap]
rfl
theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α Option β) (g : β γ m γ) (xs : Vector α n) (init : γ) :
theorem foldrM_filterMap [Monad m] [LawfulMonad m] {f : α Option β} {g : β γ m γ} {xs : Vector α n} {init : γ} :
(xs.filterMap f).foldrM g init =
xs.foldrM (fun x y => match f x with | some b => g b y | none => pure y) init := by
rcases xs with xs, rfl
simp [Array.foldrM_filterMap]
rfl
theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α Bool) (g : β α m β) (xs : Vector α n) (init : β) :
theorem foldlM_filter [Monad m] [LawfulMonad m] {p : α Bool} {g : β α m β} {xs : Vector α n} {init : β} :
(xs.filter p).foldlM g init =
xs.foldlM (fun x y => if p y then g x y else pure x) init := by
rcases xs with xs, rfl
simp [Array.foldlM_filter]
theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α Bool) (g : α β m β) (xs : Vector α n) (init : β) :
theorem foldrM_filter [Monad m] [LawfulMonad m] {p : α Bool} {g : α β m β} {xs : Vector α n} {init : β} :
(xs.filter p).foldrM g init =
xs.foldrM (fun x y => if p x then g x y else pure y) init := by
rcases xs with xs, rfl
simp [Array.foldrM_filter]
@[simp] theorem foldlM_attachWith [Monad m]
(xs : Vector α n) {q : α Prop} (H : a, a xs q a) {f : β { x // q x} m β} {b} :
{xs : Vector α n} {q : α Prop} (H : a, a xs q a) {f : β { x // q x} m β} {b} :
(xs.attachWith q H).foldlM f b = xs.attach.foldlM (fun b a, h => f b a, H _ h) b := by
rcases xs with xs, rfl
simp [Array.foldlM_map]
@[simp] theorem foldrM_attachWith [Monad m] [LawfulMonad m]
(xs : Vector α n) {q : α Prop} (H : a, a xs q a) {f : { x // q x} β m β} {b} :
{xs : Vector α n} {q : α Prop} (H : a, a xs q a) {f : { x // q x} β m β} {b} :
(xs.attachWith q H).foldrM f b = xs.attach.foldrM (fun a acc => f a.1, H _ a.2 acc) b := by
rcases xs with xs, rfl
simp [Array.foldrM_map]
@@ -114,13 +114,13 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β
cases as <;> cases bs
simp_all
@[simp] theorem forM_append [Monad m] [LawfulMonad m] (xs : Vector α n) (ys : Vector α n') (f : α m PUnit) :
@[simp] theorem forM_append [Monad m] [LawfulMonad m] {xs : Vector α n} {ys : Vector α n'} {f : α m PUnit} :
forM (xs ++ ys) f = (do forM xs f; forM ys f) := by
rcases xs with xs, rfl
rcases ys with ys, rfl
simp
@[simp] theorem forM_map [Monad m] [LawfulMonad m] (xs : Vector α n) (g : α β) (f : β m PUnit) :
@[simp] theorem forM_map [Monad m] [LawfulMonad m] {xs : Vector α n} {g : α β} {f : β m PUnit} :
forM (xs.map g) f = forM xs (fun a => f (g a)) := by
rcases xs with xs, rfl
simp
@@ -142,7 +142,7 @@ We can express a for loop over a vector as a fold,
in which whenever we reach `.done b` we keep that value through the rest of the fold.
-/
theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
(xs : Vector α n) (f : (a : α) a xs β m (ForInStep β)) (init : β) :
{xs : Vector α n} (f : (a : α) a xs β m (ForInStep β)) (init : β) :
forIn' xs init f = ForInStep.value <$>
xs.attach.foldlM (fun b a, m => match b with
| .yield b => f a m b
@@ -153,29 +153,29 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
/-- We can express a for loop over a vector which always yields as a fold. -/
@[simp] theorem forIn'_yield_eq_foldlM [Monad m] [LawfulMonad m]
(xs : Vector α n) (f : (a : α) a xs β m γ) (g : (a : α) a xs β γ β) (init : β) :
{xs : Vector α n} (f : (a : α) a xs β m γ) (g : (a : α) a xs β γ β) (init : β) :
forIn' xs init (fun a m b => (fun c => .yield (g a m b c)) <$> f a m b) =
xs.attach.foldlM (fun b a, m => g a m b <$> f a m b) init := by
rcases xs with xs, rfl
simp
@[simp] theorem forIn'_pure_yield_eq_foldl [Monad m] [LawfulMonad m]
(xs : Vector α n) (f : (a : α) a xs β β) (init : β) :
{xs : Vector α n} (f : (a : α) a xs β β) (init : β) :
forIn' xs init (fun a m b => pure (.yield (f a m b))) =
pure (f := m) (xs.attach.foldl (fun b a, h => f a h b) init) := by
rcases xs with xs, rfl
simp [Array.forIn'_pure_yield_eq_foldl, Array.foldl_map]
@[simp] theorem forIn'_yield_eq_foldl
(xs : Vector α n) (f : (a : α) a xs β β) (init : β) :
{xs : Vector α n} (f : (a : α) a xs β β) (init : β) :
forIn' (m := Id) xs init (fun a m b => .yield (f a m b)) =
xs.attach.foldl (fun b a, h => f a h b) init := by
rcases xs with xs, rfl
simp [List.foldl_map]
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
(xs : Vector α n) (g : α β) (f : (b : β) b xs.map g γ m (ForInStep γ)) :
forIn' (xs.map g) init f = forIn' xs init fun a h y => f (g a) (mem_map_of_mem g h) y := by
{xs : Vector α n} (g : α β) (f : (b : β) b xs.map g γ m (ForInStep γ)) :
forIn' (xs.map g) init f = forIn' xs init fun a h y => f (g a) (mem_map_of_mem h) y := by
rcases xs with xs, rfl
simp
@@ -184,7 +184,7 @@ We can express a for loop over a vector as a fold,
in which whenever we reach `.done b` we keep that value through the rest of the fold.
-/
theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
(f : α β m (ForInStep β)) (init : β) (xs : Vector α n) :
{xs : Vector α n} (f : α β m (ForInStep β)) (init : β) :
forIn xs init f = ForInStep.value <$>
xs.foldlM (fun b a => match b with
| .yield b => f a b
@@ -195,28 +195,28 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
/-- We can express a for loop over a vector which always yields as a fold. -/
@[simp] theorem forIn_yield_eq_foldlM [Monad m] [LawfulMonad m]
(xs : Vector α n) (f : α β m γ) (g : α β γ β) (init : β) :
{xs : Vector α n} (f : α β m γ) (g : α β γ β) (init : β) :
forIn xs init (fun a b => (fun c => .yield (g a b c)) <$> f a b) =
xs.foldlM (fun b a => g a b <$> f a b) init := by
rcases xs with xs, rfl
simp
@[simp] theorem forIn_pure_yield_eq_foldl [Monad m] [LawfulMonad m]
(xs : Vector α n) (f : α β β) (init : β) :
{xs : Vector α n} (f : α β β) (init : β) :
forIn xs init (fun a b => pure (.yield (f a b))) =
pure (f := m) (xs.foldl (fun b a => f a b) init) := by
rcases xs with xs, rfl
simp [Array.forIn_pure_yield_eq_foldl, Array.foldl_map]
@[simp] theorem forIn_yield_eq_foldl
(xs : Vector α n) (f : α β β) (init : β) :
{xs : Vector α n} (f : α β β) (init : β) :
forIn (m := Id) xs init (fun a b => .yield (f a b)) =
xs.foldl (fun b a => f a b) init := by
rcases xs with xs, rfl
simp
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
(xs : Vector α n) (g : α β) (f : β γ m (ForInStep γ)) :
{xs : Vector α n} (g : α β) (f : β γ m (ForInStep γ)) :
forIn (xs.map g) init f = forIn xs init fun a y => f (g a) y := by
rcases xs with xs, rfl
simp
@@ -224,25 +224,25 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
/-! ### allM and anyM -/
@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] (p : α Bool) (xs : Vector α n) :
@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] {p : α Bool} {xs : Vector α n} :
xs.anyM (m := m) (pure <| p ·) = pure (xs.any p) := by
cases xs
simp
@[simp] theorem allM_pure [Monad m] [LawfulMonad m] (p : α Bool) (xs : Vector α n) :
@[simp] theorem allM_pure [Monad m] [LawfulMonad m] {p : α Bool} {xs : Vector α n} :
xs.allM (m := m) (pure <| p ·) = pure (xs.all p) := by
cases xs
simp
/-! ### findM? and findSomeM? -/
theorem findM?_pure {m} [Monad m] [LawfulMonad m] (p : α Bool) (xs : Vector α n) :
theorem findM?_pure {m} [Monad m] [LawfulMonad m] {p : α Bool} {xs : Vector α n} :
findM? (m := m) (pure <| p ·) xs = pure (xs.find? p) := by
cases xs
simp
@[simp]
theorem findSomeM?_pure [Monad m] [LawfulMonad m] (f : α Option β) (xs : Vector α n) :
theorem findSomeM?_pure [Monad m] [LawfulMonad m] {f : α Option β} {xs : Vector α n} :
findSomeM? (m := m) (pure <| f ·) xs = pure (xs.findSome? f) := by
cases xs
simp

View File

@@ -16,16 +16,16 @@ set_option linter.indexVariables true -- Enforce naming conventions for index va
namespace Vector
@[simp] theorem getElem_ofFn {α n} (f : Fin n α) (i : Nat) (h : i < n) :
@[simp] theorem getElem_ofFn {α n} {f : Fin n α} (h : i < n) :
(Vector.ofFn f)[i] = f i, by simpa using h := by
simp [ofFn]
theorem getElem?_ofFn (f : Fin n α) (i : Nat) :
theorem getElem?_ofFn {α n} {f : Fin n α} :
(ofFn f)[i]? = if h : i < n then some (f i, h) else none := by
simp [getElem?_def]
@[simp 500]
theorem mem_ofFn {n} (f : Fin n α) (a : α) : a ofFn f i, f i = a := by
theorem mem_ofFn {n} {f : Fin n α} {a : α} : a ofFn f i, f i = a := by
constructor
· intro w
obtain i, h, rfl := getElem_of_mem w
@@ -33,7 +33,7 @@ theorem mem_ofFn {n} (f : Fin n → α) (a : α) : a ∈ ofFn f ↔ ∃ i, f i =
· rintro i, rfl
apply mem_of_getElem (i := i) <;> simp
theorem back_ofFn {n} [NeZero n](f : Fin n α) :
theorem back_ofFn {n} [NeZero n] {f : Fin n α} :
(ofFn f).back = f n - 1, by have := NeZero.ne n; omega := by
simp [back]

View File

@@ -25,23 +25,23 @@ open Nat
/-! ### range' -/
@[simp] theorem toArray_range' (start size step) :
@[simp] theorem toArray_range' {start size step} :
(range' start size step).toArray = Array.range' start size step := by
rfl
theorem range'_eq_mk_range' (start size step) :
theorem range'_eq_mk_range' {start size step} :
range' start size step = Vector.mk (Array.range' start size step) (by simp) := by
rfl
@[simp] theorem getElem_range' (start size step i) (h : i < size) :
@[simp] theorem getElem_range' {start size step i} (h : i < size) :
(range' start size step)[i] = start + step * i := by
simp [range', h]
@[simp] theorem getElem?_range' (start size step i) :
@[simp] theorem getElem?_range' {start size step i} :
(range' start size step)[i]? = if i < size then some (start + step * i) else none := by
simp [getElem?_def, range']
theorem range'_succ (s n step) :
theorem range'_succ {s n step} :
range' s (n + 1) step = (#v[s] ++ range' (s + step) n step).cast (by omega) := by
rw [ toArray_inj]
simp [Array.range'_succ]
@@ -61,24 +61,24 @@ theorem mem_range' {n} : m ∈ range' s n step ↔ ∃ i < n, m = s + step * i :
theorem pop_range' : (range' s n step).pop = range' s (n - 1) step := by
ext <;> simp
theorem map_add_range' (a) (s n step) : map (a + ·) (range' s n step) = range' (a + s) n step := by
theorem map_add_range' {a} (s n step) : map (a + ·) (range' s n step) = range' (a + s) n step := by
ext <;> simp <;> omega
theorem range'_succ_left : range' (s + 1) n step = (range' s n step).map (· + 1) := by
ext <;> simp <;> omega
theorem range'_append (s m n step : Nat) :
theorem range'_append {s m n step : Nat} :
range' s m step ++ range' (s + step * m) n step = range' s (m + n) step := by
rw [ toArray_inj]
simp [Array.range'_append]
@[simp] theorem range'_append_1 (s m n : Nat) :
range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append s m n 1
@[simp] theorem range'_append_1 {s m n : Nat} :
range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append (step := 1)
theorem range'_concat (s n : Nat) : range' s (n + 1) step = range' s n step ++ #v[s + step * n] := by
simpa using (range'_append s n 1 step).symm
theorem range'_concat {s n : Nat} : range' s (n + 1) step = range' s n step ++ #v[s + step * n] := by
simpa using range'_append.symm
theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ #v[s + n] := by
theorem range'_1_concat {s n : Nat} : range' s (n + 1) = range' s n ++ #v[s + n] := by
simp [range'_concat]
@[simp] theorem mem_range'_1 : m range' s n s m m < s + n := by
@@ -86,7 +86,7 @@ theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ #v[s + n]
fun i, h, e => e Nat.le_add_right .., Nat.add_lt_add_left h _,
fun h₁, h₂ => m - s, Nat.sub_lt_left_of_lt_add h₁ h₂, (Nat.add_sub_cancel' h₁).symm
theorem map_sub_range' (a s n : Nat) (h : a s) :
theorem map_sub_range' {a s n : Nat} (h : a s) :
map (· - a) (range' s n step) = range' (s - a) n step := by
conv => lhs; rw [ Nat.add_sub_cancel' h]
rw [ map_add_range', map_map, (?_ : __ = _), map_id]
@@ -115,29 +115,30 @@ theorem range'_eq_append_iff : range' s (n + m) = xs ++ ys ↔ xs = range' s n
/-! ### range -/
@[simp] theorem getElem_range (i : Nat) (hi : i < n) : (Vector.range n)[i] = i := by
@[simp] theorem getElem_range {i : Nat} (hi : i < n) : (Vector.range n)[i] = i := by
simp [Vector.range]
theorem range_eq_range' (n : Nat) : range n = range' 0 n := by
theorem range_eq_range' {n : Nat} : range n = range' 0 n := by
simp [range, range', Array.range_eq_range']
theorem range_succ_eq_map (n : Nat) : range (n + 1) =
(#v[0] ++ map succ (range n)).cast (by omega) := by
theorem range_succ_eq_map {n : Nat} :
range (n + 1) =
(#v[0] ++ map succ (range n)).cast (by omega) := by
rw [ toArray_inj]
simp [Array.range_succ_eq_map]
theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) := by
theorem range'_eq_map_range {s n : Nat} : range' s n = map (s + ·) (range n) := by
rw [range_eq_range', map_add_range']; rfl
theorem range_succ (n : Nat) : range (succ n) = range n ++ #v[n] := by
theorem range_succ {n : Nat} : range (succ n) = range n ++ #v[n] := by
rw [ toArray_inj]
simp [Array.range_succ]
theorem range_add (n m : Nat) : range (n + m) = range n ++ (range m).map (n + ·) := by
theorem range_add {n m : Nat} : range (n + m) = range n ++ (range m).map (n + ·) := by
rw [ range'_eq_map_range]
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 n m).symm
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 (s := 0)).symm
theorem reverse_range' (s n : Nat) : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by
theorem reverse_range' {s n : Nat} : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by
simp [ toList_inj, List.reverse_range']
@[simp]
@@ -146,9 +147,9 @@ theorem mem_range {m n : Nat} : m ∈ range n ↔ m < n := by
theorem not_mem_range_self {n : Nat} : n range n := by simp
theorem self_mem_range_succ (n : Nat) : n range (n + 1) := by simp
theorem self_mem_range_succ {n : Nat} : n range (n + 1) := by simp
@[simp] theorem take_range (n i : Nat) : take (range n) i = range (min i n) := by
@[simp] theorem take_range {n i : Nat} : take (range n) i = range (min i n) := by
ext <;> simp
erw [getElem_extract] -- Why is an `erw` needed here? This should be by simp!
simp
@@ -164,48 +165,50 @@ theorem self_mem_range_succ (n : Nat) : n ∈ range (n + 1) := by simp
/-! ### zipIdx -/
@[simp]
theorem getElem?_zipIdx (xs : Vector α n) (i j) : (zipIdx xs i)[j]? = xs[j]?.map fun a => (a, i + j) := by
theorem getElem?_zipIdx {xs : Vector α n} {i j} : (zipIdx xs i)[j]? = xs[j]?.map fun a => (a, i + j) := by
simp [getElem?_def]
theorem map_snd_add_zipIdx_eq_zipIdx (xs : Vector α n) (m k : Nat) :
theorem map_snd_add_zipIdx_eq_zipIdx {xs : Vector α n} {m k : Nat} :
map (Prod.map id (· + m)) (zipIdx xs k) = zipIdx xs (m + k) := by
ext <;> simp <;> omega
-- Arguments are explicit for parity with `zipIdx_map_fst`.
@[simp]
theorem zipIdx_map_snd (i) (xs : Vector α n) : map Prod.snd (zipIdx xs i) = range' i n := by
rcases xs with xs, rfl
simp [Array.zipIdx_map_snd]
-- Arguments are explicit so we can rewrite from right to left.
@[simp]
theorem zipIdx_map_fst (i) (xs : Vector α n) : map Prod.fst (zipIdx xs i) = xs := by
rcases xs with xs, rfl
simp [Array.zipIdx_map_fst]
theorem zipIdx_eq_zip_range' (xs : Vector α n) : xs.zipIdx i = xs.zip (range' i n) := by
theorem zipIdx_eq_zip_range' {xs : Vector α n} : xs.zipIdx i = xs.zip (range' i n) := by
simp [zip_of_prod (zipIdx_map_fst _ _) (zipIdx_map_snd _ _)]
@[simp]
theorem unzip_zipIdx_eq_prod (xs : Vector α n) {i : Nat} :
theorem unzip_zipIdx_eq_prod {xs : Vector α n} {i : Nat} :
(xs.zipIdx i).unzip = (xs, range' i n) := by
simp only [zipIdx_eq_zip_range', unzip_zip]
/-- Replace `zipIdx` with a starting index `i+1` with `zipIdx` starting from `i`,
followed by a `map` increasing the indices by one. -/
theorem zipIdx_succ (xs : Vector α n) (i : Nat) :
theorem zipIdx_succ {xs : Vector α n} {i : Nat} :
xs.zipIdx (i + 1) = (xs.zipIdx i).map (fun a, i => (a, i + 1)) := by
rcases xs with xs, rfl
simp [Array.zipIdx_succ]
/-- Replace `zipIdx` with a starting index with `zipIdx` starting from 0,
followed by a `map` increasing the indices. -/
theorem zipIdx_eq_map_add (xs : Vector α n) (i : Nat) :
theorem zipIdx_eq_map_add {xs : Vector α n} {i : Nat} :
xs.zipIdx i = xs.zipIdx.map (fun a, j => (a, i + j)) := by
rcases xs with xs, rfl
simp only [zipIdx_mk, map_mk, eq_mk]
rw [Array.zipIdx_eq_map_add]
@[simp]
theorem zipIdx_singleton (x : α) (k : Nat) : zipIdx #v[x] k = #v[(x, k)] :=
theorem zipIdx_singleton {x : α} {k : Nat} : zipIdx (#v[x]) k = #v[(x, k)] :=
rfl
theorem mk_add_mem_zipIdx_iff_getElem? {k i : Nat} {x : α} {xs : Vector α n} :
@@ -225,13 +228,13 @@ theorem snd_lt_of_mem_zipIdx {x : α × Nat} {k : Nat} {xs : Vector α n} (h : x
x.2 < n + k := by
simpa [Nat.add_comm] using snd_lt_add_of_mem_zipIdx h
theorem map_zipIdx (f : α β) (xs : Vector α n) (k : Nat) :
theorem map_zipIdx {f : α β} {xs : Vector α n} {k : Nat} :
map (Prod.map f id) (zipIdx xs k) = zipIdx (xs.map f) k := by
rcases xs with xs, rfl
simp [Array.map_zipIdx]
theorem fst_mem_of_mem_zipIdx {x : α × Nat} {xs : Vector α n} {k : Nat} (h : x zipIdx xs k) : x.1 xs :=
zipIdx_map_fst k xs mem_map_of_mem _ h
zipIdx_map_fst k xs mem_map_of_mem h
theorem fst_eq_of_mem_zipIdx {x : α × Nat} {xs : Vector α n} {k : Nat} (h : x zipIdx xs k) :
x.1 = xs[x.2 - k]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) := by
@@ -248,12 +251,12 @@ theorem mem_zipIdx' {x : α} {i : Nat} {xs : Vector α n} (h : (x, i) ∈ xs.zip
i < n x = xs[i]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) :=
by simpa using snd_lt_add_of_mem_zipIdx h, fst_eq_of_mem_zipIdx h
theorem zipIdx_map (xs : Vector α n) (k : Nat) (f : α β) :
theorem zipIdx_map {f : α β} {xs : Vector α n} {k : Nat} :
zipIdx (xs.map f) k = (zipIdx xs k).map (Prod.map f id) := by
rcases xs with xs, rfl
simp [Array.zipIdx_map]
theorem zipIdx_append (xs : Vector α n) (ys : Vector α m) (k : Nat) :
theorem zipIdx_append {xs : Vector α n} {ys : Vector α m} {k : Nat} :
zipIdx (xs ++ ys) k = zipIdx xs k ++ zipIdx ys (k + n) := by
rcases xs with xs, rfl
rcases ys with ys, rfl

View File

@@ -22,19 +22,19 @@ open Nat
/-! ### zipWith -/
theorem zipWith_comm (f : α β γ) (as : Vector α n) (bs : Vector β n) :
theorem zipWith_comm {f : α β γ} {as : Vector α n} {bs : Vector β n} :
zipWith f as bs = zipWith (fun b a => f a b) bs as := by
rcases as with as, rfl
rcases bs with bs, h
simpa using Array.zipWith_comm _ _ _
simpa using Array.zipWith_comm
theorem zipWith_comm_of_comm (f : α α β) (comm : x y : α, f x y = f y x) (xs ys : Vector α n) :
theorem zipWith_comm_of_comm {f : α α β} (comm : x y : α, f x y = f y x) {xs ys : Vector α n} :
zipWith f xs ys = zipWith f ys xs := by
rw [zipWith_comm]
simp only [comm]
@[simp]
theorem zipWith_self (f : α α δ) (xs : Vector α n) : zipWith f xs xs = xs.map fun a => f a a := by
theorem zipWith_self {f : α α δ} {xs : Vector α n} : zipWith f xs xs = xs.map fun a => f a a := by
cases xs
simp
@@ -71,38 +71,37 @@ theorem getElem?_zip_eq_some {as : Vector α n} {bs : Vector β n} {z : α × β
simp [Array.getElem?_zip_eq_some]
@[simp]
theorem zipWith_map {μ} (f : γ δ μ) (g : α γ) (h : β δ) (as : Vector α n) (bs : Vector β n) :
theorem zipWith_map {μ} {f : γ δ μ} {g : α γ} {h : β δ} {as : Vector α n} {bs : Vector β n} :
zipWith f (as.map g) (bs.map h) = zipWith (fun a b => f (g a) (h b)) as bs := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.zipWith_map]
theorem zipWith_map_left (as : Vector α n) (bs : Vector β n) (f : α α') (g : α' β γ) :
theorem zipWith_map_left {as : Vector α n} {bs : Vector β n} {f : α α'} {g : α' β γ} :
zipWith g (as.map f) bs = zipWith (fun a b => g (f a) b) as bs := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.zipWith_map_left]
theorem zipWith_map_right (as : Vector α n) (bs : Vector β n) (f : β β') (g : α β' γ) :
theorem zipWith_map_right {as : Vector α n} {bs : Vector β n} {f : β β'} {g : α β' γ} :
zipWith g as (bs.map f) = zipWith (fun a b => g a (f b)) as bs := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.zipWith_map_right]
theorem zipWith_foldr_eq_zip_foldr {f : α β γ} (i : δ):
theorem zipWith_foldr_eq_zip_foldr {f : α β γ} {i : δ} :
(zipWith f as bs).foldr g i = (zip as bs).foldr (fun p r => g (f p.1 p.2) r) i := by
rcases as with as, rfl
rcases bs with bs, h
simpa using Array.zipWith_foldr_eq_zip_foldr _
simpa using Array.zipWith_foldr_eq_zip_foldr
theorem zipWith_foldl_eq_zip_foldl {f : α β γ} (i : δ):
theorem zipWith_foldl_eq_zip_foldl {f : α β γ} {i : δ} :
(zipWith f as bs).foldl g i = (zip as bs).foldl (fun r p => g r (f p.1 p.2)) i := by
rcases as with as, rfl
rcases bs with bs, h
simpa using Array.zipWith_foldl_eq_zip_foldl _
simpa using Array.zipWith_foldl_eq_zip_foldl
theorem map_zipWith {δ : Type _} (f : α β) (g : γ δ α) (as : Vector γ n) (bs : Vector δ n) :
theorem map_zipWith {δ : Type _} {f : α β} {g : γ δ α} {as : Vector γ n} {bs : Vector δ n} :
map f (zipWith g as bs) = zipWith (fun x y => f (g x y)) as bs := by
rcases as with as, rfl
rcases bs with bs, h
@@ -118,8 +117,8 @@ theorem extract_zipWith : (zipWith f as bs).extract i j = zipWith f (as.extract
rcases bs with bs, h
simp [Array.extract_zipWith]
theorem zipWith_append (f : α β γ)
(as : Vector α n) (as' : Vector α m) (bs : Vector β n) (bs' : Vector β m) :
theorem zipWith_append {f : α β γ}
{as : Vector α n} {as' : Vector α m} {bs : Vector β n} {bs' : Vector β m} :
zipWith f (as ++ as') (bs ++ bs') = zipWith f as bs ++ zipWith f as' bs' := by
rcases as with as, rfl
rcases bs with bs, h
@@ -152,19 +151,19 @@ theorem zipWith_eq_append_iff {f : α → β → γ} {as : Vector α (n + m)} {b
@[deprecated zipWith_replicate (since := "2025-03-18")]
abbrev zipWith_mkVector := @zipWith_replicate
theorem map_uncurry_zip_eq_zipWith (f : α β γ) (as : Vector α n) (bs : Vector β n) :
theorem map_uncurry_zip_eq_zipWith {f : α β γ} {as : Vector α n} {bs : Vector β n} :
map (Function.uncurry f) (as.zip bs) = zipWith f as bs := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.map_uncurry_zip_eq_zipWith]
theorem map_zip_eq_zipWith (f : α × β γ) (as : Vector α n) (bs : Vector β n) :
theorem map_zip_eq_zipWith {f : α × β γ} {as : Vector α n} {bs : Vector β n} :
map f (as.zip bs) = zipWith (Function.curry f) as bs := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.map_zip_eq_zipWith]
theorem reverse_zipWith (f : α β γ) (as : Vector α n) (bs : Vector β n) :
theorem reverse_zipWith {f : α β γ} {as : Vector α n} {bs : Vector β n} :
(zipWith f as bs).reverse = zipWith f as.reverse bs.reverse := by
rcases as with as, rfl
rcases bs with bs, h
@@ -177,21 +176,21 @@ theorem getElem_zip {as : Vector α n} {bs : Vector β n} {i : Nat} {h : i < n}
(zip as bs)[i] = (as[i], bs[i]) :=
getElem_zipWith ..
theorem zip_eq_zipWith (as : Vector α n) (bs : Vector β n) : zip as bs = zipWith Prod.mk as bs := by
theorem zip_eq_zipWith {as : Vector α n} {bs : Vector β n} : zip as bs = zipWith Prod.mk as bs := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.zip_eq_zipWith, h]
theorem zip_map (f : α γ) (g : β δ) (as : Vector α n) (bs : Vector β n) :
theorem zip_map {f : α γ} {g : β δ} {as : Vector α n} {bs : Vector β n} :
zip (as.map f) (bs.map g) = (zip as bs).map (Prod.map f g) := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.zip_map, h]
theorem zip_map_left (f : α γ) (as : Vector α n) (bs : Vector β n) :
theorem zip_map_left {f : α γ} {as : Vector α n} {bs : Vector β n} :
zip (as.map f) bs = (zip as bs).map (Prod.map f id) := by rw [ zip_map, map_id]
theorem zip_map_right (f : β γ) (as : Vector α n) (bs : Vector β n) :
theorem zip_map_right {f : β γ} {as : Vector α n} {bs : Vector β n} :
zip as (bs.map f) = (zip as bs).map (Prod.map id f) := by rw [ zip_map, map_id]
theorem zip_append {as : Vector α n} {bs : Vector β n} {as' : Vector α m} {bs' : Vector β m} :
@@ -202,7 +201,7 @@ theorem zip_append {as : Vector α n} {bs : Vector β n} {as' : Vector α m} {bs
rcases bs' with bs', h'
simp [Array.zip_append, h, h']
theorem zip_map' (f : α β) (g : α γ) (xs : Vector α n) :
theorem zip_map' {f : α β} {g : α γ} {xs : Vector α n} :
zip (xs.map f) (xs.map g) = xs.map fun a => (f a, g a) := by
rcases xs with xs, rfl
simp [Array.zip_map']
@@ -212,26 +211,28 @@ theorem of_mem_zip {a b} {as : Vector α n} {bs : Vector β n} : (a, b) ∈ zip
rcases bs with bs, h
simpa using Array.of_mem_zip
theorem map_fst_zip (as : Vector α n) (bs : Vector β n) :
-- The argument `as` is explicit so we can rewrite from right to left.
theorem map_fst_zip (as : Vector α n) {bs : Vector β n} :
map Prod.fst (zip as bs) = as := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.map_fst_zip, h]
theorem map_snd_zip (as : Vector α n) (bs : Vector β n) :
-- The argument `bs` is explicit so we can rewrite from right to left.
theorem map_snd_zip {as : Vector α n} (bs : Vector β n) :
map Prod.snd (zip as bs) = bs := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.map_snd_zip, h]
theorem map_prod_left_eq_zip {xs : Vector α n} (f : α β) :
theorem map_prod_left_eq_zip {xs : Vector α n} {f : α β} :
(xs.map fun x => (x, f x)) = xs.zip (xs.map f) := by
rcases xs with xs, rfl
rw [ zip_map']
congr
simp
theorem map_prod_right_eq_zip {xs : Vector α n} (f : α β) :
theorem map_prod_right_eq_zip {xs : Vector α n} {f : α β} :
(xs.map fun x => (f x, x)) = (xs.map f).zip xs := by
rcases xs with xs, rfl
rw [ zip_map']
@@ -260,10 +261,11 @@ abbrev zip_mkVector := @zip_replicate
cases xs
simp_all
theorem unzip_eq_map (xs : Vector (α × β) n) : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by
theorem unzip_eq_map {xs : Vector (α × β) n} : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by
cases xs
simp [List.unzip_eq_map]
-- The argument `xs` is explicit so we can rewrite from right to left.
theorem zip_unzip (xs : Vector (α × β) n) : zip (unzip xs).1 (unzip xs).2 = xs := by
cases xs
simp only [unzip_mk, mk_zip_mk, Array.zip_unzip]

View File

@@ -98,7 +98,7 @@ theorem combo_eq_smul_add_smul (a : Int) (xs : Coeffs) (b : Int) (ys : Coeffs) :
theorem gcd_dvd_dot_left (xs ys : Coeffs) : (gcd xs : Int) dot xs ys :=
IntList.gcd_dvd_dot_left xs ys
theorem map_length {xs : Coeffs} : (xs.map f).length xs.length :=
Nat.le_of_eq (List.length_map xs f)
Nat.le_of_eq (List.length_map f)
theorem dot_nil_right {xs : Coeffs} : dot xs .nil = 0 := IntList.dot_nil_right
theorem get_nil : get .nil i = 0 := IntList.get_nil

View File

@@ -355,7 +355,7 @@ theorem dot_eq_zero_of_left_eq_zero {xs ys : IntList} (h : ∀ x, x ∈ xs → x
cases ys with
| nil => rfl
| cons y ys =>
rw [dot_cons₂, h x (List.mem_cons_self _ _), ih (fun x m => h x (List.mem_cons_of_mem _ m)),
rw [dot_cons₂, h x List.mem_cons_self, ih (fun x m => h x (List.mem_cons_of_mem _ m)),
Int.zero_mul, Int.add_zero]
@[simp] theorem nil_dot (xs : IntList) : dot [] xs = 0 := rfl
@@ -377,7 +377,7 @@ theorem dot_sdiv_left (xs ys : IntList) {d : Int} (h : d xs.gcd) :
abbrev bmod (x : IntList) (m : Nat) : IntList := x.map (Int.bmod · m)
theorem bmod_length (x : IntList) (m) : (bmod x m).length x.length :=
Nat.le_of_eq (List.length_map _ _)
Nat.le_of_eq (List.length_map _)
/--
The difference between the balanced mod of a dot product,

View File

@@ -121,7 +121,7 @@ theorem nonzeroMininum_map_le_nonzeroMinimum (f : α → β) (p : α → Nat) (q
have := nonzeroMinimum_eq_of_nonzero z
simp only [mem_map] at this
obtain x, a, m, rfl, eq := this
refine .inr q (f a), List.mem_map_of_mem _ (List.mem_map_of_mem _ m), ?_, ?_
refine .inr q (f a), List.mem_map_of_mem (List.mem_map_of_mem m), ?_, ?_
· rw [eq] at z
apply w _ m z
· rwa [Ne, h _ m, eq]

View File

@@ -101,7 +101,7 @@ theorem exists_bucket_of_uset [BEq α] [Hashable α]
k : α, (mkIdx self.size (by omega) (hash k)).1.toNat = i.toNat
containsKey k l = false) := by
have h₀ : 0 < self.size := by omega
obtain l₁, l₂, h₁, h₂, h₃ := Array.exists_of_uset self i d hi
obtain l₁, l₂, h₁, h₂, h₃ := Array.exists_of_uset hi
refine l₁.flatMap AssocList.toList ++ l₂.flatMap AssocList.toList, ?_, ?_, ?_
· rw [toListModel, h₁]
simpa using perm_append_comm_assoc _ _ _

View File

@@ -303,7 +303,7 @@ theorem expand.go_eq [BEq α] [Hashable α] [PartialEquivBEq α] (source : Array
refine ih.trans ?_
simp only [AssocList.foldl_eq, Array.toList_set]
rw [List.drop_eq_getElem_cons hi, List.flatMap_cons, List.foldl_append,
List.drop_set_of_lt _ _ (by omega), Array.getElem_toList]
List.drop_set_of_lt (by omega), Array.getElem_toList]
· next i source target hi =>
rw [expand.go_neg hi, List.drop_eq_nil_of_le, flatMap_nil, foldl_nil]
rwa [Array.size_eq_length_toList, Nat.not_lt] at hi
@@ -515,7 +515,7 @@ theorem wfImp_replaceₘ [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α
theorem toListModel_consₘ [BEq α] [Hashable α] [PartialEquivBEq α] [LawfulHashable α]
(m : Raw₀ α β) (h : Raw.WFImp m.1) (a : α) (b : β a) :
Perm (toListModel (m.consₘ a b).1.buckets) (a, b :: (toListModel m.1.2)) :=
toListModel_updateBucket h .rfl (fun _ => Perm.cons _) (fun _ => cons_append _ _ _)
toListModel_updateBucket h .rfl (fun _ => Perm.cons _) (fun _ => cons_append)
theorem isHashSelf_consₘ [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] (m : Raw₀ α β)
(h : Raw.WFImp m.1) (a : α) (b : β a) : IsHashSelf (m.consₘ a b).1.buckets := by

View File

@@ -43,7 +43,7 @@ theorem Ordered.right [Ord α] {sz k v l r} (h : (.inner sz k v l r : Impl α β
theorem Ordered.compare_left [Ord α] {sz k v l r} (h : (.inner sz k v l r : Impl α β).Ordered)
{k'} (hk' : k' l.toListModel) : compare k'.1 k = .lt :=
h.rel_of_mem_append hk' (List.mem_cons_self _ _)
h.rel_of_mem_append hk' List.mem_cons_self
theorem Ordered.compare_left_beq_gt [Ord α] [TransOrd α] {k : α Ordering} [IsStrictCut compare k]
{sz k' v' l r} (ho : (.inner sz k' v' l r : Impl α β).Ordered) (hcmp : (k k').isGE)

View File

@@ -225,7 +225,7 @@ theorem toListModel_find?_of_lt [Ord α] [TransOrd α] {k : α → Ordering} [Is
(inner sz k' v' l r : Impl α β).toListModel.find? (k ·.1 == .eq) =
l.toListModel.find? (k ·.1 == .eq) := by
rw [toListModel_inner, List.find?_append, Option.or_eq_left_of_none]
rw [List.find?_cons_of_neg _ (by simp [hcmp])]
rw [List.find?_cons_of_neg (by simp [hcmp])]
refine List.find?_eq_none.2 (fun p hp => by simp [IsCut.lt hcmp (ho.compare_right hp)])
theorem toListModel_filter_lt_of_gt [Ord α] [TransOrd α] {k : α Ordering} [IsCut compare k]

View File

@@ -115,7 +115,7 @@ theorem getEntry?_eq_some_iff [BEq α] [EquivBEq α] {l : List ((a : α) × β a
· rfl
· exfalso
rename_i h
have := hd.1 _ <| keys_eq_map List.mem_map_of_mem _ h
have := hd.1 _ <| keys_eq_map List.mem_map_of_mem h
simp_all [BEq.trans hlkk hbeq]
· rename_i h
replace h := h.imp BEq.symm
@@ -617,7 +617,7 @@ theorem getKey?_eq_getEntry? [BEq α] {l : List ((a : α) × β a)} {a : α} :
theorem fst_mem_keys_of_mem [BEq α] [EquivBEq α] {a : (a : α) × β a} {l : List ((a : α) × β a)}
(hm : a l) : a.1 keys l :=
keys_eq_map List.mem_map_of_mem _ hm
keys_eq_map List.mem_map_of_mem hm
theorem getKey?_eq_some_iff [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k k'}
(hd : DistinctKeys l) :
@@ -1632,7 +1632,7 @@ theorem keys_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)
theorem DistinctKeys.eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α} :
DistinctKeys l DistinctKeys (eraseKey k l) := by
apply distinctKeys_of_sublist_keys (by simpa using erase_sublist _ _)
apply distinctKeys_of_sublist_keys (by simpa using erase_sublist)
theorem getEntry?_eraseKey_self [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α}
(h : DistinctKeys l) : getEntry? k (eraseKey k l) = none := by
@@ -1691,7 +1691,7 @@ theorem DistinctKeys.filterMap [BEq α] [PartialEquivBEq α] {l : List ((a : α)
apply distinctKeys_of_sublist_keys
rw [keys_filterMap, keys_eq_map, keys_eq_map]
apply Sublist.map
exact filter_sublist l
exact filter_sublist
theorem DistinctKeys.map [BEq α] {l : List ((a : α) × β a)} {f : (a : α) β a γ a}
(h : DistinctKeys l) : DistinctKeys (l.map fun p => p.1, f p.1 p.2) :=
@@ -1699,7 +1699,7 @@ theorem DistinctKeys.map [BEq α] {l : List ((a : α) × β a)} {f : (a : α)
theorem DistinctKeys.filter [BEq α] {l : List ((a : α) × β a)} {f : (a : α) β a Bool}
(h : DistinctKeys l) : DistinctKeys (l.filter fun p => f p.1 p.2) :=
distinctKeys_of_sublist (filter_sublist _) h
distinctKeys_of_sublist filter_sublist h
section
@@ -2450,7 +2450,7 @@ theorem insertList_cons_perm [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α)
simp only [getEntry?_insertEntry]
split <;> rename_i hp <;> split <;> rename_i hh <;> try rfl
rw [DistinctKeys.def] at hl₂
have := List.rel_of_pairwise_cons hl₂ (List.mem_cons_self _ _)
have := List.rel_of_pairwise_cons hl₂ List.mem_cons_self
simp [BEq.trans hh (BEq.symm hp)] at this
theorem getEntry?_insertList [BEq α] [EquivBEq α]
@@ -2853,7 +2853,7 @@ theorem length_insertListConst_le [BEq α]
{l : List ((_ : α) × β)} {toInsert : List (α × β)} :
(insertListConst l toInsert).length l.length + toInsert.length := by
unfold insertListConst
rw [ List.length_map toInsert Prod.toSigma]
rw [ List.length_map Prod.toSigma]
apply length_insertList_le
theorem isEmpty_insertListConst [BEq α]

View File

@@ -60,7 +60,7 @@ def relabel (r : α → β) (f : CNF α) : CNF β := f.map (Clause.relabel r)
induction f <;> simp_all
@[simp] theorem relabel_append : relabel r (f1 ++ f2) = relabel r f1 ++ relabel r f2 :=
List.map_append _ _ _
List.map_append
@[simp] theorem relabel_relabel : relabel r1 (relabel r2 f) = relabel (r1 r2) f := by
simp only [relabel, List.map_map, Clause.relabel_relabel']

View File

@@ -110,7 +110,7 @@ theorem readyForRupAdd_ofArray {n : Nat} (arr : Array (Option (DefaultClause n))
have hb : (Array.replicate n unassigned).size = n := by simp only [Array.size_replicate]
have hl (acc : Array Assignment) (ih : acc.size = n) (cOpt : Option (DefaultClause n)) (_cOpt_in_arr : cOpt arr.toList) :
(ofArray_fold_fn acc cOpt).size = n := by rw [size_ofArray_fold_fn acc cOpt, ih]
exact List.foldlRecOn arr.toList ofArray_fold_fn (.replicate n unassigned) hb hl
exact List.foldlRecOn arr.toList ofArray_fold_fn hb hl
apply Exists.intro hsize
let ModifiedAssignmentsInvariant (assignments : Array Assignment) : Prop :=
hsize : assignments.size = n,
@@ -185,7 +185,7 @@ theorem readyForRupAdd_ofArray {n : Nat} (arr : Array (Option (DefaultClause n))
· next i_ne_l =>
simp only [Array.getElem_modify_of_ne (Ne.symm i_ne_l)] at h
exact ih i b h
rcases List.foldlRecOn arr.toList ofArray_fold_fn (.replicate n unassigned) hb hl with _h_size, h'
rcases List.foldlRecOn arr.toList ofArray_fold_fn hb hl with _h_size, h'
intro i b h
simp only [ofArray, Array.foldl_toList] at h
exact h' i b h
@@ -379,7 +379,7 @@ theorem mem_of_insertRupUnits {n : Nat} (f : DefaultFormula n) (units : CNF.Clau
· exact ih l l_in_acc
· rw [l_eq_unit]
exact Or.inr unit_in_units
have h_insertUnit_fold := List.foldlRecOn units insertUnit (f.rupUnits, f.assignments, false) hb hl
have h_insertUnit_fold := List.foldlRecOn units insertUnit hb hl
rcases h with h | i, h1, h2 | h1, h2 | h
· exact Or.inr <| Or.inl h
· rcases h_insertUnit_fold (i, false) h1 with h_insertUnit_fold | h_insertUnit_fold
@@ -416,7 +416,7 @@ theorem mem_of_insertRatUnits {n : Nat} (f : DefaultFormula n) (units : CNF.Clau
· exact ih l l_in_acc
· rw [l_eq_unit]
exact Or.inr unit_in_units
have h_insertUnit_fold := List.foldlRecOn units insertUnit (f.ratUnits, f.assignments, false) hb hl
have h_insertUnit_fold := List.foldlRecOn units insertUnit hb hl
rcases h with h | h | i, h1, h2 | h1, h2
· exact Or.inr <| Or.inl h
· exact (Or.inr Or.inr Or.inl) h
@@ -610,11 +610,11 @@ theorem readyForRupAdd_delete {n : Nat} (f : DefaultFormula n) (arr : Array Nat)
· have hb : f.rupUnits = #[] := h.1
have hl (acc : DefaultFormula n) (ih : acc.rupUnits = #[]) (id : Nat) (_id_in_arr : id arr.toList) :
(deleteOne acc id).rupUnits = #[] := by rw [deleteOne_preserves_rupUnits, ih]
exact List.foldlRecOn arr.toList deleteOne f hb hl
exact List.foldlRecOn arr.toList deleteOne hb hl
· have hb : StrongAssignmentsInvariant f := h.2
have hl (acc : DefaultFormula n) (ih : StrongAssignmentsInvariant acc) (id : Nat) (_id_in_arr : id arr.toList) :
StrongAssignmentsInvariant (deleteOne acc id) := deleteOne_preserves_strongAssignmentsInvariant acc id ih
exact List.foldlRecOn arr.toList deleteOne f hb hl
exact List.foldlRecOn arr.toList deleteOne hb hl
theorem deleteOne_preserves_ratUnits {n : Nat} (f : DefaultFormula n) (id : Nat) :
(deleteOne f id).ratUnits = f.ratUnits := by
@@ -629,7 +629,7 @@ theorem readyForRatAdd_delete {n : Nat} (f : DefaultFormula n) (arr : Array Nat)
have hb : f.ratUnits = #[] := h.1
have hl (acc : DefaultFormula n) (ih : acc.ratUnits = #[]) (id : Nat) (_id_in_arr : id arr.toList) :
(deleteOne acc id).ratUnits = #[] := by rw [deleteOne_preserves_ratUnits, ih]
exact List.foldlRecOn arr.toList deleteOne f hb hl
exact List.foldlRecOn arr.toList deleteOne hb hl
· exact readyForRupAdd_delete f arr h.2
theorem deleteOne_subset (f : DefaultFormula n) (id : Nat) (c : DefaultClause n) :
@@ -663,7 +663,7 @@ theorem delete_subset (f : DefaultFormula n) (arr : Array Nat) (c : DefaultClaus
have hb : c toList f c toList f := id
have hl (f' : DefaultFormula n) (ih : c toList f' c toList f) (id : Nat) (_ : id arr.toList) :
c toList (deleteOne f' id) c toList f := by intro h; exact ih <| deleteOne_subset f' id c h
exact List.foldlRecOn arr.toList deleteOne f hb hl
exact List.foldlRecOn arr.toList deleteOne hb hl
end DefaultFormula

View File

@@ -131,7 +131,7 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen
exact k_property
· intro h
simp only [ h, not_true, mostRecentUnitIdx] at hk
rw [Array.getElem_push_lt _ _ _ k_in_bounds]
rw [Array.getElem_push_lt k_in_bounds]
rw [i_eq_l] at h2
exact h2 k.1, k_in_bounds
· next i_ne_l =>
@@ -190,7 +190,7 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen
refine j.1, j_lt_updatedUnits_size, mostRecentUnitIdx, i_gt_zero, ?_
simp only [insertUnit, h5, ite_false, Array.getElem_push_eq, ne_eq, reduceCtorEq]
constructor
· rw [Array.getElem_push_lt units l j.1 j.2, h1]
· rw [Array.getElem_push_lt, h1]
· constructor
· simp +zetaDelta [i_eq_l, hl]
rfl
@@ -230,7 +230,7 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen
· simp +zetaDelta [i_eq_l, hl]
rfl
· constructor
· rw [Array.getElem_push_lt units l j.1 j.2, h1]
· rw [Array.getElem_push_lt, h1]
· constructor
· simp only [i_eq_l]
rw [Array.getElem_modify_self]
@@ -273,7 +273,7 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen
refine j.1, j_lt_updatedUnits_size, b,i_gt_zero, ?_
simp only [insertUnit, h5, ite_false, reduceCtorEq]
constructor
· rw [Array.getElem_push_lt units l j.1 j.2, h1]
· rw [Array.getElem_push_lt, h1]
· constructor
· rw [Array.getElem_modify_of_ne (Ne.symm i_ne_l), h2]
· constructor
@@ -305,11 +305,11 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen
constructor
· split
· exact h1
· simp only [Array.getElem_push_lt units l j1.1 j1.2, h1]
· simp only [Array.getElem_push_lt j1.2, h1]
· constructor
· split
· exact h2
· simp only [Array.getElem_push_lt units l j2.1 j2.2, h2]
· simp only [Array.getElem_push_lt j2.2, h2]
· constructor
· split
· exact h3
@@ -477,7 +477,7 @@ theorem size_clearUnit_foldl {α : Type u} (assignments : Array Assignment)
have hb : assignments.size = assignments.size := rfl
have hl (assignments' : Array Assignment) (hsize : assignments'.size = assignments.size) (a : α) (_ : a l) :
(f assignments' a).size = assignments.size := by rw [f_preserves_size assignments' a, hsize]
exact List.foldlRecOn l f assignments hb hl
exact List.foldlRecOn l f hb hl
def ClearInsertInductionMotive {n : Nat} (f : DefaultFormula n) (assignments_size : f.assignments.size = n)
(units : Array (Literal (PosFin n))) :
@@ -743,7 +743,7 @@ theorem size_assignments_performRupCheck {n : Nat} (f : DefaultFormula n) (rupHi
(id : Nat) (_ : id rupHints.toList) : (confirmRupHint f.clauses acc id).1.size = f.assignments.size := by
have h := size_assignemnts_confirmRupHint f.clauses acc.1 acc.2.1 acc.2.2.1 acc.2.2.2 id
rw [h, hsize]
exact List.foldlRecOn rupHints.toList (confirmRupHint f.clauses) (f.assignments, [], false, false) hb hl
exact List.foldlRecOn rupHints.toList (confirmRupHint f.clauses) hb hl
def DerivedLitsInvariant {n : Nat} (f : DefaultFormula n)
(fassignments_size : f.assignments.size = n) (assignments : Array Assignment)

View File

@@ -88,7 +88,7 @@ theorem contradiction_of_insertUnit_fold_success {n : Nat} (assignments : Array
intro insertUnit_res_success
rcases h with acc_size, h
exact contradiction_of_insertUnit_success acc.2.1 acc_size acc.1 acc.2.2 l' h insertUnit_res_success
rcases List.foldlRecOn l insertUnit acc0 hb hl with _, h
rcases List.foldlRecOn l insertUnit hb hl with _, h
exact h insertUnit_fold_success
theorem mem_insertUnit_units {n : Nat} (units : Array (Literal (PosFin n))) (assignments : Array Assignment)
@@ -118,7 +118,7 @@ theorem mem_insertUnit_fold_units {n : Nat} (units : Array (Literal (PosFin n)))
· rw [l'_eq_l'']
exact Or.inl l''_in_l
· exact h l' l'_in_acc
exact List.foldlRecOn l insertUnit (units, assignments, foundContradiction) hb hl
exact List.foldlRecOn l insertUnit hb hl
theorem sat_of_insertRup {n : Nat} (f : DefaultFormula n) (f_readyForRupAdd : ReadyForRupAdd f) (c : DefaultClause n)
(p : PosFin n Bool) (pf : p f) :
@@ -394,7 +394,7 @@ theorem unsat_of_encounteredBoth {n : Nat} (c : DefaultClause n)
simp [heq, has_both] at hp
· simp at h
· simp at h
exact List.foldlRecOn c.clause (reduce_fold_fn assignment) reducedToEmpty hb hl
exact List.foldlRecOn c.clause (reduce_fold_fn assignment) hb hl
def ReducePostconditionInductionMotive (c_arr : Array (Literal (PosFin n)))
(assignment : Array Assignment) (idx : Nat) (res : ReduceResult (PosFin n)) :

View File

@@ -6,7 +6,7 @@ def myfun (x : Array α) (i : Fin x.size) : Array α :=
let next := 2*i.1 + 1
if h : next < x.size then
have : x.size - next < x.size - i.1 := sorry
myfun (x.swap i next) next, (x.size_swap _ _).symm h
myfun (x.swap i next) next, (x.size_swap).symm h
else
x
termination_by x.size - i.1

View File

@@ -1,7 +1,7 @@
def Array.swaps (a : Array α) : List (Fin a.size × Fin a.size) Array α
| [] => a
| (i, j) :: ijs =>
have : (a.swap i j).size = a.size := a.size_swap _ _
have : (a.swap i j).size = a.size := a.size_swap
swaps (a.swap i j) (ijs.map (fun p => p.1.1, by simp, p.2.1, by simp))
termination_by l => l.length

View File

@@ -1,6 +1,6 @@
theorem all_eq_not_any_not (l : List α) (p : α Bool) :
l.all p = !l.any fun x => binderNameHint x p (!p x)
:= List.all_eq_not_any_not l p
:= List.all_eq_not_any_not
/--
error: tactic 'fail' failed

View File

@@ -14,7 +14,7 @@ example (as bs cs : Array α) (v : α)
theorem Array.getElem_set_ne_abstracted (xs : Array α) (i : Nat) (h' : i < xs.size) (v : α) {j : Nat}
(pj : j < xs.size) (h : i j) :
(xs.set i v)[j]'(by as_aux_lemma => simp [*]) = xs[j] := Array.getElem_set_ne xs i h' v pj h
(xs.set i v)[j]'(by as_aux_lemma => simp [*]) = xs[j] := Array.getElem_set_ne h' pj h
example (as bs cs : Array α) (v : α)
(i : Nat)

View File

@@ -27,11 +27,11 @@ def heapifyDown (lt : αα → Bool) (a : Array α) (i : Fin a.size) :
if lt a[j.1] a[right] then right, h, right_le else j else j
if h : i.1 = j then a, rfl else
let a' := a.swap i j
let j' := j, by rw [a.size_swap i j]; exact j.1.2
let j' := j, by rw [a.size_swap]; exact j.1.2
have : a'.size - j < a.size - i := by
rw [a.size_swap i j]; sorry
rw [a.size_swap]; sorry
let a₂, h₂ := heapifyDown lt a' j'
a₂, h₂.trans (a.size_swap i j)
a₂, h₂.trans a.size_swap
termination_by a.size - i
decreasing_by assumption
@@ -62,8 +62,8 @@ if i0 : i.1 = 0 then ⟨a, rfl⟩ else
let j : Fin a.size := (i.1 - 1) / 2, Nat.lt_trans this i.2
if lt a[j] a[i] then
let a' := a.swap i j
let a₂, h₂ := heapifyUp lt a' j.1, by rw [a.size_swap i j]; exact j.2
a₂, h₂.trans (a.size_swap i j)
let a₂, h₂ := heapifyUp lt a' j.1, by rw [a.size_swap]; exact j.2
a₂, h₂.trans (a.size_swap)
else a, rfl
termination_by i.1
decreasing_by assumption

View File

@@ -49,7 +49,7 @@ theorem ex12 {α : Type u} {n : Nat}
(a b : Array α)
(hsz₁ : a.size = n) (hsz₂ : b.size = n)
(h : (i : Nat) (hi : i < n), a.getLit i hsz₁ hi = b.getLit i hsz₂ hi) : a = b :=
Array.ext a b (hsz₁.trans hsz₂.symm) fun i hi₁ hi₂ => h i (hsz₁ hi₁)
Array.ext (hsz₁.trans hsz₂.symm) fun i hi₁ hi₂ => h i (hsz₁ hi₁)
def toArrayLit {α : Type u} (a : Array α) (n : Nat) (hsz : a.size = n) : Array α :=
List.toArray $ Array.toListLitAux a n hsz n (hsz Nat.le_refl _) []