diff --git a/src/Init/Data/Array/Attach.lean b/src/Init/Data/Array/Attach.lean index 6188478d63..1901f916fe 100644 --- a/src/Init/Data/Array/Attach.lean +++ b/src/Init/Data/Array/Attach.lean @@ -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] diff --git a/src/Init/Data/List/Attach.lean b/src/Init/Data/List/Attach.lean index aadae89a26..2e3bf485ce 100644 --- a/src/Init/Data/List/Attach.lean +++ b/src/Init/Data/List/Attach.lean @@ -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] diff --git a/src/Init/Data/Option/Attach.lean b/src/Init/Data/Option/Attach.lean index e3e1fe1bc2..051fe89163 100644 --- a/src/Init/Data/Option/Attach.lean +++ b/src/Init/Data/Option/Attach.lean @@ -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 diff --git a/src/Init/Data/Vector/Attach.lean b/src/Init/Data/Vector/Attach.lean index e5398a712f..15647493b4 100644 --- a/src/Init/Data/Vector/Attach.lean +++ b/src/Init/Data/Vector/Attach.lean @@ -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