Compare commits

...

1 Commits

Author SHA1 Message Date
Kim Morrison
a25b95ffe6 feat: grind annotations for List/Array/Vector.attach/pmap 2025-06-19 14:46:35 +10:00
4 changed files with 164 additions and 126 deletions

View File

@@ -68,15 +68,15 @@ well-founded recursion mechanism to prove that the function terminates.
l.toArray.pmap f H = (l.pmap f (by simpa using H)).toArray := by
simp [pmap]
@[simp] theorem toList_attachWith {xs : Array α} {P : α Prop} {H : x xs, P x} :
@[simp, grind =] theorem toList_attachWith {xs : Array α} {P : α Prop} {H : x xs, P x} :
(xs.attachWith P H).toList = xs.toList.attachWith P (by simpa [mem_toList_iff] using H) := by
simp [attachWith]
@[simp] theorem toList_attach {xs : Array α} :
@[simp, grind =] theorem toList_attach {xs : Array α} :
xs.attach.toList = xs.toList.attachWith (· xs) (by simp [mem_toList_iff]) := by
simp [attach]
@[simp] theorem toList_pmap {xs : Array α} {P : α Prop} {f : a, P a β} {H : a xs, P a} :
@[simp, grind =] theorem toList_pmap {xs : Array α} {P : α Prop} {f : a, P a β} {H : a xs, P a} :
(xs.pmap f H).toList = xs.toList.pmap f (fun a m => H a (mem_def.mpr m)) := by
simp [pmap]
@@ -92,16 +92,16 @@ well-founded recursion mechanism to prove that the function terminates.
intro a m h₁ h₂
congr
@[simp] theorem pmap_empty {P : α Prop} (f : a, P a β) : pmap f #[] (by simp) = #[] := rfl
@[simp, grind =] theorem pmap_empty {P : α Prop} (f : a, P a β) : pmap f #[] (by simp) = #[] := rfl
@[simp] theorem pmap_push {P : α Prop} (f : a, P a β) (a : α) (xs : Array α) (h : b xs.push a, P b) :
@[simp, grind =] theorem pmap_push {P : α Prop} (f : a, P a β) (a : α) (xs : Array α) (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]
@[simp] theorem attach_empty : (#[] : Array α).attach = #[] := rfl
@[simp, grind =] theorem attach_empty : (#[] : Array α).attach = #[] := rfl
@[simp] theorem attachWith_empty {P : α Prop} (H : x #[], P x) : (#[] : Array α).attachWith P H = #[] := rfl
@[simp, grind =] theorem attachWith_empty {P : α Prop} (H : x #[], P x) : (#[] : Array α).attachWith P H = #[] := rfl
@[simp] theorem _root_.List.attachWith_mem_toArray {l : List α} :
l.attachWith (fun x => x l.toArray) (fun x h => by simpa using h) =
@@ -122,11 +122,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]
@[grind =]
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]
@[grind =]
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
@@ -142,14 +144,14 @@ theorem attachWith_congr {xs ys : Array α} (w : xs = ys) {P : α → Prop} {H :
subst w
simp
@[simp] theorem attach_push {a : α} {xs : Array α} :
@[simp, grind =] theorem attach_push {a : α} {xs : Array α} :
(xs.push a).attach =
(xs.attach.map (fun x, h => x, mem_push_of_mem a h)).push a, by simp := by
cases xs
rw [attach_congr (List.push_toArray _ _)]
simp [Function.comp_def]
@[simp] theorem attachWith_push {a : α} {xs : Array α} {P : α Prop} {H : x xs.push a, P x} :
@[simp, grind =] theorem attachWith_push {a : α} {xs : Array α} {P : α Prop} {H : x xs.push a, P x} :
(xs.push a).attachWith P H =
(xs.attachWith P (fun x h => by simp at H; exact H x (.inl h))).push a, H a (by simp) := by
cases xs
@@ -189,38 +191,39 @@ theorem attachWith_map_subtype_val {p : α → Prop} {xs : Array α} (H : ∀ a
(xs.attachWith p H).map Subtype.val = xs := by
cases xs; simp
@[simp]
@[simp, grind]
theorem mem_attach (xs : Array α) : x, x xs.attach
| a, h => by
have := mem_map.1 (by rw [attach_map_subtype_val] <;> exact h)
rcases this with _, _, m, rfl
exact m
@[simp]
@[simp, grind]
theorem mem_attachWith {xs : Array α} {q : α Prop} (H) (x : {x // q x}) :
x xs.attachWith q H x.1 xs := by
cases xs
simp
@[simp]
@[simp, grind =]
theorem mem_pmap {p : α Prop} {f : a, p a β} {xs H b} :
b pmap f xs H (a : _) (h : a xs), f a (H a h) = b := by
simp only [pmap_eq_map_attach, mem_map, mem_attach, true_and, Subtype.exists, eq_comm]
@[grind]
theorem mem_pmap_of_mem {p : α Prop} {f : a, p a β} {xs H} {a} (h : a xs) :
f a (H a h) pmap f xs H := by
rw [mem_pmap]
exact a, h, rfl
@[simp]
@[simp, grind =]
theorem size_pmap {p : α Prop} {f : a, p a β} {xs H} : (pmap f xs H).size = xs.size := by
cases xs; simp
@[simp]
@[simp, grind =]
theorem size_attach {xs : Array α} : xs.attach.size = xs.size := by
cases xs; simp
@[simp]
@[simp, grind =]
theorem size_attachWith {p : α Prop} {xs : Array α} {H} : (xs.attachWith p H).size = xs.size := by
cases xs; simp
@@ -252,13 +255,13 @@ theorem attachWith_ne_empty_iff {xs : Array α} {P : α → Prop} {H : ∀ a ∈
xs.attachWith P H #[] xs #[] := by
cases xs; simp
@[simp]
@[simp, grind =]
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]
@[simp, grind =]
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) :
(pmap f xs h)[i] =
@@ -266,57 +269,59 @@ theorem getElem_pmap {p : α → Prop} (f : ∀ a, p a → β) {xs : Array α} (
(h _ (getElem_mem (@size_pmap _ _ p f xs h hi))) := by
cases xs; simp
@[simp]
@[simp, grind =]
theorem getElem?_attachWith {xs : Array α} {i : Nat} {P : α Prop} {H : a xs, P a} :
(xs.attachWith P H)[i]? = xs[i]?.pmap Subtype.mk (fun _ a => H _ (mem_of_getElem? a)) :=
getElem?_pmap ..
@[simp]
@[simp, grind =]
theorem getElem?_attach {xs : Array α} {i : Nat} :
xs.attach[i]? = xs[i]?.pmap Subtype.mk (fun _ a => mem_of_getElem? a) :=
getElem?_attachWith
@[simp]
@[simp, grind =]
theorem getElem_attachWith {xs : Array α} {P : α Prop} {H : a xs, P a}
{i : Nat} (h : i < (xs.attachWith P H).size) :
(xs.attachWith P H)[i] = xs[i]'(by simpa using h), H _ (getElem_mem (by simpa using h)) :=
getElem_pmap _ _ h
@[simp]
@[simp, grind =]
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, grind =] 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, grind =] 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
@[grind =]
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]
@[grind =]
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
@[simp, grind =] theorem foldl_attachWith
{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
@[simp, grind =] theorem foldr_attachWith
{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
@@ -361,18 +366,20 @@ theorem foldr_attach {xs : Array α} {f : α → β → β} {b : β} :
ext
simpa using fun a => List.mem_of_getElem? a
@[grind =]
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
@[grind =]
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}
@[simp, grind =] theorem map_attachWith {xs : Array α} {P : α Prop} {H : (a : α), a xs P a}
{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
@@ -393,6 +400,7 @@ theorem map_attach_eq_pmap {xs : Array α} {f : { x // x ∈ xs } → β} :
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
abbrev map_attach := @map_attach_eq_pmap
@[grind =]
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
@@ -400,6 +408,7 @@ theorem attach_filterMap {xs : Array α} {f : α → Option β} :
rw [attach_congr List.filterMap_toArray]
simp [List.attach_filterMap, List.map_filterMap, Function.comp_def]
@[grind =]
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
@@ -409,7 +418,7 @@ theorem attach_filter {xs : Array α} (p : α → Bool) :
-- We are still missing here `attachWith_filterMap` and `attachWith_filter`.
@[simp]
@[simp, grind =]
theorem filterMap_attachWith {q : α Prop} {xs : Array α} {f : {x // q x} Option β} (H)
(w : stop = (xs.attachWith q H).size) :
(xs.attachWith q H).filterMap f 0 stop = xs.attach.filterMap (fun x, h => f x, H _ h) := by
@@ -417,7 +426,7 @@ theorem filterMap_attachWith {q : α → Prop} {xs : Array α} {f : {x // q x}
cases xs
simp [Function.comp_def]
@[simp]
@[simp, grind =]
theorem filter_attachWith {q : α Prop} {xs : Array α} {p : {x // q x} Bool} (H)
(w : stop = (xs.attachWith q H).size) :
(xs.attachWith q H).filter p 0 stop =
@@ -426,6 +435,7 @@ theorem filter_attachWith {q : α → Prop} {xs : Array α} {p : {x // q x} →
cases xs
simp [Function.comp_def, List.filter_map]
@[grind =]
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
@@ -433,7 +443,7 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} {g : ∀ a, p a → β} {f
cases xs
simp [List.pmap_pmap, List.pmap_map]
@[simp] theorem pmap_append {p : ι Prop} {f : a : ι, p a α} {xs ys : Array ι}
@[simp, grind =] 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)) ++
@@ -448,7 +458,7 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs ys : Arr
xs.pmap f h₁ ++ ys.pmap f h₂ :=
pmap_append _
@[simp] theorem attach_append {xs ys : Array α} :
@[simp, grind =] 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
@@ -456,59 +466,62 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs ys : Arr
rw [attach_congr (List.append_toArray _ _)]
simp [List.attach_append, Function.comp_def]
@[simp] theorem attachWith_append {P : α Prop} {xs ys : Array α}
@[simp, grind =] theorem attachWith_append {P : α Prop} {xs ys : Array α}
{H : (a : α), a xs ++ ys P a} :
(xs ++ ys).attachWith P H = xs.attachWith P (fun a h => H a (mem_append_left ys h)) ++
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, grind =] 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
@[grind =]
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]
@[simp] theorem attachWith_reverse {P : α Prop} {xs : Array α}
@[simp, grind =] theorem attachWith_reverse {P : α Prop} {xs : Array α}
{H : (a : α), a xs.reverse P a} :
xs.reverse.attachWith P H =
(xs.attachWith P (fun a h => H a (by simpa using h))).reverse := by
cases xs
simp
@[grind =]
theorem reverse_attachWith {P : α Prop} {xs : Array α}
{H : (a : α), a xs P a} :
(xs.attachWith P H).reverse = (xs.reverse.attachWith P (fun a h => H a (by simpa using h))) := by
cases xs
simp
@[simp] theorem attach_reverse {xs : Array α} :
@[simp, grind =] 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]
simp
@[grind =]
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, grind =] 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
simp
@[simp] theorem back?_attachWith {P : α Prop} {xs : Array α}
@[simp, grind =] theorem back?_attachWith {P : α Prop} {xs : Array α}
{H : (a : α), a xs P a} :
(xs.attachWith P H).back? = xs.back?.pbind (fun a h => some a, H _ (mem_of_back? h)) := by
cases xs
simp
@[simp]
@[simp, grind =]
theorem back?_attach {xs : Array α} :
xs.attach.back? = xs.back?.pbind fun a h => some a, mem_of_back? h := by
cases xs
@@ -526,7 +539,7 @@ theorem countP_attachWith {p : α → Prop} {q : α → Bool} {xs : Array α} {H
cases xs
simp
@[simp]
@[simp, grind =]
theorem count_attach [BEq α] {xs : Array α} {a : {x // x xs}} :
xs.attach.count a = xs.count a := by
rcases xs with xs
@@ -535,13 +548,13 @@ theorem count_attach [BEq α] {xs : Array α} {a : {x // x ∈ xs}} :
simp only [Subtype.beq_iff]
rw [List.countP_pmap, List.countP_attach (p := (fun x => x == a.1)), List.count]
@[simp]
@[simp, grind =]
theorem count_attachWith [BEq α] {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, grind =] 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]

View File

@@ -69,14 +69,14 @@ 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, grind =] 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, grind =] 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
@[simp, grind =] theorem attach_nil : ([] : List α).attach = [] := rfl
@[simp] theorem attachWith_nil : ([] : List α).attachWith P H = [] := rfl
@[simp, grind =] theorem attachWith_nil : ([] : List α).attachWith P H = [] := rfl
@[simp]
theorem pmap_eq_map {p : α Prop} {f : α β} {l : List α} (H) :
@@ -92,12 +92,14 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a,
| cons x l ih =>
rw [pmap, pmap, h _ mem_cons_self, ih fun a ha => h a (mem_cons_of_mem _ ha)]
@[grind =]
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]
@[grind =]
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
@@ -114,7 +116,7 @@ theorem attachWith_congr {l₁ l₂ : List α} (w : l₁ = l₂) {P : α → Pro
subst w
simp
@[simp] theorem attach_cons {x : α} {xs : List α} :
@[simp, grind =] theorem attach_cons {x : α} {xs : List α} :
(x :: xs).attach =
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]
@@ -122,7 +124,7 @@ theorem attachWith_congr {l₁ l₂ : List α} (w : l₁ = l₂) {P : α → Pro
intros a _ m' _
rfl
@[simp]
@[simp, grind =]
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) ::
xs.attachWith p (fun a ha h a (mem_cons_of_mem x ha)) :=
@@ -162,14 +164,14 @@ theorem attachWith_map_subtype_val {p : α → Prop} {l : List α} (H : ∀ a
(l.attachWith p H).map Subtype.val = l :=
(attachWith_map_val _).trans (List.map_id _)
@[simp]
@[simp, grind]
theorem mem_attach (l : List α) : x, x l.attach
| a, h => by
have := mem_map.1 (by rw [attach_map_subtype_val]; exact h)
rcases this with _, _, m, rfl
exact m
@[simp]
@[simp, grind]
theorem mem_attachWith {l : List α} {q : α Prop} (H) (x : {x // q x}) :
x l.attachWith q H x.1 l := by
induction l with
@@ -182,27 +184,28 @@ theorem mem_attachWith {l : List α} {q : α → Prop} (H) (x : {x // q x}) :
· simp [ h]
· simp_all
@[simp]
@[simp, grind =]
theorem mem_pmap {p : α Prop} {f : a, p a β} {l H b} :
b pmap f l H (a : _) (h : a l), f a (H a h) = b := by
simp only [pmap_eq_map_attach, mem_map, mem_attach, true_and, Subtype.exists, eq_comm]
@[grind]
theorem mem_pmap_of_mem {p : α Prop} {f : a, p a β} {l H} {a} (h : a l) :
f a (H a h) pmap f l H := by
rw [mem_pmap]
exact a, h, rfl
@[simp]
@[simp, grind =]
theorem length_pmap {p : α Prop} {f : a, p a β} {l H} : (pmap f l H).length = l.length := by
induction l
· rfl
· simp only [*, pmap, length]
@[simp]
@[simp, grind =]
theorem length_attach {l : List α} : l.attach.length = l.length :=
length_pmap
@[simp]
@[simp, grind =]
theorem length_attachWith {p : α Prop} {l H} : length (l.attachWith p H) = length l :=
length_pmap
@@ -237,7 +240,7 @@ theorem attachWith_ne_nil_iff {l : List α} {P : α → Prop} {H : ∀ a ∈ l,
l.attachWith P H [] l [] :=
pmap_ne_nil_iff _ _
@[simp]
@[simp, grind =]
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
@@ -255,7 +258,7 @@ theorem get?_pmap {p : α → Prop} (f : ∀ a, p a → β) {l : List α} (h :
simp [getElem?_pmap, h]
-- The argument `f` is explicit to allow rewriting from right to left.
@[simp]
@[simp, grind =]
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) :
(pmap f l h)[i] =
@@ -279,40 +282,40 @@ theorem get_pmap {p : α → Prop} (f : ∀ a, p a → β) {l : List α} (h :
simp only [get_eq_getElem]
simp [getElem_pmap]
@[simp]
@[simp, grind =]
theorem getElem?_attachWith {xs : List α} {i : Nat} {P : α Prop} {H : a xs, P a} :
(xs.attachWith P H)[i]? = xs[i]?.pmap Subtype.mk (fun _ a => H _ (mem_of_getElem? a)) :=
getElem?_pmap ..
@[simp]
@[simp, grind =]
theorem getElem?_attach {xs : List α} {i : Nat} :
xs.attach[i]? = xs[i]?.pmap Subtype.mk (fun _ a => mem_of_getElem? a) :=
getElem?_attachWith
@[simp]
@[simp, grind =]
theorem getElem_attachWith {xs : List α} {P : α Prop} {H : a xs, P a}
{i : Nat} (h : i < (xs.attachWith P H).length) :
(xs.attachWith P H)[i] = xs[i]'(by simpa using h), H _ (getElem_mem (by simpa using h)) :=
getElem_pmap ..
@[simp]
@[simp, grind =]
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, grind =] 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, grind =] 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, grind =] 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
@@ -321,67 +324,69 @@ 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, grind =] 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
| nil => simp at h
| cons x xs ih => simp [head_pmap, ih]
@[simp] theorem head?_attachWith {P : α Prop} {xs : List α}
@[simp, grind =] theorem head?_attachWith {P : α Prop} {xs : List α}
(H : (a : α), a xs P a) :
(xs.attachWith P H).head? = xs.head?.pbind (fun a h => some a, H _ (mem_of_head? h)) := by
cases xs <;> simp_all
@[simp] theorem head_attachWith {P : α Prop} {xs : List α}
@[simp, grind =] theorem head_attachWith {P : α Prop} {xs : List α}
{H : (a : α), a xs P a} (h : xs.attachWith P H []) :
(xs.attachWith P H).head h = xs.head (by simpa using h), H _ (head_mem _) := by
cases xs with
| nil => simp at h
| cons x xs => simp [head_attachWith, h]
@[simp] theorem head?_attach {xs : List α} :
@[simp, grind =] theorem head?_attach {xs : List α} :
xs.attach.head? = xs.head?.pbind (fun a h => some a, mem_of_head? h) := by
cases xs <;> simp_all
@[simp] theorem head_attach {xs : List α} (h) :
@[simp, grind =] theorem head_attach {xs : List α} (h) :
xs.attach.head h = xs.head (by simpa using h), head_mem (by simpa using h) := by
cases xs with
| nil => simp at h
| cons x xs => simp [head_attach, h]
@[simp] theorem tail_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
@[simp, grind =] 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
@[simp] theorem tail_attachWith {P : α Prop} {xs : List α}
@[simp, grind =] theorem tail_attachWith {P : α Prop} {xs : List α}
{H : (a : α), a xs P a} :
(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, grind =] 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
@[grind]
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]
@[grind]
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
@[simp, grind =] theorem foldl_attachWith
{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
@[simp, grind =] theorem foldr_attachWith
{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
@@ -420,16 +425,18 @@ theorem foldr_attach {l : List α} {f : α → β → β} {b : β} :
| nil => simp
| cons a l ih => rw [foldr_cons, attach_cons, foldr_cons, foldr_map, ih]
@[grind =]
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 [*]
@[grind =]
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}
@[simp, grind =] theorem map_attachWith {l : List α} {P : α Prop} {H : (a : α), a l P a}
{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
@@ -458,6 +465,7 @@ theorem map_attach_eq_pmap {l : List α} {f : { x // x ∈ l } → β} :
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
abbrev map_attach := @map_attach_eq_pmap
@[grind =]
theorem attach_filterMap {l : List α} {f : α Option β} :
(l.filterMap f).attach = l.attach.filterMap
fun x, h => (f x).pbind (fun b m => some b, mem_filterMap.mpr x, h, m) := by
@@ -488,6 +496,7 @@ theorem attach_filterMap {l : List α} {f : α → Option β} :
ext
simp
@[grind =]
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
@@ -499,7 +508,7 @@ theorem attach_filter {l : List α} (p : α → Bool) :
-- We are still missing here `attachWith_filterMap` and `attachWith_filter`.
@[simp]
@[simp, grind =]
theorem filterMap_attachWith {q : α Prop} {l : List α} {f : {x // q x} Option β} (H) :
(l.attachWith q H).filterMap f = l.attach.filterMap (fun x, h => f x, H _ h) := by
induction l with
@@ -508,7 +517,7 @@ theorem filterMap_attachWith {q : α → Prop} {l : List α} {f : {x // q x} →
simp only [attachWith_cons, filterMap_cons]
split <;> simp_all [Function.comp_def]
@[simp]
@[simp, grind =]
theorem filter_attachWith {q : α Prop} {l : List α} {p : {x // q x} Bool} (H) :
(l.attachWith q H).filter p =
(l.attach.filter (fun x, h => p x, H _ h)).map (fun x, h => x, H _ h) := by
@@ -518,13 +527,14 @@ 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]
@[grind =]
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, grind =] 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)) ++
@@ -541,47 +551,50 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {l₁ l₂ :
l₁.pmap f h₁ ++ l₂.pmap f h₂ :=
pmap_append _
@[simp] theorem attach_append {xs ys : List α} :
@[simp, grind =] 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]
congr 1 <;>
exact pmap_congr_left _ fun _ _ _ _ => rfl
@[simp] theorem attachWith_append {P : α Prop} {xs ys : List α}
@[simp, grind =] theorem attachWith_append {P : α Prop} {xs ys : List α}
{H : (a : α), a xs ++ ys P a} :
(xs ++ ys).attachWith P H = xs.attachWith P (fun a h => H a (mem_append_left ys h)) ++
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, grind =] 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
@[grind =]
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]
@[simp] theorem attachWith_reverse {P : α Prop} {xs : List α}
@[simp, grind =] theorem attachWith_reverse {P : α Prop} {xs : List α}
{H : (a : α), a xs.reverse P a} :
xs.reverse.attachWith P H =
(xs.attachWith P (fun a h => H a (by simpa using h))).reverse :=
pmap_reverse ..
@[grind =]
theorem reverse_attachWith {P : α Prop} {xs : List α}
{H : (a : α), a xs P a} :
(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, grind =] 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
@[grind =]
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]
@@ -589,7 +602,7 @@ theorem reverse_attach {xs : List α} :
intros
rfl
@[simp] theorem getLast?_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
@[simp, grind =] 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]
@@ -597,30 +610,30 @@ theorem reverse_attach {xs : List α} :
simp only [Option.map_map]
congr
@[simp] theorem getLast_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
@[simp, grind =] 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]
simp only [reverse_pmap, head_pmap, head_reverse]
@[simp] theorem getLast?_attachWith {P : α Prop} {xs : List α}
@[simp, grind =] theorem getLast?_attachWith {P : α Prop} {xs : List α}
{H : (a : α), a xs P a} :
(xs.attachWith P H).getLast? = xs.getLast?.pbind (fun a h => some a, H _ (mem_of_getLast? h)) := by
rw [getLast?_eq_head?_reverse, reverse_attachWith, head?_attachWith]
simp
@[simp] theorem getLast_attachWith {P : α Prop} {xs : List α}
@[simp, grind =] theorem getLast_attachWith {P : α Prop} {xs : List α}
{H : (a : α), a xs P a} (h : xs.attachWith P H []) :
(xs.attachWith P H).getLast h = xs.getLast (by simpa using h), H _ (getLast_mem _) := by
simp only [getLast_eq_head_reverse, reverse_attachWith, head_attachWith, head_map]
@[simp]
@[simp, grind =]
theorem getLast?_attach {xs : List α} :
xs.attach.getLast? = xs.getLast?.pbind fun a h => some a, mem_of_getLast? h := by
rw [getLast?_eq_head?_reverse, reverse_attach, head?_map, head?_attach]
simp
@[simp]
@[simp, grind =]
theorem getLast_attach {xs : List α} (h : xs.attach []) :
xs.attach.getLast h = xs.getLast (by simpa using h), getLast_mem (by simpa using h) := by
simp only [getLast_eq_head_reverse, reverse_attach, head_map, head_attach]
@@ -640,12 +653,12 @@ theorem count_attach [BEq α] {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
@[simp]
@[simp, grind =]
theorem count_attachWith [BEq α] {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 _
@[simp] theorem countP_pmap {p : α Prop} {g : a, p a β} {f : β Bool} {l : List α} (H₁) :
@[simp, grind =] 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]

View File

@@ -95,6 +95,7 @@ theorem attach_eq_some : ∀ (o : Option α) (x : {x // o = some x}), o.attach =
| none, x, h => by simp at h
| some a, x, h => by simpa using h
@[grind]
theorem mem_attach : (o : Option α) (x : {x // o = some x}), x o.attach :=
attach_eq_some

View File

@@ -43,41 +43,41 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep
with the same elements but in the type `{x // x ∈ xs}`. -/
@[inline, expose] def attach (xs : Vector α n) : Vector {x // x xs} n := xs.attachWith _ fun _ => id
@[simp] theorem attachWith_mk {xs : Array α} {h : xs.size = n} {P : α Prop} {H : x mk xs h, P x} :
@[simp, grind =] theorem attachWith_mk {xs : Array α} {h : xs.size = n} {P : α Prop} {H : x mk xs h, P x} :
(mk xs h).attachWith P H = mk (xs.attachWith P (by simpa using H)) (by simpa using h) := by
simp [attachWith]
@[simp] theorem attach_mk {xs : Array α} {h : xs.size = n} :
@[simp, grind =] theorem attach_mk {xs : Array α} {h : xs.size = n} :
(mk xs h).attach = mk (xs.attachWith (· mk xs h) (by simp)) (by simpa using h):= by
simp [attach]
@[simp] theorem pmap_mk {xs : Array α} {h : xs.size = n} {P : α Prop} {f : a, P a β}
@[simp, grind =] theorem pmap_mk {xs : Array α} {h : xs.size = n} {P : α Prop} {f : a, P a β}
{H : a mk xs h, P a} :
(mk xs h).pmap f H = mk (xs.pmap f (by simpa using H)) (by simpa using h) := by
simp [pmap]
@[simp] theorem toArray_attachWith {xs : Vector α n} {P : α Prop} {H : x xs, P x} :
@[simp, grind =] theorem toArray_attachWith {xs : Vector α n} {P : α Prop} {H : x xs, P x} :
(xs.attachWith P H).toArray = xs.toArray.attachWith P (by simpa using H) := by
simp [attachWith]
@[simp] theorem toArray_attach {xs : Vector α n} :
@[simp, grind =] theorem toArray_attach {xs : Vector α n} :
xs.attach.toArray = xs.toArray.attachWith (· xs) (by simp) := by
simp [attach]
@[simp] theorem toArray_pmap {xs : Vector α n} {P : α Prop} {f : a, P a β} {H : a xs, P a} :
@[simp, grind =] theorem toArray_pmap {xs : Vector α n} {P : α Prop} {f : a, P a β} {H : a xs, P a} :
(xs.pmap f H).toArray = xs.toArray.pmap f (fun a m => H a (by simpa using m)) := by
simp [pmap]
@[simp] theorem toList_attachWith {xs : Vector α n} {P : α Prop} {H : x xs, P x} :
@[simp, grind =] theorem toList_attachWith {xs : Vector α n} {P : α Prop} {H : x xs, P x} :
(xs.attachWith P H).toList = xs.toList.attachWith P (by simpa using H) := by
rcases xs with xs, rfl
simp
@[simp] theorem toList_attach {xs : Vector α n} :
@[simp, grind =] theorem toList_attach {xs : Vector α n} :
xs.attach.toList = xs.toList.attachWith (· xs) (by simp) := by
simp [attach]
@[simp] theorem toList_pmap {xs : Vector α n} {P : α Prop} {f : a, P a β} {H : a xs, P a} :
@[simp, grind =] theorem toList_pmap {xs : Vector α n} {P : α Prop} {f : a, P a β} {H : a xs, P a} :
(xs.pmap f H).toList = xs.toList.pmap f (fun a m => H a (by simpa using m)) := by
rcases xs with xs, rfl
simp
@@ -94,16 +94,16 @@ 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, grind =] 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, grind =] 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]
@[simp] theorem attach_empty : (#v[] : Vector α 0).attach = #v[] := rfl
@[simp, grind =] theorem attach_empty : (#v[] : Vector α 0).attach = #v[] := rfl
@[simp] theorem attachWith_empty {P : α Prop} (H : x #v[], P x) : (#v[] : Vector α 0).attachWith P H = #v[] := rfl
@[simp, grind =] 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) :
@@ -117,11 +117,13 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a,
apply Array.pmap_congr_left
simpa using h
@[grind =]
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]
@[grind =]
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
@@ -137,13 +139,13 @@ theorem attachWith_congr {xs ys : Vector α n} (w : xs = ys) {P : α → Prop} {
subst w
simp
@[simp] theorem attach_push {a : α} {xs : Vector α n} :
@[simp, grind =] theorem attach_push {a : α} {xs : Vector α n} :
(xs.push a).attach =
(xs.attach.map (fun x, h => x, mem_push_of_mem a h)).push a, by simp := by
rcases xs with xs, rfl
simp [Array.map_attach_eq_pmap]
@[simp] theorem attachWith_push {a : α} {xs : Vector α n} {P : α Prop} {H : x xs.push a, P x} :
@[simp, grind =] theorem attachWith_push {a : α} {xs : Vector α n} {P : α Prop} {H : x xs.push a, P x} :
(xs.push a).attachWith P H =
(xs.attachWith P (fun x h => by simp at H; exact H x (.inl h))).push a, H a (by simp) := by
rcases xs with xs, rfl
@@ -188,24 +190,25 @@ theorem attachWith_map_subtype_val {p : α → Prop} {xs : Vector α n} (H : ∀
rcases xs with xs, rfl
simp
@[simp]
@[simp, grind]
theorem mem_attach (xs : Vector α n) : x, x xs.attach
| a, h => by
have := mem_map.1 (by rw [attach_map_subtype_val] <;> exact h)
rcases this with _, _, m, rfl
exact m
@[simp]
@[simp, grind]
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
@[simp]
@[simp, grind =]
theorem mem_pmap {p : α Prop} {f : a, p a β} {xs : Vector α n} {H b} :
b pmap f xs H (a : _) (h : a xs), f a (H a h) = b := by
simp only [pmap_eq_map_attach, mem_map, mem_attach, true_and, Subtype.exists, eq_comm]
@[grind]
theorem mem_pmap_of_mem {p : α Prop} {f : a, p a β} {xs : Vector α n} {H} {a} (h : a xs) :
f a (H a h) pmap f xs H := by
rw [mem_pmap]
@@ -216,59 +219,61 @@ theorem pmap_eq_self {xs : Vector α n} {p : α → Prop} {hp : ∀ (a : α), a
rcases xs with xs, rfl
simp [Array.pmap_eq_self]
@[simp]
@[simp, grind =]
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]
@[simp, grind =]
theorem getElem_pmap {p : α Prop} (f : a, p a β) {xs : Vector α n} (h : a xs, p a) {i : Nat}
(hn : i < n) :
(pmap f xs h)[i] = f (xs[i]) (h _ (by simp)) := by
rcases xs with xs, rfl
simp
@[simp]
@[simp, grind =]
theorem getElem?_attachWith {xs : Vector α n} {i : Nat} {P : α Prop} {H : a xs, P a} :
(xs.attachWith P H)[i]? = xs[i]?.pmap Subtype.mk (fun _ a => H _ (mem_of_getElem? a)) :=
getElem?_pmap ..
@[simp]
@[simp, grind =]
theorem getElem?_attach {xs : Vector α n} {i : Nat} :
xs.attach[i]? = xs[i]?.pmap Subtype.mk (fun _ a => mem_of_getElem? a) :=
getElem?_attachWith
@[simp]
@[simp, grind =]
theorem getElem_attachWith {xs : Vector α n} {P : α Prop} {H : a xs, P a}
{i : Nat} (h : i < n) :
(xs.attachWith P H)[i] = xs[i]'(by simpa using h), H _ (getElem_mem (by simpa using h)) :=
getElem_pmap _ _ h
@[simp]
@[simp, grind =]
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, grind =] 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, grind =] 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
@[grind =]
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]
@[grind =]
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
@@ -304,18 +309,20 @@ theorem foldr_attach {xs : Vector α n} {f : α → β → β} {b : β} :
rcases xs with xs, rfl
simp [Array.foldr_attach]
@[grind =]
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
@[grind =]
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}
@[simp, grind =] theorem map_attachWith {xs : Vector α n} {P : α Prop} {H : (a : α), a xs P a}
{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
@@ -337,6 +344,7 @@ 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
@[grind =]
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
@@ -344,7 +352,7 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} {g : ∀ a, p a → β} {f
rcases xs with xs, rfl
ext <;> simp
@[simp] theorem pmap_append {p : ι Prop} {f : a : ι, p a α} {xs : Vector ι n} {ys : Vector ι m}
@[simp, grind =] 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)) ++
@@ -359,66 +367,69 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs : Vector
xs.pmap f h₁ ++ ys.pmap f h₂ :=
pmap_append _
@[simp] theorem attach_append {xs : Vector α n} {ys : Vector α m} :
@[simp, grind =] 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
rcases ys with ys, rfl
simp [Array.map_attach_eq_pmap]
@[simp] theorem attachWith_append {P : α Prop} {xs : Vector α n} {ys : Vector α m}
@[simp, grind =] theorem attachWith_append {P : α Prop} {xs : Vector α n} {ys : Vector α m}
{H : (a : α), a xs ++ ys P a} :
(xs ++ ys).attachWith P H = xs.attachWith P (fun a h => H a (mem_append_left ys h)) ++
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, grind =] 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
@[grind =]
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]
@[simp] theorem attachWith_reverse {P : α Prop} {xs : Vector α n}
@[simp, grind =] theorem attachWith_reverse {P : α Prop} {xs : Vector α n}
{H : (a : α), a xs.reverse P a} :
xs.reverse.attachWith P H =
(xs.attachWith P (fun a h => H a (by simpa using h))).reverse := by
cases xs
simp
@[grind =]
theorem reverse_attachWith {P : α Prop} {xs : Vector α n}
{H : (a : α), a xs P a} :
(xs.attachWith P H).reverse = (xs.reverse.attachWith P (fun a h => H a (by simpa using h))) := by
cases xs
simp
@[simp] theorem attach_reverse {xs : Vector α n} :
@[simp, grind =] 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]
@[grind =]
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, grind =] 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
simp
@[simp] theorem back?_attachWith {P : α Prop} {xs : Vector α n}
@[simp, grind =] theorem back?_attachWith {P : α Prop} {xs : Vector α n}
{H : (a : α), a xs P a} :
(xs.attachWith P H).back? = xs.back?.pbind (fun a h => some a, H _ (mem_of_back? h)) := by
cases xs
simp
@[simp]
@[simp, grind =]
theorem back?_attach {xs : Vector α n} :
xs.attach.back? = xs.back?.pbind fun a h => some a, mem_of_back? h := by
cases xs
@@ -436,13 +447,13 @@ theorem countP_attachWith {p : α → Prop} {q : α → Bool} {xs : Vector α n}
cases xs
simp
@[simp]
@[simp, grind =]
theorem count_attach [BEq α] {xs : Vector α n} {a : {x // x xs}} :
xs.attach.count a = xs.count a := by
rcases xs with xs, rfl
simp
@[simp]
@[simp, grind =]
theorem count_attachWith [BEq α] {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