diff --git a/src/Init/Data/Array/Attach.lean b/src/Init/Data/Array/Attach.lean index 8239e7f832..11b3645d5e 100644 --- a/src/Init/Data/Array/Attach.lean +++ b/src/Init/Data/Array/Attach.lean @@ -109,7 +109,7 @@ well-founded recursion mechanism to prove that the function terminates. simp @[simp] -theorem pmap_eq_map (p : α → Prop) (f : α → β) (xs : Array α) (H) : +theorem pmap_eq_map {p : α → Prop} {f : α → β} {xs : Array α} (H) : @pmap _ _ p (fun a _ => f a) xs H = map f xs := by cases xs; simp @@ -120,13 +120,13 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a, simp only [List.pmap_toArray, mk.injEq] rw [List.pmap_congr_left _ h] -theorem map_pmap {p : α → Prop} (g : β → γ) (f : ∀ a, p a → β) (xs H) : +theorem map_pmap {p : α → Prop} {g : β → γ} {f : ∀ a, p a → β} {xs : Array α} (H) : map g (pmap f xs H) = pmap (fun a h => g (f a h)) xs H := by cases xs simp [List.map_pmap] -theorem pmap_map {p : β → Prop} (g : ∀ b, p b → γ) (f : α → β) (xs H) : - pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem _ h) := by +theorem pmap_map {p : β → Prop} {g : ∀ b, p b → γ} {f : α → β} {xs : Array α} (H) : + pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem h) := by cases xs simp [List.pmap_map] @@ -153,13 +153,13 @@ theorem attachWith_congr {xs ys : Array α} (w : xs = ys) {P : α → Prop} {H : cases xs simp [attachWith_congr (List.push_toArray _ _)] -theorem pmap_eq_map_attach {p : α → Prop} (f : ∀ a, p a → β) (xs H) : +theorem pmap_eq_map_attach {p : α → Prop} {f : ∀ a, p a → β} {xs : Array α} (H) : pmap f xs H = xs.attach.map fun x => f x.1 (H _ x.2) := by cases xs simp [List.pmap_eq_map_attach] @[simp] -theorem pmap_eq_attachWith {p q : α → Prop} (f : ∀ a, p a → q a) (xs H) : +theorem pmap_eq_attachWith {p q : α → Prop} {f : ∀ a, p a → q a} {xs : Array α} (H) : pmap (fun a h => ⟨a, f a h⟩) xs H = xs.attachWith q (fun x h => f x (H x h)) := by cases xs simp [List.pmap_eq_attachWith] @@ -172,17 +172,18 @@ theorem attach_map_val (xs : Array α) (f : α → β) : @[deprecated attach_map_val (since := "2025-02-17")] abbrev attach_map_coe := @attach_map_val +-- The argument `xs : Array α` is explicit to allow rewriting from right to left. theorem attach_map_subtype_val (xs : Array α) : xs.attach.map Subtype.val = xs := by cases xs; simp -theorem attachWith_map_val {p : α → Prop} (f : α → β) (xs : Array α) (H : ∀ a ∈ xs, p a) : +theorem attachWith_map_val {p : α → Prop} {f : α → β} {xs : Array α} (H : ∀ a ∈ xs, p a) : ((xs.attachWith p H).map fun (i : { i // p i}) => f i) = xs.map f := by cases xs; simp @[deprecated attachWith_map_val (since := "2025-02-17")] abbrev attachWith_map_coe := @attachWith_map_val -theorem attachWith_map_subtype_val {p : α → Prop} (xs : Array α) (H : ∀ a ∈ xs, p a) : +theorem attachWith_map_subtype_val {p : α → Prop} {xs : Array α} (H : ∀ a ∈ xs, p a) : (xs.attachWith p H).map Subtype.val = xs := by cases xs; simp @@ -194,7 +195,7 @@ theorem mem_attach (xs : Array α) : ∀ x, x ∈ xs.attach exact m @[simp] -theorem mem_attachWith (xs : Array α) {q : α → Prop} (H) (x : {x // q x}) : +theorem mem_attachWith {xs : Array α} {q : α → Prop} (H) (x : {x // q x}) : x ∈ xs.attachWith q H ↔ x.1 ∈ xs := by cases xs simp @@ -250,10 +251,11 @@ theorem attachWith_ne_empty_iff {xs : Array α} {P : α → Prop} {H : ∀ a ∈ cases xs; simp @[simp] -theorem getElem?_pmap {p : α → Prop} (f : ∀ a, p a → β) {xs : Array α} (h : ∀ a ∈ xs, p a) (i : Nat) : +theorem getElem?_pmap {p : α → Prop} {f : ∀ a, p a → β} {xs : Array α} (h : ∀ a ∈ xs, p a) (i : Nat) : (pmap f xs h)[i]? = Option.pmap f xs[i]? fun x H => h x (mem_of_getElem? H) := by cases xs; simp +-- The argument `f` is explicit to allow rewriting from right to left. @[simp] theorem getElem_pmap {p : α → Prop} (f : ∀ a, p a → β) {xs : Array α} (h : ∀ a ∈ xs, p a) {i : Nat} (hi : i < (pmap f xs h).size) : @@ -283,37 +285,37 @@ theorem getElem_attach {xs : Array α} {i : Nat} (h : i < xs.attach.size) : xs.attach[i] = ⟨xs[i]'(by simpa using h), getElem_mem (by simpa using h)⟩ := getElem_attachWith h -@[simp] theorem pmap_attach (xs : Array α) {p : {x // x ∈ xs} → Prop} (f : ∀ a, p a → β) (H) : +@[simp] theorem pmap_attach {xs : Array α} {p : {x // x ∈ xs} → Prop} {f : ∀ a, p a → β} (H) : pmap f xs.attach H = xs.pmap (P := fun a => ∃ h : a ∈ xs, p ⟨a, h⟩) (fun a h => f ⟨a, h.1⟩ h.2) (fun a h => ⟨h, H ⟨a, h⟩ (by simp)⟩) := by ext <;> simp -@[simp] theorem pmap_attachWith (xs : Array α) {p : {x // q x} → Prop} (f : ∀ a, p a → β) (H₁ H₂) : +@[simp] theorem pmap_attachWith {xs : Array α} {p : {x // q x} → Prop} {f : ∀ a, p a → β} (H₁ H₂) : pmap f (xs.attachWith q H₁) H₂ = xs.pmap (P := fun a => ∃ h : q a, p ⟨a, h⟩) (fun a h => f ⟨a, h.1⟩ h.2) (fun a h => ⟨H₁ _ h, H₂ ⟨a, H₁ _ h⟩ (by simpa)⟩) := by ext <;> simp -theorem foldl_pmap (xs : Array α) {P : α → Prop} (f : (a : α) → P a → β) - (H : ∀ (a : α), a ∈ xs → P a) (g : γ → β → γ) (x : γ) : +theorem foldl_pmap {xs : Array α} {P : α → Prop} {f : (a : α) → P a → β} + (H : ∀ (a : α), a ∈ xs → P a) (g : γ → β → γ) (x : γ) : (xs.pmap f H).foldl g x = xs.attach.foldl (fun acc a => g acc (f a.1 (H _ a.2))) x := by rw [pmap_eq_map_attach, foldl_map] -theorem foldr_pmap (xs : Array α) {P : α → Prop} (f : (a : α) → P a → β) - (H : ∀ (a : α), a ∈ xs → P a) (g : β → γ → γ) (x : γ) : +theorem foldr_pmap {xs : Array α} {P : α → Prop} {f : (a : α) → P a → β} + (H : ∀ (a : α), a ∈ xs → P a) (g : β → γ → γ) (x : γ) : (xs.pmap f H).foldr g x = xs.attach.foldr (fun a acc => g (f a.1 (H _ a.2)) acc) x := by rw [pmap_eq_map_attach, foldr_map] @[simp] theorem foldl_attachWith - (xs : Array α) {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : β → { x // q x} → β} {b} (w : stop = xs.size) : + {xs : Array α} {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : β → { x // q x} → β} {b} (w : stop = xs.size) : (xs.attachWith q H).foldl f b 0 stop = xs.attach.foldl (fun b ⟨a, h⟩ => f b ⟨a, H _ h⟩) b := by subst w rcases xs with ⟨xs⟩ simp [List.foldl_attachWith, List.foldl_map] @[simp] theorem foldr_attachWith - (xs : Array α) {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : { x // q x} → β → β} {b} (w : start = xs.size) : + {xs : Array α} {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : { x // q x} → β → β} {b} (w : start = xs.size) : (xs.attachWith q H).foldr f b start 0 = xs.attach.foldr (fun a acc => f ⟨a.1, H _ a.2⟩ acc) b := by subst w rcases xs with ⟨xs⟩ @@ -329,7 +331,7 @@ Unfortunately this can't be applied by `simp` because of the higher order unific and even when rewriting we need to specify the function explicitly. See however `foldl_subtype` below. -/ -theorem foldl_attach (xs : Array α) (f : β → α → β) (b : β) : +theorem foldl_attach {xs : Array α} {f : β → α → β} {b : β} : xs.attach.foldl (fun acc t => f acc t.1) b = xs.foldl f b := by rcases xs with ⟨xs⟩ simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray, @@ -348,7 +350,7 @@ Unfortunately this can't be applied by `simp` because of the higher order unific and even when rewriting we need to specify the function explicitly. See however `foldr_subtype` below. -/ -theorem foldr_attach (xs : Array α) (f : α → β → β) (b : β) : +theorem foldr_attach {xs : Array α} {f : α → β → β} {b : β} : xs.attach.foldr (fun t acc => f t.1 acc) b = xs.foldr f b := by rcases xs with ⟨xs⟩ simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray, @@ -357,31 +359,31 @@ theorem foldr_attach (xs : Array α) (f : α → β → β) (b : β) : ext simpa using fun a => List.mem_of_getElem? a -theorem attach_map {xs : Array α} (f : α → β) : - (xs.map f).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨f x, mem_map_of_mem f h⟩) := by +theorem attach_map {xs : Array α} {f : α → β} : + (xs.map f).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨f x, mem_map_of_mem h⟩) := by cases xs ext <;> simp -theorem attachWith_map {xs : Array α} (f : α → β) {P : β → Prop} {H : ∀ (b : β), b ∈ xs.map f → P b} : - (xs.map f).attachWith P H = (xs.attachWith (P ∘ f) (fun _ h => H _ (mem_map_of_mem f h))).map +theorem attachWith_map {xs : Array α} {f : α → β} {P : β → Prop} (H : ∀ (b : β), b ∈ xs.map f → P b) : + (xs.map f).attachWith P H = (xs.attachWith (P ∘ f) (fun _ h => H _ (mem_map_of_mem h))).map fun ⟨x, h⟩ => ⟨f x, h⟩ := by cases xs simp [List.attachWith_map] @[simp] theorem map_attachWith {xs : Array α} {P : α → Prop} {H : ∀ (a : α), a ∈ xs → P a} - (f : { x // P x } → β) : + {f : { x // P x } → β} : (xs.attachWith P H).map f = xs.attach.map fun ⟨x, h⟩ => f ⟨x, H _ h⟩ := by cases xs <;> simp_all theorem map_attachWith_eq_pmap {xs : Array α} {P : α → Prop} {H : ∀ (a : α), a ∈ xs → P a} - (f : { x // P x } → β) : + {f : { x // P x } → β} : (xs.attachWith P H).map f = xs.pmap (fun a (h : a ∈ xs ∧ P a) => f ⟨a, H _ h.1⟩) (fun a h => ⟨h, H a h⟩) := by cases xs ext <;> simp /-- See also `pmap_eq_map_attach` for writing `pmap` in terms of `map` and `attach`. -/ -theorem map_attach_eq_pmap {xs : Array α} (f : { x // x ∈ xs } → β) : +theorem map_attach_eq_pmap {xs : Array α} {f : { x // x ∈ xs } → β} : xs.attach.map f = xs.pmap (fun a h => f ⟨a, h⟩) (fun _ => id) := by cases xs ext <;> simp @@ -393,14 +395,14 @@ theorem attach_filterMap {xs : Array α} {f : α → Option β} : (xs.filterMap f).attach = xs.attach.filterMap fun ⟨x, h⟩ => (f x).pbind (fun b m => some ⟨b, mem_filterMap.mpr ⟨x, h, m⟩⟩) := by cases xs - rw [attach_congr (List.filterMap_toArray f _)] + rw [attach_congr List.filterMap_toArray] simp [List.attach_filterMap, List.map_filterMap, Function.comp_def] theorem attach_filter {xs : Array α} (p : α → Bool) : (xs.filter p).attach = xs.attach.filterMap fun x => if w : p x.1 then some ⟨x.1, mem_filter.mpr ⟨x.2, w⟩⟩ else none := by cases xs - rw [attach_congr (List.filter_toArray p _)] + rw [attach_congr List.filter_toArray] simp [List.attach_filter, List.map_filterMap, Function.comp_def] -- We are still missing here `attachWith_filterMap` and `attachWith_filter`. @@ -422,14 +424,14 @@ theorem filter_attachWith {q : α → Prop} {xs : Array α} {p : {x // q x} → cases xs simp [Function.comp_def, List.filter_map] -theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f : ∀ b, q b → γ) (xs H₁ H₂) : +theorem pmap_pmap {p : α → Prop} {q : β → Prop} {g : ∀ a, p a → β} {f : ∀ b, q b → γ} {xs} (H₁ H₂) : pmap f (pmap g xs H₁) H₂ = pmap (α := { x // x ∈ xs }) (fun a h => f (g a h) (H₂ (g a h) (mem_pmap_of_mem a.2))) xs.attach (fun a _ => H₁ a a.2) := by cases xs simp [List.pmap_pmap, List.pmap_map] -@[simp] theorem pmap_append {p : ι → Prop} (f : ∀ a : ι, p a → α) (xs ys : Array ι) +@[simp] theorem pmap_append {p : ι → Prop} {f : ∀ a : ι, p a → α} {xs ys : Array ι} (h : ∀ a ∈ xs ++ ys, p a) : (xs ++ ys).pmap f h = (xs.pmap f fun a ha => h a (mem_append_left ys ha)) ++ @@ -438,13 +440,13 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f cases ys simp -theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (xs ys : Array α) +theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs ys : Array α} (h₁ : ∀ a ∈ xs, p a) (h₂ : ∀ a ∈ ys, p a) : ((xs ++ ys).pmap f fun a ha => (mem_append.1 ha).elim (h₁ a) (h₂ a)) = xs.pmap f h₁ ++ ys.pmap f h₂ := - pmap_append f xs ys _ + pmap_append _ -@[simp] theorem attach_append (xs ys : Array α) : +@[simp] theorem attach_append {xs ys : Array α} : (xs ++ ys).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨x, mem_append_left ys h⟩) ++ ys.attach.map fun ⟨x, h⟩ => ⟨x, mem_append_right xs h⟩ := by cases xs @@ -458,12 +460,12 @@ theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (xs ys : Arr ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by simp [attachWith, attach_append, map_pmap, pmap_append] -@[simp] theorem pmap_reverse {P : α → Prop} (f : (a : α) → P a → β) (xs : Array α) +@[simp] theorem pmap_reverse {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α} (H : ∀ (a : α), a ∈ xs.reverse → P a) : xs.reverse.pmap f H = (xs.pmap f (fun a h => H a (by simpa using h))).reverse := by induction xs <;> simp_all -theorem reverse_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : Array α) +theorem reverse_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α} (H : ∀ (a : α), a ∈ xs → P a) : (xs.pmap f H).reverse = xs.reverse.pmap f (fun a h => H a (by simpa using h)) := by rw [pmap_reverse] @@ -481,18 +483,18 @@ theorem reverse_attachWith {P : α → Prop} {xs : Array α} cases xs simp -@[simp] theorem attach_reverse (xs : Array α) : +@[simp] theorem attach_reverse {xs : Array α} : xs.reverse.attach = xs.attach.reverse.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by cases xs - rw [attach_congr (List.reverse_toArray _)] + rw [attach_congr List.reverse_toArray] simp -theorem reverse_attach (xs : Array α) : +theorem reverse_attach {xs : Array α} : xs.attach.reverse = xs.reverse.attach.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by cases xs simp -@[simp] theorem back?_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : Array α) +@[simp] theorem back?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α} (H : ∀ (a : α), a ∈ xs → P a) : (xs.pmap f H).back? = xs.attach.back?.map fun ⟨a, m⟩ => f a (H a m) := by cases xs @@ -511,19 +513,19 @@ theorem back?_attach {xs : Array α} : simp @[simp] -theorem countP_attach (xs : Array α) (p : α → Bool) : +theorem countP_attach {xs : Array α} {p : α → Bool} : xs.attach.countP (fun a : {x // x ∈ xs} => p a) = xs.countP p := by cases xs simp [Function.comp_def] @[simp] -theorem countP_attachWith {p : α → Prop} (xs : Array α) (H : ∀ a ∈ xs, p a) (q : α → Bool) : +theorem countP_attachWith {p : α → Prop} {q : α → Bool} {xs : Array α} {H : ∀ a ∈ xs, p a} : (xs.attachWith p H).countP (fun a : {x // p x} => q a) = xs.countP q := by cases xs simp @[simp] -theorem count_attach [DecidableEq α] (xs : Array α) (a : {x // x ∈ xs}) : +theorem count_attach [DecidableEq α] {xs : Array α} {a : {x // x ∈ xs}} : xs.attach.count a = xs.count ↑a := by rcases xs with ⟨xs⟩ simp only [List.attach_toArray, List.attachWith_mem_toArray, List.count_toArray] @@ -532,12 +534,12 @@ theorem count_attach [DecidableEq α] (xs : Array α) (a : {x // x ∈ xs}) : rw [List.countP_pmap, List.countP_attach (p := (fun x => x == a.1)), List.count] @[simp] -theorem count_attachWith [DecidableEq α] {p : α → Prop} (xs : Array α) (H : ∀ a ∈ xs, p a) (a : {x // p x}) : +theorem count_attachWith [DecidableEq α] {p : α → Prop} {xs : Array α} (H : ∀ a ∈ xs, p a) {a : {x // p x}} : (xs.attachWith p H).count a = xs.count ↑a := by cases xs simp -@[simp] theorem countP_pmap {p : α → Prop} (g : ∀ a, p a → β) (f : β → Bool) (xs : Array α) (H₁) : +@[simp] theorem countP_pmap {p : α → Prop} {g : ∀ a, p a → β} {f : β → Bool} {xs : Array α} (H₁) : (xs.pmap g H₁).countP f = xs.attach.countP (fun ⟨a, m⟩ => f (g a (H₁ a m))) := by simp [pmap_eq_map_attach, countP_map, Function.comp_def] @@ -752,65 +754,64 @@ abbrev unattach_mkArray := @unattach_replicate /-! ### Well-founded recursion preprocessing setup -/ -@[wf_preprocess] theorem Array.map_wfParam (xs : Array α) (f : α → β) : +@[wf_preprocess] theorem map_wfParam {xs : Array α} {f : α → β} : (wfParam xs).map f = xs.attach.unattach.map f := by simp [wfParam] -@[wf_preprocess] theorem Array.map_unattach (P : α → Prop) (xs : Array (Subtype P)) (f : α → β) : +@[wf_preprocess] theorem map_unattach {P : α → Prop} {xs : Array (Subtype P)} {f : α → β} : xs.unattach.map f = xs.map fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] -@[wf_preprocess] theorem foldl_wfParam (xs : Array α) (f : β → α → β) (x : β) : +@[wf_preprocess] theorem foldl_wfParam {xs : Array α} {f : β → α → β} {x : β} : (wfParam xs).foldl f x = xs.attach.unattach.foldl f x := by simp [wfParam] -@[wf_preprocess] theorem foldl_unattach (P : α → Prop) (xs : Array (Subtype P)) (f : β → α → β) (x : β): +@[wf_preprocess] theorem foldl_unattach {P : α → Prop} {xs : Array (Subtype P)} {f : β → α → β} {x : β} : xs.unattach.foldl f x = xs.foldl (fun s ⟨x, h⟩ => binderNameHint s f <| binderNameHint x (f s) <| binderNameHint h () <| f s (wfParam x)) x := by simp [wfParam] -@[wf_preprocess] theorem foldr_wfParam (xs : Array α) (f : α → β → β) (x : β) : +@[wf_preprocess] theorem foldr_wfParam {xs : Array α} {f : α → β → β} {x : β} : (wfParam xs).foldr f x = xs.attach.unattach.foldr f x := by simp [wfParam] -@[wf_preprocess] theorem foldr_unattach (P : α → Prop) (xs : Array (Subtype P)) (f : α → β → β) (x : β): +@[wf_preprocess] theorem foldr_unattach {P : α → Prop} {xs : Array (Subtype P)} {f : α → β → β} {x : β} : xs.unattach.foldr f x = xs.foldr (fun ⟨x, h⟩ s => binderNameHint x f <| binderNameHint s (f x) <| binderNameHint h () <| f (wfParam x) s) x := by simp [wfParam] -@[wf_preprocess] theorem filter_wfParam (xs : Array α) (f : α → Bool) : +@[wf_preprocess] theorem filter_wfParam {xs : Array α} {f : α → Bool} : (wfParam xs).filter f = xs.attach.unattach.filter f:= by simp [wfParam] -@[wf_preprocess] theorem filter_unattach (P : α → Prop) (xs : Array (Subtype P)) (f : α → Bool) : +@[wf_preprocess] theorem filter_unattach {P : α → Prop} {xs : Array (Subtype P)} {f : α → Bool} : xs.unattach.filter f = (xs.filter (fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x))).unattach := by simp [wfParam] -@[wf_preprocess] theorem reverse_wfParam (xs : Array α) : +@[wf_preprocess] theorem reverse_wfParam {xs : Array α} : (wfParam xs).reverse = xs.attach.unattach.reverse := by simp [wfParam] -@[wf_preprocess] theorem reverse_unattach (P : α → Prop) (xs : Array (Subtype P)) : +@[wf_preprocess] theorem reverse_unattach {P : α → Prop} {xs : Array (Subtype P)} : xs.unattach.reverse = xs.reverse.unattach := by simp -@[wf_preprocess] theorem filterMap_wfParam (xs : Array α) (f : α → Option β) : +@[wf_preprocess] theorem filterMap_wfParam {xs : Array α} {f : α → Option β} : (wfParam xs).filterMap f = xs.attach.unattach.filterMap f := by simp [wfParam] -@[wf_preprocess] theorem filterMap_unattach (P : α → Prop) (xs : Array (Subtype P)) (f : α → Option β) : +@[wf_preprocess] theorem filterMap_unattach {P : α → Prop} {xs : Array (Subtype P)} {f : α → Option β} : xs.unattach.filterMap f = xs.filterMap fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] -@[wf_preprocess] theorem flatMap_wfParam (xs : Array α) (f : α → Array β) : +@[wf_preprocess] theorem flatMap_wfParam {xs : Array α} {f : α → Array β} : (wfParam xs).flatMap f = xs.attach.unattach.flatMap f := by simp [wfParam] -@[wf_preprocess] theorem flatMap_unattach (P : α → Prop) (xs : Array (Subtype P)) (f : α → Array β) : +@[wf_preprocess] theorem flatMap_unattach {P : α → Prop} {xs : Array (Subtype P)} {f : α → Array β} : xs.unattach.flatMap f = xs.flatMap fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] - end Array diff --git a/src/Init/Data/Array/Basic.lean b/src/Init/Data/Array/Basic.lean index 1280cd9045..0b6410ed1f 100644 --- a/src/Init/Data/Array/Basic.lean +++ b/src/Init/Data/Array/Basic.lean @@ -38,14 +38,14 @@ namespace Array /-! ### Preliminary theorems -/ -@[simp] theorem size_set (xs : Array α) (i : Nat) (v : α) (h : i < xs.size) : +@[simp] theorem size_set {xs : Array α} {i : Nat} {v : α} (h : i < xs.size) : (set xs i v h).size = xs.size := List.length_set .. -@[simp] theorem size_push (xs : Array α) (v : α) : (push xs v).size = xs.size + 1 := +@[simp] theorem size_push {xs : Array α} (v : α) : (push xs v).size = xs.size + 1 := List.length_concat .. -theorem ext (xs ys : Array α) +theorem ext {xs ys : Array α} (h₁ : xs.size = ys.size) (h₂ : (i : Nat) → (hi₁ : i < xs.size) → (hi₂ : i < ys.size) → xs[i] = ys[i]) : xs = ys := by @@ -83,10 +83,10 @@ theorem ext (xs ys : Array α) theorem ext' {xs ys : Array α} (h : xs.toList = ys.toList) : xs = ys := by cases xs; cases ys; simp at h; rw [h] -@[simp] theorem toArrayAux_eq (as : List α) (acc : Array α) : (as.toArrayAux acc).toList = acc.toList ++ as := by +@[simp] theorem toArrayAux_eq {as : List α} {acc : Array α} : (as.toArrayAux acc).toList = acc.toList ++ as := by induction as generalizing acc <;> simp [*, List.toArrayAux, Array.push, List.append_assoc, List.concat_eq_append] -@[simp] theorem toArray_toList (xs : Array α) : xs.toList.toArray = xs := rfl +@[simp] theorem toArray_toList {xs : Array α} : xs.toList.toArray = xs := rfl @[simp] theorem getElem_toList {xs : Array α} {i : Nat} (h : i < xs.size) : xs.toList[i] = xs[i] := rfl @@ -120,12 +120,12 @@ namespace List abbrev toArray_toList := @Array.toArray_toList -- This does not need to be a simp lemma, as already after the `whnfR` the right hand side is `as`. -theorem toList_toArray (as : List α) : as.toArray.toList = as := rfl +theorem toList_toArray {as : List α} : as.toArray.toList = as := rfl @[deprecated toList_toArray (since := "2025-02-17")] abbrev _root_.Array.toList_toArray := @List.toList_toArray -@[simp] theorem size_toArray (as : List α) : as.toArray.size = as.length := by simp [Array.size] +@[simp] theorem size_toArray {as : List α} : as.toArray.size = as.length := by simp [Array.size] @[deprecated size_toArray (since := "2025-02-17")] abbrev _root_.Array.size_toArray := @List.size_toArray @@ -144,7 +144,7 @@ end List namespace Array -theorem size_eq_length_toList (xs : Array α) : xs.size = xs.toList.length := rfl +theorem size_eq_length_toList {xs : Array α} : xs.size = xs.toList.length := rfl @[deprecated toList_toArray (since := "2024-09-09")] abbrev data_toArray := @List.toList_toArray @@ -192,7 +192,7 @@ Examples: def pop (xs : Array α) : Array α where toList := xs.toList.dropLast -@[simp] theorem size_pop (xs : Array α) : xs.pop.size = xs.size - 1 := by +@[simp] theorem size_pop {xs : Array α} : xs.pop.size = xs.size - 1 := by match xs with | ⟨[]⟩ => rfl | ⟨a::as⟩ => simp [pop, Nat.succ_sub_succ_eq_sub, size] @@ -240,11 +240,11 @@ def swap (xs : Array α) (i j : @& Nat) (hi : i < xs.size := by get_elem_tactic) let v₁ := xs[i] let v₂ := xs[j] let xs' := xs.set i v₂ - xs'.set j v₁ (Nat.lt_of_lt_of_eq hj (size_set xs i v₂ _).symm) + xs'.set j v₁ (Nat.lt_of_lt_of_eq hj (size_set _).symm) -@[simp] theorem size_swap (xs : Array α) (i j : Nat) {hi hj} : (xs.swap i j hi hj).size = xs.size := by +@[simp] theorem size_swap {xs : Array α} {i j : Nat} {hi hj} : (xs.swap i j hi hj).size = xs.size := by show ((xs.set i xs[j]).set j xs[i] - (Nat.lt_of_lt_of_eq hj (size_set xs i xs[j] _).symm)).size = xs.size + (Nat.lt_of_lt_of_eq hj (size_set _).symm)).size = xs.size rw [size_set, size_set] /-- @@ -465,7 +465,7 @@ Examples: -/ abbrev take (xs : Array α) (i : Nat) : Array α := extract xs 0 i -@[simp] theorem take_eq_extract (xs : Array α) (i : Nat) : xs.take i = xs.extract 0 i := rfl +@[simp] theorem take_eq_extract {xs : Array α} {i : Nat} : xs.take i = xs.extract 0 i := rfl /-- Removes the first `i` elements of `xs`. If `xs` has fewer than `i` elements, the new array is empty. @@ -479,7 +479,7 @@ Examples: -/ abbrev drop (xs : Array α) (i : Nat) : Array α := extract xs i xs.size -@[simp] theorem drop_eq_extract (xs : Array α) (i : Nat) : xs.drop i = xs.extract i xs.size := rfl +@[simp] theorem drop_eq_extract {xs : Array α} {i : Nat} : xs.drop i = xs.extract i xs.size := rfl @[inline] unsafe def modifyMUnsafe [Monad m] (xs : Array α) (i : Nat) (f : α → m α) : m (Array α) := do @@ -490,7 +490,7 @@ unsafe def modifyMUnsafe [Monad m] (xs : Array α) (i : Nat) (f : α → m α) : -- of the element type, and that it is valid to store `box(0)` in any array. let xs' := xs.set i (unsafeCast ()) let v ← f v - pure <| xs'.set i v (Nat.lt_of_lt_of_eq h (size_set xs ..).symm) + pure <| xs'.set i v (Nat.lt_of_lt_of_eq h (size_set ..).symm) else pure xs @@ -1026,7 +1026,7 @@ instance : ForM m (Array α) α where forM xs f := Array.forM f xs -- We simplify `Array.forM` to `forM`. -@[simp] theorem forM_eq_forM [Monad m] (f : α → m PUnit) : +@[simp] theorem forM_eq_forM [Monad m] {f : α → m PUnit} : Array.forM f as 0 as.size = forM as f := rfl /-- @@ -1735,7 +1735,7 @@ def popWhile (p : α → Bool) (as : Array α) : Array α := as decreasing_by simp_wf; decreasing_trivial_pre_omega -@[simp] theorem popWhile_empty (p : α → Bool) : +@[simp] theorem popWhile_empty {p : α → Bool} : popWhile p #[] = #[] := by simp [popWhile] @@ -1784,7 +1784,7 @@ termination_by xs.size - i decreasing_by simp_wf; exact Nat.sub_succ_lt_self _ _ h -- This is required in `Lean.Data.PersistentHashMap`. -@[simp] theorem size_eraseIdx (xs : Array α) (i : Nat) (h) : (xs.eraseIdx i h).size = xs.size - 1 := by +@[simp] theorem size_eraseIdx {xs : Array α} (i : Nat) (h) : (xs.eraseIdx i h).size = xs.size - 1 := by induction xs, i, h using Array.eraseIdx.induct with | @case1 xs i h h' xs' ih => unfold eraseIdx diff --git a/src/Init/Data/Array/BasicAux.lean b/src/Init/Data/Array/BasicAux.lean index a7849840c8..63f15838b0 100644 --- a/src/Init/Data/Array/BasicAux.lean +++ b/src/Init/Data/Array/BasicAux.lean @@ -17,7 +17,7 @@ theorem Array.of_push_eq_push {as bs : Array α} (h : as.push a = bs.push b) : a cases as; cases bs simp_all -private theorem List.size_toArrayAux (as : List α) (bs : Array α) : (as.toArrayAux bs).size = as.length + bs.size := by +private theorem List.size_toArrayAux {as : List α} {bs : Array α} : (as.toArrayAux bs).size = as.length + bs.size := by induction as generalizing bs with | nil => simp [toArrayAux] | cons a as ih => simp +arith [toArrayAux, *] @@ -35,7 +35,7 @@ private theorem List.of_toArrayAux_eq_toArrayAux {as bs : List α} {cs ds : Arra have := Array.of_push_eq_push ih₂ simp [this] -theorem List.toArray_eq_toArray_eq (as bs : List α) : (as.toArray = bs.toArray) = (as = bs) := by +theorem List.toArray_eq_toArray_eq {as bs : List α} : (as.toArray = bs.toArray) = (as = bs) := by simp /-- diff --git a/src/Init/Data/Array/Bootstrap.lean b/src/Init/Data/Array/Bootstrap.lean index 9608cb89e6..0a377630ab 100644 --- a/src/Init/Data/Array/Bootstrap.lean +++ b/src/Init/Data/Array/Bootstrap.lean @@ -42,35 +42,35 @@ def get! {α : Type u} [Inhabited α] (a : @& Array α) (i : @& Nat) : α := Array.getD a i default theorem foldlM_toList.aux [Monad m] - (f : β → α → m β) (xs : Array α) (i j) (H : xs.size ≤ i + j) (b) : + {f : β → α → m β} {xs : Array α} {i j} (H : xs.size ≤ i + j) {b} : foldlM.loop f xs xs.size (Nat.le_refl _) i j b = (xs.toList.drop j).foldlM f b := by unfold foldlM.loop split; split · cases Nat.not_le_of_gt ‹_› (Nat.zero_add _ ▸ H) · rename_i i; rw [Nat.succ_add] at H - simp [foldlM_toList.aux f xs i (j+1) H] + simp [foldlM_toList.aux (j := j+1) H] rw (occs := [2]) [← List.getElem_cons_drop_succ_eq_drop ‹_›] rfl · rw [List.drop_of_length_le (Nat.ge_of_not_lt ‹_›)]; rfl @[simp] theorem foldlM_toList [Monad m] - (f : β → α → m β) (init : β) (xs : Array α) : + {f : β → α → m β} {init : β} {xs : Array α} : xs.toList.foldlM f init = xs.foldlM f init := by simp [foldlM, foldlM_toList.aux] -@[simp] theorem foldl_toList (f : β → α → β) (init : β) (xs : Array α) : +@[simp] theorem foldl_toList (f : β → α → β) {init : β} {xs : Array α} : xs.toList.foldl f init = xs.foldl f init := List.foldl_eq_foldlM .. ▸ foldlM_toList .. theorem foldrM_eq_reverse_foldlM_toList.aux [Monad m] - (f : α → β → m β) (xs : Array α) (init : β) (i h) : + {f : α → β → m β} {xs : Array α} {init : β} {i} (h) : (xs.toList.take i).reverse.foldlM (fun x y => f y x) init = foldrM.fold f xs 0 i h init := by unfold foldrM.fold match i with | 0 => simp [List.foldlM, List.take] - | i+1 => rw [← List.take_concat_get _ _ h]; simp [← (aux f xs · i)] + | i+1 => rw [← List.take_concat_get h]; simp [← aux] -theorem foldrM_eq_reverse_foldlM_toList [Monad m] (f : α → β → m β) (init : β) (xs : Array α) : +theorem foldrM_eq_reverse_foldlM_toList [Monad m] {f : α → β → m β} {init : β} {xs : Array α} : xs.foldrM f init = xs.toList.reverse.foldlM (fun x y => f y x) init := by have : xs = #[] ∨ 0 < xs.size := match xs with | ⟨[]⟩ => .inl rfl | ⟨a::l⟩ => .inr (Nat.zero_lt_succ _) @@ -78,31 +78,31 @@ theorem foldrM_eq_reverse_foldlM_toList [Monad m] (f : α → β → m β) (init simp [foldrM, h, ← foldrM_eq_reverse_foldlM_toList.aux, List.take_length] @[simp] theorem foldrM_toList [Monad m] - (f : α → β → m β) (init : β) (xs : Array α) : + {f : α → β → m β} {init : β} {xs : Array α} : xs.toList.foldrM f init = xs.foldrM f init := by rw [foldrM_eq_reverse_foldlM_toList, List.foldlM_reverse] -@[simp] theorem foldr_toList (f : α → β → β) (init : β) (xs : Array α) : +@[simp] theorem foldr_toList (f : α → β → β) {init : β} {xs : Array α} : xs.toList.foldr f init = xs.foldr f init := List.foldr_eq_foldrM .. ▸ foldrM_toList .. -@[simp] theorem push_toList (xs : Array α) (a : α) : (xs.push a).toList = xs.toList ++ [a] := by +@[simp] theorem push_toList {xs : Array α} {a : α} : (xs.push a).toList = xs.toList ++ [a] := by simp [push, List.concat_eq_append] -@[simp] theorem toListAppend_eq (xs : Array α) (l : List α) : xs.toListAppend l = xs.toList ++ l := by +@[simp] theorem toListAppend_eq {xs : Array α} {l : List α} : xs.toListAppend l = xs.toList ++ l := by simp [toListAppend, ← foldr_toList] -@[simp] theorem toListImpl_eq (xs : Array α) : xs.toListImpl = xs.toList := by +@[simp] theorem toListImpl_eq {xs : Array α} : xs.toListImpl = xs.toList := by simp [toListImpl, ← foldr_toList] -@[simp] theorem toList_pop (xs : Array α) : xs.pop.toList = xs.toList.dropLast := rfl +@[simp] theorem toList_pop {xs : Array α} : xs.pop.toList = xs.toList.dropLast := rfl @[deprecated toList_pop (since := "2025-02-17")] abbrev pop_toList := @Array.toList_pop -@[simp] theorem append_eq_append (xs ys : Array α) : xs.append ys = xs ++ ys := rfl +@[simp] theorem append_eq_append {xs ys : Array α} : xs.append ys = xs ++ ys := rfl -@[simp] theorem toList_append (xs ys : Array α) : +@[simp] theorem toList_append {xs ys : Array α} : (xs ++ ys).toList = xs.toList ++ ys.toList := by rw [← append_eq_append]; unfold Array.append rw [← foldl_toList] @@ -110,25 +110,24 @@ abbrev pop_toList := @Array.toList_pop @[simp] theorem toList_empty : (#[] : Array α).toList = [] := rfl -@[simp] theorem append_empty (xs : Array α) : xs ++ #[] = xs := by +@[simp] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by apply ext'; simp only [toList_append, toList_empty, List.append_nil] @[deprecated append_empty (since := "2025-01-13")] abbrev append_nil := @append_empty -@[simp] theorem empty_append (xs : Array α) : #[] ++ xs = xs := by +@[simp] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by apply ext'; simp only [toList_append, toList_empty, List.nil_append] @[deprecated empty_append (since := "2025-01-13")] abbrev nil_append := @empty_append -@[simp] theorem append_assoc (xs ys zs : Array α) : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by +@[simp] theorem append_assoc {xs ys zs : Array α} : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by apply ext'; simp only [toList_append, List.append_assoc] -@[simp] theorem appendList_eq_append - (xs : Array α) (l : List α) : xs.appendList l = xs ++ l := rfl +@[simp] theorem appendList_eq_append {xs : Array α} {l : List α} : xs.appendList l = xs ++ l := rfl -@[simp] theorem toList_appendList (xs : Array α) (l : List α) : +@[simp] theorem toList_appendList {xs : Array α} {l : List α} : (xs ++ l).toList = xs.toList ++ l := by rw [← appendList_eq_append]; unfold Array.appendList induction l generalizing xs <;> simp [*] @@ -138,25 +137,23 @@ abbrev appendList_toList := @toList_appendList @[deprecated "Use the reverse direction of `foldrM_toList`." (since := "2024-11-13")] theorem foldrM_eq_foldrM_toList [Monad m] - (f : α → β → m β) (init : β) (xs : Array α) : + {f : α → β → m β} {init : β} {xs : Array α} : xs.foldrM f init = xs.toList.foldrM f init := by simp @[deprecated "Use the reverse direction of `foldlM_toList`." (since := "2024-11-13")] theorem foldlM_eq_foldlM_toList [Monad m] - (f : β → α → m β) (init : β) (xs : Array α) : + {f : β → α → m β} {init : β} {xs : Array α} : xs.foldlM f init = xs.toList.foldlM f init:= by simp @[deprecated "Use the reverse direction of `foldr_toList`." (since := "2024-11-13")] -theorem foldr_eq_foldr_toList - (f : α → β → β) (init : β) (xs : Array α) : +theorem foldr_eq_foldr_toList {f : α → β → β} {init : β} {xs : Array α} : xs.foldr f init = xs.toList.foldr f init := by simp @[deprecated "Use the reverse direction of `foldl_toList`." (since := "2024-11-13")] -theorem foldl_eq_foldl_toList - (f : β → α → β) (init : β) (xs : Array α) : +theorem foldl_eq_foldl_toList {f : β → α → β} {init : β} {xs : Array α} : xs.foldl f init = xs.toList.foldl f init:= by simp diff --git a/src/Init/Data/Array/Count.lean b/src/Init/Data/Array/Count.lean index d1ec631af2..f2a12f6bda 100644 --- a/src/Init/Data/Array/Count.lean +++ b/src/Init/Data/Array/Count.lean @@ -21,9 +21,9 @@ open Nat /-! ### countP -/ section countP -variable (p q : α → Bool) +variable {p q : α → Bool} -@[simp] theorem _root_.List.countP_toArray (l : List α) : countP p l.toArray = l.countP p := by +@[simp] theorem _root_.List.countP_toArray {l : List α} : countP p l.toArray = l.countP p := by simp [countP] induction l with | nil => rfl @@ -31,32 +31,32 @@ variable (p q : α → Bool) simp only [List.foldr_cons, ih, List.countP_cons] split <;> simp_all -@[simp] theorem countP_toList (xs : Array α) : xs.toList.countP p = countP p xs := by +@[simp] theorem countP_toList {xs : Array α} : xs.toList.countP p = countP p xs := by cases xs simp @[simp] theorem countP_empty : countP p #[] = 0 := rfl -@[simp] theorem countP_push_of_pos (xs) (pa : p a) : countP p (xs.push a) = countP p xs + 1 := by +@[simp] theorem countP_push_of_pos {xs : Array α} (pa : p a) : countP p (xs.push a) = countP p xs + 1 := by rcases xs with ⟨xs⟩ simp_all -@[simp] theorem countP_push_of_neg (xs) (pa : ¬p a) : countP p (xs.push a) = countP p xs := by +@[simp] theorem countP_push_of_neg {xs : Array α} (pa : ¬p a) : countP p (xs.push a) = countP p xs := by rcases xs with ⟨xs⟩ simp_all -theorem countP_push (a : α) (xs) : countP p (xs.push a) = countP p xs + if p a then 1 else 0 := by +theorem countP_push {a : α} {xs : Array α} : countP p (xs.push a) = countP p xs + if p a then 1 else 0 := by rcases xs with ⟨xs⟩ simp_all -@[simp] theorem countP_singleton (a : α) : countP p #[a] = if p a then 1 else 0 := by +@[simp] theorem countP_singleton {a : α} : countP p #[a] = if p a then 1 else 0 := by simp [countP_push] -theorem size_eq_countP_add_countP (xs) : xs.size = countP p xs + countP (fun a => ¬p a) xs := by +theorem size_eq_countP_add_countP {xs : Array α} : xs.size = countP p xs + countP (fun a => ¬p a) xs := by rcases xs with ⟨xs⟩ simp [List.length_eq_countP_add_countP (p := p)] -theorem countP_eq_size_filter (xs) : countP p xs = (filter p xs).size := by +theorem countP_eq_size_filter {xs : Array α} : countP p xs = (filter p xs).size := by rcases xs with ⟨xs⟩ simp [List.countP_eq_length_filter] @@ -68,7 +68,7 @@ theorem countP_le_size : countP p xs ≤ xs.size := by simp only [countP_eq_size_filter] apply size_filter_le -@[simp] theorem countP_append (xs ys) : countP p (xs ++ ys) = countP p xs + countP p ys := by +@[simp] theorem countP_append {xs ys : Array α} : countP p (xs ++ ys) = countP p xs + countP p ys := by rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ simp @@ -88,24 +88,23 @@ theorem countP_le_size : countP p xs ≤ xs.size := by rcases xs with ⟨xs⟩ simp -theorem countP_replicate (p : α → Bool) (a : α) (n : Nat) : - countP p (replicate n a) = if p a then n else 0 := by +theorem countP_replicate {a : α} {n : Nat} : countP p (replicate n a) = if p a then n else 0 := by simp [← List.toArray_replicate, List.countP_replicate] @[deprecated countP_replicate (since := "2025-03-18")] abbrev countP_mkArray := @countP_replicate -theorem boole_getElem_le_countP (p : α → Bool) (xs : Array α) (i : Nat) (h : i < xs.size) : +theorem boole_getElem_le_countP {xs : Array α} {i : Nat} (h : i < xs.size) : (if p xs[i] then 1 else 0) ≤ xs.countP p := by rcases xs with ⟨xs⟩ simp [List.boole_getElem_le_countP] -theorem countP_set (p : α → Bool) (xs : Array α) (i : Nat) (a : α) (h : i < xs.size) : +theorem countP_set {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) : (xs.set i a).countP p = xs.countP p - (if p xs[i] then 1 else 0) + (if p a then 1 else 0) := by rcases xs with ⟨xs⟩ simp [List.countP_set, h] -theorem countP_filter (xs : Array α) : +theorem countP_filter {xs : Array α} : countP p (filter q xs) = countP (fun a => p a && q a) xs := by rcases xs with ⟨xs⟩ simp [List.countP_filter] @@ -118,37 +117,35 @@ theorem countP_filter (xs : Array α) : funext xs simp -@[simp] theorem countP_map (p : β → Bool) (f : α → β) (xs : Array α) : +@[simp] theorem countP_map {p : β → Bool} {f : α → β} {xs : Array α} : countP p (map f xs) = countP (p ∘ f) xs := by rcases xs with ⟨xs⟩ simp -theorem size_filterMap_eq_countP (f : α → Option β) (xs : Array α) : +theorem size_filterMap_eq_countP {f : α → Option β} {xs : Array α} : (filterMap f xs).size = countP (fun a => (f a).isSome) xs := by rcases xs with ⟨xs⟩ simp [List.length_filterMap_eq_countP] -theorem countP_filterMap (p : β → Bool) (f : α → Option β) (xs : Array α) : +theorem countP_filterMap {p : β → Bool} {f : α → Option β} {xs : Array α} : countP p (filterMap f xs) = countP (fun a => ((f a).map p).getD false) xs := by rcases xs with ⟨xs⟩ simp [List.countP_filterMap] -@[simp] theorem countP_flatten (xss : Array (Array α)) : +@[simp] theorem countP_flatten {xss : Array (Array α)} : countP p xss.flatten = (xss.map (countP p)).sum := by cases xss using array₂_induction simp [List.countP_flatten, Function.comp_def] -theorem countP_flatMap (p : β → Bool) (xs : Array α) (f : α → Array β) : +theorem countP_flatMap {p : β → Bool} {xs : Array α} {f : α → Array β} : countP p (xs.flatMap f) = sum (map (countP p ∘ f) xs) := by rcases xs with ⟨xs⟩ simp [List.countP_flatMap, Function.comp_def] -@[simp] theorem countP_reverse (xs : Array α) : countP p xs.reverse = countP p xs := by +@[simp] theorem countP_reverse {xs : Array α} : countP p xs.reverse = countP p xs := by rcases xs with ⟨xs⟩ simp [List.countP_reverse] -variable {p q} - theorem countP_mono_left (h : ∀ x ∈ xs, p x → q x) : countP p xs ≤ countP q xs := by rcases xs with ⟨xs⟩ simpa using List.countP_mono_left (by simpa using h) @@ -165,62 +162,62 @@ section count variable [BEq α] -@[simp] theorem _root_.List.count_toArray (l : List α) (a : α) : count a l.toArray = l.count a := by +@[simp] theorem _root_.List.count_toArray {l : List α} {a : α} : count a l.toArray = l.count a := by simp [count, List.count_eq_countP] -@[simp] theorem count_toList (xs : Array α) (a : α) : xs.toList.count a = xs.count a := by +@[simp] theorem count_toList {xs : Array α} {a : α} : xs.toList.count a = xs.count a := by cases xs simp -@[simp] theorem count_empty (a : α) : count a #[] = 0 := rfl +@[simp] theorem count_empty {a : α} : count a #[] = 0 := rfl -theorem count_push (a b : α) (xs : Array α) : +theorem count_push {a b : α} {xs : Array α} : count a (xs.push b) = count a xs + if b == a then 1 else 0 := by simp [count, countP_push] -theorem count_eq_countP (a : α) (xs : Array α) : count a xs = countP (· == a) xs := rfl +theorem count_eq_countP {a : α} {xs : Array α} : count a xs = countP (· == a) xs := rfl theorem count_eq_countP' {a : α} : count a = countP (· == a) := by funext xs apply count_eq_countP -theorem count_le_size (a : α) (xs : Array α) : count a xs ≤ xs.size := countP_le_size _ +theorem count_le_size {a : α} {xs : Array α} : count a xs ≤ xs.size := countP_le_size -theorem count_le_count_push (a b : α) (xs : Array α) : count a xs ≤ count a (xs.push b) := by +theorem count_le_count_push {a b : α} {xs : Array α} : count a xs ≤ count a (xs.push b) := by simp [count_push] -theorem count_singleton (a b : α) : count a #[b] = if b == a then 1 else 0 := by +theorem count_singleton {a b : α} : count a #[b] = if b == a then 1 else 0 := by simp [count_eq_countP] -@[simp] theorem count_append (a : α) : ∀ xs ys, count a (xs ++ ys) = count a xs + count a ys := - countP_append _ +@[simp] theorem count_append {a : α} {xs ys : Array α} : count a (xs ++ ys) = count a xs + count a ys := + countP_append -@[simp] theorem count_flatten (a : α) (xss : Array (Array α)) : +@[simp] theorem count_flatten {a : α} {xss : Array (Array α)} : count a xss.flatten = (xss.map (count a)).sum := by cases xss using array₂_induction simp [List.count_flatten, Function.comp_def] -@[simp] theorem count_reverse (a : α) (xs : Array α) : count a xs.reverse = count a xs := by +@[simp] theorem count_reverse {a : α} {xs : Array α} : count a xs.reverse = count a xs := by rcases xs with ⟨xs⟩ simp -theorem boole_getElem_le_count (a : α) (xs : Array α) (i : Nat) (h : i < xs.size) : +theorem boole_getElem_le_count {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) : (if xs[i] == a then 1 else 0) ≤ xs.count a := by rw [count_eq_countP] - apply boole_getElem_le_countP (· == a) + apply boole_getElem_le_countP (p := (· == a)) -theorem count_set (a b : α) (xs : Array α) (i : Nat) (h : i < xs.size) : +theorem count_set {xs : Array α} {i : Nat} {a b : α} (h : i < xs.size) : (xs.set i a).count b = xs.count b - (if xs[i] == b then 1 else 0) + (if a == b then 1 else 0) := by simp [count_eq_countP, countP_set, h] variable [LawfulBEq α] -@[simp] theorem count_push_self (a : α) (xs : Array α) : count a (xs.push a) = count a xs + 1 := by +@[simp] theorem count_push_self {a : α} {xs : Array α} : count a (xs.push a) = count a xs + 1 := by simp [count_push] -@[simp] theorem count_push_of_ne (h : b ≠ a) (xs : Array α) : count a (xs.push b) = count a xs := by +@[simp] theorem count_push_of_ne {xs : Array α} (h : b ≠ a) : count a (xs.push b) = count a xs := by simp_all [count_push, h] -theorem count_singleton_self (a : α) : count a #[a] = 1 := by simp +theorem count_singleton_self {a : α} : count a #[a] = 1 := by simp @[simp] theorem count_pos_iff {a : α} {xs : Array α} : 0 < count a xs ↔ a ∈ xs := by @@ -244,24 +241,24 @@ theorem count_eq_size {xs : Array α} : count a xs = xs.size ↔ ∀ b ∈ xs, a · simpa using h b hb · rw [h b hb, beq_self_eq_true] -@[simp] theorem count_replicate_self (a : α) (n : Nat) : count a (replicate n a) = n := by +@[simp] theorem count_replicate_self {a : α} {n : Nat} : count a (replicate n a) = n := by simp [← List.toArray_replicate] @[deprecated count_replicate_self (since := "2025-03-18")] abbrev count_mkArray_self := @count_replicate_self -theorem count_replicate (a b : α) (n : Nat) : count a (replicate n b) = if b == a then n else 0 := by +theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by simp [← List.toArray_replicate, List.count_replicate] @[deprecated count_replicate (since := "2025-03-18")] abbrev count_mkArray := @count_replicate -theorem filter_beq (xs : Array α) (a : α) : xs.filter (· == a) = replicate (count a xs) a := by +theorem filter_beq {xs : Array α} (a : α) : xs.filter (· == a) = replicate (count a xs) a := by rcases xs with ⟨xs⟩ simp [List.filter_beq] -theorem filter_eq {α} [DecidableEq α] (xs : Array α) (a : α) : xs.filter (· = a) = replicate (count a xs) a := - filter_beq xs a +theorem filter_eq {α} [DecidableEq α] {xs : Array α} (a : α) : xs.filter (· = a) = replicate (count a xs) a := + filter_beq a theorem replicate_count_eq_of_count_eq_size {xs : Array α} (h : count a xs = xs.size) : replicate (count a xs) a = xs := by @@ -276,17 +273,17 @@ abbrev mkArray_count_eq_of_count_eq_size := @replicate_count_eq_of_count_eq_size rcases xs with ⟨xs⟩ simp [List.count_filter, h] -theorem count_le_count_map [DecidableEq β] (xs : Array α) (f : α → β) (x : α) : +theorem count_le_count_map [DecidableEq β] {xs : Array α} {f : α → β} {x : α} : count x xs ≤ count (f x) (map f xs) := by rcases xs with ⟨xs⟩ simp [List.count_le_count_map, countP_map] -theorem count_filterMap {α} [BEq β] (b : β) (f : α → Option β) (xs : Array α) : +theorem count_filterMap {α} [BEq β] {b : β} {f : α → Option β} {xs : Array α} : count b (filterMap f xs) = countP (fun a => f a == some b) xs := by rcases xs with ⟨xs⟩ simp [List.count_filterMap, countP_filterMap] -theorem count_flatMap {α} [BEq β] (xs : Array α) (f : α → Array β) (x : β) : +theorem count_flatMap {α} [BEq β] {xs : Array α} {f : α → Array β} {x : β} : count x (xs.flatMap f) = sum (map (count x ∘ f) xs) := by rcases xs with ⟨xs⟩ simp [List.count_flatMap, countP_flatMap, Function.comp_def] diff --git a/src/Init/Data/Array/DecidableEq.lean b/src/Init/Data/Array/DecidableEq.lean index e383c7764a..34f5f8d4ca 100644 --- a/src/Init/Data/Array/DecidableEq.lean +++ b/src/Init/Data/Array/DecidableEq.lean @@ -71,7 +71,7 @@ theorem isEqv_eq_decide (xs ys : Array α) (r) : theorem eq_of_isEqv [DecidableEq α] (xs ys : Array α) (h : Array.isEqv xs ys (fun x y => x = y)) : xs = ys := by have ⟨h, h'⟩ := rel_of_isEqv h - exact ext _ _ h (fun i lt _ => by simpa using h' i lt) + exact ext h (fun i lt _ => by simpa using h' i lt) private theorem isEqvAux_self (r : α → α → Bool) (hr : ∀ a, r a a) (xs : Array α) (i : Nat) (h : i ≤ xs.size) : Array.isEqvAux xs xs rfl r i h = true := by diff --git a/src/Init/Data/Array/Erase.lean b/src/Init/Data/Array/Erase.lean index c7ddcfba4e..b22d89396e 100644 --- a/src/Init/Data/Array/Erase.lean +++ b/src/Init/Data/Array/Erase.lean @@ -46,6 +46,7 @@ theorem exists_of_eraseP {xs : Array α} {a} (hm : a ∈ xs) (hp : p a) : obtain ⟨a, l₁, l₂, h₁, h₂, rfl, h₃⟩ := List.exists_of_eraseP (by simpa using hm) (hp) refine ⟨a, ⟨l₁⟩, ⟨l₂⟩, by simpa using h₁, h₂, by simp, by simpa using h₃⟩ +-- The arguments are explicit here, so this lemma can be used as a case split. theorem exists_or_eq_self_of_eraseP (p) (xs : Array α) : xs.eraseP p = xs ∨ ∃ a ys zs, (∀ b ∈ ys, ¬p b) ∧ p a ∧ xs = ys.push a ++ zs ∧ xs.eraseP p = ys ++ zs := @@ -69,13 +70,13 @@ theorem size_eraseP {xs : Array α} : (xs.eraseP p).size = if xs.any p then xs.s rw [eraseP_of_forall_getElem_not] simp_all -theorem size_eraseP_le (xs : Array α) : (xs.eraseP p).size ≤ xs.size := by +theorem size_eraseP_le {xs : Array α} : (xs.eraseP p).size ≤ xs.size := by rcases xs with ⟨xs⟩ - simpa using List.length_eraseP_le xs + simpa using List.length_eraseP_le -theorem le_size_eraseP (xs : Array α) : xs.size - 1 ≤ (xs.eraseP p).size := by +theorem le_size_eraseP {xs : Array α} : xs.size - 1 ≤ (xs.eraseP p).size := by rcases xs with ⟨xs⟩ - simpa using List.le_length_eraseP xs + simpa using List.le_length_eraseP theorem mem_of_mem_eraseP {xs : Array α} : a ∈ xs.eraseP p → a ∈ xs := by rcases xs with ⟨xs⟩ @@ -89,19 +90,19 @@ theorem mem_of_mem_eraseP {xs : Array α} : a ∈ xs.eraseP p → a ∈ xs := by rcases xs with ⟨xs⟩ simp -theorem eraseP_map (f : β → α) (xs : Array β) : (xs.map f).eraseP p = (xs.eraseP (p ∘ f)).map f := by +theorem eraseP_map {f : β → α} {xs : Array β} : (xs.map f).eraseP p = (xs.eraseP (p ∘ f)).map f := by rcases xs with ⟨xs⟩ - simpa using List.eraseP_map f xs + simpa using List.eraseP_map -theorem eraseP_filterMap (f : α → Option β) (xs : Array α) : +theorem eraseP_filterMap {f : α → Option β} {xs : Array α} : (filterMap f xs).eraseP p = filterMap f (xs.eraseP (fun x => match f x with | some y => p y | none => false)) := by rcases xs with ⟨xs⟩ - simpa using List.eraseP_filterMap f xs + simpa using List.eraseP_filterMap -theorem eraseP_filter (f : α → Bool) (xs : Array α) : +theorem eraseP_filter {f : α → Bool} {xs : Array α} : (filter f xs).eraseP p = filter f (xs.eraseP (fun x => p x && f x)) := by rcases xs with ⟨xs⟩ - simpa using List.eraseP_filter f xs + simpa using List.eraseP_filter theorem eraseP_append_left {a : α} (pa : p a) {xs : Array α} {ys : Array α} (h : a ∈ xs) : (xs ++ ys).eraseP p = xs.eraseP p ++ ys := by @@ -122,7 +123,7 @@ theorem eraseP_append {xs : Array α} {ys : Array α} : simp only [List.append_toArray, List.eraseP_toArray, List.eraseP_append, List.any_toArray] split <;> simp -theorem eraseP_replicate (n : Nat) (a : α) (p : α → Bool) : +theorem eraseP_replicate {n : Nat} {a : α} {p : α → Bool} : (replicate n a).eraseP p = if p a then replicate (n - 1) a else replicate n a := by simp only [← List.toArray_replicate, List.eraseP_toArray, List.eraseP_replicate] split <;> simp @@ -175,10 +176,12 @@ theorem erase_of_not_mem [LawfulBEq α] {a : α} {xs : Array α} (h : a ∉ xs) rcases xs with ⟨xs⟩ simp [List.erase_of_not_mem (by simpa using h)] +-- The arguments are intentionally explicit. theorem erase_eq_eraseP' (a : α) (xs : Array α) : xs.erase a = xs.eraseP (· == a) := by rcases xs with ⟨xs⟩ simp [List.erase_eq_eraseP'] +-- The arguments are intentionally explicit. theorem erase_eq_eraseP [LawfulBEq α] (a : α) (xs : Array α) : xs.erase a = xs.eraseP (a == ·) := by rcases xs with ⟨xs⟩ simp [List.erase_eq_eraseP] @@ -202,19 +205,19 @@ theorem exists_erase_eq [LawfulBEq α] {a : α} {xs : Array α} (h : a ∈ xs) : (xs.erase a).size = xs.size - 1 := by rw [erase_eq_eraseP]; exact size_eraseP_of_mem h (beq_self_eq_true a) -theorem size_erase [LawfulBEq α] (a : α) (xs : Array α) : +theorem size_erase [LawfulBEq α] {a : α} {xs : Array α} : (xs.erase a).size = if a ∈ xs then xs.size - 1 else xs.size := by rw [erase_eq_eraseP, size_eraseP] congr simp [mem_iff_getElem, eq_comm (a := a)] -theorem size_erase_le (a : α) (xs : Array α) : (xs.erase a).size ≤ xs.size := by +theorem size_erase_le {a : α} {xs : Array α} : (xs.erase a).size ≤ xs.size := by rcases xs with ⟨xs⟩ - simpa using List.length_erase_le a xs + simpa using List.length_erase_le -theorem le_size_erase [LawfulBEq α] (a : α) (xs : Array α) : xs.size - 1 ≤ (xs.erase a).size := by +theorem le_size_erase [LawfulBEq α] {a : α} {xs : Array α} : xs.size - 1 ≤ (xs.erase a).size := by rcases xs with ⟨xs⟩ - simpa using List.le_length_erase a xs + simpa using List.le_length_erase theorem mem_of_mem_erase {a b : α} {xs : Array α} (h : a ∈ xs.erase b) : a ∈ xs := by rcases xs with ⟨xs⟩ @@ -228,10 +231,10 @@ theorem mem_of_mem_erase {a b : α} {xs : Array α} (h : a ∈ xs.erase b) : a rw [erase_eq_eraseP', eraseP_eq_self_iff] simp [forall_mem_ne'] -theorem erase_filter [LawfulBEq α] (f : α → Bool) (xs : Array α) : +theorem erase_filter [LawfulBEq α] {f : α → Bool} {xs : Array α} : (filter f xs).erase a = filter f (xs.erase a) := by rcases xs with ⟨xs⟩ - simpa using List.erase_filter f xs + simpa using List.erase_filter theorem erase_append_left [LawfulBEq α] {xs : Array α} (ys) (h : a ∈ xs) : (xs ++ ys).erase a = xs.erase a ++ ys := by @@ -252,7 +255,7 @@ theorem erase_append [LawfulBEq α] {a : α} {xs ys : Array α} : simp only [List.append_toArray, List.erase_toArray, List.erase_append, mem_toArray] split <;> simp -theorem erase_replicate [LawfulBEq α] (n : Nat) (a b : α) : +theorem erase_replicate [LawfulBEq α] {n : Nat} {a b : α} : (replicate n a).erase b = if b == a then replicate (n - 1) a else replicate n a := by simp only [← List.toArray_replicate, List.erase_toArray] simp only [List.erase_replicate, beq_iff_eq, List.toArray_replicate] @@ -261,10 +264,12 @@ theorem erase_replicate [LawfulBEq α] (n : Nat) (a b : α) : @[deprecated erase_replicate (since := "2025-03-18")] abbrev erase_mkArray := @erase_replicate -theorem erase_comm [LawfulBEq α] (a b : α) (xs : Array α) : +-- The arguments `a b` are explicit, +-- so they can be specified to prevent `simp` repeatedly applying the lemma. +theorem erase_comm [LawfulBEq α] (a b : α) {xs : Array α} : (xs.erase a).erase b = (xs.erase b).erase a := by rcases xs with ⟨xs⟩ - simpa using List.erase_comm a b xs + simpa using List.erase_comm a b theorem erase_eq_iff [LawfulBEq α] {a : α} {xs : Array α} : xs.erase a = ys ↔ @@ -304,7 +309,8 @@ theorem eraseIdx_eq_eraseIdxIfInBounds {xs : Array α} {i : Nat} (h : i < xs.siz xs.eraseIdx i h = xs.eraseIdxIfInBounds i := by simp [eraseIdxIfInBounds, h] -theorem eraseIdx_eq_take_drop_succ (xs : Array α) (i : Nat) (h) : xs.eraseIdx i = xs.take i ++ xs.drop (i + 1) := by +theorem eraseIdx_eq_take_drop_succ {xs : Array α} {i : Nat} (h) : + xs.eraseIdx i h = xs.take i ++ xs.drop (i + 1) := by rcases xs with ⟨xs⟩ simp only [List.size_toArray] at h simp only [List.eraseIdx_toArray, List.eraseIdx_eq_take_drop_succ, take_eq_extract, @@ -313,24 +319,24 @@ theorem eraseIdx_eq_take_drop_succ (xs : Array α) (i : Nat) (h) : xs.eraseIdx i rw [List.take_of_length_le] simp -theorem getElem?_eraseIdx (xs : Array α) (i : Nat) (h : i < xs.size) (j : Nat) : +theorem getElem?_eraseIdx {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} : (xs.eraseIdx i)[j]? = if j < i then xs[j]? else xs[j + 1]? := by rcases xs with ⟨xs⟩ simp [List.getElem?_eraseIdx] -theorem getElem?_eraseIdx_of_lt (xs : Array α) (i : Nat) (h : i < xs.size) (j : Nat) (h' : j < i) : +theorem getElem?_eraseIdx_of_lt {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} (h' : j < i) : (xs.eraseIdx i)[j]? = xs[j]? := by rw [getElem?_eraseIdx] simp [h'] -theorem getElem?_eraseIdx_of_ge (xs : Array α) (i : Nat) (h : i < xs.size) (j : Nat) (h' : i ≤ j) : +theorem getElem?_eraseIdx_of_ge {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} (h' : i ≤ j) : (xs.eraseIdx i)[j]? = xs[j + 1]? := by rw [getElem?_eraseIdx] simp only [dite_eq_ite, ite_eq_right_iff] intro h' omega -theorem getElem_eraseIdx (xs : Array α) (i : Nat) (h : i < xs.size) (j : Nat) (h' : j < (xs.eraseIdx i).size) : +theorem getElem_eraseIdx {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} (h' : j < (xs.eraseIdx i).size) : (xs.eraseIdx i)[j] = if h'' : j < i then xs[j] else @@ -388,18 +394,18 @@ theorem mem_eraseIdx_iff_getElem? {x : α} {xs : Array α} {k} {h} : x ∈ xs.er rcases xs with ⟨xs⟩ simp [List.mem_eraseIdx_iff_getElem?, *] -theorem erase_eq_eraseIdx_of_idxOf [BEq α] [LawfulBEq α] (xs : Array α) (a : α) (i : Nat) (w : xs.idxOf a = i) (h : i < xs.size) : +theorem erase_eq_eraseIdx_of_idxOf [BEq α] [LawfulBEq α] {xs : Array α} {a : α} {i : Nat} (w : xs.idxOf a = i) (h : i < xs.size) : xs.erase a = xs.eraseIdx i := by rcases xs with ⟨xs⟩ simp at w simp [List.erase_eq_eraseIdx_of_idxOf, *] -theorem getElem_eraseIdx_of_lt (xs : Array α) (i : Nat) (w : i < xs.size) (j : Nat) (h : j < (xs.eraseIdx i).size) (h' : j < i) : +theorem getElem_eraseIdx_of_lt {xs : Array α} {i : Nat} (w : i < xs.size) {j : Nat} (h : j < (xs.eraseIdx i).size) (h' : j < i) : (xs.eraseIdx i)[j] = xs[j] := by rcases xs with ⟨xs⟩ simp [List.getElem_eraseIdx_of_lt, *] -theorem getElem_eraseIdx_of_ge (xs : Array α) (i : Nat) (w : i < xs.size) (j : Nat) (h : j < (xs.eraseIdx i).size) (h' : i ≤ j) : +theorem getElem_eraseIdx_of_ge {xs : Array α} {i : Nat} (w : i < xs.size) {j : Nat} (h : j < (xs.eraseIdx i).size) (h' : i ≤ j) : (xs.eraseIdx i)[j] = xs[j + 1]'(by simp at h; omega) := by rcases xs with ⟨xs⟩ simp [List.getElem_eraseIdx_of_ge, *] diff --git a/src/Init/Data/Array/Extract.lean b/src/Init/Data/Array/Extract.lean index b399426669..1fe13bcdc8 100644 --- a/src/Init/Data/Array/Extract.lean +++ b/src/Init/Data/Array/Extract.lean @@ -322,32 +322,32 @@ theorem reverse_extract {as : Array α} {i j : Nat} : /-! ### takeWhile -/ -theorem takeWhile_map (f : α → β) (p : β → Bool) (as : Array α) : +theorem takeWhile_map {f : α → β} {p : β → Bool} {as : Array α} : (as.map f).takeWhile p = (as.takeWhile (p ∘ f)).map f := by rcases as with ⟨as⟩ simp [List.takeWhile_map] -theorem popWhile_map (f : α → β) (p : β → Bool) (as : Array α) : +theorem popWhile_map {f : α → β} {p : β → Bool} {as : Array α} : (as.map f).popWhile p = (as.popWhile (p ∘ f)).map f := by rcases as with ⟨as⟩ simp [List.dropWhile_map, ← List.map_reverse] -theorem takeWhile_filterMap (f : α → Option β) (p : β → Bool) (as : Array α) : +theorem takeWhile_filterMap {f : α → Option β} {p : β → Bool} {as : Array α} : (as.filterMap f).takeWhile p = (as.takeWhile fun a => (f a).all p).filterMap f := by rcases as with ⟨as⟩ simp [List.takeWhile_filterMap] -theorem popWhile_filterMap (f : α → Option β) (p : β → Bool) (as : Array α) : +theorem popWhile_filterMap {f : α → Option β} {p : β → Bool} {as : Array α} : (as.filterMap f).popWhile p = (as.popWhile fun a => (f a).all p).filterMap f := by rcases as with ⟨as⟩ simp [List.dropWhile_filterMap, ← List.filterMap_reverse] -theorem takeWhile_filter (p q : α → Bool) (as : Array α) : +theorem takeWhile_filter {p q : α → Bool} {as : Array α} : (as.filter p).takeWhile q = (as.takeWhile fun a => !p a || q a).filter p := by rcases as with ⟨as⟩ simp [List.takeWhile_filter] -theorem popWhile_filter (p q : α → Bool) (as : Array α) : +theorem popWhile_filter {p q : α → Bool} {as : Array α} : (as.filter p).popWhile q = (as.popWhile fun a => !p a || q a).filter p := by rcases as with ⟨as⟩ simp [List.dropWhile_filter, ← List.filter_reverse] @@ -390,28 +390,28 @@ theorem popWhile_append {xs ys : Array α} : rw [List.dropWhile_append_of_pos] simpa -@[simp] theorem takeWhile_replicate_eq_filter (p : α → Bool) : +@[simp] theorem takeWhile_replicate_eq_filter {p : α → Bool} : (replicate n a).takeWhile p = (replicate n a).filter p := by simp [← List.toArray_replicate] @[deprecated takeWhile_replicate_eq_filter (since := "2025-03-18")] abbrev takeWhile_mkArray_eq_filter := @takeWhile_replicate_eq_filter -theorem takeWhile_replicate (p : α → Bool) : +theorem takeWhile_replicate {p : α → Bool} : (replicate n a).takeWhile p = if p a then replicate n a else #[] := by simp [takeWhile_replicate_eq_filter, filter_replicate] @[deprecated takeWhile_replicate (since := "2025-03-18")] abbrev takeWhile_mkArray := @takeWhile_replicate -@[simp] theorem popWhile_replicate_eq_filter_not (p : α → Bool) : +@[simp] theorem popWhile_replicate_eq_filter_not {p : α → Bool} : (replicate n a).popWhile p = (replicate n a).filter (fun a => !p a) := by simp [← List.toArray_replicate, ← List.filter_reverse] @[deprecated popWhile_replicate_eq_filter_not (since := "2025-03-18")] abbrev popWhile_mkArray_eq_filter_not := @popWhile_replicate_eq_filter_not -theorem popWhile_replicate (p : α → Bool) : +theorem popWhile_replicate {p : α → Bool} : (replicate n a).popWhile p = if p a then #[] else replicate n a := by simp only [popWhile_replicate_eq_filter_not, size_replicate, filter_replicate, Bool.not_eq_eq_eq_not, Bool.not_true] diff --git a/src/Init/Data/Array/FinRange.lean b/src/Init/Data/Array/FinRange.lean index 2cc622385d..6b7114d4fa 100644 --- a/src/Init/Data/Array/FinRange.lean +++ b/src/Init/Data/Array/FinRange.lean @@ -21,23 +21,23 @@ Examples: -/ protected def finRange (n : Nat) : Array (Fin n) := ofFn fun i => i -@[simp] theorem size_finRange (n) : (Array.finRange n).size = n := by +@[simp] theorem size_finRange {n} : (Array.finRange n).size = n := by simp [Array.finRange] -@[simp] theorem getElem_finRange (i : Nat) (h : i < (Array.finRange n).size) : - (Array.finRange n)[i] = Fin.cast (size_finRange n) ⟨i, h⟩ := by +@[simp] theorem getElem_finRange {i : Nat} (h : i < (Array.finRange n).size) : + (Array.finRange n)[i] = Fin.cast size_finRange ⟨i, h⟩ := by simp [Array.finRange] @[simp] theorem finRange_zero : Array.finRange 0 = #[] := by simp [Array.finRange] -theorem finRange_succ (n) : Array.finRange (n+1) = #[0] ++ (Array.finRange n).map Fin.succ := by +theorem finRange_succ {n} : Array.finRange (n+1) = #[0] ++ (Array.finRange n).map Fin.succ := by ext · simp [Nat.add_comm] · simp [getElem_append] split <;> · simp; omega -theorem finRange_succ_last (n) : +theorem finRange_succ_last {n} : Array.finRange (n+1) = (Array.finRange n).map Fin.castSucc ++ #[Fin.last n] := by ext · simp @@ -47,7 +47,7 @@ theorem finRange_succ_last (n) : · simp_all omega -theorem finRange_reverse (n) : (Array.finRange n).reverse = (Array.finRange n).map Fin.rev := by +theorem finRange_reverse {n} : (Array.finRange n).reverse = (Array.finRange n).map Fin.rev := by ext i h · simp · simp diff --git a/src/Init/Data/Array/Find.lean b/src/Init/Data/Array/Find.lean index e3598283f6..5522e31282 100644 --- a/src/Init/Data/Array/Find.lean +++ b/src/Init/Data/Array/Find.lean @@ -21,10 +21,10 @@ open Nat /-! ### findSome? -/ -@[simp] theorem findSomeRev?_push_of_isSome (xs : Array α) (h : (f a).isSome) : (xs.push a).findSomeRev? f = f a := by +@[simp] theorem findSomeRev?_push_of_isSome {xs : Array α} (h : (f a).isSome) : (xs.push a).findSomeRev? f = f a := by cases xs; simp_all -@[simp] theorem findSomeRev?_push_of_isNone (xs : Array α) (h : (f a).isNone) : (xs.push a).findSomeRev? f = xs.findSomeRev? f := by +@[simp] theorem findSomeRev?_push_of_isNone {xs : Array α} (h : (f a).isNone) : (xs.push a).findSomeRev? f = xs.findSomeRev? f := by cases xs; simp_all theorem exists_of_findSome?_eq_some {f : α → Option β} {xs : Array α} (w : xs.findSome? f = some b) : @@ -48,31 +48,31 @@ theorem findSome?_eq_some_iff {f : α → Option β} {xs : Array α} {b : β} : · rintro ⟨xs, a, ys, h₀, h₁, h₂⟩ exact ⟨xs.toList, a, ys.toList, by simpa using congrArg toList h₀, h₁, by simpa⟩ -@[simp] theorem findSome?_guard (xs : Array α) : findSome? (Option.guard fun x => p x) xs = find? p xs := by +@[simp] theorem findSome?_guard {xs : Array α} : findSome? (Option.guard fun x => p x) xs = find? p xs := by cases xs; simp -theorem find?_eq_findSome?_guard (xs : Array α) : find? p xs = findSome? (Option.guard fun x => p x) xs := - (findSome?_guard xs).symm +theorem find?_eq_findSome?_guard {xs : Array α} : find? p xs = findSome? (Option.guard fun x => p x) xs := + findSome?_guard.symm -@[simp] theorem getElem?_zero_filterMap (f : α → Option β) (xs : Array α) : (xs.filterMap f)[0]? = xs.findSome? f := by +@[simp] theorem getElem?_zero_filterMap {f : α → Option β} {xs : Array α} : (xs.filterMap f)[0]? = xs.findSome? f := by cases xs; simp [← List.head?_eq_getElem?] -@[simp] theorem getElem_zero_filterMap (f : α → Option β) (xs : Array α) (h) : +@[simp] theorem getElem_zero_filterMap {f : α → Option β} {xs : Array α} (h) : (xs.filterMap f)[0] = (xs.findSome? f).get (by cases xs; simpa [List.length_filterMap_eq_countP] using h) := by cases xs; simp [← List.head_eq_getElem, ← getElem?_zero_filterMap] -@[simp] theorem back?_filterMap (f : α → Option β) (xs : Array α) : (xs.filterMap f).back? = xs.findSomeRev? f := by +@[simp] theorem back?_filterMap {f : α → Option β} {xs : Array α} : (xs.filterMap f).back? = xs.findSomeRev? f := by cases xs; simp -@[simp] theorem back!_filterMap [Inhabited β] (f : α → Option β) (xs : Array α) : +@[simp] theorem back!_filterMap [Inhabited β] {f : α → Option β} {xs : Array α} : (xs.filterMap f).back! = (xs.findSomeRev? f).getD default := by cases xs; simp -@[simp] theorem map_findSome? (f : α → Option β) (g : β → γ) (xs : Array α) : +@[simp] theorem map_findSome? {f : α → Option β} {g : β → γ} {xs : Array α} : (xs.findSome? f).map g = xs.findSome? (Option.map g ∘ f) := by cases xs; simp -theorem findSome?_map (f : β → γ) (xs : Array β) : findSome? p (xs.map f) = xs.findSome? (p ∘ f) := by +theorem findSome?_map {f : β → γ} {xs : Array β} : findSome? p (xs.map f) = xs.findSome? (p ∘ f) := by cases xs; simp [List.findSome?_map] theorem findSome?_append {xs ys : Array α} : (xs ++ ys).findSome? f = (xs.findSome? f).or (ys.findSome? f) := by @@ -129,15 +129,15 @@ abbrev findSome?_mkArray_of_isNone := @findSome?_replicate_of_isNone /-! ### find? -/ -@[simp] theorem find?_singleton (a : α) (p : α → Bool) : +@[simp] theorem find?_singleton {a : α} {p : α → Bool} : #[a].find? p = if p a then some a else none := by simp [singleton_eq_toArray_singleton] -@[simp] theorem findRev?_push_of_pos (xs : Array α) (h : p a) : +@[simp] theorem findRev?_push_of_pos {xs : Array α} (h : p a) : findRev? p (xs.push a) = some a := by cases xs; simp [h] -@[simp] theorem findRev?_cons_of_neg (xs : Array α) (h : ¬p a) : +@[simp] theorem findRev?_cons_of_neg {xs : Array α} (h : ¬p a) : findRev? p (xs.push a) = findRev? p xs := by cases xs; simp [h] @@ -183,28 +183,28 @@ theorem get_find?_mem {xs : Array α} (h) : (xs.find? p).get h ∈ xs := by (xs.filter p).find? q = xs.find? (fun a => p a ∧ q a) := by cases xs; simp -@[simp] theorem getElem?_zero_filter (p : α → Bool) (xs : Array α) : +@[simp] theorem getElem?_zero_filter {p : α → Bool} {xs : Array α} : (xs.filter p)[0]? = xs.find? p := by cases xs; simp [← List.head?_eq_getElem?] -@[simp] theorem getElem_zero_filter (p : α → Bool) (xs : Array α) (h) : +@[simp] theorem getElem_zero_filter {p : α → Bool} {xs : Array α} (h) : (xs.filter p)[0] = (xs.find? p).get (by cases xs; simpa [← List.countP_eq_length_filter] using h) := by cases xs simp [List.getElem_zero_eq_head] -@[simp] theorem back?_filter (p : α → Bool) (xs : Array α) : (xs.filter p).back? = xs.findRev? p := by +@[simp] theorem back?_filter {p : α → Bool} {xs : Array α} : (xs.filter p).back? = xs.findRev? p := by cases xs; simp -@[simp] theorem back!_filter [Inhabited α] (p : α → Bool) (xs : Array α) : +@[simp] theorem back!_filter [Inhabited α] {p : α → Bool} {xs : Array α} : (xs.filter p).back! = (xs.findRev? p).get! := by cases xs; simp [Option.get!_eq_getD] -@[simp] theorem find?_filterMap (xs : Array α) (f : α → Option β) (p : β → Bool) : +@[simp] theorem find?_filterMap {xs : Array α} {f : α → Option β} {p : β → Bool} : (xs.filterMap f).find? p = (xs.find? (fun a => (f a).any p)).bind f := by cases xs; simp -@[simp] theorem find?_map (f : β → α) (xs : Array β) : +@[simp] theorem find?_map {f : β → α} {xs : Array β} : find? p (xs.map f) = (xs.find? (p ∘ f)).map f := by cases xs; simp @@ -214,7 +214,7 @@ theorem get_find?_mem {xs : Array α} (h) : (xs.find? p).get h ∈ xs := by cases ys simp -@[simp] theorem find?_flatten (xss : Array (Array α)) (p : α → Bool) : +@[simp] theorem find?_flatten {xss : Array (Array α)} {p : α → Bool} : xss.flatten.find? p = xss.findSome? (·.find? p) := by cases xss using array₂_induction simp [List.findSome?_map, Function.comp_def] @@ -254,7 +254,7 @@ theorem find?_flatten_eq_some_iff {xss : Array (Array α)} {p : α → Bool} {a @[deprecated find?_flatten_eq_some_iff (since := "2025-02-03")] abbrev find?_flatten_eq_some := @find?_flatten_eq_some_iff -@[simp] theorem find?_flatMap (xs : Array α) (f : α → Array β) (p : β → Bool) : +@[simp] theorem find?_flatMap {xs : Array α} {f : α → Array β} {p : β → Bool} : (xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by cases xs simp [List.find?_flatMap, Array.flatMap_toArray] @@ -311,15 +311,15 @@ abbrev find?_mkArray_eq_some_iff := @find?_replicate_eq_some_iff @[deprecated find?_replicate_eq_some_iff (since := "2025-02-03")] abbrev find?_mkArray_eq_some := @find?_replicate_eq_some_iff -@[simp] theorem get_find?_replicate (n : Nat) (a : α) (p : α → Bool) (h) : +@[simp] theorem get_find?_replicate {n : Nat} {a : α} {p : α → Bool} (h) : ((replicate n a).find? p).get h = a := by simp [← List.toArray_replicate] @[deprecated get_find?_replicate (since := "2025-03-18")] abbrev get_find?_mkArray := @get_find?_replicate -theorem find?_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : Array α) - (H : ∀ (a : α), a ∈ xs → P a) (p : β → Bool) : +theorem find?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α} + (H : ∀ (a : α), a ∈ xs → P a) {p : β → Bool} : (xs.pmap f H).find? p = (xs.attach.find? (fun ⟨a, m⟩ => p (f a (H a m)))).map fun ⟨a, m⟩ => f a (H a m) := by simp only [pmap_eq_map_attach, find?_map] rfl @@ -359,7 +359,7 @@ theorem findIdx_eq_size_of_false {p : α → Bool} {xs : Array α} (h : ∀ x rcases xs with ⟨xs⟩ simp_all -theorem findIdx_le_size (p : α → Bool) {xs : Array α} : xs.findIdx p ≤ xs.size := by +theorem findIdx_le_size {p : α → Bool} {xs : Array α} : xs.findIdx p ≤ xs.size := by by_cases e : ∃ x ∈ xs, p x · exact Nat.le_of_lt (findIdx_lt_size_of_exists e) · simp at e @@ -373,7 +373,7 @@ theorem findIdx_lt_size {p : α → Bool} {xs : Array α} : /-- `p` does not hold for elements with indices less than `xs.findIdx p`. -/ theorem not_of_lt_findIdx {p : α → Bool} {xs : Array α} {i : Nat} (h : i < xs.findIdx p) : - p (xs[i]'(Nat.le_trans h (findIdx_le_size p))) = false := by + p (xs[i]'(Nat.le_trans h findIdx_le_size)) = false := by rcases xs with ⟨xs⟩ simpa using List.not_of_lt_findIdx (by simpa using h) @@ -404,7 +404,7 @@ theorem findIdx_eq {p : α → Bool} {xs : Array α} {i : Nat} (h : i < xs.size) simp at h3 simp_all [not_of_lt_findIdx h3] -theorem findIdx_append (p : α → Bool) (xs ys : Array α) : +theorem findIdx_append {p : α → Bool} {xs ys : Array α} : (xs ++ ys).findIdx p = if xs.findIdx p < xs.size then xs.findIdx p else ys.findIdx p + xs.size := by rcases xs with ⟨xs⟩ @@ -492,7 +492,8 @@ theorem of_findIdx?_eq_none {xs : Array α} {p : α → Bool} (w : xs.findIdx? p rcases xs with ⟨xs⟩ simpa using List.of_findIdx?_eq_none (by simpa using w) -@[simp] theorem findIdx?_map (f : β → α) (xs : Array β) : findIdx? p (xs.map f) = xs.findIdx? (p ∘ f) := by +@[simp] theorem findIdx?_map {f : β → α} {xs : Array β} {p : α → Bool} : + findIdx? p (xs.map f) = xs.findIdx? (p ∘ f) := by rcases xs with ⟨xs⟩ simp [List.findIdx?_map] diff --git a/src/Init/Data/Array/GetLit.lean b/src/Init/Data/Array/GetLit.lean index d95c8fced6..6ca9c20415 100644 --- a/src/Init/Data/Array/GetLit.lean +++ b/src/Init/Data/Array/GetLit.lean @@ -23,7 +23,7 @@ theorem extLit {n : Nat} (xs ys : Array α) (hsz₁ : xs.size = n) (hsz₂ : ys.size = n) (h : (i : Nat) → (hi : i < n) → xs.getLit i hsz₁ hi = ys.getLit i hsz₂ hi) : xs = ys := - Array.ext xs ys (hsz₁.trans hsz₂.symm) fun i hi₁ _ => h i (hsz₁ ▸ hi₁) + Array.ext (hsz₁.trans hsz₂.symm) fun i hi₁ _ => h i (hsz₁ ▸ hi₁) def toListLitAux (xs : Array α) (n : Nat) (hsz : xs.size = n) : ∀ (i : Nat), i ≤ xs.size → List α → List α | 0, _, acc => acc diff --git a/src/Init/Data/Array/InsertIdx.lean b/src/Init/Data/Array/InsertIdx.lean index 83d1b22e4f..3c853cfed6 100644 --- a/src/Init/Data/Array/InsertIdx.lean +++ b/src/Init/Data/Array/InsertIdx.lean @@ -30,13 +30,13 @@ section InsertIdx variable {a : α} -@[simp] theorem toList_insertIdx (xs : Array α) (i x) (h) : +@[simp] theorem toList_insertIdx {xs : Array α} {i : Nat} {x : α} (h : i ≤ xs.size) : (xs.insertIdx i x h).toList = xs.toList.insertIdx i x := by rcases xs with ⟨xs⟩ simp @[simp] -theorem insertIdx_zero (xs : Array α) (x : α) : xs.insertIdx 0 x = #[x] ++ xs := by +theorem insertIdx_zero {xs : Array α} {x : α} : xs.insertIdx 0 x = #[x] ++ xs := by rcases xs with ⟨xs⟩ simp @@ -44,7 +44,7 @@ theorem insertIdx_zero (xs : Array α) (x : α) : xs.insertIdx 0 x = #[x] ++ xs rcases xs with ⟨xs⟩ simp [List.length_insertIdx, h] -theorem eraseIdx_insertIdx (i : Nat) (xs : Array α) (h : i ≤ xs.size) : +theorem eraseIdx_insertIdx {i : Nat} {xs : Array α} (h : i ≤ xs.size) : (xs.insertIdx i a).eraseIdx i (by simp; omega) = xs := by rcases xs with ⟨xs⟩ simp_all @@ -54,27 +54,27 @@ theorem insertIdx_eraseIdx_of_ge {as : Array α} (as.eraseIdx i).insertIdx j a = (as.insertIdx (j + 1) a (by simp at w₂; omega)).eraseIdx i (by simp_all; omega) := by cases as - simpa using List.insertIdx_eraseIdx_of_ge _ _ _ (by simpa) (by simpa) + simpa using List.insertIdx_eraseIdx_of_ge (by simpa) (by simpa) theorem insertIdx_eraseIdx_of_le {as : Array α} (w₁ : i < as.size) (w₂ : j ≤ (as.eraseIdx i).size) (h : j ≤ i) : (as.eraseIdx i).insertIdx j a = (as.insertIdx j a (by simp at w₂; omega)).eraseIdx (i + 1) (by simp_all) := by cases as - simpa using List.insertIdx_eraseIdx_of_le _ _ _ (by simpa) (by simpa) + simpa using List.insertIdx_eraseIdx_of_le (by simpa) (by simpa) -theorem insertIdx_comm (a b : α) (i j : Nat) (xs : Array α) (_ : i ≤ j) (_ : j ≤ xs.size) : +theorem insertIdx_comm (a b : α) {i j : Nat} {xs : Array α} (_ : i ≤ j) (_ : j ≤ xs.size) : (xs.insertIdx i a).insertIdx (j + 1) b (by simpa) = (xs.insertIdx j b).insertIdx i a (by simp; omega) := by rcases xs with ⟨xs⟩ - simpa using List.insertIdx_comm a b i j _ (by simpa) (by simpa) + simpa using List.insertIdx_comm a b (by simpa) (by simpa) theorem mem_insertIdx {xs : Array α} {h : i ≤ xs.size} : a ∈ xs.insertIdx i b h ↔ a = b ∨ a ∈ xs := by rcases xs with ⟨xs⟩ simpa using List.mem_insertIdx (by simpa) @[simp] -theorem insertIdx_size_self (xs : Array α) (x : α) : xs.insertIdx xs.size x = xs.push x := by +theorem insertIdx_size_self {xs : Array α} {x : α} : xs.insertIdx xs.size x = xs.push x := by rcases xs with ⟨xs⟩ simp diff --git a/src/Init/Data/Array/Lemmas.lean b/src/Init/Data/Array/Lemmas.lean index c48ea60350..1db5a4acf7 100644 --- a/src/Init/Data/Array/Lemmas.lean +++ b/src/Init/Data/Array/Lemmas.lean @@ -34,10 +34,10 @@ namespace Array @[simp] theorem toList_inj {xs ys : Array α} : xs.toList = ys.toList ↔ xs = ys := by cases xs; cases ys; simp -@[simp] theorem toList_eq_nil_iff (xs : Array α) : xs.toList = [] ↔ xs = #[] := by +@[simp] theorem toList_eq_nil_iff {xs : Array α} : xs.toList = [] ↔ xs = #[] := by cases xs <;> simp -@[simp] theorem mem_toList_iff (a : α) (xs : Array α) : a ∈ xs.toList ↔ a ∈ xs := by +@[simp] theorem mem_toList_iff {a : α} {xs : Array α} : a ∈ xs.toList ↔ a ∈ xs := by cases xs <;> simp @[simp] theorem length_toList {xs : Array α} : xs.toList.length = xs.size := rfl @@ -57,10 +57,10 @@ theorem toArray_eq : List.toArray as = xs ↔ as = xs.toList := by theorem size_empty : (#[] : Array α).size = 0 := rfl -@[simp] theorem emptyWithCapacity_eq (α n) : @emptyWithCapacity α n = #[] := rfl +@[simp] theorem emptyWithCapacity_eq {α n} : @emptyWithCapacity α n = #[] := rfl @[deprecated emptyWithCapacity_eq (since := "2025-03-12")] -theorem mkEmpty_eq (α n) : @mkEmpty α n = #[] := rfl +theorem mkEmpty_eq {α n} : @mkEmpty α n = #[] := rfl /-! ### size -/ @@ -150,11 +150,11 @@ theorem getElem_eq_iff {xs : Array α} {i : Nat} {h : i < xs.size} : xs[i] = x simp only [getElem?_eq_some_iff] exact ⟨fun w => ⟨h, w⟩, fun h => h.2⟩ -theorem getElem_eq_getElem?_get (xs : Array α) (i : Nat) (h : i < xs.size) : +theorem getElem_eq_getElem?_get {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] = xs[i]?.get (by simp [getElem?_eq_getElem, h]) := by simp [getElem_eq_iff] -theorem getD_getElem? (xs : Array α) (i : Nat) (d : α) : +theorem getD_getElem? {xs : Array α} {i : Nat} {d : α} : xs[i]?.getD d = if p : i < xs.size then xs[i]'p else d := by if h : i < xs.size then simp [h, getElem?_def] @@ -164,16 +164,16 @@ theorem getD_getElem? (xs : Array α) (i : Nat) (d : α) : @[simp] theorem getElem?_empty {i : Nat} : (#[] : Array α)[i]? = none := rfl -theorem getElem_push_lt (xs : Array α) (x : α) (i : Nat) (h : i < xs.size) : +theorem getElem_push_lt {xs : Array α} {x : α} {i : Nat} (h : i < xs.size) : have : i < (xs.push x).size := by simp [*, Nat.lt_succ_of_le, Nat.le_of_lt] (xs.push x)[i] = xs[i] := by simp only [push, ← getElem_toList, List.concat_eq_append, List.getElem_append_left, h] -@[simp] theorem getElem_push_eq (xs : Array α) (x : α) : (xs.push x)[xs.size] = x := by +@[simp] theorem getElem_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size] = x := by simp only [push, ← getElem_toList, List.concat_eq_append] rw [List.getElem_append_right] <;> simp [← getElem_toList, Nat.zero_lt_one] -theorem getElem_push (xs : Array α) (x : α) (i : Nat) (h : i < (xs.push x).size) : +theorem getElem_push {xs : Array α} {x : α} {i : Nat} (h : i < (xs.push x).size) : (xs.push x)[i] = if h : i < xs.size then xs[i] else x := by by_cases h' : i < xs.size · simp [getElem_push_lt, h'] @@ -187,11 +187,11 @@ theorem getElem?_push {xs : Array α} {x} : (xs.push x)[i]? = if i = xs.size the @[simp] theorem getElem?_push_size {xs : Array α} {x} : (xs.push x)[xs.size]? = some x := by simp [getElem?_push] -@[simp] theorem getElem_singleton (a : α) (h : i < 1) : #[a][i] = a := +@[simp] theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : #[a][i] = a := match i, h with | 0, _ => rfl -theorem getElem?_singleton (a : α) (i : Nat) : #[a][i]? = if i = 0 then some a else none := by +theorem getElem?_singleton {a : α} {i : Nat} : #[a][i]? = if i = 0 then some a else none := by simp [List.getElem?_singleton] theorem ext_getElem? {xs ys : Array α} (h : ∀ i : Nat, xs[i]? = ys[i]?) : xs = ys := by @@ -203,14 +203,14 @@ theorem ext_getElem? {xs ys : Array α} (h : ∀ i : Nat, xs[i]? = ys[i]?) : xs @[simp] theorem pop_empty : (#[] : Array α).pop = #[] := rfl -@[simp] theorem pop_push (xs : Array α) : (xs.push x).pop = xs := by simp [pop] +@[simp] theorem pop_push {xs : Array α} {x : α} : (xs.push x).pop = xs := by simp [pop] @[simp] theorem getElem_pop {xs : Array α} {i : Nat} (h : i < xs.pop.size) : xs.pop[i] = xs[i]'(by simp at h; omega) := by rcases xs with ⟨xs⟩ simp [List.getElem_dropLast] -theorem getElem?_pop (xs : Array α) (i : Nat) : +theorem getElem?_pop {xs : Array α} {i : Nat} : xs.pop[i]? = if i < xs.size - 1 then xs[i]? else none := by rcases xs with ⟨xs⟩ simp [List.getElem?_dropLast] @@ -231,7 +231,7 @@ theorem back?_pop {xs : Array α} : rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ simp only [List.append_toArray, List.pop_toArray, mk.injEq] - rw [List.dropLast_append_of_ne_nil _ (by simpa using h)] + rw [List.dropLast_append_of_ne_nil (by simpa using h)] /-! ### push -/ @@ -274,7 +274,7 @@ theorem push_eq_push {a b : α} {xs ys : Array α} : xs.push a = ys.push b ↔ a · rintro ⟨rfl, rfl⟩ rfl -theorem push_eq_append_singleton (as : Array α) (x) : as.push x = as ++ #[x] := rfl +theorem push_eq_append_singleton {as : Array α} {x : α} : as.push x = as ++ #[x] := rfl theorem exists_push_of_ne_empty {xs : Array α} (h : xs ≠ #[]) : ∃ (ys : Array α) (a : α), xs = ys.push a := by @@ -323,7 +323,7 @@ theorem singleton_inj : #[a] = #[b] ↔ a = b := by /-! ### replicate -/ -@[simp] theorem size_replicate (n : Nat) (v : α) : (replicate n v).size = n := +@[simp] theorem size_replicate {n : Nat} {v : α} : (replicate n v).size = n := List.length_replicate .. @[deprecated size_replicate (since := "2025-03-18")] @@ -347,13 +347,13 @@ theorem replicate_succ : replicate (n + 1) a = (replicate n a).push a := by @[deprecated replicate_succ (since := "2025-03-18")] abbrev mkArray_succ := @replicate_succ -@[simp] theorem getElem_replicate (n : Nat) (v : α) (h : i < (replicate n v).size) : +@[simp] theorem getElem_replicate {n : Nat} {v : α} {i : Nat} (h : i < (replicate n v).size) : (replicate n v)[i] = v := by simp [← getElem_toList] @[deprecated getElem_replicate (since := "2025-03-18")] abbrev getElem_mkArray := @getElem_replicate -@[simp] theorem getElem?_replicate (n : Nat) (v : α) (i : Nat) : +@[simp] theorem getElem?_replicate {n : Nat} {v : α} {i : Nat} : (replicate n v)[i]? = if i < n then some v else none := by simp [getElem?_def] @@ -382,6 +382,8 @@ theorem eq_push_append_of_mem {xs : Array α} {x : α} (h : x ∈ xs) : theorem mem_push_of_mem {xs : Array α} {x : α} (y : α) (h : x ∈ xs) : x ∈ xs.push y := mem_push.2 (Or.inl h) +-- The argument `xs : Array α` is intentionally explicit, +-- as a tactic may generate `h` without determining `xs`. theorem exists_mem_of_ne_empty (xs : Array α) (h : xs ≠ #[]) : ∃ x, x ∈ xs := by simpa using List.exists_mem_of_ne_nil xs.toList (by simpa using h) @@ -548,15 +550,15 @@ instance {xs : Array α} {p : α → Prop} [DecidablePred p] : /-! ### any / all -/ -theorem anyM_eq_anyM_loop [Monad m] (p : α → m Bool) (as : Array α) (start stop) : +theorem anyM_eq_anyM_loop [Monad m] {p : α → m Bool} {as : Array α} {start stop} : anyM p as start stop = anyM.loop p as (min stop as.size) (Nat.min_le_right ..) start := by simp only [anyM, Nat.min_def]; split <;> rfl -theorem anyM_stop_le_start [Monad m] (p : α → m Bool) (as : Array α) (start stop) +theorem anyM_stop_le_start [Monad m] {p : α → m Bool} {as : Array α} {start stop} (h : min stop as.size ≤ start) : anyM p as start stop = pure false := by rw [anyM_eq_anyM_loop, anyM.loop, dif_neg (Nat.not_lt.2 h)] -theorem anyM_loop_cons [Monad m] (p : α → m Bool) (a : α) (as : List α) (stop start : Nat) +theorem anyM_loop_cons [Monad m] {p : α → m Bool} {a : α} {as : List α} {stop start : Nat} (h : stop + 1 ≤ (a :: as).length) : anyM.loop p ⟨a :: as⟩ (stop + 1) h (start + 1) = anyM.loop p ⟨as⟩ stop (by simpa using h) start := by @@ -569,7 +571,7 @@ theorem anyM_loop_cons [Monad m] (p : α → m Bool) (a : α) (as : List α) (st · rw [dif_neg] omega -@[simp] theorem anyM_toList [Monad m] (p : α → m Bool) (as : Array α) : +@[simp] theorem anyM_toList [Monad m] {p : α → m Bool} {as : Array α} : as.toList.anyM p = as.anyM p := match as with | ⟨[]⟩ => by simp [anyM, anyM.loop] @@ -582,7 +584,7 @@ theorem anyM_loop_cons [Monad m] (p : α → m Bool) (a : α) (as : List α) (st · simp · simp only [Bool.false_eq_true, ↓reduceIte] rw [anyM_loop_cons] - simpa [anyM] using anyM_toList p ⟨as⟩ + simpa [anyM] using anyM_toList -- Auxiliary for `any_iff_exists`. theorem anyM_loop_iff_exists {p : α → Bool} {as : Array α} {start stop} (h : stop ≤ as.size) : @@ -628,23 +630,23 @@ theorem any_iff_exists {p : α → Bool} {as : Array α} {start stop} : rw [Bool.eq_false_iff, Ne, any_eq_true] simp -@[simp] theorem any_toList {p : α → Bool} (as : Array α) : as.toList.any p = as.any p := by +@[simp] theorem any_toList {p : α → Bool} {as : Array α} : as.toList.any p = as.any p := by rw [Bool.eq_iff_iff, any_eq_true, List.any_eq_true] simp only [List.mem_iff_getElem, getElem_toList] exact ⟨fun ⟨_, ⟨i, w, rfl⟩, h⟩ => ⟨i, w, h⟩, fun ⟨i, w, h⟩ => ⟨_, ⟨i, w, rfl⟩, h⟩⟩ -theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] (p : α → m Bool) (as : Array α) : +theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] {p : α → m Bool} {as : Array α} : allM p as = (! ·) <$> anyM ((! ·) <$> p ·) as := by dsimp [allM, anyM] simp -@[simp] theorem allM_toList [Monad m] [LawfulMonad m] (p : α → m Bool) (as : Array α) : +@[simp] theorem allM_toList [Monad m] [LawfulMonad m] {p : α → m Bool} {as : Array α} : as.toList.allM p = as.allM p := by rw [allM_eq_not_anyM_not] rw [← anyM_toList] rw [List.allM_eq_not_anyM_not] -theorem all_eq_not_any_not (p : α → Bool) (as : Array α) (start stop) : +theorem all_eq_not_any_not {p : α → Bool} {as : Array α} {start stop} : as.all p start stop = !(as.any (!p ·) start stop) := by dsimp [all, allM] rfl @@ -667,7 +669,7 @@ theorem all_iff_forall {p : α → Bool} {as : Array α} {start stop} : rw [Bool.eq_false_iff, Ne, all_eq_true] simp -@[simp] theorem all_toList {p : α → Bool} (as : Array α) : as.toList.all p = as.all p := by +@[simp] theorem all_toList {p : α → Bool} {as : Array α} : as.toList.all p = as.all p := by rw [Bool.eq_iff_iff, all_eq_true, List.all_eq_true] simp only [List.mem_iff_getElem, getElem_toList] constructor @@ -680,43 +682,45 @@ theorem all_eq_true_iff_forall_mem {xs : Array α} : xs.all p ↔ ∀ x, x ∈ x simp only [← all_toList, List.all_eq_true, mem_def] /-- Variant of `anyM_toArray` with a side condition on `stop`. -/ -@[simp] theorem _root_.List.anyM_toArray' [Monad m] [LawfulMonad m] (p : α → m Bool) (l : List α) +@[simp] theorem _root_.List.anyM_toArray' [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} {stop} (h : stop = l.toArray.size) : l.toArray.anyM p 0 stop = l.anyM p := by subst h rw [← anyM_toList] /-- Variant of `any_toArray` with a side condition on `stop`. -/ -@[simp] theorem _root_.List.any_toArray' (p : α → Bool) (l : List α) (h : stop = l.toArray.size) : +@[simp] theorem _root_.List.any_toArray' {p : α → Bool} {l : List α} {stop} + (h : stop = l.toArray.size) : l.toArray.any p 0 stop = l.any p := by subst h rw [any_toList] /-- Variant of `allM_toArray` with a side condition on `stop`. -/ -@[simp] theorem _root_.List.allM_toArray' [Monad m] [LawfulMonad m] (p : α → m Bool) (l : List α) +@[simp] theorem _root_.List.allM_toArray' [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} {stop} (h : stop = l.toArray.size) : l.toArray.allM p 0 stop = l.allM p := by subst h rw [← allM_toList] /-- Variant of `all_toArray` with a side condition on `stop`. -/ -@[simp] theorem _root_.List.all_toArray' (p : α → Bool) (l : List α) (h : stop = l.toArray.size) : +@[simp] theorem _root_.List.all_toArray' {p : α → Bool} {l : List α} {stop} + (h : stop = l.toArray.size) : l.toArray.all p 0 stop = l.all p := by subst h rw [all_toList] -theorem _root_.List.anyM_toArray [Monad m] [LawfulMonad m] (p : α → m Bool) (l : List α) : +theorem _root_.List.anyM_toArray [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} : l.toArray.anyM p = l.anyM p := by rw [← anyM_toList] -theorem _root_.List.any_toArray (p : α → Bool) (l : List α) : l.toArray.any p = l.any p := by +theorem _root_.List.any_toArray {p : α → Bool} {l : List α} : l.toArray.any p = l.any p := by rw [any_toList] -theorem _root_.List.allM_toArray [Monad m] [LawfulMonad m] (p : α → m Bool) (l : List α) : +theorem _root_.List.allM_toArray [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} : l.toArray.allM p = l.allM p := by rw [← allM_toList] -theorem _root_.List.all_toArray (p : α → Bool) (l : List α) : l.toArray.all p = l.all p := by +theorem _root_.List.all_toArray {p : α → Bool} {l : List α} : l.toArray.all p = l.all p := by rw [all_toList] /-- Variant of `any_eq_true` in terms of membership rather than an array index. -/ @@ -835,10 +839,10 @@ theorem elem_iff [BEq α] [LawfulBEq α] {a : α} {xs : Array α} : theorem contains_iff [BEq α] [LawfulBEq α] {a : α} {xs : Array α} : xs.contains a = true ↔ a ∈ xs := ⟨mem_of_contains_eq_true, contains_eq_true_of_mem⟩ -theorem elem_eq_mem [BEq α] [LawfulBEq α] (a : α) (xs : Array α) : +theorem elem_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} : elem a xs = decide (a ∈ xs) := by rw [Bool.eq_iff_iff, elem_iff, decide_eq_true_iff] -@[simp] theorem contains_eq_mem [BEq α] [LawfulBEq α] (a : α) (xs : Array α) : +@[simp] theorem contains_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} : xs.contains a = decide (a ∈ xs) := by rw [← elem_eq_contains, elem_eq_mem] /-- Variant of `any_push` with a side condition on `stop`. -/ @@ -869,7 +873,7 @@ theorem all_push [BEq α] {xs : Array α} {a : α} {p : α → Bool} : /-! ### set -/ -@[simp] theorem getElem_set_self (xs : Array α) (i : Nat) (h : i < xs.size) (v : α) : +@[simp] theorem getElem_set_self {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} : (xs.set i v)[i]'(by simp [h]) = v := by cases xs simp @@ -877,28 +881,28 @@ theorem all_push [BEq α] {xs : Array α} {a : α} {p : α → Bool} : @[deprecated getElem_set_self (since := "2024-12-11")] abbrev getElem_set_eq := @getElem_set_self -@[simp] theorem getElem?_set_self (xs : Array α) (i : Nat) (h : i < xs.size) (v : α) : +@[simp] theorem getElem?_set_self {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} : (xs.set i v)[i]? = v := by simp [getElem?_eq_getElem, h] @[deprecated getElem?_set_self (since := "2024-12-11")] abbrev getElem?_set_eq := @getElem?_set_self -@[simp] theorem getElem_set_ne (xs : Array α) (i : Nat) (h' : i < xs.size) (v : α) {j : Nat} +@[simp] theorem getElem_set_ne {xs : Array α} {i : Nat} (h' : i < xs.size) {v : α} {j : Nat} (pj : j < xs.size) (h : i ≠ j) : (xs.set i v)[j]'(by simp [*]) = xs[j] := by simp only [set, ← getElem_toList, List.getElem_set_ne h] -@[simp] theorem getElem?_set_ne (xs : Array α) (i : Nat) (h : i < xs.size) {j : Nat} (v : α) +@[simp] theorem getElem?_set_ne {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} {j : Nat} (ne : i ≠ j) : (xs.set i v)[j]? = xs[j]? := by by_cases h : j < xs.size <;> simp [getElem?_eq_getElem, getElem?_eq_none, Nat.ge_of_not_lt, ne, h] -theorem getElem_set (xs : Array α) (i : Nat) (h' : i < xs.size) (v : α) (j : Nat) +theorem getElem_set {xs : Array α} {i : Nat} (h' : i < xs.size) {v : α} {j : Nat} (h : j < (xs.set i v).size) : (xs.set i v)[j] = if i = j then v else xs[j]'(by simpa using h) := by simp at h by_cases p : i = j <;> simp [p, h] -theorem getElem?_set (xs : Array α) (i : Nat) (h : i < xs.size) (v : α) (j : Nat) : +theorem getElem?_set {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} {j : Nat} : (xs.set i v)[j]? = if i = j then some v else xs[j]? := by split <;> simp_all @@ -907,23 +911,23 @@ theorem getElem?_set (xs : Array α) (i : Nat) (h : i < xs.size) (v : α) (j : N cases xs simp -@[simp] theorem set_eq_empty_iff {xs : Array α} (i : Nat) (a : α) (h) : - xs.set i a = #[] ↔ xs = #[] := by +@[simp] theorem set_eq_empty_iff {xs : Array α} {i : Nat} {a : α} {h : i < xs.size} : + xs.set i a = #[] ↔ xs = #[] := by cases xs <;> cases i <;> simp [set] theorem set_comm (a b : α) - {i j : Nat} (xs : Array α) {hi : i < xs.size} {hj : j < (xs.set i a).size} (h : i ≠ j) : + {i j : Nat} {xs : Array α} {hi : i < xs.size} {hj : j < (xs.set i a).size} (h : i ≠ j) : (xs.set i a).set j b = (xs.set j b (by simpa using hj)).set i a (by simpa using hi) := by cases xs - simp [List.set_comm _ _ _ h] + simp [List.set_comm _ _ h] @[simp] -theorem set_set (a b : α) (xs : Array α) (i : Nat) (h : i < xs.size) : +theorem set_set (a : α) {b : α} {xs : Array α} {i : Nat} (h : i < xs.size) : (xs.set i a).set i b (by simpa using h) = xs.set i b := by cases xs simp -theorem mem_set (xs : Array α) (i : Nat) (h : i < xs.size) (a : α) : +theorem mem_set {xs : Array α} {i : Nat} (h : i < xs.size) {a : α} : a ∈ xs.set i a := by simp [mem_iff_getElem] exact ⟨i, (by simpa using h), by simp⟩ @@ -940,14 +944,14 @@ theorem mem_or_eq_of_mem_set @[deprecated set!_eq_setIfInBounds (since := "2024-12-12")] abbrev set!_is_setIfInBounds := @set!_eq_setIfInBounds -@[simp] theorem size_setIfInBounds (xs : Array α) (i : Nat) (a : α) : +@[simp] theorem size_setIfInBounds {xs : Array α} {i : Nat} {a : α} : (xs.setIfInBounds i a).size = xs.size := by if h : i < xs.size then simp [setIfInBounds, h] else simp [setIfInBounds, h] -theorem getElem_setIfInBounds (xs : Array α) (i : Nat) (a : α) (j : Nat) +theorem getElem_setIfInBounds {xs : Array α} {i : Nat} {a : α} {j : Nat} (hj : j < xs.size) : (xs.setIfInBounds i a)[j]'(by simp [hj]) = if i = j then a else xs[j] := by simp only [setIfInBounds] @@ -956,7 +960,7 @@ theorem getElem_setIfInBounds (xs : Array α) (i : Nat) (a : α) (j : Nat) · rw [if_neg] omega -@[simp] theorem getElem_setIfInBounds_self (xs : Array α) {i : Nat} (a : α) (h : _) : +@[simp] theorem getElem_setIfInBounds_self {xs : Array α} {i : Nat} {a : α} (h : i < (xs.setIfInBounds i a).size) : (xs.setIfInBounds i a)[i]'h = a := by simp at h simp only [setIfInBounds, h, ↓reduceDIte, getElem_set_self] @@ -964,7 +968,7 @@ theorem getElem_setIfInBounds (xs : Array α) (i : Nat) (a : α) (j : Nat) @[deprecated getElem_setIfInBounds_self (since := "2024-12-11")] abbrev getElem_setIfInBounds_eq := @getElem_setIfInBounds_self -@[simp] theorem getElem_setIfInBounds_ne (xs : Array α) {i : Nat} (a : α) {j : Nat} +@[simp] theorem getElem_setIfInBounds_ne {xs : Array α} {i : Nat} {a : α} {j : Nat} (hj : j < xs.size) (h : i ≠ j) : (xs.setIfInBounds i a)[j]'(by simpa using hj) = xs[j] := by simp [getElem_setIfInBounds, hj, h] @@ -974,12 +978,12 @@ theorem getElem?_setIfInBounds {xs : Array α} {i j : Nat} {a : α} : cases xs simp [List.getElem?_set] -theorem getElem?_setIfInBounds_self (xs : Array α) {i : Nat} (a : α) : +theorem getElem?_setIfInBounds_self {xs : Array α} {i : Nat} {a : α} : (xs.setIfInBounds i a)[i]? = if i < xs.size then some a else none := by simp [getElem?_setIfInBounds] @[simp] -theorem getElem?_setIfInBounds_self_of_lt (xs : Array α) {i : Nat} (a : α) (h : i < xs.size) : +theorem getElem?_setIfInBounds_self_of_lt {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) : (xs.setIfInBounds i a)[i]? = some a := by simp [getElem?_setIfInBounds, h] @@ -995,23 +999,23 @@ theorem setIfInBounds_eq_of_size_le {xs : Array α} {i : Nat} (h : xs.size ≤ i cases xs simp [List.set_eq_of_length_le (by simpa using h)] -@[simp] theorem setIfInBounds_eq_empty_iff {xs : Array α} (i : Nat) (a : α) : +@[simp] theorem setIfInBounds_eq_empty_iff {xs : Array α} {i : Nat} {a : α} : xs.setIfInBounds i a = #[] ↔ xs = #[] := by cases xs <;> cases i <;> simp theorem setIfInBounds_comm (a b : α) - {i j : Nat} (xs : Array α) (h : i ≠ j) : + {i j : Nat} {xs : Array α} (h : i ≠ j) : (xs.setIfInBounds i a).setIfInBounds j b = (xs.setIfInBounds j b).setIfInBounds i a := by cases xs - simp [List.set_comm _ _ _ h] + simp [List.set_comm _ _ h] @[simp] -theorem setIfInBounds_setIfInBounds (a b : α) (xs : Array α) (i : Nat) : +theorem setIfInBounds_setIfInBounds (a : α) {b : α} {xs : Array α} {i : Nat} : (xs.setIfInBounds i a).setIfInBounds i b = xs.setIfInBounds i b := by cases xs simp -theorem mem_setIfInBounds (xs : Array α) (i : Nat) (h : i < xs.size) (a : α) : +theorem mem_setIfInBounds {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) : a ∈ xs.setIfInBounds i a := by simp [mem_iff_getElem] exact ⟨i, (by simpa using h), by simp⟩ @@ -1022,12 +1026,12 @@ theorem mem_or_eq_of_mem_setIfInBounds simpa using List.mem_or_eq_of_mem_set (by simpa using h) /-- Simplifies a normal form from `get!` -/ -@[simp] theorem getD_get?_setIfInBounds (xs : Array α) (i : Nat) (v d : α) : +@[simp] theorem getD_get?_setIfInBounds {xs : Array α} {i : Nat} {v d : α} : (xs.setIfInBounds i v)[i]?.getD d = if i < xs.size then v else d := by by_cases h : i < xs.size <;> simp [setIfInBounds, Nat.not_lt_of_le, h, getD_getElem?] -@[simp] theorem toList_setIfInBounds (xs : Array α) (i x) : +@[simp] theorem toList_setIfInBounds {xs : Array α} {i : Nat} {x : α} : (xs.setIfInBounds i x).toList = xs.toList.set i x := by simp only [setIfInBounds] split <;> rename_i h @@ -1114,11 +1118,11 @@ private theorem beq_of_beq_singleton [BEq α] {a b : α} : #[a] == #[b] → a == /-! ### back -/ -theorem back_eq_getElem (xs : Array α) (h : 0 < xs.size) : xs.back = xs[xs.size - 1] := by +theorem back_eq_getElem {xs : Array α} (h : 0 < xs.size) : xs.back = xs[xs.size - 1] := by cases xs simp [List.getLast_eq_getElem] -theorem back?_eq_getElem? (xs : Array α) : xs.back? = xs[xs.size - 1]? := by +theorem back?_eq_getElem? {xs : Array α} : xs.back? = xs[xs.size - 1]? := by cases xs simp [List.getLast?_eq_getElem?] @@ -1128,7 +1132,7 @@ theorem back?_eq_getElem? (xs : Array α) : xs.back? = xs[xs.size - 1]? := by /-! ### map -/ -theorem mapM_eq_foldlM [Monad m] [LawfulMonad m] (f : α → m β) (xs : Array α) : +theorem mapM_eq_foldlM [Monad m] [LawfulMonad m] {f : α → m β} {xs : Array α} : xs.mapM f = xs.foldlM (fun bs a => bs.push <$> f a) #[] := by rw [mapM, aux, ← foldlM_toList]; rfl where @@ -1143,35 +1147,37 @@ where termination_by xs.size - i decreasing_by decreasing_trivial_pre_omega -@[simp] theorem toList_map (f : α → β) (xs : Array α) : (xs.map f).toList = xs.toList.map f := by +@[simp] theorem toList_map {f : α → β} {xs : Array α} : (xs.map f).toList = xs.toList.map f := by rw [map, mapM_eq_foldlM] - apply congrArg toList (foldl_toList (fun bs a => push bs (f a)) #[] xs).symm |>.trans + apply congrArg toList (foldl_toList fun bs a => push bs (f a)).symm |>.trans have H (l xs) : List.foldl (fun bs a => push bs (f a)) xs l = ⟨xs.toList ++ l.map f⟩ := by induction l generalizing xs <;> simp [*] simp [H] -@[simp] theorem _root_.List.map_toArray (f : α → β) (l : List α) : +@[simp] theorem _root_.List.map_toArray {f : α → β} {l : List α} : l.toArray.map f = (l.map f).toArray := by apply ext' simp -@[simp] theorem size_map (f : α → β) (xs : Array α) : (xs.map f).size = xs.size := by +@[simp] theorem size_map {f : α → β} {xs : Array α} : (xs.map f).size = xs.size := by simp only [← length_toList] simp -@[simp] theorem getElem_map (f : α → β) (xs : Array α) (i : Nat) (hi : i < (xs.map f).size) : +-- The argument `f : α → β` is explicit, to facilitate rewriting from right to left. +@[simp] theorem getElem_map (f : α → β) {xs : Array α} {i : Nat} (hi : i < (xs.map f).size) : (xs.map f)[i] = f (xs[i]'(by simpa using hi)) := by cases xs simp -@[simp] theorem getElem?_map (f : α → β) (xs : Array α) (i : Nat) : +@[simp] theorem getElem?_map {f : α → β} {xs : Array α} {i : Nat} : (xs.map f)[i]? = xs[i]?.map f := by simp [getElem?_def] +-- The argument `f : α → m β` is explicit, as otherwise the monad may not be inferred. @[simp] theorem mapM_empty [Monad m] (f : α → m β) : mapM f #[] = pure #[] := by rw [mapM, mapM.map]; rfl -@[simp] theorem map_empty (f : α → β) : map f #[] = #[] := mapM_empty f +@[simp] theorem map_empty {f : α → β} : map f #[] = #[] := mapM_empty f @[simp] theorem map_push {f : α → β} {as : Array α} {x : α} : (as.push x).map f = (as.map f).push (f x) := by @@ -1188,18 +1194,21 @@ where @[simp] theorem map_id_fun' : map (fun (a : α) => a) = id := map_id_fun -- This is not a `@[simp]` lemma because `map_id_fun` will apply. +-- The argument `xs : Array α` is explicit to allow rewriting from right to left. theorem map_id (xs : Array α) : map (id : α → α) xs = xs := by cases xs <;> simp_all /-- `map_id'` differs from `map_id` by representing the identity function as a lambda, rather than `id`. -/ -- This is not a `@[simp]` lemma because `map_id_fun'` will apply. +-- The argument `xs : Array α` is explicit to allow rewriting from right to left. theorem map_id' (xs : Array α) : map (fun (a : α) => a) xs = xs := map_id xs /-- Variant of `map_id`, with a side condition that the function is pointwise the identity. -/ +-- The argument `xs : Array α` is explicit to allow rewriting from right to left. theorem map_id'' {f : α → α} (h : ∀ x, f x = x) (xs : Array α) : map f xs = xs := by simp [show f = id from funext h] -theorem map_singleton (f : α → β) (a : α) : map f #[a] = #[f a] := by simp +theorem map_singleton {f : α → β} {a : α} : map f #[a] = #[f a] := by simp -- We use a lower priority here as there are more specific lemmas in downstream libraries -- which should be able to fire first. @@ -1208,7 +1217,7 @@ theorem map_singleton (f : α → β) (a : α) : map f #[a] = #[f a] := by simp theorem exists_of_mem_map (h : b ∈ map f l) : ∃ a, a ∈ l ∧ f a = b := mem_map.1 h -theorem mem_map_of_mem (f : α → β) (h : a ∈ l) : f a ∈ map f l := mem_map.2 ⟨_, h, rfl⟩ +theorem mem_map_of_mem {f : α → β} (h : a ∈ l) : f a ∈ map f l := mem_map.2 ⟨_, h, rfl⟩ theorem forall_mem_map {f : α → β} {xs : Array α} {P : β → Prop} : (∀ (i) (_ : i ∈ xs.map f), P i) ↔ ∀ (j) (_ : j ∈ xs), P (f j) := by @@ -1265,9 +1274,9 @@ theorem map_eq_iff {f : α → β} {xs : Array α} {ys : Array β} : cases ys simp [List.map_eq_iff] -theorem map_eq_foldl (f : α → β) (xs : Array α) : +theorem map_eq_foldl {f : α → β} {xs : Array α} : map f xs = foldl (fun bs a => bs.push (f a)) #[] xs := by - simpa using mapM_eq_foldlM (m := Id) f xs + simpa using mapM_eq_foldlM @[simp] theorem map_set {f : α → β} {xs : Array α} {i : Nat} {h : i < xs.size} {a : α} : (xs.set i a).map f = (xs.map f).set i (f a) (by simpa using h) := by @@ -1291,7 +1300,7 @@ theorem map_eq_foldl (f : α → β) (xs : Array α) : (as.map f).map g = as.map (g ∘ f) := by cases as; simp -theorem mapM_eq_mapM_toList [Monad m] [LawfulMonad m] (f : α → m β) (xs : Array α) : +theorem mapM_eq_mapM_toList [Monad m] [LawfulMonad m] {f : α → m β} {xs : Array α} : xs.mapM f = List.toArray <$> (xs.toList.mapM f) := by rw [mapM_eq_foldlM, ← foldlM_toList, ← List.foldrM_reverse] conv => rhs; rw [← List.reverse_reverse xs.toList] @@ -1299,12 +1308,12 @@ theorem mapM_eq_mapM_toList [Monad m] [LawfulMonad m] (f : α → m β) (xs : Ar | nil => simp | cons a l ih => simp [ih] -@[simp] theorem toList_mapM [Monad m] [LawfulMonad m] (f : α → m β) (xs : Array α) : +@[simp] theorem toList_mapM [Monad m] [LawfulMonad m] {f : α → m β} {xs : Array α} : toList <$> xs.mapM f = xs.toList.mapM f := by simp [mapM_eq_mapM_toList] @[deprecated "Use `mapM_eq_foldlM` instead" (since := "2025-01-08")] -theorem mapM_map_eq_foldl (as : Array α) (f : α → β) (i) : +theorem mapM_map_eq_foldl {as : Array α} {f : α → β} {i : Nat} : mapM.map (m := Id) f as i b = as.foldl (start := i) (fun acc a => acc.push (f a)) b := by unfold mapM.map split <;> rename_i h @@ -1353,7 +1362,7 @@ theorem filter_congr {xs ys : Array α} (h : xs = ys) filter f xs start stop = filter g ys start' stop' := by congr -@[simp] theorem toList_filter' (p : α → Bool) (xs : Array α) (h : stop = xs.size) : +@[simp] theorem toList_filter' {p : α → Bool} {xs : Array α} {stop : Nat} (h : stop = xs.size) : (xs.filter p 0 stop).toList = xs.toList.filter p := by subst h dsimp only [filter] @@ -1365,16 +1374,16 @@ theorem filter_congr {xs ys : Array α} (h : xs = ys) induction xs with simp | cons => split <;> simp [*] -theorem toList_filter (p : α → Bool) (xs : Array α) : +theorem toList_filter {p : α → Bool} {xs : Array α} : (xs.filter p).toList = xs.toList.filter p := by simp -@[simp] theorem _root_.List.filter_toArray' (p : α → Bool) (l : List α) (h : stop = l.length) : +@[simp] theorem _root_.List.filter_toArray' {p : α → Bool} {l : List α} {stop : Nat} (h : stop = l.length) : l.toArray.filter p 0 stop = (l.filter p).toArray := by apply ext' simp [h] -theorem _root_.List.filter_toArray (p : α → Bool) (l : List α) : +theorem _root_.List.filter_toArray {p : α → Bool} {l : List α} : l.toArray.filter p = (l.filter p).toArray := by simp @@ -1396,7 +1405,7 @@ theorem filter_push {p : α → Bool} {a : α} {xs : Array α} : (xs.push a).filter p = if p a then (xs.filter p).push a else xs.filter p := by split <;> simp [*] -theorem size_filter_le (p : α → Bool) (xs : Array α) : +theorem size_filter_le {p : α → Bool} {xs : Array α} : (xs.filter p).size ≤ xs.size := by rcases xs with ⟨xs⟩ simpa using List.length_filter_le p xs @@ -1425,28 +1434,28 @@ theorem forall_mem_filter {p : α → Bool} {xs : Array α} {P : α → Prop} : (∀ (i) (_ : i ∈ xs.filter p), P i) ↔ ∀ (j) (_ : j ∈ xs), p j → P j := by simp -@[simp] theorem filter_filter (q) (xs : Array α) : +@[simp] theorem filter_filter {p q : α → Bool} {xs : Array α} : filter p (filter q xs) = filter (fun a => p a && q a) xs := by apply ext' simp only [toList_filter, List.filter_filter] -theorem foldl_filter (p : α → Bool) (f : β → α → β) (xs : Array α) (init : β) : +theorem foldl_filter {p : α → Bool} {f : β → α → β} {xs : Array α} {init : β} : (xs.filter p).foldl f init = xs.foldl (fun x y => if p y then f x y else x) init := by rcases xs with ⟨xs⟩ rw [List.filter_toArray] simp [List.foldl_filter] -theorem foldr_filter (p : α → Bool) (f : α → β → β) (xs : Array α) (init : β) : +theorem foldr_filter {p : α → Bool} {f : α → β → β} {xs : Array α} {init : β} : (xs.filter p).foldr f init = xs.foldr (fun x y => if p x then f x y else y) init := by rcases xs with ⟨xs⟩ rw [List.filter_toArray] simp [List.foldr_filter] -theorem filter_map (f : β → α) (xs : Array β) : filter p (map f xs) = map f (filter (p ∘ f) xs) := by +theorem filter_map {f : β → α} {xs : Array β} : filter p (map f xs) = map f (filter (p ∘ f) xs) := by rcases xs with ⟨xs⟩ simp [List.filter_map] -theorem map_filter_eq_foldl (f : α → β) (p : α → Bool) (xs : Array α) : +theorem map_filter_eq_foldl {f : α → β} {p : α → Bool} {xs : Array α} : map f (filter p xs) = foldl (fun acc x => bif p x then acc.push (f x) else acc) #[] xs := by rcases xs with ⟨xs⟩ apply ext' @@ -1460,7 +1469,7 @@ theorem map_filter_eq_foldl (f : α → β) (p : α → Bool) (xs : Array α) : simp only [List.filter_cons, List.foldr_cons] split <;> simp_all -@[simp] theorem filter_append {p : α → Bool} (xs ys : Array α) (w : stop = xs.size + ys.size) : +@[simp] theorem filter_append {p : α → Bool} {xs ys : Array α} {stop : Nat} (w : stop = xs.size + ys.size) : filter p (xs ++ ys) 0 stop = filter p xs ++ filter p ys := by subst w rcases xs with ⟨xs⟩ @@ -1521,7 +1530,7 @@ theorem filterMap_congr {as bs : Array α} (h : as = bs) filterMap f as start stop = filterMap g bs start' stop' := by congr -@[simp] theorem toList_filterMap' (f : α → Option β) (xs : Array α) (w : stop = xs.size) : +@[simp] theorem toList_filterMap' {f : α → Option β} {xs : Array α} {stop : Nat} (w : stop = xs.size) : (xs.filterMap f 0 stop).toList = xs.toList.filterMap f := by subst w dsimp only [filterMap, filterMapM] @@ -1535,17 +1544,17 @@ theorem filterMap_congr {as bs : Array α} (h : as = bs) · simp_all [Id.run, List.filterMap_cons] split <;> simp_all -theorem toList_filterMap (f : α → Option β) (xs : Array α) : +theorem toList_filterMap {f : α → Option β} {xs : Array α} : (xs.filterMap f).toList = xs.toList.filterMap f := by simp [toList_filterMap'] -@[simp] theorem _root_.List.filterMap_toArray' (f : α → Option β) (l : List α) (h : stop = l.length) : +@[simp] theorem _root_.List.filterMap_toArray' {f : α → Option β} {l : List α} {stop : Nat} (h : stop = l.length) : l.toArray.filterMap f 0 stop = (l.filterMap f).toArray := by apply ext' simp [h] -theorem _root_.List.filterMap_toArray (f : α → Option β) (l : List α) : +theorem _root_.List.filterMap_toArray {f : α → Option β} {l : List α} : l.toArray.filterMap f = (l.filterMap f).toArray := by simp @@ -1563,7 +1572,7 @@ theorem _root_.List.filterMap_toArray (f : α → Option β) (l : List α) : rcases xs with ⟨xs⟩ simp [h] -@[simp] theorem filterMap_eq_map (f : α → β) (w : stop = as.size) : +@[simp] theorem filterMap_eq_map {f : α → β} (w : stop = as.size) : filterMap (some ∘ f) as 0 stop = map f as := by subst w cases as @@ -1571,25 +1580,25 @@ theorem _root_.List.filterMap_toArray (f : α → Option β) (l : List α) : /-- Variant of `filterMap_eq_map` with `some ∘ f` expanded out to a lambda. -/ @[simp] -theorem filterMap_eq_map' (f : α → β) (w : stop = as.size) : +theorem filterMap_eq_map' {f : α → β} (w : stop = as.size) : filterMap (fun x => some (f x)) as 0 stop = map f as := - filterMap_eq_map f w + filterMap_eq_map w theorem filterMap_some_fun : filterMap (some : α → Option α) = id := by funext xs cases xs simp -@[simp] theorem filterMap_some (xs : Array α) : filterMap some xs = xs := by +@[simp] theorem filterMap_some {xs : Array α} : filterMap some xs = xs := by cases xs simp -theorem map_filterMap_some_eq_filterMap_isSome (f : α → Option β) (xs : Array α) : +theorem map_filterMap_some_eq_filterMap_isSome {f : α → Option β} {xs : Array α} : (xs.filterMap f).map some = (xs.map f).filter fun b => b.isSome := by cases xs simp [List.map_filterMap_some_eq_filter_map_isSome] -theorem size_filterMap_le (f : α → Option β) (xs : Array α) : +theorem size_filterMap_le {f : α → Option β} {xs : Array α} : (xs.filterMap f).size ≤ xs.size := by cases xs simp [List.length_filterMap_le] @@ -1600,33 +1609,33 @@ theorem size_filterMap_le (f : α → Option β) (xs : Array α) : simp [List.filterMap_length_eq_length] @[simp] -theorem filterMap_eq_filter (p : α → Bool) (w : stop = as.size) : +theorem filterMap_eq_filter {p : α → Bool} (w : stop = as.size) : filterMap (Option.guard (p ·)) as 0 stop = filter p as := by subst w cases as simp -theorem filterMap_filterMap (f : α → Option β) (g : β → Option γ) (xs : Array α) : +theorem filterMap_filterMap {f : α → Option β} {g : β → Option γ} {xs : Array α} : filterMap g (filterMap f xs) = filterMap (fun x => (f x).bind g) xs := by cases xs simp [List.filterMap_filterMap] -theorem map_filterMap (f : α → Option β) (g : β → γ) (xs : Array α) : +theorem map_filterMap {f : α → Option β} {g : β → γ} {xs : Array α} : map g (filterMap f xs) = filterMap (fun x => (f x).map g) xs := by cases xs simp [List.map_filterMap] -@[simp] theorem filterMap_map (f : α → β) (g : β → Option γ) (xs : Array α) : +@[simp] theorem filterMap_map {f : α → β} {g : β → Option γ} {xs : Array α} : filterMap g (map f xs) = filterMap (g ∘ f) xs := by cases xs simp [List.filterMap_map] -theorem filter_filterMap (f : α → Option β) (p : β → Bool) (xs : Array α) : +theorem filter_filterMap {f : α → Option β} {p : β → Bool} {xs : Array α} : filter p (filterMap f xs) = filterMap (fun x => (f x).filter p) xs := by cases xs simp [List.filter_filterMap] -theorem filterMap_filter (p : α → Bool) (f : α → Option β) (xs : Array α) : +theorem filterMap_filter {p : α → Bool} {f : α → Option β} {xs : Array α} : filterMap f (filter p xs) = filterMap (fun x => if p x then f x else none) xs := by cases xs simp [List.filterMap_filter] @@ -1643,15 +1652,16 @@ theorem forall_mem_filterMap {f : α → Option β} {xs : Array α} {P : β → intro a rw [forall_comm] -@[simp] theorem filterMap_append {α β : Type _} {xs ys : Array α} (f : α → Option β) (w : stop = xs.size + ys.size) : +@[simp] theorem filterMap_append {α β : Type _} {xs ys : Array α} {f : α → Option β} {stop : Nat} (w : stop = xs.size + ys.size) : filterMap f (xs ++ ys) 0 stop = filterMap f xs ++ filterMap f ys := by subst w cases xs cases ys simp -theorem map_filterMap_of_inv (f : α → Option β) (g : β → α) (H : ∀ x : α, (f x).map g = some x) - (xs : Array α) : map g (filterMap f xs) = xs := by simp only [map_filterMap, H, filterMap_some, id] +theorem map_filterMap_of_inv {f : α → Option β} {g : β → α} (H : ∀ x : α, (f x).map g = some x) {xs : Array α} : + map g (filterMap f xs) = xs := by + simp only [map_filterMap, H, filterMap_some, id] theorem forall_none_of_filterMap_eq_empty (h : filterMap f xs = #[]) : ∀ x ∈ xs, f x = none := by cases xs @@ -1692,11 +1702,11 @@ theorem size_filterMap_lt_size_iff_exists {xs : Array α} {f : α → Option β} /-! ### singleton -/ -@[simp] theorem singleton_def (v : α) : Array.singleton v = #[v] := rfl +@[simp] theorem singleton_def {v : α} : Array.singleton v = #[v] := rfl /-! ### append -/ -@[simp] theorem size_append (xs ys : Array α) : (xs ++ ys).size = xs.size + ys.size := by +@[simp] theorem size_append {xs ys : Array α} : (xs ++ ys).size = xs.size + ys.size := by simp only [size, toList_append, List.length_append] @[simp] theorem push_append {a : α} {xs ys : Array α} : (xs ++ ys).push a = xs ++ ys.push a := by @@ -1726,7 +1736,7 @@ theorem toArray_append {xs : List α} {ys : Array α} : cases ys simp -theorem singleton_eq_toArray_singleton (a : α) : #[a] = [a].toArray := rfl +theorem singleton_eq_toArray_singleton {a : α} : #[a] = [a].toArray := rfl @[simp] theorem empty_append_fun : ((#[] : Array α) ++ ·) = id := by funext ⟨l⟩ @@ -1801,7 +1811,7 @@ theorem getElem?_append {xs ys : Array α} {i : Nat} : · exact getElem?_append_right (by simpa using h) /-- Variant of `getElem_append_left` useful for rewriting from the small array to the big array. -/ -theorem getElem_append_left' (ys : Array α) {xs : Array α} {i : Nat} (hi : i < xs.size) : +theorem getElem_append_left' {xs : Array α} {i : Nat} (hi : i < xs.size) (ys : Array α) : xs[i] = (xs ++ ys)[i]'(by simpa using Nat.lt_add_right ys.size hi) := by rw [getElem_append_left] <;> simp @@ -1990,7 +2000,7 @@ theorem append_eq_filterMap_iff {f : α → Option β} : ∃ as bs, zs = as ++ bs ∧ filterMap f as = xs ∧ filterMap f bs = ys := by rw [eq_comm, filterMap_eq_append_iff] -@[simp] theorem map_append (f : α → β) (xs ys : Array α) : +@[simp] theorem map_append {f : α → β} {xs ys : Array α} : map f (xs ++ ys) = map f xs ++ map f ys := by rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ @@ -2019,27 +2029,27 @@ theorem append_eq_map_iff {f : α → β} : | nil => simp | cons as => induction as.toList <;> simp [*] -@[simp] theorem flatten_map_toArray (L : List (List α)) : +@[simp] theorem flatten_map_toArray {L : List (List α)} : (L.toArray.map List.toArray).flatten = L.flatten.toArray := by apply ext' simp [Function.comp_def] -@[simp] theorem flatten_toArray_map (L : List (List α)) : +@[simp] theorem flatten_toArray_map {L : List (List α)} : (L.map List.toArray).toArray.flatten = L.flatten.toArray := by rw [← flatten_map_toArray] simp -- We set this to lower priority so that `flatten_toArray_map` is applied first when relevant. -@[simp 500] theorem flatten_toArray (l : List (Array α)) : +@[simp 500] theorem flatten_toArray {l : List (Array α)} : l.toArray.flatten = (l.map Array.toList).flatten.toArray := by apply ext' simp -@[simp] theorem size_flatten (xss : Array (Array α)) : xss.flatten.size = (xss.map size).sum := by +@[simp] theorem size_flatten {xss : Array (Array α)} : xss.flatten.size = (xss.map size).sum := by cases xss using array₂_induction simp [Function.comp_def] -@[simp] theorem flatten_singleton (xs : Array α) : #[xs].flatten = xs := by simp [flatten]; rfl +@[simp] theorem flatten_singleton {xs : Array α} : #[xs].flatten = xs := by simp [flatten]; rfl theorem mem_flatten : ∀ {xss : Array (Array α)}, a ∈ xss.flatten ↔ ∃ xs, xs ∈ xss ∧ a ∈ xs := by simp only [mem_def, toList_flatten, List.mem_flatten, List.mem_map] @@ -2074,7 +2084,7 @@ theorem flatten_eq_flatMap {xss : Array (Array α)} : flatten xss = xss.flatMap rw [flatten_toArray_map, List.flatten_eq_flatMap] simp [List.flatMap_map] -@[simp] theorem map_flatten (f : α → β) (xss : Array (Array α)) : +@[simp] theorem map_flatten {f : α → β} {xss : Array (Array α)} : (flatten xss).map f = (map (map f) xss).flatten := by induction xss using array₂_induction with | of xss => @@ -2082,7 +2092,7 @@ theorem flatten_eq_flatMap {xss : Array (Array α)} : flatten xss = xss.flatMap Function.comp_def] rw [← Function.comp_def, ← List.map_map, flatten_toArray_map] -@[simp] theorem filterMap_flatten (f : α → Option β) (xss : Array (Array α)) (w : stop = xss.flatten.size) : +@[simp] theorem filterMap_flatten {f : α → Option β} {xss : Array (Array α)} {stop : Nat} (w : stop = xss.flatten.size) : filterMap f (flatten xss) 0 stop = flatten (map (filterMap f) xss) := by subst w induction xss using array₂_induction @@ -2090,7 +2100,7 @@ theorem flatten_eq_flatMap {xss : Array (Array α)} : flatten xss = xss.flatMap List.filterMap_flatten, List.map_toArray, List.map_map, Function.comp_def] rw [← Function.comp_def, ← List.map_map, flatten_toArray_map] -@[simp] theorem filter_flatten (p : α → Bool) (xss : Array (Array α)) (w : stop = xss.flatten.size) : +@[simp] theorem filter_flatten {p : α → Bool} {xss : Array (Array α)} {stop : Nat} (w : stop = xss.flatten.size) : filter p (flatten xss) 0 stop = flatten (map (filter p) xss) := by subst w induction xss using array₂_induction @@ -2108,13 +2118,13 @@ theorem flatten_filter_ne_empty [DecidablePred fun xs : Array α => xs ≠ #[]] simp only [ne_eq, ← isEmpty_iff, Bool.not_eq_true, Bool.decide_eq_false, flatten_filter_not_isEmpty] -@[simp] theorem flatten_append (xss₁ xss₂ : Array (Array α)) : +@[simp] theorem flatten_append {xss₁ xss₂ : Array (Array α)} : flatten (xss₁ ++ xss₂) = flatten xss₁ ++ flatten xss₂ := by induction xss₁ using array₂_induction induction xss₂ using array₂_induction simp [← List.map_append] -theorem flatten_push (xss : Array (Array α)) (xs : Array α) : +theorem flatten_push {xss : Array (Array α)} {xs : Array α} : flatten (xss.push xs) = flatten xss ++ xs := by induction xss using array₂_induction rcases xs with ⟨l⟩ @@ -2195,7 +2205,7 @@ theorem eq_iff_flatten_eq {xss₁ xss₂ : Array (Array α)} : rw [List.map_inj_right] simp +contextual -@[simp] theorem flatten_toArray_map_toArray (xss : List (List α)) : +@[simp] theorem flatten_toArray_map_toArray {xss : List (List α)} : (xss.map List.toArray).toArray.flatten = xss.flatten.toArray := by simp [flatten] suffices ∀ as, List.foldl (fun acc bs => acc ++ bs) as (List.map List.toArray xss) = as ++ xss.flatten.toArray by @@ -2207,23 +2217,23 @@ theorem eq_iff_flatten_eq {xss₁ xss₂ : Array (Array α)} : /-! ### flatMap -/ -theorem flatMap_def (xs : Array α) (f : α → Array β) : xs.flatMap f = flatten (map f xs) := by +theorem flatMap_def {xs : Array α} {f : α → Array β} : xs.flatMap f = flatten (map f xs) := by rcases xs with ⟨l⟩ simp [flatten_toArray, Function.comp_def, List.flatMap_def] -@[simp] theorem flatMap_empty {β} (f : α → Array β) : (#[] : Array α).flatMap f = #[] := rfl +@[simp] theorem flatMap_empty {β} {f : α → Array β} : (#[] : Array α).flatMap f = #[] := rfl -theorem flatMap_toList (xs : Array α) (f : α → List β) : +theorem flatMap_toList {xs : Array α} {f : α → List β} : xs.toList.flatMap f = (xs.flatMap (fun a => (f a).toArray)).toList := by rcases xs with ⟨l⟩ simp -@[simp] theorem toList_flatMap (xs : Array α) (f : α → Array β) : +@[simp] theorem toList_flatMap {xs : Array α} {f : α → Array β} : (xs.flatMap f).toList = xs.toList.flatMap fun a => (f a).toList := by rcases xs with ⟨l⟩ simp -theorem flatMap_toArray_cons {β} (f : α → Array β) (a : α) (as : List α) : +theorem flatMap_toArray_cons {β} {f : α → Array β} {a : α} {as : List α} : (a :: as).toArray.flatMap f = f a ++ as.toArray.flatMap f := by simp [flatMap] suffices ∀ cs, List.foldl (fun bs a => bs ++ f a) (f a ++ cs) as = @@ -2233,7 +2243,7 @@ theorem flatMap_toArray_cons {β} (f : α → Array β) (a : α) (as : List α) intro cs induction as generalizing cs <;> simp_all -@[simp] theorem flatMap_toArray {β} (f : α → Array β) (as : List α) : +@[simp] theorem flatMap_toArray {β} {f : α → Array β} {as : List α} : as.toArray.flatMap f = (as.flatMap (fun a => (f a).toList)).toArray := by induction as with | nil => simp @@ -2241,12 +2251,12 @@ theorem flatMap_toArray_cons {β} (f : α → Array β) (a : α) (as : List α) apply ext' simp [ih, flatMap_toArray_cons] -@[simp] theorem flatMap_id (xss : Array (Array α)) : xss.flatMap id = xss.flatten := by simp [flatMap_def] +@[simp] theorem flatMap_id {xss : Array (Array α)} : xss.flatMap id = xss.flatten := by simp [flatMap_def] -@[simp] theorem flatMap_id' (xss : Array (Array α)) : xss.flatMap (fun xs => xs) = xss.flatten := by simp [flatMap_def] +@[simp] theorem flatMap_id' {xss : Array (Array α)} : xss.flatMap (fun xs => xs) = xss.flatten := by simp [flatMap_def] @[simp] -theorem size_flatMap (xs : Array α) (f : α → Array β) : +theorem size_flatMap {xs : Array α} {f : α → Array β} : (xs.flatMap f).size = sum (map (fun a => (f a).size) xs) := by rcases xs with ⟨l⟩ simp [Function.comp_def] @@ -2271,49 +2281,50 @@ theorem forall_mem_flatMap {p : β → Prop} {xs : Array α} {f : α → Array simp only [mem_flatMap, forall_exists_index, and_imp] constructor <;> (intros; solve_by_elim) -theorem flatMap_singleton (f : α → Array β) (x : α) : #[x].flatMap f = f x := by +theorem flatMap_singleton {f : α → Array β} {x : α} : #[x].flatMap f = f x := by simp +-- The argument `xs : Array α` is explicit, to allow rewriting from right to left. @[simp] theorem flatMap_singleton' (xs : Array α) : (xs.flatMap fun x => #[x]) = xs := by rcases xs with ⟨xs⟩ simp -@[simp] theorem flatMap_append (xs ys : Array α) (f : α → Array β) : +@[simp] theorem flatMap_append {xs ys : Array α} {f : α → Array β} : (xs ++ ys).flatMap f = xs.flatMap f ++ ys.flatMap f := by rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ simp -theorem flatMap_assoc {α β} (xs : Array α) (f : α → Array β) (g : β → Array γ) : +theorem flatMap_assoc {xs : Array α} {f : α → Array β} {g : β → Array γ} : (xs.flatMap f).flatMap g = xs.flatMap fun x => (f x).flatMap g := by rcases xs with ⟨xs⟩ simp [List.flatMap_assoc, ← toList_flatMap] -theorem map_flatMap (f : β → γ) (g : α → Array β) (xs : Array α) : +theorem map_flatMap {f : β → γ} {g : α → Array β} {xs : Array α} : (xs.flatMap g).map f = xs.flatMap fun a => (g a).map f := by rcases xs with ⟨xs⟩ simp [List.map_flatMap] -theorem flatMap_map (f : α → β) (g : β → Array γ) (xs : Array α) : +theorem flatMap_map {f : α → β} {g : β → Array γ} {xs : Array α} : (xs.map f).flatMap g = xs.flatMap (fun a => g (f a)) := by rcases xs with ⟨xs⟩ simp [List.flatMap_map] -theorem map_eq_flatMap {α β} (f : α → β) (xs : Array α) : map f xs = xs.flatMap fun x => #[f x] := by +theorem map_eq_flatMap {f : α → β} {xs : Array α} : map f xs = xs.flatMap fun x => #[f x] := by simp only [← map_singleton] rw [← flatMap_singleton' xs, map_flatMap, flatMap_singleton'] -theorem filterMap_flatMap {β γ} (xs : Array α) (g : α → Array β) (f : β → Option γ) : +theorem filterMap_flatMap {xs : Array α} {g : α → Array β} {f : β → Option γ} : (xs.flatMap g).filterMap f = xs.flatMap fun a => (g a).filterMap f := by rcases xs with ⟨xs⟩ simp [List.filterMap_flatMap] -theorem filter_flatMap (xs : Array α) (g : α → Array β) (f : β → Bool) : +theorem filter_flatMap {xs : Array α} {g : α → Array β} {f : β → Bool} : (xs.flatMap g).filter f = xs.flatMap fun a => (g a).filter f := by rcases xs with ⟨xs⟩ simp [List.filter_flatMap] -theorem flatMap_eq_foldl (f : α → Array β) (xs : Array α) : +theorem flatMap_eq_foldl {f : α → Array β} {xs : Array α} : xs.flatMap f = xs.foldl (fun acc a => acc ++ f a) #[] := by rcases xs with ⟨xs⟩ simp only [List.flatMap_toArray, List.flatMap_eq_foldl, List.size_toArray, List.foldl_toArray'] @@ -2361,13 +2372,13 @@ theorem forall_mem_replicate {p : α → Prop} {a : α} {n} : @[deprecated forall_mem_replicate (since := "2025-03-18")] abbrev forall_mem_mkArray := @forall_mem_replicate -@[simp] theorem replicate_succ_ne_empty (n : Nat) (a : α) : replicate (n+1) a ≠ #[] := by +@[simp] theorem replicate_succ_ne_empty {n : Nat} {a : α} : replicate (n+1) a ≠ #[] := by simp [replicate_succ] @[deprecated replicate_succ_ne_empty (since := "2025-03-18")] abbrev mkArray_succ_ne_empty := @replicate_succ_ne_empty -@[simp] theorem replicate_eq_empty_iff {n : Nat} (a : α) : replicate n a = #[] ↔ n = 0 := by +@[simp] theorem replicate_eq_empty_iff {n : Nat} {a : α} : replicate n a = #[] ↔ n = 0 := by cases n <;> simp @[deprecated replicate_eq_empty_iff (since := "2025-03-18")] @@ -2402,17 +2413,17 @@ theorem map_eq_replicate_iff {xs : Array α} {f : α → β} {b : β} : @[deprecated map_eq_replicate_iff (since := "2025-03-18")] abbrev map_eq_mkArray_iff := @map_eq_replicate_iff -@[simp] theorem map_const (xs : Array α) (b : β) : map (Function.const α b) xs = replicate xs.size b := +@[simp] theorem map_const {xs : Array α} {b : β} : map (Function.const α b) xs = replicate xs.size b := map_eq_replicate_iff.mpr fun _ _ => rfl -@[simp] theorem map_const_fun (x : β) : map (Function.const α x) = (replicate ·.size x) := by +@[simp] theorem map_const_fun {x : β} : map (Function.const α x) = (replicate ·.size x) := by funext xs simp /-- Variant of `map_const` using a lambda rather than `Function.const`. -/ -- This can not be a `@[simp]` lemma because it would fire on every `List.map`. -theorem map_const' (xs : Array α) (b : β) : map (fun _ => b) xs = replicate xs.size b := - map_const xs b +theorem map_const' {xs : Array α} {b : β} : map (fun _ => b) xs = replicate xs.size b := + map_const @[simp] theorem set_replicate_self : (replicate n a).set i a h = replicate n a := by apply Array.ext' @@ -2534,7 +2545,7 @@ abbrev flatten_mkArray_singleton := @flatten_replicate_singleton @[deprecated flatten_replicate_replicate (since := "2025-03-18")] abbrev flatten_mkArray_replicate := @flatten_replicate_replicate -theorem flatMap_replicate {β} (f : α → Array β) : (replicate n a).flatMap f = (replicate n (f a)).flatten := by +theorem flatMap_replicate {f : α → Array β} : (replicate n a).flatMap f = (replicate n (f a)).flatten := by rw [← toList_inj] simp [flatMap_toList, List.flatMap_replicate] @@ -2548,7 +2559,7 @@ abbrev flatMap_mkArray := @flatMap_replicate @[deprecated isEmpty_replicate (since := "2025-03-18")] abbrev isEmpty_mkArray := @isEmpty_replicate -@[simp] theorem sum_replicate_nat (n : Nat) (a : Nat) : (replicate n a).sum = n * a := by +@[simp] theorem sum_replicate_nat {n : Nat} {a : Nat} : (replicate n a).sum = n * a := by rw [← List.toArray_replicate, List.sum_toArray] simp @@ -2557,13 +2568,13 @@ abbrev sum_mkArray_nat := @sum_replicate_nat /-! ### Preliminaries about `swap` needed for `reverse`. -/ -theorem getElem?_swap (xs : Array α) (i j : Nat) (hi hj) (k : Nat) : (xs.swap i j hi hj)[k]? = +theorem getElem?_swap {xs : Array α} {i j : Nat} (hi hj) {k : Nat} : (xs.swap i j hi hj)[k]? = if j = k then some xs[i] else if i = k then some xs[j] else xs[k]? := by simp [swap_def, getElem?_set] /-! ### reverse -/ -@[simp] theorem size_reverse (xs : Array α) : xs.reverse.size = xs.size := by +@[simp] theorem size_reverse {xs : Array α} : xs.reverse.size = xs.size := by let rec go (as : Array α) (i j) : (reverse.loop as i j).size = as.size := by rw [reverse.loop] if h : i < j then @@ -2572,7 +2583,7 @@ theorem getElem?_swap (xs : Array α) (i j : Nat) (hi hj) (k : Nat) : (xs.swap i termination_by j - i simp only [reverse]; split <;> simp [go] -@[simp] theorem toList_reverse (xs : Array α) : xs.reverse.toList = xs.toList.reverse := by +@[simp] theorem toList_reverse {xs : Array α} : xs.reverse.toList = xs.toList.reverse := by let rec go (as : Array α) (i j hj) (h : i + j + 1 = xs.size) (h₂ : as.size = xs.size) (H : ∀ k, as.toList[k]? = if i ≤ k ∧ k ≤ j then xs.toList[k]? else xs.toList.reverse[k]?) @@ -2589,16 +2600,16 @@ theorem getElem?_swap (xs : Array α) (i j : Nat) (hi hj) (k : Nat) : (xs.swap i ← getElem?_toList] split <;> rename_i h₂ · simp only [← h₂, Nat.not_le.2 (Nat.lt_succ_self _), Nat.le_refl, and_false] - exact (List.getElem?_reverse' (j+1) i (Eq.trans (by simp +arith) h)).symm + exact (List.getElem?_reverse' (Eq.trans (by simp +arith) h)).symm split <;> rename_i h₃ · simp only [← h₃, Nat.not_le.2 (Nat.lt_succ_self _), Nat.le_refl, false_and] - exact (List.getElem?_reverse' i (j+1) (Eq.trans (by simp +arith) h)).symm + exact (List.getElem?_reverse' (Eq.trans (by simp +arith) h)).symm simp only [Nat.succ_le, Nat.lt_iff_le_and_ne.trans (and_iff_left h₃), Nat.lt_succ.symm.trans (Nat.lt_iff_le_and_ne.trans (and_iff_left (Ne.symm h₂)))] · rw [H]; split <;> rename_i h₂ · cases Nat.le_antisymm (Nat.not_lt.1 h₁) (Nat.le_trans h₂.1 h₂.2) cases Nat.le_antisymm h₂.1 h₂.2 - exact (List.getElem?_reverse' _ _ h).symm + exact (List.getElem?_reverse' h).symm · rfl termination_by j - i simp only [reverse] @@ -2613,11 +2624,11 @@ theorem getElem?_swap (xs : Array α) (i j : Nat) (hi hj) (k : Nat) : (xs.swap i true_and, Nat.not_lt] at h rw [List.getElem?_eq_none_iff.2 ‹_›, List.getElem?_eq_none_iff.2 (xs.toList.length_reverse ▸ ‹_›)] -@[simp] theorem _root_.List.reverse_toArray (l : List α) : l.toArray.reverse = l.reverse.toArray := by +@[simp] theorem _root_.List.reverse_toArray {l : List α} : l.toArray.reverse = l.reverse.toArray := by apply ext' simp only [toList_reverse] -@[simp] theorem reverse_push (xs : Array α) (a : α) : (xs.push a).reverse = #[a] ++ xs.reverse := by +@[simp] theorem reverse_push {xs : Array α} {a : α} : (xs.push a).reverse = #[a] ++ xs.reverse := by cases xs simp @@ -2625,7 +2636,7 @@ theorem getElem?_swap (xs : Array α) (i j : Nat) (hi hj) (k : Nat) : (xs.swap i cases xs simp -@[simp] theorem getElem_reverse (xs : Array α) (i : Nat) (hi : i < xs.reverse.size) : +@[simp] theorem getElem_reverse {xs : Array α} {i : Nat} (hi : i < xs.reverse.size) : (xs.reverse)[i] = xs[xs.size - 1 - i]'(by simp at hi; omega) := by cases xs simp @@ -2648,11 +2659,11 @@ theorem reverse_ne_empty_iff {xs : Array α} : xs.reverse ≠ #[] ↔ xs ≠ #[] simp /-- Variant of `getElem?_reverse` with a hypothesis giving the linear relation between the indices. -/ -theorem getElem?_reverse' {xs : Array α} (i j) (h : i + j + 1 = xs.size) : xs.reverse[i]? = xs[j]? := by +theorem getElem?_reverse' {xs : Array α} {i j} (h : i + j + 1 = xs.size) : xs.reverse[i]? = xs[j]? := by rcases xs with ⟨xs⟩ simp at h simp only [List.reverse_toArray, List.getElem?_toArray] - rw [List.getElem?_reverse' (l := xs) _ _ h] + rw [List.getElem?_reverse' h] @[simp] theorem getElem?_reverse {xs : Array α} {i} (h : i < xs.size) : @@ -2660,6 +2671,7 @@ theorem getElem?_reverse {xs : Array α} {i} (h : i < xs.size) : cases xs simp_all +-- The argument `xs : Array α` is explicit to allow rewriting from right to left. @[simp] theorem reverse_reverse (xs : Array α) : xs.reverse.reverse = xs := by cases xs simp @@ -2674,32 +2686,32 @@ theorem reverse_eq_iff {xs ys : Array α} : xs.reverse = ys ↔ xs = ys.reverse xs.reverse = ys.push a ↔ xs = #[a] ++ ys.reverse := by rw [reverse_eq_iff, reverse_push] -@[simp] theorem map_reverse (f : α → β) (xs : Array α) : xs.reverse.map f = (xs.map f).reverse := by +@[simp] theorem map_reverse {f : α → β} {xs : Array α} : xs.reverse.map f = (xs.map f).reverse := by cases xs <;> simp [*] /-- Variant of `filter_reverse` with a hypothesis giving the stop condition. -/ -@[simp] theorem filter_reverse' (p : α → Bool) (xs : Array α) (w : stop = xs.size) : +@[simp] theorem filter_reverse' {p : α → Bool} {xs : Array α} {stop : Nat} (w : stop = xs.size) : (xs.reverse.filter p 0 stop) = (xs.filter p).reverse := by subst w cases xs simp -theorem filter_reverse (p : α → Bool) (xs : Array α) : (xs.reverse.filter p) = (xs.filter p).reverse := by +theorem filter_reverse {p : α → Bool} {xs : Array α} : (xs.reverse.filter p) = (xs.filter p).reverse := by cases xs simp /-- Variant of `filterMap_reverse` with a hypothesis giving the stop condition. -/ -@[simp] theorem filterMap_reverse' (f : α → Option β) (xs : Array α) (w : stop = xs.size) : +@[simp] theorem filterMap_reverse' {f : α → Option β} {xs : Array α} {stop : Nat} (w : stop = xs.size) : (xs.reverse.filterMap f 0 stop) = (xs.filterMap f).reverse := by subst w cases xs simp -theorem filterMap_reverse (f : α → Option β) (xs : Array α) : (xs.reverse.filterMap f) = (xs.filterMap f).reverse := by +theorem filterMap_reverse {f : α → Option β} {xs : Array α} : (xs.reverse.filterMap f) = (xs.filterMap f).reverse := by cases xs simp -@[simp] theorem reverse_append (xs ys : Array α) : (xs ++ ys).reverse = ys.reverse ++ xs.reverse := by +@[simp] theorem reverse_append {xs ys : Array α} : (xs ++ ys).reverse = ys.reverse ++ xs.reverse := by cases xs cases ys simp @@ -2712,28 +2724,28 @@ theorem filterMap_reverse (f : α → Option β) (xs : Array α) : (xs.reverse.f simp /-- Reversing a flatten is the same as reversing the order of parts and reversing all parts. -/ -theorem reverse_flatten (xss : Array (Array α)) : +theorem reverse_flatten {xss : Array (Array α)} : xss.flatten.reverse = (xss.map reverse).reverse.flatten := by cases xss using array₂_induction simp [flatten_toArray, List.reverse_flatten, Function.comp_def] /-- Flattening a reverse is the same as reversing all parts and reversing the flattened result. -/ -theorem flatten_reverse (xss : Array (Array α)) : +theorem flatten_reverse {xss : Array (Array α)} : xss.reverse.flatten = (xss.map reverse).flatten.reverse := by cases xss using array₂_induction simp [flatten_toArray, List.flatten_reverse, Function.comp_def] -theorem reverse_flatMap {β} (xs : Array α) (f : α → Array β) : +theorem reverse_flatMap {β} {xs : Array α} {f : α → Array β} : (xs.flatMap f).reverse = xs.reverse.flatMap (reverse ∘ f) := by cases xs simp [List.reverse_flatMap, Function.comp_def] -theorem flatMap_reverse {β} (xs : Array α) (f : α → Array β) : +theorem flatMap_reverse {β} {xs : Array α} {f : α → Array β} : (xs.reverse.flatMap f) = (xs.flatMap (reverse ∘ f)).reverse := by cases xs simp [List.flatMap_reverse, Function.comp_def] -@[simp] theorem reverse_replicate (n) (a : α) : reverse (replicate n a) = replicate n a := by +@[simp] theorem reverse_replicate {n : Nat} {a : α} : reverse (replicate n a) = replicate n a := by rw [← toList_inj] simp @@ -2742,37 +2754,37 @@ abbrev reverse_mkArray := @reverse_replicate /-! ### extract -/ -theorem extract_loop_zero (xs ys : Array α) (start : Nat) : extract.loop xs 0 start ys = ys := by +theorem extract_loop_zero {xs ys : Array α} {start : Nat} : extract.loop xs 0 start ys = ys := by rw [extract.loop]; split <;> rfl -theorem extract_loop_succ (xs ys : Array α) (size start : Nat) (h : start < xs.size) : +theorem extract_loop_succ {xs ys : Array α} {size start : Nat} (h : start < xs.size) : extract.loop xs (size+1) start ys = extract.loop xs size (start+1) (ys.push xs[start]) := by rw [extract.loop, dif_pos h]; rfl -theorem extract_loop_of_ge (xs ys : Array α) (size start : Nat) (h : start ≥ xs.size) : +theorem extract_loop_of_ge {xs ys : Array α} {size start : Nat} (h : start ≥ xs.size) : extract.loop xs size start ys = ys := by rw [extract.loop, dif_neg (Nat.not_lt_of_ge h)] -theorem extract_loop_eq_aux (xs ys : Array α) (size start : Nat) : +theorem extract_loop_eq_aux {xs ys : Array α} {size start : Nat} : extract.loop xs size start ys = ys ++ extract.loop xs size start #[] := by induction size using Nat.recAux generalizing start ys with | zero => rw [extract_loop_zero, extract_loop_zero, append_empty] | succ size ih => if h : start < xs.size then - rw [extract_loop_succ (h := h), ih (ys.push _), push_eq_append_singleton] - rw [extract_loop_succ (h := h), ih (#[].push _), push_eq_append_singleton, empty_append] + rw [extract_loop_succ (h := h), ih, push_eq_append_singleton] + rw [extract_loop_succ (h := h), ih (ys := #[].push _), push_eq_append_singleton, empty_append] rw [append_assoc] else rw [extract_loop_of_ge (h := Nat.le_of_not_lt h)] rw [extract_loop_of_ge (h := Nat.le_of_not_lt h)] rw [append_empty] -theorem extract_loop_eq (xs ys : Array α) (size start : Nat) (h : start + size ≤ xs.size) : +theorem extract_loop_eq {xs ys : Array α} {size start : Nat} (h : start + size ≤ xs.size) : extract.loop xs size start ys = ys ++ xs.extract start (start + size) := by simp only [extract, Nat.sub_eq, emptyWithCapacity_eq] rw [extract_loop_eq_aux, Nat.min_eq_left h, Nat.add_sub_cancel_left] -theorem size_extract_loop (xs ys : Array α) (size start : Nat) : +theorem size_extract_loop {xs ys : Array α} {size start : Nat} : (extract.loop xs size start ys).size = ys.size + min size (xs.size - start) := by induction size using Nat.recAux generalizing start ys with | zero => rw [extract_loop_zero, Nat.zero_min, Nat.add_zero] @@ -2784,26 +2796,26 @@ theorem size_extract_loop (xs ys : Array α) (size start : Nat) : have h := Nat.le_of_not_gt h rw [extract_loop_of_ge (h:=h), Nat.sub_eq_zero_of_le h, Nat.min_zero, Nat.add_zero] -@[simp] theorem size_extract (xs : Array α) (start stop : Nat) : +@[simp] theorem size_extract {xs : Array α} {start stop : Nat} : (xs.extract start stop).size = min stop xs.size - start := by simp only [extract, Nat.sub_eq, emptyWithCapacity_eq] rw [size_extract_loop, size_empty, Nat.zero_add, Nat.sub_min_sub_right, Nat.min_assoc, Nat.min_self] -theorem getElem_extract_loop_lt_aux (xs ys : Array α) (size start : Nat) (hlt : i < ys.size) : +theorem getElem_extract_loop_lt_aux {xs ys : Array α} {size start : Nat} (hlt : i < ys.size) : i < (extract.loop xs size start ys).size := by rw [size_extract_loop] apply Nat.lt_of_lt_of_le hlt exact Nat.le_add_right .. -theorem getElem_extract_loop_lt (xs ys : Array α) (size start : Nat) (hlt : i < ys.size) - (h := getElem_extract_loop_lt_aux xs ys size start hlt) : +theorem getElem_extract_loop_lt {xs ys : Array α} {size start : Nat} (hlt : i < ys.size) + (h := getElem_extract_loop_lt_aux hlt) : (extract.loop xs size start ys)[i] = ys[i] := by apply Eq.trans _ (getElem_append_left (ys := extract.loop xs size start #[]) hlt) · rw [size_append]; exact Nat.lt_of_lt_of_le hlt (Nat.le_add_right ..) · congr; rw [extract_loop_eq_aux] -theorem getElem_extract_loop_ge_aux (xs ys : Array α) (size start : Nat) (hge : i ≥ ys.size) +theorem getElem_extract_loop_ge_aux {xs ys : Array α} {size start : Nat} (hge : i ≥ ys.size) (h : i < (extract.loop xs size start ys).size) : start + i - ys.size < xs.size := by have h : i < ys.size + (xs.size - start) := by apply Nat.lt_of_lt_of_le h @@ -2814,9 +2826,9 @@ theorem getElem_extract_loop_ge_aux (xs ys : Array α) (size start : Nat) (hge : apply Nat.add_lt_of_lt_sub' exact Nat.sub_lt_left_of_lt_add hge h -theorem getElem_extract_loop_ge (xs ys : Array α) (size start : Nat) (hge : i ≥ ys.size) +theorem getElem_extract_loop_ge {xs ys : Array α} {size start : Nat} (hge : i ≥ ys.size) (h : i < (extract.loop xs size start ys).size) - (h' := getElem_extract_loop_ge_aux xs ys size start hge h) : + (h' := getElem_extract_loop_ge_aux hge h) : (extract.loop xs size start ys)[i] = xs[start + i - ys.size] := by induction size using Nat.recAux generalizing start ys with | zero => @@ -2838,11 +2850,11 @@ theorem getElem_extract_loop_ge (xs ys : Array α) (size start : Nat) (hge : i have h₂ : ys.size < (extract.loop xs size (start+1) (ys.push xs[start])).size := by rw [size_extract_loop]; apply Nat.lt_of_lt_of_le h₁; exact Nat.le_add_right .. have h : (extract.loop xs size (start + 1) (ys.push xs[start]))[ys.size] = xs[start] := by - rw [getElem_extract_loop_lt xs (ys.push xs[start]) size (start+1) h₁ h₂, getElem_push_eq] + rw [getElem_extract_loop_lt h₁ h₂, getElem_push_eq] rw [h]; congr; rw [Nat.add_sub_cancel] else have hge : ys.size + 1 ≤ i := Nat.lt_of_le_of_ne hge hi - rw [ih (ys.push xs[start]) (start+1) ((size_push ..).symm ▸ hge)] + rw [ih ((size_push ..).symm ▸ hge)] congr 1; rw [size_push, Nat.add_right_comm, Nat.add_sub_add_right] theorem getElem_extract_aux {xs : Array α} {start stop : Nat} (h : i < (xs.extract start stop).size) : @@ -2871,7 +2883,7 @@ theorem getElem?_extract {xs : Array α} {start stop : Nat} : subst w h h' rfl -@[simp] theorem toList_extract (xs : Array α) (start stop : Nat) : +@[simp] theorem toList_extract {xs : Array α} {start stop : Nat} : (xs.extract start stop).toList = xs.toList.extract start stop := by apply List.ext_getElem · simp only [length_toList, size_extract, List.length_take, List.length_drop] @@ -2879,7 +2891,7 @@ theorem getElem?_extract {xs : Array α} {start stop : Nat} : · intros n h₁ h₂ simp -@[simp] theorem extract_size (xs : Array α) : xs.extract 0 xs.size = xs := by +@[simp] theorem extract_size {xs : Array α} : xs.extract 0 xs.size = xs := by apply ext · rw [size_extract, Nat.min_self, Nat.sub_zero] · intros; rw [getElem_extract]; congr; rw [Nat.zero_add] @@ -2887,62 +2899,62 @@ theorem getElem?_extract {xs : Array α} {start stop : Nat} : @[deprecated extract_size (since := "2025-01-19")] abbrev extract_all := @extract_size -theorem extract_empty_of_stop_le_start (xs : Array α) {start stop : Nat} (h : stop ≤ start) : +theorem extract_empty_of_stop_le_start {xs : Array α} {start stop : Nat} (h : stop ≤ start) : xs.extract start stop = #[] := by simp only [extract, Nat.sub_eq, emptyWithCapacity_eq] rw [←Nat.sub_min_sub_right, Nat.sub_eq_zero_of_le h, Nat.zero_min, extract_loop_zero] -theorem extract_empty_of_size_le_start (xs : Array α) {start stop : Nat} (h : xs.size ≤ start) : +theorem extract_empty_of_size_le_start {xs : Array α} {start stop : Nat} (h : xs.size ≤ start) : xs.extract start stop = #[] := by simp only [extract, Nat.sub_eq, emptyWithCapacity_eq] rw [←Nat.sub_min_sub_right, Nat.sub_eq_zero_of_le h, Nat.min_zero, extract_loop_zero] -@[simp] theorem extract_empty (start stop : Nat) : (#[] : Array α).extract start stop = #[] := - extract_empty_of_size_le_start _ (Nat.zero_le _) +@[simp] theorem extract_empty {start stop : Nat} : (#[] : Array α).extract start stop = #[] := + extract_empty_of_size_le_start (Nat.zero_le _) -@[simp] theorem _root_.List.extract_toArray (l : List α) (start stop : Nat) : +@[simp] theorem _root_.List.extract_toArray {l : List α} {start stop : Nat} : l.toArray.extract start stop = (l.extract start stop).toArray := by apply ext' simp @[deprecated extract_size (since := "2025-02-27")] -theorem take_size (xs : Array α) : xs.take xs.size = xs := by +theorem take_size {xs : Array α} : xs.take xs.size = xs := by cases xs simp /-! ### shrink -/ -@[simp] theorem size_shrink_loop (xs : Array α) (n : Nat) : (shrink.loop n xs).size = xs.size - n := by +@[simp] theorem size_shrink_loop {xs : Array α} {n : Nat} : (shrink.loop n xs).size = xs.size - n := by induction n generalizing xs with | zero => simp [shrink.loop] | succ n ih => simp [shrink.loop, ih] omega -@[simp] theorem getElem_shrink_loop (xs : Array α) (n : Nat) (i : Nat) (h : i < (shrink.loop n xs).size) : +@[simp] theorem getElem_shrink_loop {xs : Array α} {n i : Nat} (h : i < (shrink.loop n xs).size) : (shrink.loop n xs)[i] = xs[i]'(by simp at h; omega) := by induction n generalizing xs i with | zero => simp [shrink.loop] | succ n ih => simp [shrink.loop, ih] -@[simp] theorem size_shrink (xs : Array α) (i : Nat) : (xs.shrink i).size = min i xs.size := by +@[simp] theorem size_shrink {xs : Array α} {i : Nat} : (xs.shrink i).size = min i xs.size := by simp [shrink] omega -@[simp] theorem getElem_shrink (xs : Array α) (i : Nat) (j : Nat) (h : j < (xs.shrink i).size) : +@[simp] theorem getElem_shrink {xs : Array α} {i j : Nat} (h : j < (xs.shrink i).size) : (xs.shrink i)[j] = xs[j]'(by simp at h; omega) := by simp [shrink] -@[simp] theorem toList_shrink (xs : Array α) (i : Nat) : (xs.shrink i).toList = xs.toList.take i := by +@[simp] theorem toList_shrink {xs : Array α} {i : Nat} : (xs.shrink i).toList = xs.toList.take i := by apply List.ext_getElem <;> simp -@[simp] theorem shrink_eq_take (xs : Array α) (i : Nat) : xs.shrink i = xs.take i := by +@[simp] theorem shrink_eq_take {xs : Array α} {i : Nat} : xs.shrink i = xs.take i := by ext <;> simp /-! ### foldlM and foldrM -/ -theorem foldlM_start_stop {m} [Monad m] (xs : Array α) (f : β → α → m β) (b) (start stop : Nat) : +theorem foldlM_start_stop {m} [Monad m] {xs : Array α} {f : β → α → m β} {b} {start stop : Nat} : xs.foldlM f b start stop = (xs.extract start stop).foldlM f b := by unfold foldlM simp only [Nat.sub_zero, size_extract, Nat.le_refl, ↓reduceDIte] @@ -2979,7 +2991,7 @@ theorem foldlM_start_stop {m} [Monad m] (xs : Array α) (f : β → α → m β) simp [← Nat.add_assoc] at ih rw [ih] -theorem foldrM_start_stop {m} [Monad m] (xs : Array α) (f : α → β → m β) (b) (start stop : Nat) : +theorem foldrM_start_stop {m} [Monad m] {xs : Array α} {f : α → β → m β} {b} {start stop : Nat} : xs.foldrM f b start stop = (xs.extract stop start).foldrM f b := by unfold foldrM simp only [size_extract, Nat.le_refl, ↓reduceDIte] @@ -3049,19 +3061,19 @@ theorem foldrM_start_stop {m} [Monad m] (xs : Array α) (f : α → β → m β) simp_all /-- Variant of `foldlM_append` with a side condition for the `stop` argument. -/ -@[simp] theorem foldlM_append' [Monad m] [LawfulMonad m] (f : β → α → m β) (b) (xs xs' : Array α) - (w : stop = xs.size + xs'.size) : +@[simp] theorem foldlM_append' [Monad m] [LawfulMonad m] {f : β → α → m β} {b} {xs xs' : Array α} + {stop} (w : stop = xs.size + xs'.size) : (xs ++ xs').foldlM f b 0 stop = xs.foldlM f b >>= xs'.foldlM f := by subst w rcases xs with ⟨xs⟩ rcases xs' with ⟨xs'⟩ simp -theorem foldlM_append [Monad m] [LawfulMonad m] (f : β → α → m β) (b) (xs xs' : Array α) : +theorem foldlM_append [Monad m] [LawfulMonad m] {f : β → α → m β} {b} {xs xs' : Array α} : (xs ++ xs').foldlM f b = xs.foldlM f b >>= xs'.foldlM f := by simp -@[simp] theorem foldlM_loop_empty [Monad m] (f : β → α → m β) (init : β) (i j : Nat) : +@[simp] theorem foldlM_loop_empty [Monad m] {f : β → α → m β} {init : β} {i j : Nat} : foldlM.loop f #[] s h i j init = pure init := by unfold foldlM.loop; split · split @@ -3070,11 +3082,11 @@ theorem foldlM_append [Monad m] [LawfulMonad m] (f : β → α → m β) (b) (xs omega · rfl -@[simp] theorem foldlM_empty [Monad m] (f : β → α → m β) (init : β) : +@[simp] theorem foldlM_empty [Monad m] {f : β → α → m β} {init : β} : foldlM f init #[] start stop = return init := by simp [foldlM] -@[simp] theorem foldrM_fold_empty [Monad m] (f : α → β → m β) (init : β) (i j : Nat) (h) : +@[simp] theorem foldrM_fold_empty [Monad m] {f : α → β → m β} {init : β} {i j : Nat} (h) : foldrM.fold f #[] i j h init = pure init := by unfold foldrM.fold split <;> rename_i h₁ @@ -3083,45 +3095,45 @@ theorem foldlM_append [Monad m] [LawfulMonad m] (f : β → α → m β) (b) (xs · rfl · simp at h₂ -@[simp] theorem foldrM_empty [Monad m] (f : α → β → m β) (init : β) : +@[simp] theorem foldrM_empty [Monad m] {f : α → β → m β} {init : β} {start stop : Nat} : foldrM f init #[] start stop = return init := by simp [foldrM] /-- Variant of `foldlM_push` with a side condition for the `stop` argument. -/ -@[simp] theorem foldlM_push' [Monad m] [LawfulMonad m] (xs : Array α) (a : α) (f : β → α → m β) (b) - (w : stop = xs.size + 1) : +@[simp] theorem foldlM_push' [Monad m] [LawfulMonad m] {xs : Array α} {a : α} {f : β → α → m β} {b} + {stop} (w : stop = xs.size + 1) : (xs.push a).foldlM f b 0 stop = xs.foldlM f b >>= fun b => f b a := by subst w simp [← append_singleton] -theorem foldlM_push [Monad m] [LawfulMonad m] (xs : Array α) (a : α) (f : β → α → m β) (b) : +theorem foldlM_push [Monad m] [LawfulMonad m] {xs : Array α} {a : α} {f : β → α → m β} {b} : (xs.push a).foldlM f b = xs.foldlM f b >>= fun b => f b a := by simp -@[simp] theorem foldlM_pure [Monad m] [LawfulMonad m] (f : β → α → β) (b) (xs : Array α) : +@[simp] theorem foldlM_pure [Monad m] [LawfulMonad m] {f : β → α → β} {b} {xs : Array α} {start stop : Nat} : xs.foldlM (m := m) (pure <| f · ·) b start stop = pure (xs.foldl f b start stop) := by rw [foldl, foldlM_start_stop, ← foldlM_toList, List.foldlM_pure, foldl_toList, foldl, ← foldlM_start_stop] -@[simp] theorem foldrM_pure [Monad m] [LawfulMonad m] (f : α → β → β) (b) (xs : Array α) : +@[simp] theorem foldrM_pure [Monad m] [LawfulMonad m] {f : α → β → β} {b} {xs : Array α} {start stop : Nat} : xs.foldrM (m := m) (pure <| f · ·) b start stop = pure (xs.foldr f b start stop) := by rw [foldr, foldrM_start_stop, ← foldrM_toList, List.foldrM_pure, foldr_toList, foldr, ← foldrM_start_stop] -theorem foldl_eq_foldlM (f : β → α → β) (b) (xs : Array α) : +theorem foldl_eq_foldlM {f : β → α → β} {b} {xs : Array α} {start stop : Nat} : xs.foldl f b start stop = xs.foldlM (m := Id) f b start stop := by simp [foldl, Id.run] -theorem foldr_eq_foldrM (f : α → β → β) (b) (xs : Array α) : +theorem foldr_eq_foldrM {f : α → β → β} {b} {xs : Array α} {start stop : Nat} : xs.foldr f b start stop = xs.foldrM (m := Id) f b start stop := by simp [foldr, Id.run] -@[simp] theorem id_run_foldlM (f : β → α → Id β) (b) (xs : Array α) : - Id.run (xs.foldlM f b start stop) = xs.foldl f b start stop := (foldl_eq_foldlM f b xs).symm +@[simp] theorem id_run_foldlM {f : β → α → Id β} {b} {xs : Array α} {start stop : Nat} : + Id.run (xs.foldlM f b start stop) = xs.foldl f b start stop := foldl_eq_foldlM.symm -@[simp] theorem id_run_foldrM (f : α → β → Id β) (b) (xs : Array α) : - Id.run (xs.foldrM f b start stop) = xs.foldr f b start stop := (foldr_eq_foldrM f b xs).symm +@[simp] theorem id_run_foldrM {f : α → β → Id β} {b} {xs : Array α} {start stop : Nat} : + Id.run (xs.foldrM f b start stop) = xs.foldr f b start stop := foldr_eq_foldrM.symm /-- Variant of `foldlM_reverse` with a side condition for the `stop` argument. -/ -@[simp] theorem foldlM_reverse' [Monad m] (xs : Array α) (f : β → α → m β) (b) +@[simp] theorem foldlM_reverse' [Monad m] {xs : Array α} {f : β → α → m β} {b} {stop : Nat} (w : stop = xs.size) : xs.reverse.foldlM f b 0 stop = xs.foldrM (fun x y => f y x) b := by subst w @@ -3129,23 +3141,23 @@ theorem foldr_eq_foldrM (f : α → β → β) (b) (xs : Array α) : simp [List.foldlM_reverse] /-- Variant of `foldrM_reverse` with a side condition for the `start` argument. -/ -@[simp] theorem foldrM_reverse' [Monad m] (xs : Array α) (f : α → β → m β) (b) +@[simp] theorem foldrM_reverse' [Monad m] {xs : Array α} {f : α → β → m β} {b} {start : Nat} (w : start = xs.size) : xs.reverse.foldrM f b start 0 = xs.foldlM (fun x y => f y x) b := by subst w rcases xs with ⟨xs⟩ simp [List.foldrM_reverse] -theorem foldlM_reverse [Monad m] (xs : Array α) (f : β → α → m β) (b) : +theorem foldlM_reverse [Monad m] {xs : Array α} {f : β → α → m β} {b} : xs.reverse.foldlM f b = xs.foldrM (fun x y => f y x) b := by simp -theorem foldrM_reverse [Monad m] (xs : Array α) (f : α → β → m β) (b) : +theorem foldrM_reverse [Monad m] {xs : Array α} {f : α → β → m β} {b} : xs.reverse.foldrM f b = xs.foldlM (fun x y => f y x) b := by rcases xs with ⟨xs⟩ simp -theorem foldrM_push [Monad m] (f : α → β → m β) (init : β) (xs : Array α) (a : α) : +theorem foldrM_push [Monad m] {f : α → β → m β} {init : β} {xs : Array α} {a : α} : (xs.push a).foldrM f init = f a init >>= xs.foldrM f := by simp only [foldrM_eq_reverse_foldlM_toList, push_toList, List.reverse_append, List.reverse_cons, List.reverse_nil, List.nil_append, List.singleton_append, List.foldlM_cons, List.foldlM_reverse] @@ -3154,15 +3166,13 @@ theorem foldrM_push [Monad m] (f : α → β → m β) (init : β) (xs : Array Variant of `foldrM_push` with `h : start = arr.size + 1` rather than `(arr.push a).size` as the argument. -/ -@[simp] theorem foldrM_push' [Monad m] (f : α → β → m β) (init : β) (xs : Array α) (a : α) +@[simp] theorem foldrM_push' [Monad m] {f : α → β → m β} {init : β} {xs : Array α} {a : α} {start} (h : start = xs.size + 1) : (xs.push a).foldrM f init start = f a init >>= xs.foldrM f := by simp [← foldrM_push, h] /-! ### foldl / foldr -/ --- This proof is the pure version of `Array.SatisfiesM_foldlM` in Batteries, --- reproduced to avoid a dependency on `SatisfiesM`. theorem foldl_induction {as : Array α} (motive : Nat → β → Prop) {init : β} (h0 : motive 0 init) {f : β → α → β} (hf : ∀ i : Fin as.size, ∀ b, motive i.1 b → motive (i.1 + 1) (f b as[i])) : @@ -3177,8 +3187,6 @@ theorem foldl_induction · next hj => exact Nat.le_antisymm h₁ (Nat.ge_of_not_lt hj) ▸ H simpa [foldl, foldlM] using go (Nat.zero_le _) (Nat.le_refl _) h0 --- This proof is the pure version of `Array.SatisfiesM_foldrM` in Batteries, --- reproduced to avoid a dependency on `SatisfiesM`. theorem foldr_induction {as : Array α} (motive : Nat → β → Prop) {init : β} (h0 : motive as.size init) {f : α → β → β} (hf : ∀ i : Fin as.size, ∀ b, motive (i.1 + 1) b → motive i.1 (f as[i] b)) : @@ -3206,16 +3214,16 @@ theorem foldr_congr {as bs : Array α} (h₀ : as = bs) {f g : α → β → β} as.foldr f a start stop = bs.foldr g b start' stop' := by congr -theorem foldr_push (f : α → β → β) (init : β) (xs : Array α) (a : α) : +theorem foldr_push {f : α → β → β} {init : β} {xs : Array α} {a : α} : (xs.push a).foldr f init = xs.foldr f (f a init) := foldrM_push .. /-- Variant of `foldr_push` with the `h : start = arr.size + 1` rather than `(arr.push a).size` as the argument. -/ -@[simp] theorem foldr_push' (f : α → β → β) (init : β) (xs : Array α) (a : α) {start} +@[simp] theorem foldr_push' {f : α → β → β} {init : β} {xs : Array α} {a : α} {start : Nat} (h : start = xs.size + 1) : (xs.push a).foldr f init start = xs.foldr f (f a init) := - foldrM_push' _ _ _ _ h + foldrM_push' h @[simp] theorem foldl_push_eq_append {as : Array α} {bs : Array β} {f : α → β} (w : stop = as.size) : as.foldl (fun acc a => acc.push (f a)) bs 0 stop = bs ++ as.map f := by @@ -3244,49 +3252,51 @@ rather than `(arr.push a).size` as the argument. rcases as with ⟨as⟩ simp -@[simp] theorem foldr_append_eq_append (xs : Array α) (f : α → Array β) (ys : Array β) : +@[simp] theorem foldr_append_eq_append {xs : Array α} {f : α → Array β} {ys : Array β} : xs.foldr (f · ++ ·) ys = (xs.map f).flatten ++ ys := by rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ induction xs <;> simp_all [Function.comp_def, flatten_toArray] -@[simp] theorem foldl_append_eq_append (xs : Array α) (f : α → Array β) (ys : Array β) : +@[simp] theorem foldl_append_eq_append {xs : Array α} {f : α → Array β} {ys : Array β} : xs.foldl (· ++ f ·) ys = ys ++ (xs.map f).flatten := by rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ induction xs generalizing ys <;> simp_all [Function.comp_def, flatten_toArray] -@[simp] theorem foldr_flip_append_eq_append (xs : Array α) (f : α → Array β) (ys : Array β) : +@[simp] theorem foldr_flip_append_eq_append {xs : Array α} {f : α → Array β} {ys : Array β} : xs.foldr (fun x acc => acc ++ f x) ys = ys ++ (xs.map f).reverse.flatten := by rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ induction xs generalizing ys <;> simp_all [Function.comp_def, flatten_toArray] -@[simp] theorem foldl_flip_append_eq_append (xs : Array α) (f : α → Array β) (ys : Array β) : +@[simp] theorem foldl_flip_append_eq_append {xs : Array α} {f : α → Array β} {ys : Array β} : xs.foldl (fun acc y => f y ++ acc) ys = (xs.map f).reverse.flatten ++ ys:= by rcases xs with ⟨l⟩ rcases ys with ⟨l'⟩ induction l generalizing l' <;> simp_all [Function.comp_def, flatten_toArray] -theorem foldl_map' (f : β₁ → β₂) (g : α → β₂ → α) (xs : Array β₁) (init : α) (w : stop = xs.size) : +theorem foldl_map' {f : β₁ → β₂} {g : α → β₂ → α} {xs : Array β₁} {init : α} {stop : Nat} + (w : stop = xs.size) : (xs.map f).foldl g init 0 stop = xs.foldl (fun x y => g x (f y)) init := by subst w cases xs; simp [List.foldl_map] -theorem foldr_map' (f : α₁ → α₂) (g : α₂ → β → β) (xs : Array α₁) (init : β) (w : start = xs.size) : +theorem foldr_map' {f : α₁ → α₂} {g : α₂ → β → β} {xs : Array α₁} {init : β} {start : Nat} + (w : start = xs.size) : (xs.map f).foldr g init start 0 = xs.foldr (fun x y => g (f x) y) init := by subst w cases xs; simp [List.foldr_map] -theorem foldl_map (f : β₁ → β₂) (g : α → β₂ → α) (xs : Array β₁) (init : α) : +theorem foldl_map {f : β₁ → β₂} {g : α → β₂ → α} {xs : Array β₁} {init : α} : (xs.map f).foldl g init = xs.foldl (fun x y => g x (f y)) init := by cases xs; simp [List.foldl_map] -theorem foldr_map (f : α₁ → α₂) (g : α₂ → β → β) (xs : Array α₁) (init : β) : +theorem foldr_map {f : α₁ → α₂} {g : α₂ → β → β} {xs : Array α₁} {init : β} : (xs.map f).foldr g init = xs.foldr (fun x y => g (f x) y) init := by cases xs; simp [List.foldr_map] -theorem foldl_filterMap' (f : α → Option β) (g : γ → β → γ) (xs : Array α) (init : γ) +theorem foldl_filterMap' {f : α → Option β} {g : γ → β → γ} {xs : Array α} {init : γ} {stop : Nat} (w : stop = (xs.filterMap f).size) : (xs.filterMap f).foldl g init 0 stop = xs.foldl (fun x y => match f y with | some b => g x b | none => x) init := by subst w @@ -3294,7 +3304,7 @@ theorem foldl_filterMap' (f : α → Option β) (g : γ → β → γ) (xs : Arr simp [List.foldl_filterMap] rfl -theorem foldr_filterMap' (f : α → Option β) (g : β → γ → γ) (xs : Array α) (init : γ) +theorem foldr_filterMap' {f : α → Option β} {g : β → γ → γ} {xs : Array α} {init : γ} {start : Nat} (w : start = (xs.filterMap f).size) : (xs.filterMap f).foldr g init start 0 = xs.foldr (fun x y => match f x with | some b => g b y | none => y) init := by subst w @@ -3302,58 +3312,58 @@ theorem foldr_filterMap' (f : α → Option β) (g : β → γ → γ) (xs : Arr simp [List.foldr_filterMap] rfl -theorem foldl_filterMap (f : α → Option β) (g : γ → β → γ) (xs : Array α) (init : γ) : +theorem foldl_filterMap {f : α → Option β} {g : γ → β → γ} {xs : Array α} {init : γ} : (xs.filterMap f).foldl g init = xs.foldl (fun x y => match f y with | some b => g x b | none => x) init := by simp [foldl_filterMap'] -theorem foldr_filterMap (f : α → Option β) (g : β → γ → γ) (xs : Array α) (init : γ) : +theorem foldr_filterMap {f : α → Option β} {g : β → γ → γ} {xs : Array α} {init : γ} : (xs.filterMap f).foldr g init = xs.foldr (fun x y => match f x with | some b => g b y | none => y) init := by simp [foldr_filterMap'] -theorem foldl_map_hom' (g : α → β) (f : α → α → α) (f' : β → β → β) (a : α) (xs : Array α) - (h : ∀ x y, f' (g x) (g y) = g (f x y)) (w : stop = xs.size) : +theorem foldl_map_hom' {g : α → β} {f : α → α → α} {f' : β → β → β} {a : α} {xs : Array α} + {stop : Nat} (h : ∀ x y, f' (g x) (g y) = g (f x y)) (w : stop = xs.size) : (xs.map g).foldl f' (g a) 0 stop = g (xs.foldl f a) := by subst w cases xs simp - rw [List.foldl_map_hom _ _ _ _ _ h] + rw [List.foldl_map_hom h] -theorem foldr_map_hom' (g : α → β) (f : α → α → α) (f' : β → β → β) (a : α) (xs : Array α) - (h : ∀ x y, f' (g x) (g y) = g (f x y)) (w : start = xs.size) : +theorem foldr_map_hom' {g : α → β} {f : α → α → α} {f' : β → β → β} {a : α} {xs : Array α} + {start : Nat} (h : ∀ x y, f' (g x) (g y) = g (f x y)) (w : start = xs.size) : (xs.map g).foldr f' (g a) start 0 = g (xs.foldr f a) := by subst w cases xs simp - rw [List.foldr_map_hom _ _ _ _ _ h] + rw [List.foldr_map_hom h] -theorem foldl_map_hom (g : α → β) (f : α → α → α) (f' : β → β → β) (a : α) (xs : Array α) +theorem foldl_map_hom {g : α → β} {f : α → α → α} {f' : β → β → β} {a : α} {xs : Array α} (h : ∀ x y, f' (g x) (g y) = g (f x y)) : (xs.map g).foldl f' (g a) = g (xs.foldl f a) := by cases xs simp - rw [List.foldl_map_hom _ _ _ _ _ h] + rw [List.foldl_map_hom h] -theorem foldr_map_hom (g : α → β) (f : α → α → α) (f' : β → β → β) (a : α) (xs : Array α) +theorem foldr_map_hom {g : α → β} {f : α → α → α} {f' : β → β → β} {a : α} {xs : Array α} (h : ∀ x y, f' (g x) (g y) = g (f x y)) : (xs.map g).foldr f' (g a) = g (xs.foldr f a) := by cases xs simp - rw [List.foldr_map_hom _ _ _ _ _ h] + rw [List.foldr_map_hom h] /-- Variant of `foldrM_append` with a side condition for the `start` argument. -/ -@[simp] theorem foldrM_append' [Monad m] [LawfulMonad m] (f : α → β → m β) (b) (xs ys : Array α) - (w : start = xs.size + ys.size) : +@[simp] theorem foldrM_append' [Monad m] [LawfulMonad m] {f : α → β → m β} {b} {xs ys : Array α} + {start : Nat} (w : start = xs.size + ys.size) : (xs ++ ys).foldrM f b start 0 = ys.foldrM f b >>= xs.foldrM f := by subst w rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ simp -theorem foldrM_append [Monad m] [LawfulMonad m] (f : α → β → m β) (b) (xs ys : Array α) : +theorem foldrM_append [Monad m] [LawfulMonad m] {f : α → β → m β} {b} {xs ys : Array α} : (xs ++ ys).foldrM f b = ys.foldrM f b >>= xs.foldrM f := by simp -@[simp] theorem foldl_append' {β : Type _} (f : β → α → β) (b) (xs ys : Array α) +@[simp] theorem foldl_append' {β : Type _} {f : β → α → β} {b} {xs ys : Array α} {stop : Nat} (w : stop = xs.size + ys.size) : (xs ++ ys).foldl f b 0 stop = ys.foldl f (xs.foldl f b) := by subst w @@ -3361,65 +3371,67 @@ theorem foldrM_append [Monad m] [LawfulMonad m] (f : α → β → m β) (b) (xs rcases ys with ⟨ys⟩ simp -@[simp] theorem foldr_append' (f : α → β → β) (b) (xs ys : Array α) +@[simp] theorem foldr_append' {f : α → β → β} {b} {xs ys : Array α} {start : Nat} (w : start = xs.size + ys.size) : (xs ++ ys).foldr f b start 0 = xs.foldr f (ys.foldr f b) := by subst w simp [foldr_eq_foldrM] -theorem foldl_append {β : Type _} (f : β → α → β) (b) (xs ys : Array α) : +theorem foldl_append {β : Type _} {f : β → α → β} {b} {xs ys : Array α} : (xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) := by simp [foldl_eq_foldlM] -theorem foldr_append (f : α → β → β) (b) (xs ys : Array α) : +theorem foldr_append {f : α → β → β} {b} {xs ys : Array α} : (xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) := by simp [foldr_eq_foldrM] -@[simp] theorem foldl_flatten' (f : β → α → β) (b : β) (xss : Array (Array α)) +@[simp] theorem foldl_flatten' {f : β → α → β} {b} {xss : Array (Array α)} {stop : Nat} (w : stop = xss.flatten.size) : (flatten xss).foldl f b 0 stop = xss.foldl (fun b xs => xs.foldl f b) b := by subst w cases xss using array₂_induction simp [List.foldl_flatten, List.foldl_map] -@[simp] theorem foldr_flatten' (f : α → β → β) (b : β) (xss : Array (Array α)) +@[simp] theorem foldr_flatten' {f : α → β → β} {b} {xss : Array (Array α)} {start : Nat} (w : start = xss.flatten.size) : (flatten xss).foldr f b start 0 = xss.foldr (fun xs b => xs.foldr f b) b := by subst w cases xss using array₂_induction simp [List.foldr_flatten, List.foldr_map] -theorem foldl_flatten (f : β → α → β) (b : β) (xss : Array (Array α)) : +theorem foldl_flatten {f : β → α → β} {b} {xss : Array (Array α)} : (flatten xss).foldl f b = xss.foldl (fun b xs => xs.foldl f b) b := by cases xss using array₂_induction simp [List.foldl_flatten, List.foldl_map] -theorem foldr_flatten (f : α → β → β) (b : β) (xss : Array (Array α)) : +theorem foldr_flatten {f : α → β → β} {b} {xss : Array (Array α)} : (flatten xss).foldr f b = xss.foldr (fun xs b => xs.foldr f b) b := by cases xss using array₂_induction simp [List.foldr_flatten, List.foldr_map] /-- Variant of `foldl_reverse` with a side condition for the `stop` argument. -/ -@[simp] theorem foldl_reverse' (xs : Array α) (f : β → α → β) (b) (w : stop = xs.size) : +@[simp] theorem foldl_reverse' {xs : Array α} {f : β → α → β} {b} {stop : Nat} + (w : stop = xs.size) : xs.reverse.foldl f b 0 stop = xs.foldr (fun x y => f y x) b := by simp [w, foldl_eq_foldlM, foldr_eq_foldrM] /-- Variant of `foldr_reverse` with a side condition for the `start` argument. -/ -@[simp] theorem foldr_reverse' (xs : Array α) (f : α → β → β) (b) (w : start = xs.size) : +@[simp] theorem foldr_reverse' {xs : Array α} {f : α → β → β} {b} {start : Nat} + (w : start = xs.size) : xs.reverse.foldr f b start 0 = xs.foldl (fun x y => f y x) b := by simp [w, foldl_eq_foldlM, foldr_eq_foldrM] -theorem foldl_reverse (xs : Array α) (f : β → α → β) (b) : +theorem foldl_reverse {xs : Array α} {f : β → α → β} {b} : xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b := by simp [foldl_eq_foldlM, foldr_eq_foldrM] -theorem foldr_reverse (xs : Array α) (f : α → β → β) (b) : +theorem foldr_reverse {xs : Array α} {f : α → β → β} {b} : xs.reverse.foldr f b = xs.foldl (fun x y => f y x) b := (foldl_reverse ..).symm.trans <| by simp -theorem foldl_eq_foldr_reverse (xs : Array α) (f : β → α → β) (b) : +theorem foldl_eq_foldr_reverse {xs : Array α} {f : β → α → β} {b} : xs.foldl f b = xs.reverse.foldr (fun x y => f y x) b := by simp -theorem foldr_eq_foldl_reverse (xs : Array α) (f : α → β → β) (b) : +theorem foldr_eq_foldl_reverse {xs : Array α} {f : α → β → β} {b} : xs.foldr f b = xs.reverse.foldl (fun x y => f y x) b := by simp @[simp] theorem foldr_push_eq_append {as : Array α} {bs : Array β} {f : α → β} (w : start = as.size) : @@ -3439,46 +3451,48 @@ theorem foldr_assoc {op : α → α → α} [ha : Std.Associative op] {xs : Arra rcases xs with ⟨l⟩ simp [List.foldr_assoc] -theorem foldl_hom (f : α₁ → α₂) (g₁ : α₁ → β → α₁) (g₂ : α₂ → β → α₂) (xs : Array β) (init : α₁) +-- The argument `f : α₁ → α₂` is intentionally explicit, as it is sometimes not found by unification. +theorem foldl_hom (f : α₁ → α₂) {g₁ : α₁ → β → α₁} {g₂ : α₂ → β → α₂} {xs : Array β} {init : α₁} (H : ∀ x y, g₂ (f x) y = f (g₁ x y)) : xs.foldl g₂ (f init) = f (xs.foldl g₁ init) := by cases xs simp - rw [List.foldl_hom _ _ _ _ _ H] + rw [List.foldl_hom _ H] -theorem foldr_hom (f : β₁ → β₂) (g₁ : α → β₁ → β₁) (g₂ : α → β₂ → β₂) (xs : Array α) (init : β₁) +-- The argument `f : β₁ → β₂` is intentionally explicit, as it is sometimes not found by unification. +theorem foldr_hom (f : β₁ → β₂) {g₁ : α → β₁ → β₁} {g₂ : α → β₂ → β₂} {xs : Array α} {init : β₁} (H : ∀ x y, g₂ x (f y) = f (g₁ x y)) : xs.foldr g₂ (f init) = f (xs.foldr g₁ init) := by cases xs simp - rw [List.foldr_hom _ _ _ _ _ H] + rw [List.foldr_hom _ H] /-- We can prove that two folds over the same array are related (by some arbitrary relation) if we know that the initial elements are related and the folding function, for each element of the array, preserves the relation. -/ -theorem foldl_rel {xs : Array α} {f g : β → α → β} {a b : β} (r : β → β → Prop) +theorem foldl_rel {xs : Array α} {f g : β → α → β} {a b : β} {r : β → β → Prop} (h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c c' : β), r c c' → r (f c a) (g c' a)) : r (xs.foldl (fun acc a => f acc a) a) (xs.foldl (fun acc a => g acc a) b) := by rcases xs with ⟨xs⟩ - simpa using List.foldl_rel r h (by simpa using h') + simpa using List.foldl_rel h (by simpa using h') /-- We can prove that two folds over the same array are related (by some arbitrary relation) if we know that the initial elements are related and the folding function, for each element of the array, preserves the relation. -/ -theorem foldr_rel {xs : Array α} {f g : α → β → β} {a b : β} (r : β → β → Prop) +theorem foldr_rel {xs : Array α} {f g : α → β → β} {a b : β} {r : β → β → Prop} (h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c c' : β), r c c' → r (f a c) (g a c')) : r (xs.foldr (fun a acc => f a acc) a) (xs.foldr (fun a acc => g a acc) b) := by rcases xs with ⟨xs⟩ - simpa using List.foldr_rel r h (by simpa using h') + simpa using List.foldr_rel h (by simpa using h') -@[simp] theorem foldl_add_const (xs : Array α) (a b : Nat) : +@[simp] theorem foldl_add_const {xs : Array α} {a b : Nat} : xs.foldl (fun x _ => x + a) b = b + a * xs.size := by rcases xs with ⟨xs⟩ simp -@[simp] theorem foldr_add_const (xs : Array α) (a b : Nat) : +@[simp] theorem foldr_add_const {xs : Array α} {a b : Nat} : xs.foldr (fun _ x => x + a) b = b + a * xs.size := by rcases xs with ⟨xs⟩ simp @@ -3564,7 +3578,7 @@ theorem back_filterMap_of_eq_some {f : α → Option β} {xs : Array α} {w : 0 rcases xs with ⟨xs⟩ simp only [List.back_toArray] at h simp only [List.size_toArray, List.filterMap_toArray', List.back_toArray] - rw [List.getLast_filterMap_of_eq_some h] + rw [List.getLast_filterMap_of_eq_some _ h] theorem back?_flatMap {xs : Array α} {f : α → Array β} : (xs.flatMap f).back? = xs.reverse.findSome? fun a => (f a).back? := by @@ -3575,7 +3589,7 @@ theorem back?_flatten {xss : Array (Array α)} : (flatten xss).back? = xss.reverse.findSome? fun xs => xs.back? := by simp [← flatMap_id, back?_flatMap] -theorem back?_replicate (a : α) (n : Nat) : +theorem back?_replicate {a : α} {n : Nat} : (replicate n a).back? = if n = 0 then none else some a := by rw [replicate_eq_toArray_replicate] simp only [List.back?_toArray, List.getLast?_replicate] @@ -3596,17 +3610,17 @@ abbrev back_mkArray := @back_replicate -- We unfold `leftpad` and `rightpad` for verification purposes. attribute [simp] leftpad rightpad -theorem size_leftpad (n : Nat) (a : α) (xs : Array α) : +theorem size_leftpad {n : Nat} {a : α} {xs : Array α} : (leftpad n a xs).size = max n xs.size := by simp; omega -theorem size_rightpad (n : Nat) (a : α) (xs : Array α) : +theorem size_rightpad {n : Nat} {a : α} {xs : Array α} : (rightpad n a xs).size = max n xs.size := by simp; omega /-! ### contains -/ theorem elem_cons_self [BEq α] [LawfulBEq α] {xs : Array α} {a : α} : (xs.push a).elem a = true := by simp -theorem contains_eq_any_beq [BEq α] (xs : Array α) (a : α) : xs.contains a = xs.any (a == ·) := by +theorem contains_eq_any_beq [BEq α] {xs : Array α} {a : α} : xs.contains a = xs.any (a == ·) := by rcases xs with ⟨xs⟩ simp [List.contains_eq_any_beq] @@ -3625,7 +3639,7 @@ theorem pop_append {xs ys : Array α} : (xs ++ ys).pop = if ys.isEmpty then xs.pop else xs ++ ys.pop := by split <;> simp_all -@[simp] theorem pop_replicate (n) (a : α) : (replicate n a).pop = replicate (n - 1) a := by +@[simp] theorem pop_replicate {n : Nat} {a : α} : (replicate n a).pop = replicate (n - 1) a := by ext <;> simp @[deprecated pop_replicate (since := "2025-03-18")] @@ -3633,7 +3647,7 @@ abbrev pop_mkArray := @pop_replicate /-! ### modify -/ -@[simp] theorem size_modify (xs : Array α) (i : Nat) (f : α → α) : (xs.modify i f).size = xs.size := by +@[simp] theorem size_modify {xs : Array α} {i : Nat} {f : α → α} : (xs.modify i f).size = xs.size := by unfold modify modifyM Id.run split <;> simp @@ -3644,7 +3658,7 @@ theorem getElem_modify {xs : Array α} {j i} (h : i < (xs.modify j f).size) : · simp only [Id.bind_eq, getElem_set]; split <;> simp [*] · rw [if_neg (mt (by rintro rfl; exact h) (by simp_all))] -@[simp] theorem toList_modify (xs : Array α) (f : α → α) : +@[simp] theorem toList_modify {xs : Array α} {f : α → α} {i : Nat} : (xs.modify i f).toList = xs.toList.modify i f := by apply List.ext_getElem · simp @@ -3666,29 +3680,29 @@ theorem getElem?_modify {xs : Array α} {i : Nat} {f : α → α} {j : Nat} : /-! ### swap -/ -@[simp] theorem getElem_swap_right (xs : Array α) {i j : Nat} {hi hj} : +@[simp] theorem getElem_swap_right {xs : Array α} {i j : Nat} {hi hj} : (xs.swap i j hi hj)[j]'(by simpa using hj) = xs[i] := by simp [swap_def, getElem_set] -@[simp] theorem getElem_swap_left (xs : Array α) {i j : Nat} {hi hj} : +@[simp] theorem getElem_swap_left {xs : Array α} {i j : Nat} {hi hj} : (xs.swap i j hi hj)[i]'(by simpa using hi) = xs[j] := by simp +contextual [swap_def, getElem_set] -@[simp] theorem getElem_swap_of_ne (xs : Array α) {i j : Nat} {hi hj} (hp : k < xs.size) +@[simp] theorem getElem_swap_of_ne {xs : Array α} {i j : Nat} {hi hj} (hp : k < xs.size) (hi' : k ≠ i) (hj' : k ≠ j) : (xs.swap i j hi hj)[k]'(xs.size_swap .. |>.symm ▸ hp) = xs[k] := by simp [swap_def, getElem_set, hi'.symm, hj'.symm] -theorem getElem_swap' (xs : Array α) (i j : Nat) {hi hj} (k : Nat) (hk : k < xs.size) : +theorem getElem_swap' {xs : Array α} {i j : Nat} {hi hj} {k : Nat} (hk : k < xs.size) : (xs.swap i j hi hj)[k]'(by simp_all) = if k = i then xs[j] else if k = j then xs[i] else xs[k] := by split · simp_all only [getElem_swap_left] · split <;> simp_all -theorem getElem_swap (xs : Array α) (i j : Nat) {hi hj} (k : Nat) (hk : k < (xs.swap i j hi hj).size) : +theorem getElem_swap {xs : Array α} {i j : Nat} (hi hj) {k : Nat} (hk : k < (xs.swap i j hi hj).size) : (xs.swap i j hi hj)[k] = if k = i then xs[j] else if k = j then xs[i] else xs[k]'(by simp_all) := by apply getElem_swap' -@[simp] theorem swap_swap (xs : Array α) {i j : Nat} (hi hj) : +@[simp] theorem swap_swap {xs : Array α} {i j : Nat} (hi hj) : (xs.swap i j hi hj).swap i j ((xs.size_swap ..).symm ▸ hi) ((xs.size_swap ..).symm ▸ hj) = xs := by apply ext · simp only [size_swap] @@ -3698,7 +3712,7 @@ theorem getElem_swap (xs : Array α) (i j : Nat) {hi hj} (k : Nat) (hk : k < (xs · simp_all · split <;> simp_all -theorem swap_comm (xs : Array α) {i j : Nat} {hi hj} : xs.swap i j hi hj = xs.swap j i hj hi := by +theorem swap_comm {xs : Array α} {i j : Nat} (hi hj) : xs.swap i j hi hj = xs.swap j i hj hi := by apply ext · simp only [size_swap] · intros @@ -3707,24 +3721,24 @@ theorem swap_comm (xs : Array α) {i j : Nat} {hi hj} : xs.swap i j hi hj = xs.s · split <;> simp_all · split <;> simp_all -@[simp] theorem size_swapIfInBounds (xs : Array α) (i j) : +@[simp] theorem size_swapIfInBounds {xs : Array α} {i j : Nat} : (xs.swapIfInBounds i j).size = xs.size := by unfold swapIfInBounds; split <;> (try split) <;> simp [size_swap] @[deprecated size_swapIfInBounds (since := "2024-11-24")] abbrev size_swap! := @size_swapIfInBounds /-! ### swapAt -/ -@[simp] theorem swapAt_def (xs : Array α) (i : Nat) (v : α) (hi) : +@[simp] theorem swapAt_def {xs : Array α} {i : Nat} {v : α} (hi) : xs.swapAt i v hi = (xs[i], xs.set i v) := rfl -theorem size_swapAt (xs : Array α) (i : Nat) (v : α) (hi) : +theorem size_swapAt {xs : Array α} {i : Nat} {v : α} (hi) : (xs.swapAt i v hi).2.size = xs.size := by simp @[simp] -theorem swapAt!_def (xs : Array α) (i : Nat) (v : α) (h : i < xs.size) : +theorem swapAt!_def {xs : Array α} {i : Nat} {v : α} (h : i < xs.size) : xs.swapAt! i v = (xs[i], xs.set i v) := by simp [swapAt!, h] -@[simp] theorem size_swapAt! (xs : Array α) (i : Nat) (v : α) : +@[simp] theorem size_swapAt! {xs : Array α} {i : Nat} {v : α} : (xs.swapAt! i v).2.size = xs.size := by simp only [swapAt!] split @@ -3816,35 +3830,35 @@ end replace /-! ### any / all -/ -theorem not_any_eq_all_not (xs : Array α) (p : α → Bool) : (!xs.any p) = xs.all fun a => !p a := by +theorem not_any_eq_all_not {xs : Array α} {p : α → Bool} : (!xs.any p) = xs.all fun a => !p a := by rcases xs with ⟨xs⟩ simp [List.not_any_eq_all_not] -theorem not_all_eq_any_not (xs : Array α) (p : α → Bool) : (!xs.all p) = xs.any fun a => !p a := by +theorem not_all_eq_any_not {xs : Array α} {p : α → Bool} : (!xs.all p) = xs.any fun a => !p a := by rcases xs with ⟨xs⟩ simp [List.not_all_eq_any_not] -theorem and_any_distrib_left (xs : Array α) (p : α → Bool) (q : Bool) : +theorem and_any_distrib_left {xs : Array α} {p : α → Bool} {q : Bool} : (q && xs.any p) = xs.any fun a => q && p a := by rcases xs with ⟨xs⟩ simp [List.and_any_distrib_left] -theorem and_any_distrib_right (xs : Array α) (p : α → Bool) (q : Bool) : +theorem and_any_distrib_right {xs : Array α} {p : α → Bool} {q : Bool} : (xs.any p && q) = xs.any fun a => p a && q := by rcases xs with ⟨xs⟩ simp [List.and_any_distrib_right] -theorem or_all_distrib_left (xs : Array α) (p : α → Bool) (q : Bool) : +theorem or_all_distrib_left {xs : Array α} {p : α → Bool} {q : Bool} : (q || xs.all p) = xs.all fun a => q || p a := by rcases xs with ⟨xs⟩ simp [List.or_all_distrib_left] -theorem or_all_distrib_right (xs : Array α) (p : α → Bool) (q : Bool) : +theorem or_all_distrib_right {xs : Array α} {p : α → Bool} {q : Bool} : (xs.all p || q) = xs.all fun a => p a || q := by rcases xs with ⟨xs⟩ simp [List.or_all_distrib_right] -theorem any_eq_not_all_not (xs : Array α) (p : α → Bool) : xs.any p = !xs.all (!p .) := by +theorem any_eq_not_all_not {xs : Array α} {p : α → Bool} : xs.any p = !xs.all (!p .) := by simp only [not_all_eq_any_not, Bool.not_not] /-- Variant of `any_map` with a side condition for the `stop` argument. -/ @@ -4064,34 +4078,34 @@ Examples: -/ @[inline] def toListRev (xs : Array α) : List α := xs.foldl (fun l t => t :: l) [] -@[simp] theorem toListRev_eq (xs : Array α) : xs.toListRev = xs.toList.reverse := by +@[simp] theorem toListRev_eq {xs : Array α} : xs.toListRev = xs.toList.reverse := by rw [toListRev, ← foldl_toList, ← List.foldr_reverse, List.foldr_cons_nil] /-! ### appendList -/ -@[simp] theorem appendList_nil (xs : Array α) : xs ++ ([] : List α) = xs := Array.ext' (by simp) +@[simp] theorem appendList_nil {xs : Array α} : xs ++ ([] : List α) = xs := Array.ext' (by simp) -@[simp] theorem appendList_cons (xs : Array α) (a : α) (l : List α) : +@[simp] theorem appendList_cons {xs : Array α} {a : α} {l : List α} : xs ++ (a :: l) = xs.push a ++ l := Array.ext' (by simp) /-! ### Preliminaries about `ofFn` -/ -@[simp] theorem size_ofFn_go {n} (f : Fin n → α) (i acc) : +@[simp] theorem size_ofFn_go {n} {f : Fin n → α} {i acc} : (ofFn.go f i acc).size = acc.size + (n - i) := by if hin : i < n then unfold ofFn.go have : 1 + (n - (i + 1)) = n - i := Nat.sub_sub .. ▸ Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. ▸ hin)) - rw [dif_pos hin, size_ofFn_go f (i+1), size_push, Nat.add_assoc, this] + rw [dif_pos hin, size_ofFn_go, size_push, Nat.add_assoc, this] else have : n - i = 0 := Nat.sub_eq_zero_of_le (Nat.le_of_not_lt hin) unfold ofFn.go simp [hin, this] termination_by n - i -@[simp] theorem size_ofFn (f : Fin n → α) : (ofFn f).size = n := by simp [ofFn] +@[simp] theorem size_ofFn {n : Nat} {f : Fin n → α} : (ofFn f).size = n := by simp [ofFn] -theorem getElem_ofFn_go (f : Fin n → α) (i) {acc k} +theorem getElem_ofFn_go {f : Fin n → α} {i} {acc k} (hki : k < n) (hin : i ≤ n) (hi : i = acc.size) (hacc : ∀ j, ∀ hj : j < acc.size, acc[j] = f ⟨j, Nat.lt_of_lt_of_le hj (hi ▸ hin)⟩) : haveI : acc.size + (n - acc.size) = n := Nat.add_sub_cancel' (hi ▸ hin) @@ -4101,7 +4115,7 @@ theorem getElem_ofFn_go (f : Fin n → α) (i) {acc k} have : 1 + (n - (i + 1)) = n - i := Nat.sub_sub .. ▸ Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. ▸ hin)) simp only [dif_pos hin] - rw [getElem_ofFn_go f (i+1) _ hin (by simp [*]) (fun j hj => ?hacc)] + rw [getElem_ofFn_go _ hin (by simp [*]) (fun j hj => ?hacc)] cases (Nat.lt_or_eq_of_le <| Nat.le_of_lt_succ (by simpa using hj)) with | inl hj => simp [getElem_push, hj, hacc j hj] | inr hj => simp [getElem_push, *] @@ -4109,11 +4123,11 @@ theorem getElem_ofFn_go (f : Fin n → α) (i) {acc k} simp [hin, hacc k (Nat.lt_of_lt_of_le hki (Nat.le_of_not_lt (hi ▸ hin)))] termination_by n - i -@[simp] theorem getElem_ofFn (f : Fin n → α) (i : Nat) (h) : - (ofFn f)[i] = f ⟨i, size_ofFn f ▸ h⟩ := - getElem_ofFn_go _ _ _ (by simp) (by simp) nofun +@[simp] theorem getElem_ofFn {f : Fin n → α} {i : Nat} (h : i < (ofFn f).size) : + (ofFn f)[i] = f ⟨i, size_ofFn (f := f) ▸ h⟩ := + getElem_ofFn_go _ (by simp) (by simp) nofun -theorem getElem?_ofFn (f : Fin n → α) (i : Nat) : +theorem getElem?_ofFn {f : Fin n → α} {i : Nat} : (ofFn f)[i]? = if h : i < n then some (f ⟨i, h⟩) else none := by simp [getElem?_def] @@ -4136,7 +4150,7 @@ theorem getElem?_range' {start size step : Nat} {i : Nat} : (Array.range' start size step)[i]? = if i < size then some (start + step * i) else none := by simp [getElem?_def, getElem_range'] -@[simp] theorem _root_.List.toArray_range' (start size step : Nat) : +@[simp] theorem _root_.List.toArray_range' {start size step : Nat} : (List.range' start size step).toArray = Array.range' start size step := by apply ext' simp @@ -4144,7 +4158,7 @@ theorem getElem?_range' {start size step : Nat} {i : Nat} : @[simp] theorem size_range {n : Nat} : (range n).size = n := by simp [range] -@[simp] theorem toList_range (n : Nat) : (range n).toList = List.range n := by +@[simp] theorem toList_range {n : Nat} : (range n).toList = List.range n := by apply List.ext_getElem <;> simp [range] @[simp] @@ -4154,7 +4168,7 @@ theorem getElem_range {n : Nat} {i : Nat} (h : i < (Array.range n).size) : (Arra theorem getElem?_range {n : Nat} {i : Nat} : (Array.range n)[i]? = if i < n then some i else none := by simp [getElem?_def, getElem_range] -@[simp] theorem _root_.List.toArray_range (n : Nat) : (List.range n).toArray = Array.range n := by +@[simp] theorem _root_.List.toArray_range {n : Nat} : (List.range n).toArray = Array.range n := by apply ext' simp @@ -4162,17 +4176,17 @@ theorem getElem?_range {n : Nat} {i : Nat} : (Array.range n)[i]? = if i < n then /-! ### sum -/ -theorem sum_eq_sum_toList [Add α] [Zero α] (as : Array α) : as.toList.sum = as.sum := by +theorem sum_eq_sum_toList [Add α] [Zero α] {as : Array α} : as.toList.sum = as.sum := by cases as simp [Array.sum, List.sum] -theorem foldl_toList_eq_flatMap (l : List α) (acc : Array β) - (F : Array β → α → Array β) (G : α → List β) +theorem foldl_toList_eq_flatMap {l : List α} {acc : Array β} + {F : Array β → α → Array β} {G : α → List β} (H : ∀ acc a, (F acc a).toList = acc.toList ++ G a) : (l.foldl F acc).toList = acc.toList ++ l.flatMap G := by induction l generalizing acc <;> simp [*, List.flatMap] -theorem foldl_toList_eq_map (l : List α) (acc : Array β) (G : α → β) : +theorem foldl_toList_eq_map {l : List α} {acc : Array β} {G : α → β} : (l.foldl (fun acc a => acc.push (G a)) acc).toList = acc.toList ++ l.map G := by induction l generalizing acc <;> simp [*] @@ -4180,20 +4194,24 @@ theorem foldl_toList_eq_map (l : List α) (acc : Array β) (G : α → β) : attribute [simp] uset -theorem size_uset (xs : Array α) (v i h) : (uset xs i v h).size = xs.size := by simp +theorem size_uset {xs : Array α} {v : α} {i : USize} (h : i.toNat < xs.size) : + (uset xs i v h).size = xs.size := by + simp /-! # get -/ -@[simp] theorem getD_eq_getD_getElem? (xs : Array α) (i d) : xs.getD i d = xs[i]?.getD d := by +@[simp] theorem getD_eq_getD_getElem? {xs : Array α} {i : Nat} {d : α} : + xs.getD i d = xs[i]?.getD d := by simp only [getD]; split <;> simp [getD_getElem?, *] -theorem getElem!_eq_getD [Inhabited α] (xs : Array α) : xs[i]! = xs.getD i default := by +theorem getElem!_eq_getD [Inhabited α] {xs : Array α} {i} : xs[i]! = xs.getD i default := by rfl /-! # mem -/ @[simp] theorem mem_toList {a : α} {xs : Array α} : a ∈ xs.toList ↔ a ∈ xs := mem_def.symm +@[deprecated not_mem_empty (since := "2025-03-25")] theorem not_mem_nil (a : α) : ¬ a ∈ #[] := nofun /-! # get lemmas -/ @@ -4202,47 +4220,44 @@ theorem lt_of_getElem {x : α} {xs : Array α} {i : Nat} {hidx : i < xs.size} (_ i < xs.size := hidx -theorem getElem_fin_eq_getElem_toList (xs : Array α) (i : Fin xs.size) : xs[i] = xs.toList[i] := rfl +theorem getElem_fin_eq_getElem_toList {xs : Array α} {i : Fin xs.size} : xs[i] = xs.toList[i] := rfl -@[simp] theorem ugetElem_eq_getElem (xs : Array α) {i : USize} (h : i.toNat < xs.size) : +@[simp] theorem ugetElem_eq_getElem {xs : Array α} {i : USize} (h : i.toNat < xs.size) : xs[i] = xs[i.toNat] := rfl -theorem getElem?_size_le (xs : Array α) (i : Nat) (h : xs.size ≤ i) : xs[i]? = none := by +theorem getElem?_size_le {xs : Array α} {i : Nat} (h : xs.size ≤ i) : xs[i]? = none := by simp [getElem?_neg, h] -theorem getElem_mem_toList (xs : Array α) (i : Nat) (h : i < xs.size) : xs[i] ∈ xs.toList := by +theorem getElem_mem_toList {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] ∈ xs.toList := by simp only [← getElem_toList, List.getElem_mem] -theorem back!_eq_back? [Inhabited α] (xs : Array α) : xs.back! = xs.back?.getD default := by +theorem back!_eq_back? [Inhabited α] {xs : Array α} : xs.back! = xs.back?.getD default := by simp [back!, back?, getElem!_def, Option.getD]; rfl -@[simp] theorem back?_push (xs : Array α) : (xs.push x).back? = some x := by +@[simp] theorem back?_push {xs : Array α} {x : α} : (xs.push x).back? = some x := by simp [back?, ← getElem?_toList] -@[simp] theorem back!_push [Inhabited α] (xs : Array α) : (xs.push x).back! = x := by +@[simp] theorem back!_push [Inhabited α] {xs : Array α} {x : α} : (xs.push x).back! = x := by simp [back!_eq_back?] -theorem getElem?_push_lt (xs : Array α) (x : α) (i : Nat) (h : i < xs.size) : +theorem getElem?_push_lt {xs : Array α} {x : α} {i : Nat} (h : i < xs.size) : (xs.push x)[i]? = some xs[i] := by rw [getElem?_pos, getElem_push_lt] -theorem getElem?_push_eq (xs : Array α) (x : α) : (xs.push x)[xs.size]? = some x := by +theorem getElem?_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size]? = some x := by rw [getElem?_pos, getElem_push_eq] @[simp] theorem getElem?_size {xs : Array α} : xs[xs.size]? = none := by simp only [getElem?_def, Nat.lt_irrefl, dite_false] - - - /-! ### forIn -/ -@[simp] theorem forIn_toList [Monad m] (xs : Array α) (b : β) (f : α → β → m (ForInStep β)) : +@[simp] theorem forIn_toList [Monad m] {xs : Array α} {b : β} {f : α → β → m (ForInStep β)} : forIn xs.toList b f = forIn xs b f := by cases xs simp -@[simp] theorem forIn'_toList [Monad m] (xs : Array α) (b : β) (f : (a : α) → a ∈ xs.toList → β → m (ForInStep β)) : +@[simp] theorem forIn'_toList [Monad m] {xs : Array α} {b : β} {f : (a : α) → a ∈ xs.toList → β → m (ForInStep β)} : forIn' xs.toList b f = forIn' xs b (fun a m b => f a (mem_toList.mpr m) b) := by cases xs simp @@ -4265,31 +4280,31 @@ instance [DecidableEq α] (a : α) (xs : Array α) : Decidable (a ∈ xs) := /-! ### zipWith -/ -@[simp] theorem toList_zipWith (f : α → β → γ) (xs : Array α) (ys : Array β) : +@[simp] theorem toList_zipWith {f : α → β → γ} {xs : Array α} {ys : Array β} : (zipWith f xs ys).toList = List.zipWith f xs.toList ys.toList := by cases xs cases ys simp -@[simp] theorem toList_zip (xs : Array α) (ys : Array β) : +@[simp] theorem toList_zip {xs : Array α} {ys : Array β} : (zip xs ys).toList = List.zip xs.toList ys.toList := by simp [zip, toList_zipWith, List.zip] -@[simp] theorem toList_zipWithAll (f : Option α → Option β → γ) (xs : Array α) (ys : Array β) : +@[simp] theorem toList_zipWithAll {f : Option α → Option β → γ} {xs : Array α} {ys : Array β} : (zipWithAll f xs ys).toList = List.zipWithAll f xs.toList ys.toList := by cases xs cases ys simp -@[simp] theorem size_zipWith (xs : Array α) (ys : Array β) (f : α → β → γ) : +@[simp] theorem size_zipWith {xs : Array α} {ys : Array β} {f : α → β → γ} : (zipWith f xs ys).size = min xs.size ys.size := by rw [size_eq_length_toList, toList_zipWith, List.length_zipWith] -@[simp] theorem size_zip (xs : Array α) (ys : Array β) : +@[simp] theorem size_zip {xs : Array α} {ys : Array β} : (zip xs ys).size = min xs.size ys.size := - xs.size_zipWith ys Prod.mk + size_zipWith -@[simp] theorem getElem_zipWith (xs : Array α) (ys : Array β) (f : α → β → γ) (i : Nat) +@[simp] theorem getElem_zipWith {xs : Array α} {ys : Array β} {f : α → β → γ} {i : Nat} (hi : i < (zipWith f xs ys).size) : (zipWith f xs ys)[i] = f (xs[i]'(by simp at hi; omega)) (ys[i]'(by simp at hi; omega)) := by cases xs @@ -4298,32 +4313,32 @@ instance [DecidableEq α] (a : α) (xs : Array α) : Decidable (a ∈ xs) := /-! ### findSomeM?, findM?, findSome?, find? -/ -@[simp] theorem findSomeM?_toList [Monad m] [LawfulMonad m] (p : α → m (Option β)) (xs : Array α) : +@[simp] theorem findSomeM?_toList [Monad m] [LawfulMonad m] {p : α → m (Option β)} {xs : Array α} : xs.toList.findSomeM? p = xs.findSomeM? p := by cases xs simp -@[simp] theorem findM?_toList [Monad m] [LawfulMonad m] (p : α → m Bool) (xs : Array α) : +@[simp] theorem findM?_toList [Monad m] [LawfulMonad m] {p : α → m Bool} {xs : Array α} : xs.toList.findM? p = xs.findM? p := by cases xs simp -@[simp] theorem findSome?_toList (p : α → Option β) (xs : Array α) : +@[simp] theorem findSome?_toList {p : α → Option β} {xs : Array α} : xs.toList.findSome? p = xs.findSome? p := by cases xs simp -@[simp] theorem find?_toList (p : α → Bool) (xs : Array α) : +@[simp] theorem find?_toList {p : α → Bool} {xs : Array α} : xs.toList.find? p = xs.find? p := by cases xs simp -@[simp] theorem finIdxOf?_toList [BEq α] (a : α) (xs : Array α) : +@[simp] theorem finIdxOf?_toList [BEq α] {a : α} {xs : Array α} : xs.toList.finIdxOf? a = (xs.finIdxOf? a).map (Fin.cast (by simp)) := by cases xs simp -@[simp] theorem findFinIdx?_toList (p : α → Bool) (xs : Array α) : +@[simp] theorem findFinIdx?_toList {p : α → Bool} {xs : Array α} : xs.toList.findFinIdx? p = (xs.findFinIdx? p).map (Fin.cast (by simp)) := by cases xs simp @@ -4340,12 +4355,12 @@ namespace List Our goal is to have `simp` "pull `List.toArray` outwards" as much as possible. -/ -theorem toListRev_toArray (l : List α) : l.toArray.toListRev = l.reverse := by simp +theorem toListRev_toArray {l : List α} : l.toArray.toListRev = l.reverse := by simp -@[simp] theorem take_toArray (l : List α) (i : Nat) : l.toArray.take i = (l.take i).toArray := by +@[simp] theorem take_toArray {l : List α} {i : Nat} : l.toArray.take i = (l.take i).toArray := by apply Array.ext <;> simp -@[simp] theorem mapM_toArray [Monad m] [LawfulMonad m] (f : α → m β) (l : List α) : +@[simp] theorem mapM_toArray [Monad m] [LawfulMonad m] {f : α → m β} {l : List α} : l.toArray.mapM f = List.toArray <$> l.mapM f := by simp only [← mapM'_eq_mapM, mapM_eq_foldlM] suffices ∀ xs : Array β, @@ -4359,15 +4374,15 @@ theorem toListRev_toArray (l : List α) : l.toArray.toListRev = l.reverse := by rw [size_toArray, mapM'_cons, foldlM_toArray] simp [ih] -theorem uset_toArray (l : List α) (i : USize) (a : α) (h : i.toNat < l.toArray.size) : +theorem uset_toArray {l : List α} {i : USize} {a : α} {h : i.toNat < l.toArray.size} : l.toArray.uset i a h = (l.set i.toNat a).toArray := by simp -@[simp] theorem modify_toArray (f : α → α) (l : List α) : +@[simp] theorem modify_toArray {f : α → α} {l : List α} {i : Nat} : l.toArray.modify i f = (l.modify i f).toArray := by apply ext' simp -@[simp] theorem flatten_toArray (L : List (List α)) : +@[simp] theorem flatten_toArray {L : List (List α)} : (L.toArray.map List.toArray).flatten = L.flatten.toArray := by apply ext' simp [Function.comp_def] @@ -4376,16 +4391,16 @@ end List namespace Array -@[simp] theorem toList_takeWhile (p : α → Bool) (as : Array α) : +@[simp] theorem toList_takeWhile {p : α → Bool} {as : Array α} : (as.takeWhile p).toList = as.toList.takeWhile p := by induction as; simp -@[simp] theorem toList_eraseIdx (xs : Array α) (i : Nat) (h : i < xs.size) : +@[simp] theorem toList_eraseIdx {xs : Array α} {i : Nat} {h : i < xs.size} : (xs.eraseIdx i h).toList = xs.toList.eraseIdx i := by induction xs simp -@[simp] theorem toList_eraseIdxIfInBounds (xs : Array α) (i : Nat) : +@[simp] theorem toList_eraseIdxIfInBounds {xs : Array α} {i : Nat} : (xs.eraseIdxIfInBounds i).toList = xs.toList.eraseIdx i := by induction xs simp @@ -4393,60 +4408,60 @@ namespace Array /-! ### findSomeRevM?, findRevM?, findSomeRev?, findRev? -/ @[simp] theorem findSomeRevM?_eq_findSomeM?_reverse - [Monad m] [LawfulMonad m] (f : α → m (Option β)) (xs : Array α) : + [Monad m] [LawfulMonad m] {f : α → m (Option β)} {xs : Array α} : xs.findSomeRevM? f = xs.reverse.findSomeM? f := by cases xs rw [List.findSomeRevM?_toArray] simp @[simp] theorem findRevM?_eq_findM?_reverse - [Monad m] [LawfulMonad m] (f : α → m Bool) (xs : Array α) : + [Monad m] [LawfulMonad m] {f : α → m Bool} {xs : Array α} : xs.findRevM? f = xs.reverse.findM? f := by cases xs rw [List.findRevM?_toArray] simp -@[simp] theorem findSomeRev?_eq_findSome?_reverse (f : α → Option β) (xs : Array α) : +@[simp] theorem findSomeRev?_eq_findSome?_reverse {f : α → Option β} {xs : Array α} : xs.findSomeRev? f = xs.reverse.findSome? f := by cases xs simp [findSomeRev?, Id.run] -@[simp] theorem findRev?_eq_find?_reverse (f : α → Bool) (xs : Array α) : +@[simp] theorem findRev?_eq_find?_reverse {f : α → Bool} {xs : Array α} : xs.findRev? f = xs.reverse.find? f := by cases xs simp [findRev?, Id.run] /-! ### unzip -/ -@[simp] theorem fst_unzip (xs : Array (α × β)) : (Array.unzip xs).fst = xs.map Prod.fst := by +@[simp] theorem fst_unzip {xs : Array (α × β)} : (Array.unzip xs).fst = xs.map Prod.fst := by simp only [unzip] rcases xs with ⟨xs⟩ simp only [List.foldl_toArray'] rw [← List.foldl_hom (f := Prod.fst) (g₂ := fun bs x => bs.push x.1) (H := by simp), ← List.foldl_map] simp -@[simp] theorem snd_unzip (xs : Array (α × β)) : (Array.unzip xs).snd = xs.map Prod.snd := by +@[simp] theorem snd_unzip {xs : Array (α × β)} : (Array.unzip xs).snd = xs.map Prod.snd := by simp only [unzip] rcases xs with ⟨xs⟩ simp only [List.foldl_toArray'] rw [← List.foldl_hom (f := Prod.snd) (g₂ := fun bs x => bs.push x.2) (H := by simp), ← List.foldl_map] simp -theorem toList_fst_unzip (xs : Array (α × β)) : +theorem toList_fst_unzip {xs : Array (α × β)} : xs.unzip.1.toList = xs.toList.unzip.1 := by simp -theorem toList_snd_unzip (xs : Array (α × β)) : +theorem toList_snd_unzip {xs : Array (α × β)} : xs.unzip.2.toList = xs.toList.unzip.2 := by simp end Array namespace List -@[simp] theorem unzip_toArray (as : List (α × β)) : +@[simp] theorem unzip_toArray {as : List (α × β)} : as.toArray.unzip = Prod.map List.toArray List.toArray as.unzip := by ext1 <;> simp -@[simp] theorem firstM_toArray [Alternative m] (as : List α) (f : α → m β) : +@[simp] theorem firstM_toArray [Alternative m] {as : List α} {f : α → m β} : as.toArray.firstM f = as.firstM f := by unfold Array.firstM suffices ∀ i, i ≤ as.length → firstM.go f as.toArray (as.length - i) = firstM f (as.drop (as.length - i)) by diff --git a/src/Init/Data/Array/Lex/Lemmas.lean b/src/Init/Data/Array/Lex/Lemmas.lean index ad93603d97..a6d85412a9 100644 --- a/src/Init/Data/Array/Lex/Lemmas.lean +++ b/src/Init/Data/Array/Lex/Lemmas.lean @@ -14,18 +14,18 @@ namespace Array /-! ### Lexicographic ordering -/ -@[simp] theorem _root_.List.lt_toArray [LT α] (l₁ l₂ : List α) : l₁.toArray < l₂.toArray ↔ l₁ < l₂ := Iff.rfl -@[simp] theorem _root_.List.le_toArray [LT α] (l₁ l₂ : List α) : l₁.toArray ≤ l₂.toArray ↔ l₁ ≤ l₂ := Iff.rfl +@[simp] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray ↔ l₁ < l₂ := Iff.rfl +@[simp] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray ≤ l₂.toArray ↔ l₁ ≤ l₂ := Iff.rfl -@[simp] theorem lt_toList [LT α] (xs ys : Array α) : xs.toList < ys.toList ↔ xs < ys := Iff.rfl -@[simp] theorem le_toList [LT α] (xs ys : Array α) : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl +@[simp] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList ↔ xs < ys := Iff.rfl +@[simp] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl -protected theorem not_lt_iff_ge [LT α] (l₁ l₂ : List α) : ¬ l₁ < l₂ ↔ l₂ ≤ l₁ := Iff.rfl -protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] (l₁ l₂ : List α) : +protected theorem not_lt_iff_ge [LT α] {l₁ l₂ : List α} : ¬ l₁ < l₂ ↔ l₂ ≤ l₁ := Iff.rfl +protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {l₁ l₂ : List α} : ¬ l₁ ≤ l₂ ↔ l₂ < l₁ := Decidable.not_not -@[simp] theorem lex_empty [BEq α] {lt : α → α → Bool} (xs : Array α) : xs.lex #[] lt = false := by +@[simp] theorem lex_empty [BEq α] {lt : α → α → Bool} {xs : Array α} : xs.lex #[] lt = false := by simp [lex, Id.run] @[simp] theorem singleton_lex_singleton [BEq α] {lt : α → α → Bool} : #[a].lex #[b] lt = lt a b := by @@ -45,7 +45,7 @@ private theorem cons_lex_cons [BEq α] {lt : α → α → Bool} {a b : α} {xs cases a == b <;> simp · simp -@[simp] theorem _root_.List.lex_toArray [BEq α] (lt : α → α → Bool) (l₁ l₂ : List α) : +@[simp] theorem _root_.List.lex_toArray [BEq α] {lt : α → α → Bool} {l₁ l₂ : List α} : l₁.toArray.lex l₂.toArray lt = l₁.lex l₂ lt := by induction l₁ generalizing l₂ with | nil => cases l₂ <;> simp [lex, Id.run] @@ -55,7 +55,7 @@ private theorem cons_lex_cons [BEq α] {lt : α → α → Bool} {a b : α} {xs | cons y l₂ => rw [List.toArray_cons, List.toArray_cons y, cons_lex_cons, List.lex, ih] -@[simp] theorem lex_toList [BEq α] (lt : α → α → Bool) (xs ys : Array α) : +@[simp] theorem lex_toList [BEq α] {lt : α → α → Bool} {xs ys : Array α} : xs.toList.lex ys.toList lt = xs.lex ys lt := by cases xs <;> cases ys <;> simp @@ -68,7 +68,7 @@ instance ltIrrefl [LT α] [Std.Irrefl (· < · : α → α → Prop)] : Std.Irre @[simp] theorem not_lt_empty [LT α] (xs : Array α) : ¬ xs < #[] := List.not_lt_nil xs.toList @[simp] theorem empty_le [LT α] (xs : Array α) : #[] ≤ xs := List.nil_le xs.toList -@[simp] theorem le_empty [LT α] (xs : Array α) : xs ≤ #[] ↔ xs = #[] := by +@[simp] theorem le_empty [LT α] {xs : Array α} : xs ≤ #[] ↔ xs = #[] := by cases xs simp diff --git a/src/Init/Data/Array/MapIdx.lean b/src/Init/Data/Array/MapIdx.lean index 19c59a5047..bb4cbffa8c 100644 --- a/src/Init/Data/Array/MapIdx.lean +++ b/src/Init/Data/Array/MapIdx.lean @@ -42,66 +42,66 @@ theorem mapFinIdx_induction (xs : Array α) (f : (i : Nat) → α → (h : i < x · exact (hs j (by omega) hm).2 simp [mapFinIdx, mapFinIdxM]; exact go rfl nofun h0 -theorem mapFinIdx_spec (xs : Array α) (f : (i : Nat) → α → (h : i < xs.size) → β) - (p : (i : Nat) → β → (h : i < xs.size) → Prop) (hs : ∀ i h, p i (f i xs[i] h) h) : +theorem mapFinIdx_spec {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} + {p : (i : Nat) → β → (h : i < xs.size) → Prop} (hs : ∀ i h, p i (f i xs[i] h) h) : ∃ eq : (Array.mapFinIdx xs f).size = xs.size, ∀ i h, p i ((Array.mapFinIdx xs f)[i]) h := (mapFinIdx_induction _ _ (fun _ => True) trivial p fun _ _ _ => ⟨hs .., trivial⟩).2 -@[simp] theorem size_mapFinIdx (xs : Array α) (f : (i : Nat) → α → (h : i < xs.size) → β) : +@[simp] theorem size_mapFinIdx {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} : (xs.mapFinIdx f).size = xs.size := (mapFinIdx_spec (p := fun _ _ _ => True) (hs := fun _ _ => trivial)).1 -@[simp] theorem size_zipIdx (xs : Array α) (k : Nat) : (xs.zipIdx k).size = xs.size := - Array.size_mapFinIdx _ _ +@[simp] theorem size_zipIdx {xs : Array α} {k : Nat} : (xs.zipIdx k).size = xs.size := + Array.size_mapFinIdx @[deprecated size_zipIdx (since := "2025-01-21")] abbrev size_zipWithIndex := @size_zipIdx -@[simp] theorem getElem_mapFinIdx (xs : Array α) (f : (i : Nat) → α → (h : i < xs.size) → β) (i : Nat) +@[simp] theorem getElem_mapFinIdx {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} {i : Nat} (h : i < (xs.mapFinIdx f).size) : (xs.mapFinIdx f)[i] = f i (xs[i]'(by simp_all)) (by simp_all) := - (mapFinIdx_spec _ _ (fun i b h => b = f i xs[i] h) fun _ _ => rfl).2 i _ + (mapFinIdx_spec (p := fun i b h => b = f i xs[i] h) fun _ _ => rfl).2 i _ -@[simp] theorem getElem?_mapFinIdx (xs : Array α) (f : (i : Nat) → α → (h : i < xs.size) → β) (i : Nat) : +@[simp] theorem getElem?_mapFinIdx {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} {i : Nat} : (xs.mapFinIdx f)[i]? = xs[i]?.pbind fun b h => f i b (getElem?_eq_some_iff.1 h).1 := by simp only [getElem?_def, size_mapFinIdx, getElem_mapFinIdx] split <;> simp_all -@[simp] theorem toList_mapFinIdx (xs : Array α) (f : (i : Nat) → α → (h : i < xs.size) → β) : +@[simp] theorem toList_mapFinIdx {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} : (xs.mapFinIdx f).toList = xs.toList.mapFinIdx (fun i a h => f i a (by simpa)) := by apply List.ext_getElem <;> simp /-! ### mapIdx -/ -theorem mapIdx_induction (f : Nat → α → β) (xs : Array α) - (motive : Nat → Prop) (h0 : motive 0) - (p : (i : Nat) → β → (h : i < xs.size) → Prop) +theorem mapIdx_induction {f : Nat → α → β} {xs : Array α} + {motive : Nat → Prop} (h0 : motive 0) + {p : (i : Nat) → β → (h : i < xs.size) → Prop} (hs : ∀ i h, motive i → p i (f i xs[i]) h ∧ motive (i + 1)) : motive xs.size ∧ ∃ eq : (xs.mapIdx f).size = xs.size, ∀ i h, p i ((xs.mapIdx f)[i]) h := mapFinIdx_induction xs (fun i a _ => f i a) motive h0 p hs -theorem mapIdx_spec (f : Nat → α → β) (xs : Array α) - (p : (i : Nat) → β → (h : i < xs.size) → Prop) (hs : ∀ i h, p i (f i xs[i]) h) : +theorem mapIdx_spec {f : Nat → α → β} {xs : Array α} + {p : (i : Nat) → β → (h : i < xs.size) → Prop} (hs : ∀ i h, p i (f i xs[i]) h) : ∃ eq : (xs.mapIdx f).size = xs.size, ∀ i h, p i ((xs.mapIdx f)[i]) h := - (mapIdx_induction _ _ (fun _ => True) trivial p fun _ _ _ => ⟨hs .., trivial⟩).2 + (mapIdx_induction (motive := fun _ => True) trivial fun _ _ _ => ⟨hs .., trivial⟩).2 -@[simp] theorem size_mapIdx (f : Nat → α → β) (xs : Array α) : (xs.mapIdx f).size = xs.size := +@[simp] theorem size_mapIdx {f : Nat → α → β} {xs : Array α} : (xs.mapIdx f).size = xs.size := (mapIdx_spec (p := fun _ _ _ => True) (hs := fun _ _ => trivial)).1 -@[simp] theorem getElem_mapIdx (f : Nat → α → β) (xs : Array α) (i : Nat) +@[simp] theorem getElem_mapIdx {f : Nat → α → β} {xs : Array α} {i : Nat} (h : i < (xs.mapIdx f).size) : (xs.mapIdx f)[i] = f i (xs[i]'(by simp_all)) := - (mapIdx_spec _ _ (fun i b h => b = f i xs[i]) fun _ _ => rfl).2 i (by simp_all) + (mapIdx_spec (p := fun i b h => b = f i xs[i]) fun _ _ => rfl).2 i (by simp_all) -@[simp] theorem getElem?_mapIdx (f : Nat → α → β) (xs : Array α) (i : Nat) : +@[simp] theorem getElem?_mapIdx {f : Nat → α → β} {xs : Array α} {i : Nat} : (xs.mapIdx f)[i]? = xs[i]?.map (f i) := by simp [getElem?_def, size_mapIdx, getElem_mapIdx] -@[simp] theorem toList_mapIdx (f : Nat → α → β) (xs : Array α) : +@[simp] theorem toList_mapIdx {f : Nat → α → β} {xs : Array α} : (xs.mapIdx f).toList = xs.toList.mapIdx (fun i a => f i a) := by apply List.ext_getElem <;> simp @@ -109,11 +109,11 @@ end Array namespace List -@[simp] theorem mapFinIdx_toArray (l : List α) (f : (i : Nat) → α → (h : i < l.length) → β) : +@[simp] theorem mapFinIdx_toArray {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} : l.toArray.mapFinIdx f = (l.mapFinIdx f).toArray := by ext <;> simp -@[simp] theorem mapIdx_toArray (f : Nat → α → β) (l : List α) : +@[simp] theorem mapIdx_toArray {f : Nat → α → β} {l : List α} : l.toArray.mapIdx f = (l.mapIdx f).toArray := by ext <;> simp @@ -123,7 +123,7 @@ namespace Array /-! ### zipIdx -/ -@[simp] theorem getElem_zipIdx (xs : Array α) (k : Nat) (i : Nat) (h : i < (xs.zipIdx k).size) : +@[simp] theorem getElem_zipIdx {xs : Array α} {k : Nat} {i : Nat} (h : i < (xs.zipIdx k).size) : (xs.zipIdx k)[i] = (xs[i]'(by simp_all), k + i) := by simp [zipIdx] @@ -137,7 +137,7 @@ abbrev getElem_zipWithIndex := @getElem_zipIdx @[deprecated zipIdx_toArray (since := "2025-01-21")] abbrev zipWithIndex_toArray := @zipIdx_toArray -@[simp] theorem toList_zipIdx (xs : Array α) (k : Nat) : +@[simp] theorem toList_zipIdx {xs : Array α} {k : Nat} : (xs.zipIdx k).toList = xs.toList.zipIdx k := by rcases xs with ⟨xs⟩ simp @@ -452,8 +452,8 @@ end Array namespace List -theorem mapFinIdxM_toArray [Monad m] [LawfulMonad m] (l : List α) - (f : (i : Nat) → α → (h : i < l.length) → m β) : +theorem mapFinIdxM_toArray [Monad m] [LawfulMonad m] {l : List α} + {f : (i : Nat) → α → (h : i < l.length) → m β} : l.toArray.mapFinIdxM f = toArray <$> l.mapFinIdxM f := by let rec go (i : Nat) (acc : Array β) (inv : i + acc.size = l.length) : Array.mapFinIdxM.map l.toArray f i acc.size inv acc @@ -464,17 +464,17 @@ theorem mapFinIdxM_toArray [Monad m] [LawfulMonad m] (l : List α) rw [Nat.zero_add] at inv simp only [Array.mapFinIdxM.map, inv, drop_length, mapFinIdxM.go, map_pure] | k + 1 => - conv => enter [2, 2, 3]; rw [← getElem_cons_drop l acc.size (by omega)] + conv => enter [2, 2, 3]; rw [← getElem_cons_drop (by omega)] simp only [Array.mapFinIdxM.map, mapFinIdxM.go, _root_.map_bind] congr; funext x - conv => enter [1, 4]; rw [← Array.size_push _ x] - conv => enter [2, 2, 3]; rw [← Array.size_push _ x] + conv => enter [1, 4]; rw [← Array.size_push x] + conv => enter [2, 2, 3]; rw [← Array.size_push x] refine go k (acc.push x) _ simp only [Array.mapFinIdxM, mapFinIdxM] exact go _ #[] _ -theorem mapIdxM_toArray [Monad m] [LawfulMonad m] (l : List α) - (f : Nat → α → m β) : +theorem mapIdxM_toArray [Monad m] [LawfulMonad m] {l : List α} + {f : Nat → α → m β} : l.toArray.mapIdxM f = toArray <$> l.mapIdxM f := by let rec go (bs : List α) (acc : Array β) (inv : bs.length + acc.size = l.length) : mapFinIdxM.go l (fun i a h => f i a) bs acc inv = mapIdxM.go f bs acc := by @@ -490,14 +490,14 @@ end List namespace Array -theorem toList_mapFinIdxM [Monad m] [LawfulMonad m] (xs : Array α) - (f : (i : Nat) → α → (h : i < xs.size) → m β) : +theorem toList_mapFinIdxM [Monad m] [LawfulMonad m] {xs : Array α} + {f : (i : Nat) → α → (h : i < xs.size) → m β} : toList <$> xs.mapFinIdxM f = xs.toList.mapFinIdxM f := by rw [List.mapFinIdxM_toArray] simp only [Functor.map_map, id_map'] -theorem toList_mapIdxM [Monad m] [LawfulMonad m] (xs : Array α) - (f : Nat → α → m β) : +theorem toList_mapIdxM [Monad m] [LawfulMonad m] {xs : Array α} + {f : Nat → α → m β} : toList <$> xs.mapIdxM f = xs.toList.mapIdxM f := by rw [List.mapIdxM_toArray] simp only [Functor.map_map, id_map'] diff --git a/src/Init/Data/Array/Monadic.lean b/src/Init/Data/Array/Monadic.lean index 92a3504f79..e647e682d6 100644 --- a/src/Init/Data/Array/Monadic.lean +++ b/src/Init/Data/Array/Monadic.lean @@ -23,20 +23,20 @@ open Nat /-! ### mapM -/ -@[simp] theorem mapM_pure [Monad m] [LawfulMonad m] (xs : Array α) (f : α → β) : +@[simp] theorem mapM_pure [Monad m] [LawfulMonad m] {xs : Array α} {f : α → β} : xs.mapM (m := m) (pure <| f ·) = pure (xs.map f) := by induction xs; simp_all @[simp] theorem mapM_id {xs : Array α} {f : α → Id β} : xs.mapM f = xs.map f := - mapM_pure _ _ + mapM_pure -@[simp] theorem mapM_append [Monad m] [LawfulMonad m] (f : α → m β) {xs ys : Array α} : +@[simp] theorem mapM_append [Monad m] [LawfulMonad m] {f : α → m β} {xs ys : Array α} : (xs ++ ys).mapM f = (return (← xs.mapM f) ++ (← ys.mapM f)) := by rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ simp -theorem mapM_eq_foldlM_push [Monad m] [LawfulMonad m] (f : α → m β) (xs : Array α) : +theorem mapM_eq_foldlM_push [Monad m] [LawfulMonad m] {f : α → m β} {xs : Array α} : mapM f xs = xs.foldlM (fun acc a => return (acc.push (← f a))) #[] := by rcases xs with ⟨xs⟩ simp only [List.mapM_toArray, bind_pure_comp, List.size_toArray, List.foldlM_toArray'] @@ -53,21 +53,21 @@ theorem mapM_eq_foldlM_push [Monad m] [LawfulMonad m] (f : α → m β) (xs : Ar /-! ### foldlM and foldrM -/ -theorem foldlM_map [Monad m] (f : β₁ → β₂) (g : α → β₂ → m α) (xs : Array β₁) (init : α) (w : stop = xs.size) : +theorem foldlM_map [Monad m] {f : β₁ → β₂} {g : α → β₂ → m α} {xs : Array β₁} {init : α} {w : stop = xs.size} : (xs.map f).foldlM g init 0 stop = xs.foldlM (fun x y => g x (f y)) init 0 stop := by subst w cases xs simp [List.foldlM_map] -theorem foldrM_map [Monad m] [LawfulMonad m] (f : β₁ → β₂) (g : β₂ → α → m α) (xs : Array β₁) - (init : α) (w : start = xs.size) : +theorem foldrM_map [Monad m] [LawfulMonad m] {f : β₁ → β₂} {g : β₂ → α → m α} {xs : Array β₁} + {init : α} {w : start = xs.size} : (xs.map f).foldrM g init start 0 = xs.foldrM (fun x y => g (f x) y) init start 0 := by subst w cases xs simp [List.foldrM_map] -theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : γ → β → m γ) - (xs : Array α) (init : γ) (w : stop = (xs.filterMap f).size) : +theorem foldlM_filterMap [Monad m] [LawfulMonad m] {f : α → Option β} {g : γ → β → m γ} {xs : Array α} + {init : γ} {w : stop = (xs.filterMap f).size} : (xs.filterMap f).foldlM g init 0 stop = xs.foldlM (fun x y => match f y with | some b => g x b | none => pure x) init := by subst w @@ -75,8 +75,8 @@ theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : simp [List.foldlM_filterMap] rfl -theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : β → γ → m γ) - (xs : Array α) (init : γ) (w : start = (xs.filterMap f).size) : +theorem foldrM_filterMap [Monad m] [LawfulMonad m] {f : α → Option β} {g : β → γ → m γ} {xs : Array α} + {init : γ} {w : start = (xs.filterMap f).size} : (xs.filterMap f).foldrM g init start 0 = xs.foldrM (fun x y => match f x with | some b => g b y | none => pure y) init := by subst w @@ -84,16 +84,16 @@ theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : simp [List.foldrM_filterMap] rfl -theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : β → α → m β) - (xs : Array α) (init : β) (w : stop = (xs.filter p).size) : +theorem foldlM_filter [Monad m] [LawfulMonad m] {p : α → Bool} {g : β → α → m β} {xs : Array α} + {init : β} {w : stop = (xs.filter p).size} : (xs.filter p).foldlM g init 0 stop = xs.foldlM (fun x y => if p y then g x y else pure x) init := by subst w cases xs simp [List.foldlM_filter] -theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β → m β) - (xs : Array α) (init : β) (w : start = (xs.filter p).size) : +theorem foldrM_filter [Monad m] [LawfulMonad m] {p : α → Bool} {g : α → β → m β} {xs : Array α} + {init : β} {w : start = (xs.filter p).size} : (xs.filter p).foldrM g init start 0 = xs.foldrM (fun x y => if p x then g x y else pure y) init := by subst w @@ -101,7 +101,7 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β simp [List.foldrM_filter] @[simp] theorem foldlM_attachWith [Monad m] - (xs : Array α) {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : β → { x // q x} → m β} {b} (w : stop = xs.size): + {xs : Array α} {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : β → { x // q x} → m β} {b} (w : stop = xs.size): (xs.attachWith q H).foldlM f b 0 stop = xs.attach.foldlM (fun b ⟨a, h⟩ => f b ⟨a, H _ h⟩) b := by subst w @@ -109,7 +109,8 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β simp [List.foldlM_map] @[simp] theorem foldrM_attachWith [Monad m] [LawfulMonad m] - (xs : Array α) {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : { x // q x} → β → m β} {b} (w : start = xs.size): + {xs : Array α} {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : { x // q x} → β → m β} {b} + {w : start = xs.size} : (xs.attachWith q H).foldrM f b start 0 = xs.attach.foldrM (fun a acc => f ⟨a.1, H _ a.2⟩ acc) b := by subst w @@ -124,13 +125,13 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β cases as <;> cases bs simp_all -@[simp] theorem forM_append [Monad m] [LawfulMonad m] (xs ys : Array α) (f : α → m PUnit) : +@[simp] theorem forM_append [Monad m] [LawfulMonad m] {xs ys : Array α} {f : α → m PUnit} : forM (xs ++ ys) f = (do forM xs f; forM ys f) := by rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ simp -@[simp] theorem forM_map [Monad m] [LawfulMonad m] (xs : Array α) (g : α → β) (f : β → m PUnit) : +@[simp] theorem forM_map [Monad m] [LawfulMonad m] {xs : Array α} {g : α → β} {f : β → m PUnit} : forM (xs.map g) f = forM xs (fun a => f (g a)) := by rcases xs with ⟨xs⟩ simp @@ -152,7 +153,7 @@ We can express a for loop over an array as a fold, in which whenever we reach `.done b` we keep that value through the rest of the fold. -/ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m] - (xs : Array α) (f : (a : α) → a ∈ xs → β → m (ForInStep β)) (init : β) : + {xs : Array α} (f : (a : α) → a ∈ xs → β → m (ForInStep β)) (init : β) : forIn' xs init f = ForInStep.value <$> xs.attach.foldlM (fun b ⟨a, m⟩ => match b with | .yield b => f a m b @@ -163,29 +164,29 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m] /-- We can express a for loop over an array which always yields as a fold. -/ @[simp] theorem forIn'_yield_eq_foldlM [Monad m] [LawfulMonad m] - (xs : Array α) (f : (a : α) → a ∈ xs → β → m γ) (g : (a : α) → a ∈ xs → β → γ → β) (init : β) : + {xs : Array α} (f : (a : α) → a ∈ xs → β → m γ) (g : (a : α) → a ∈ xs → β → γ → β) (init : β) : forIn' xs init (fun a m b => (fun c => .yield (g a m b c)) <$> f a m b) = xs.attach.foldlM (fun b ⟨a, m⟩ => g a m b <$> f a m b) init := by rcases xs with ⟨xs⟩ simp [List.foldlM_map] @[simp] theorem forIn'_pure_yield_eq_foldl [Monad m] [LawfulMonad m] - (xs : Array α) (f : (a : α) → a ∈ xs → β → β) (init : β) : + {xs : Array α} (f : (a : α) → a ∈ xs → β → β) (init : β) : forIn' xs init (fun a m b => pure (.yield (f a m b))) = pure (f := m) (xs.attach.foldl (fun b ⟨a, h⟩ => f a h b) init) := by rcases xs with ⟨xs⟩ simp [List.forIn'_pure_yield_eq_foldl, List.foldl_map] @[simp] theorem forIn'_yield_eq_foldl - (xs : Array α) (f : (a : α) → a ∈ xs → β → β) (init : β) : + {xs : Array α} (f : (a : α) → a ∈ xs → β → β) (init : β) : forIn' (m := Id) xs init (fun a m b => .yield (f a m b)) = xs.attach.foldl (fun b ⟨a, h⟩ => f a h b) init := by rcases xs with ⟨xs⟩ simp [List.foldl_map] @[simp] theorem forIn'_map [Monad m] [LawfulMonad m] - (xs : Array α) (g : α → β) (f : (b : β) → b ∈ xs.map g → γ → m (ForInStep γ)) : - forIn' (xs.map g) init f = forIn' xs init fun a h y => f (g a) (mem_map_of_mem g h) y := by + {xs : Array α} (g : α → β) (f : (b : β) → b ∈ xs.map g → γ → m (ForInStep γ)) : + forIn' (xs.map g) init f = forIn' xs init fun a h y => f (g a) (mem_map_of_mem h) y := by rcases xs with ⟨xs⟩ simp @@ -194,7 +195,7 @@ We can express a for loop over an array as a fold, in which whenever we reach `.done b` we keep that value through the rest of the fold. -/ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m] - (f : α → β → m (ForInStep β)) (init : β) (xs : Array α) : + {xs : Array α} (f : α → β → m (ForInStep β)) (init : β) : forIn xs init f = ForInStep.value <$> xs.foldlM (fun b a => match b with | .yield b => f a b @@ -205,40 +206,40 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m] /-- We can express a for loop over an array which always yields as a fold. -/ @[simp] theorem forIn_yield_eq_foldlM [Monad m] [LawfulMonad m] - (xs : Array α) (f : α → β → m γ) (g : α → β → γ → β) (init : β) : + {xs : Array α} (f : α → β → m γ) (g : α → β → γ → β) (init : β) : forIn xs init (fun a b => (fun c => .yield (g a b c)) <$> f a b) = xs.foldlM (fun b a => g a b <$> f a b) init := by rcases xs with ⟨xs⟩ simp [List.foldlM_map] @[simp] theorem forIn_pure_yield_eq_foldl [Monad m] [LawfulMonad m] - (xs : Array α) (f : α → β → β) (init : β) : + {xs : Array α} (f : α → β → β) (init : β) : forIn xs init (fun a b => pure (.yield (f a b))) = pure (f := m) (xs.foldl (fun b a => f a b) init) := by rcases xs with ⟨xs⟩ simp [List.forIn_pure_yield_eq_foldl, List.foldl_map] @[simp] theorem forIn_yield_eq_foldl - (xs : Array α) (f : α → β → β) (init : β) : + {xs : Array α} (f : α → β → β) (init : β) : forIn (m := Id) xs init (fun a b => .yield (f a b)) = xs.foldl (fun b a => f a b) init := by rcases xs with ⟨xs⟩ simp [List.foldl_map] @[simp] theorem forIn_map [Monad m] [LawfulMonad m] - (xs : Array α) (g : α → β) (f : β → γ → m (ForInStep γ)) : + {xs : Array α} {g : α → β} {f : β → γ → m (ForInStep γ)} : forIn (xs.map g) init f = forIn xs init fun a y => f (g a) y := by rcases xs with ⟨xs⟩ simp /-! ### allM and anyM -/ -@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] (p : α → Bool) (xs : Array α) : +@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] {p : α → Bool} {xs : Array α} : xs.anyM (m := m) (pure <| p ·) = pure (xs.any p) := by cases xs simp -@[simp] theorem allM_pure [Monad m] [LawfulMonad m] (p : α → Bool) (xs : Array α) : +@[simp] theorem allM_pure [Monad m] [LawfulMonad m] {p : α → Bool} {xs : Array α} : xs.allM (m := m) (pure <| p ·) = pure (xs.all p) := by cases xs simp @@ -246,13 +247,13 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m] /-! ### findM? and findSomeM? -/ @[simp] -theorem findM?_pure {m} [Monad m] [LawfulMonad m] (p : α → Bool) (xs : Array α) : +theorem findM?_pure {m} [Monad m] [LawfulMonad m] {p : α → Bool} {xs : Array α} : findM? (m := m) (pure <| p ·) xs = pure (xs.find? p) := by cases xs simp @[simp] -theorem findSomeM?_pure [Monad m] [LawfulMonad m] (f : α → Option β) (xs : Array α) : +theorem findSomeM?_pure [Monad m] [LawfulMonad m] {f : α → Option β} {xs : Array α} : findSomeM? (m := m) (pure <| f ·) xs = pure (xs.findSome? f) := by cases xs simp @@ -261,7 +262,7 @@ end Array namespace List -theorem filterM_toArray [Monad m] [LawfulMonad m] (l : List α) (p : α → m Bool) : +theorem filterM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} : l.toArray.filterM p = toArray <$> l.filterM p := by simp only [Array.filterM, filterM, foldlM_toArray, bind_pure_comp, Functor.map_map] conv => lhs; rw [← reverse_nil] @@ -276,24 +277,24 @@ theorem filterM_toArray [Monad m] [LawfulMonad m] (l : List α) (p : α → m Bo exact ih (x :: acc) /-- Variant of `filterM_toArray` with a side condition for the stop position. -/ -@[simp] theorem filterM_toArray' [Monad m] [LawfulMonad m] (l : List α) (p : α → m Bool) (w : stop = l.length) : +@[simp] theorem filterM_toArray' [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} (w : stop = l.length) : l.toArray.filterM p 0 stop = toArray <$> l.filterM p := by subst w rw [filterM_toArray] -theorem filterRevM_toArray [Monad m] [LawfulMonad m] (l : List α) (p : α → m Bool) : +theorem filterRevM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} : l.toArray.filterRevM p = toArray <$> l.filterRevM p := by simp [Array.filterRevM, filterRevM] rw [← foldlM_reverse, ← foldlM_toArray, ← Array.filterM, filterM_toArray] simp only [filterM, bind_pure_comp, Functor.map_map, reverse_toArray, reverse_reverse] /-- Variant of `filterRevM_toArray` with a side condition for the start position. -/ -@[simp] theorem filterRevM_toArray' [Monad m] [LawfulMonad m] (l : List α) (p : α → m Bool) (w : start = l.length) : +@[simp] theorem filterRevM_toArray' [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} (w : start = l.length) : l.toArray.filterRevM p start 0 = toArray <$> l.filterRevM p := by subst w rw [filterRevM_toArray] -theorem filterMapM_toArray [Monad m] [LawfulMonad m] (l : List α) (f : α → m (Option β)) : +theorem filterMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α → m (Option β)} : l.toArray.filterMapM f = toArray <$> l.filterMapM f := by simp [Array.filterMapM, filterMapM] conv => lhs; rw [← reverse_nil] @@ -306,12 +307,12 @@ theorem filterMapM_toArray [Monad m] [LawfulMonad m] (l : List α) (f : α → m · simp only [pure_bind]; rw [← List.reverse_cons]; exact ih _ /-- Variant of `filterMapM_toArray` with a side condition for the stop position. -/ -@[simp] theorem filterMapM_toArray' [Monad m] [LawfulMonad m] (l : List α) (f : α → m (Option β)) (w : stop = l.length) : +@[simp] theorem filterMapM_toArray' [Monad m] [LawfulMonad m] {l : List α} {f : α → m (Option β)} (w : stop = l.length) : l.toArray.filterMapM f 0 stop = toArray <$> l.filterMapM f := by subst w rw [filterMapM_toArray] -@[simp] theorem flatMapM_toArray [Monad m] [LawfulMonad m] (l : List α) (f : α → m (Array β)) : +@[simp] theorem flatMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α → m (Array β)} : l.toArray.flatMapM f = toArray <$> l.flatMapM (fun a => Array.toList <$> f a) := by simp only [Array.flatMapM, bind_pure_comp, foldlM_toArray, flatMapM] conv => lhs; arg 2; change [].reverse.flatten.toArray @@ -352,22 +353,22 @@ namespace Array subst w simp [flatMapM, h] -theorem toList_filterM [Monad m] [LawfulMonad m] (xs : Array α) (p : α → m Bool) : +theorem toList_filterM [Monad m] [LawfulMonad m] {xs : Array α} {p : α → m Bool} : toList <$> xs.filterM p = xs.toList.filterM p := by rw [List.filterM_toArray] simp only [Functor.map_map, id_map'] -theorem toList_filterRevM [Monad m] [LawfulMonad m] (xs : Array α) (p : α → m Bool) : +theorem toList_filterRevM [Monad m] [LawfulMonad m] {xs : Array α} {p : α → m Bool} : toList <$> xs.filterRevM p = xs.toList.filterRevM p := by rw [List.filterRevM_toArray] simp only [Functor.map_map, id_map'] -theorem toList_filterMapM [Monad m] [LawfulMonad m] (xs : Array α) (f : α → m (Option β)) : +theorem toList_filterMapM [Monad m] [LawfulMonad m] {xs : Array α} {f : α → m (Option β)} : toList <$> xs.filterMapM f = xs.toList.filterMapM f := by rw [List.filterMapM_toArray] simp only [Functor.map_map, id_map'] -theorem toList_flatMapM [Monad m] [LawfulMonad m] (xs : Array α) (f : α → m (Array β)) : +theorem toList_flatMapM [Monad m] [LawfulMonad m] {xs : Array α} {f : α → m (Array β)} : toList <$> xs.flatMapM f = xs.toList.flatMapM (fun a => toList <$> f a) := by rw [List.flatMapM_toArray] simp only [Functor.map_map, id_map'] @@ -387,11 +388,11 @@ and simplifies these to the function directly taking the value. simp rw [List.foldlM_subtype hf] -@[wf_preprocess] theorem foldlM_wfParam [Monad m] (xs : Array α) (f : β → α → m β) (init : β) : +@[wf_preprocess] theorem foldlM_wfParam [Monad m] {xs : Array α} {f : β → α → m β} {init : β} : (wfParam xs).foldlM f init = xs.attach.unattach.foldlM f init := by simp [wfParam] -@[wf_preprocess] theorem foldlM_unattach [Monad m] (P : α → Prop) (xs : Array (Subtype P)) (f : β → α → m β) (init : β) : +@[wf_preprocess] theorem foldlM_unattach [Monad m] {P : α → Prop} {xs : Array (Subtype P)} {f : β → α → m β} {init : β} : xs.unattach.foldlM f init = xs.foldlM (init := init) fun b ⟨x, h⟩ => binderNameHint b f <| binderNameHint x (f b) <| binderNameHint h () <| f b (wfParam x) := by @@ -411,11 +412,11 @@ and simplifies these to the function directly taking the value. rw [List.foldrM_subtype hf] -@[wf_preprocess] theorem foldrM_wfParam [Monad m] [LawfulMonad m] (xs : Array α) (f : α → β → m β) (init : β) : +@[wf_preprocess] theorem foldrM_wfParam [Monad m] [LawfulMonad m] {xs : Array α} {f : α → β → m β} {init : β} : (wfParam xs).foldrM f init = xs.attach.unattach.foldrM f init := by simp [wfParam] -@[wf_preprocess] theorem foldrM_unattach [Monad m] [LawfulMonad m] (P : α → Prop) (xs : Array (Subtype P)) (f : α → β → m β) (init : β): +@[wf_preprocess] theorem foldrM_unattach [Monad m] [LawfulMonad m] {P : α → Prop} {xs : Array (Subtype P)} {f : α → β → m β} {init : β} : xs.unattach.foldrM f init = xs.foldrM (init := init) fun ⟨x, h⟩ b => binderNameHint x f <| binderNameHint h () <| binderNameHint b (f x) <| f (wfParam x) b := by @@ -432,11 +433,11 @@ and simplifies these to the function directly taking the value. simp rw [List.mapM_subtype hf] -@[wf_preprocess] theorem mapM_wfParam [Monad m] [LawfulMonad m] (xs : Array α) (f : α → m β) : +@[wf_preprocess] theorem mapM_wfParam [Monad m] [LawfulMonad m] {xs : Array α} {f : α → m β} : (wfParam xs).mapM f = xs.attach.unattach.mapM f := by simp [wfParam] -@[wf_preprocess] theorem mapM_unattach [Monad m] [LawfulMonad m] (P : α → Prop) (xs : Array (Subtype P)) (f : α → m β) : +@[wf_preprocess] theorem mapM_unattach [Monad m] [LawfulMonad m] {P : α → Prop} {xs : Array (Subtype P)} {f : α → m β} : xs.unattach.mapM f = xs.mapM fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] @@ -451,12 +452,12 @@ and simplifies these to the function directly taking the value. @[wf_preprocess] theorem filterMapM_wfParam [Monad m] [LawfulMonad m] - (xs : Array α) (f : α → m (Option β)) : + {xs : Array α} {f : α → m (Option β)} : (wfParam xs).filterMapM f = xs.attach.unattach.filterMapM f := by simp [wfParam] @[wf_preprocess] theorem filterMapM_unattach [Monad m] [LawfulMonad m] - (P : α → Prop) (xs : Array (Subtype P)) (f : α → m (Option β)) : + {P : α → Prop} {xs : Array (Subtype P)} {f : α → m (Option β)} : xs.unattach.filterMapM f = xs.filterMapM fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] @@ -470,12 +471,12 @@ and simplifies these to the function directly taking the value. simp [hf] @[wf_preprocess] theorem flatMapM_wfParam [Monad m] [LawfulMonad m] - (xs : Array α) (f : α → m (Array β)) : + {xs : Array α} {f : α → m (Array β)} : (wfParam xs).flatMapM f = xs.attach.unattach.flatMapM f := by simp [wfParam] @[wf_preprocess] theorem flatMapM_unattach [Monad m] [LawfulMonad m] - (P : α → Prop) (xs : Array (Subtype P)) (f : α → m (Array β)) : + {P : α → Prop} {xs : Array (Subtype P)} {f : α → m (Array β)} : xs.unattach.flatMapM f = xs.flatMapM fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] diff --git a/src/Init/Data/Array/OfFn.lean b/src/Init/Data/Array/OfFn.lean index fc46829ef5..d701487f2b 100644 --- a/src/Init/Data/Array/OfFn.lean +++ b/src/Init/Data/Array/OfFn.lean @@ -16,10 +16,10 @@ set_option linter.indexVariables true -- Enforce naming conventions for index va namespace Array -@[simp] theorem ofFn_zero (f : Fin 0 → α) : ofFn f = #[] := by +@[simp] theorem ofFn_zero {f : Fin 0 → α} : ofFn f = #[] := by simp [ofFn, ofFn.go] -theorem ofFn_succ (f : Fin (n+1) → α) : +theorem ofFn_succ {f : Fin (n+1) → α} : ofFn f = (ofFn (fun (i : Fin n) => f i.castSucc)).push (f ⟨n, by omega⟩) := by ext i h₁ h₂ · simp @@ -30,10 +30,10 @@ theorem ofFn_succ (f : Fin (n+1) → α) : simp at h₁ h₂ omega -@[simp] theorem _rooy_.List.toArray_ofFn (f : Fin n → α) : (List.ofFn f).toArray = Array.ofFn f := by +@[simp] theorem _root_.List.toArray_ofFn {f : Fin n → α} : (List.ofFn f).toArray = Array.ofFn f := by ext <;> simp -@[simp] theorem toList_ofFn (f : Fin n → α) : (Array.ofFn f).toList = List.ofFn f := by +@[simp] theorem toList_ofFn {f : Fin n → α} : (Array.ofFn f).toList = List.ofFn f := by apply List.ext_getElem <;> simp @[simp] @@ -42,7 +42,7 @@ theorem ofFn_eq_empty_iff {f : Fin n → α} : ofFn f = #[] ↔ n = 0 := by simp @[simp 500] -theorem mem_ofFn {n} (f : Fin n → α) (a : α) : a ∈ ofFn f ↔ ∃ i, f i = a := by +theorem mem_ofFn {n} {f : Fin n → α} {a : α} : a ∈ ofFn f ↔ ∃ i, f i = a := by constructor · intro w obtain ⟨i, h, rfl⟩ := getElem_of_mem w diff --git a/src/Init/Data/Array/Range.lean b/src/Init/Data/Array/Range.lean index 4b033d3596..c75143fc88 100644 --- a/src/Init/Data/Array/Range.lean +++ b/src/Init/Data/Array/Range.lean @@ -26,14 +26,14 @@ open Nat /-! ### range' -/ -theorem range'_succ (s n step) : range' s (n + 1) step = #[s] ++ range' (s + step) n step := by +theorem range'_succ {s n step} : range' s (n + 1) step = #[s] ++ range' (s + step) n step := by rw [← toList_inj] simp [List.range'_succ] @[simp] theorem range'_eq_empty_iff : range' s n step = #[] ↔ n = 0 := by rw [← size_eq_zero_iff, size_range'] -theorem range'_ne_empty_iff (s : Nat) {n step : Nat} : range' s n step ≠ #[] ↔ n ≠ 0 := by +theorem range'_ne_empty_iff : range' s n step ≠ #[] ↔ n ≠ 0 := by cases n <;> simp @[simp] theorem range'_zero : range' s 0 step = #[] := by @@ -57,13 +57,13 @@ theorem mem_range' {n} : m ∈ range' s n step ↔ ∃ i < n, m = s + step * i : theorem pop_range' : (range' s n step).pop = range' s (n - 1) step := by ext <;> simp -theorem map_add_range' (a) (s n step) : map (a + ·) (range' s n step) = range' (a + s) n step := by +theorem map_add_range' {a} (s n step) : map (a + ·) (range' s n step) = range' (a + s) n step := by ext <;> simp <;> omega theorem range'_succ_left : range' (s + 1) n step = (range' s n step).map (· + 1) := by ext <;> simp <;> omega -theorem range'_append (s m n step : Nat) : +theorem range'_append {s m n step : Nat} : range' s m step ++ range' (s + step * m) n step = range' s (m + n) step := by ext i h₁ h₂ · simp @@ -74,13 +74,13 @@ theorem range'_append (s m n step : Nat) : have : step * m ≤ step * i := by exact mul_le_mul_left step h omega -@[simp] theorem range'_append_1 (s m n : Nat) : - range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append s m n 1 +@[simp] theorem range'_append_1 {s m n : Nat} : + range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append (step := 1) -theorem range'_concat (s n : Nat) : range' s (n + 1) step = range' s n step ++ #[s + step * n] := by - simpa using (range'_append s n 1 step).symm +theorem range'_concat {s n : Nat} : range' s (n + 1) step = range' s n step ++ #[s + step * n] := by + simpa using range'_append.symm -theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ #[s + n] := by +theorem range'_1_concat {s n : Nat} : range' s (n + 1) = range' s n ++ #[s + n] := by simp [range'_concat] @[simp] theorem mem_range'_1 : m ∈ range' s n ↔ s ≤ m ∧ m < s + n := by @@ -88,7 +88,7 @@ theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ #[s + n] fun ⟨i, h, e⟩ => e ▸ ⟨Nat.le_add_right .., Nat.add_lt_add_left h _⟩, fun ⟨h₁, h₂⟩ => ⟨m - s, Nat.sub_lt_left_of_lt_add h₁ h₂, (Nat.add_sub_cancel' h₁).symm⟩⟩ -theorem map_sub_range' (a s n : Nat) (h : a ≤ s) : +theorem map_sub_range' {a s n : Nat} (h : a ≤ s) : map (· - a) (range' s n step) = range' (s - a) n step := by conv => lhs; rw [← Nat.add_sub_cancel' h] rw [← map_add_range', map_map, (?_ : _∘_ = _), map_id] @@ -121,10 +121,10 @@ theorem erase_range' : /-! ### range -/ -theorem range_eq_range' (n : Nat) : range n = range' 0 n := by +theorem range_eq_range' {n : Nat} : range n = range' 0 n := by simp [range, range'] -theorem range_succ_eq_map (n : Nat) : range (n + 1) = #[0] ++ map succ (range n) := by +theorem range_succ_eq_map {n : Nat} : range (n + 1) = #[0] ++ map succ (range n) := by ext i h₁ h₂ · simp omega @@ -133,7 +133,7 @@ theorem range_succ_eq_map (n : Nat) : range (n + 1) = #[0] ++ map succ (range n) succ_eq_add_one, dite_eq_ite] split <;> omega -theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) := by +theorem range'_eq_map_range {s n : Nat} : range' s n = map (s + ·) (range n) := by rw [range_eq_range', map_add_range']; rfl @[simp] theorem range_eq_empty_iff {n : Nat} : range n = #[] ↔ n = 0 := by @@ -142,7 +142,7 @@ theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) := theorem range_ne_empty_iff {n : Nat} : range n ≠ #[] ↔ n ≠ 0 := by cases n <;> simp -theorem range_succ (n : Nat) : range (succ n) = range n ++ #[n] := by +theorem range_succ {n : Nat} : range (succ n) = range n ++ #[n] := by ext i h₁ h₂ · simp · simp only [succ_eq_add_one, size_range] at h₁ @@ -150,11 +150,11 @@ theorem range_succ (n : Nat) : range (succ n) = range n ++ #[n] := by dite_eq_ite] split <;> omega -theorem range_add (n m : Nat) : range (n + m) = range n ++ (range m).map (n + ·) := by +theorem range_add {n m : Nat} : range (n + m) = range n ++ (range m).map (n + ·) := by rw [← range'_eq_map_range] - simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 n m).symm + simpa [range_eq_range', Nat.add_comm] using (range'_append_1 (s := 0)).symm -theorem reverse_range' (s n : Nat) : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by +theorem reverse_range' {s n : Nat} : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by simp [← toList_inj, List.reverse_range'] @[simp] @@ -163,9 +163,9 @@ theorem mem_range {m n : Nat} : m ∈ range n ↔ m < n := by theorem not_mem_range_self {n : Nat} : n ∉ range n := by simp -theorem self_mem_range_succ (n : Nat) : n ∈ range (n + 1) := by simp +theorem self_mem_range_succ {n : Nat} : n ∈ range (n + 1) := by simp -@[simp] theorem take_range (i n : Nat) : take (range n) i = range (min i n) := by +@[simp] theorem take_range {i n : Nat} : take (range n) i = range (min i n) := by ext <;> simp @[simp] theorem find?_range_eq_some {n : Nat} {i : Nat} {p : Nat → Bool} : @@ -188,48 +188,50 @@ theorem zipIdx_eq_empty_iff {xs : Array α} {i : Nat} : xs.zipIdx i = #[] ↔ xs simp @[simp] -theorem getElem?_zipIdx (xs : Array α) (i j) : (zipIdx xs i)[j]? = xs[j]?.map fun a => (a, i + j) := by +theorem getElem?_zipIdx {xs : Array α} {i j} : (zipIdx xs i)[j]? = xs[j]?.map fun a => (a, i + j) := by simp [getElem?_def] -theorem map_snd_add_zipIdx_eq_zipIdx (xs : Array α) (n k : Nat) : +theorem map_snd_add_zipIdx_eq_zipIdx {xs : Array α} {n k : Nat} : map (Prod.map id (· + n)) (zipIdx xs k) = zipIdx xs (n + k) := ext_getElem? fun i ↦ by simp [(· ∘ ·), Nat.add_comm, Nat.add_left_comm]; rfl +-- Arguments are explicit for parity with `zipIdx_map_fst`. @[simp] theorem zipIdx_map_snd (i) (xs : Array α) : map Prod.snd (zipIdx xs i) = range' i xs.size := by cases xs simp +-- Arguments are explicit so we can rewrite from right to left. @[simp] theorem zipIdx_map_fst (i) (xs : Array α) : map Prod.fst (zipIdx xs i) = xs := by cases xs simp -theorem zipIdx_eq_zip_range' (xs : Array α) {i : Nat} : xs.zipIdx i = xs.zip (range' i xs.size) := by +theorem zipIdx_eq_zip_range' {xs : Array α} {i : Nat} : xs.zipIdx i = xs.zip (range' i xs.size) := by simp [zip_of_prod (zipIdx_map_fst _ _) (zipIdx_map_snd _ _)] @[simp] -theorem unzip_zipIdx_eq_prod (xs : Array α) {i : Nat} : +theorem unzip_zipIdx_eq_prod {xs : Array α} {i : Nat} : (xs.zipIdx i).unzip = (xs, range' i xs.size) := by simp only [zipIdx_eq_zip_range', unzip_zip, size_range'] /-- Replace `zipIdx` with a starting index `n+1` with `zipIdx` starting from `n`, followed by a `map` increasing the indices by one. -/ -theorem zipIdx_succ (xs : Array α) (i : Nat) : +theorem zipIdx_succ {xs : Array α} {i : Nat} : xs.zipIdx (i + 1) = (xs.zipIdx i).map (fun ⟨a, j⟩ => (a, j + 1)) := by cases xs simp [List.zipIdx_succ] /-- Replace `zipIdx` with a starting index with `zipIdx` starting from 0, followed by a `map` increasing the indices. -/ -theorem zipIdx_eq_map_add (xs : Array α) (i : Nat) : +theorem zipIdx_eq_map_add {xs : Array α} {i : Nat} : xs.zipIdx i = (xs.zipIdx 0).map (fun ⟨a, j⟩ => (a, i + j)) := by cases xs simp only [zipIdx_toArray, List.map_toArray, mk.injEq] rw [List.zipIdx_eq_map_add] @[simp] -theorem zipIdx_singleton (x : α) (k : Nat) : zipIdx #[x] k = #[(x, k)] := +theorem zipIdx_singleton {x : α} {k : Nat} : zipIdx #[x] k = #[(x, k)] := rfl theorem mk_add_mem_zipIdx_iff_getElem? {k i : Nat} {x : α} {xs : Array α} : @@ -248,13 +250,13 @@ theorem snd_lt_add_of_mem_zipIdx {x : α × Nat} {k : Nat} {xs : Array α} (h : theorem snd_lt_of_mem_zipIdx {x : α × Nat} {k : Nat} {xs : Array α} (h : x ∈ zipIdx xs k) : x.2 < xs.size + k := by simpa [Nat.add_comm] using snd_lt_add_of_mem_zipIdx h -theorem map_zipIdx (f : α → β) (xs : Array α) (k : Nat) : +theorem map_zipIdx {f : α → β} {xs : Array α} {k : Nat} : map (Prod.map f id) (zipIdx xs k) = zipIdx (xs.map f) k := by cases xs simp [List.map_zipIdx] theorem fst_mem_of_mem_zipIdx {x : α × Nat} {xs : Array α} {k : Nat} (h : x ∈ zipIdx xs k) : x.1 ∈ xs := - zipIdx_map_fst k xs ▸ mem_map_of_mem _ h + zipIdx_map_fst k xs ▸ mem_map_of_mem h theorem fst_eq_of_mem_zipIdx {x : α × Nat} {xs : Array α} {k : Nat} (h : x ∈ zipIdx xs k) : x.1 = xs[x.2 - k]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) := by @@ -271,12 +273,12 @@ theorem mem_zipIdx' {x : α} {i : Nat} {xs : Array α} (h : (x, i) ∈ xs.zipIdx i < xs.size ∧ x = xs[i]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) := ⟨by simpa using snd_lt_add_of_mem_zipIdx h, fst_eq_of_mem_zipIdx h⟩ -theorem zipIdx_map (xs : Array α) (k : Nat) (f : α → β) : +theorem zipIdx_map {xs : Array α} {k : Nat} {f : α → β} : zipIdx (xs.map f) k = (zipIdx xs k).map (Prod.map f id) := by cases xs simp [List.zipIdx_map] -theorem zipIdx_append (xs ys : Array α) (k : Nat) : +theorem zipIdx_append {xs ys : Array α} {k : Nat} : zipIdx (xs ++ ys) k = zipIdx xs k ++ zipIdx ys (k + xs.size) := by cases xs cases ys diff --git a/src/Init/Data/Array/TakeDrop.lean b/src/Init/Data/Array/TakeDrop.lean index 09d3c47c36..8ed803c5e4 100644 --- a/src/Init/Data/Array/TakeDrop.lean +++ b/src/Init/Data/Array/TakeDrop.lean @@ -26,7 +26,7 @@ end List namespace Array -theorem exists_of_uset (xs : Array α) (i d h) : +theorem exists_of_uset {xs : Array α} {i d} (h) : ∃ l₁ l₂, xs.toList = l₁ ++ xs[i] :: l₂ ∧ List.length l₁ = i.toNat ∧ (xs.uset i d h).toList = l₁ ++ d :: l₂ := by simpa only [ugetElem_eq_getElem, ← getElem_toList, uset, toList_set] using diff --git a/src/Init/Data/Array/Zip.lean b/src/Init/Data/Array/Zip.lean index 08e3a03c92..a199b2e65f 100644 --- a/src/Init/Data/Array/Zip.lean +++ b/src/Init/Data/Array/Zip.lean @@ -22,19 +22,19 @@ open Nat /-! ### zipWith -/ -theorem zipWith_comm (f : α → β → γ) (as : Array α) (bs : Array β) : +theorem zipWith_comm {f : α → β → γ} {as : Array α} {bs : Array β} : zipWith f as bs = zipWith (fun b a => f a b) bs as := by cases as cases bs - simpa using List.zipWith_comm _ _ _ + simpa using List.zipWith_comm -theorem zipWith_comm_of_comm (f : α → α → β) (comm : ∀ x y : α, f x y = f y x) (xs ys : Array α) : +theorem zipWith_comm_of_comm {f : α → α → β} (comm : ∀ x y : α, f x y = f y x) {xs ys : Array α} : zipWith f xs ys = zipWith f ys xs := by rw [zipWith_comm] simp only [comm] @[simp] -theorem zipWith_self (f : α → α → δ) (xs : Array α) : zipWith f xs xs = xs.map fun a => f a a := by +theorem zipWith_self {f : α → α → δ} {xs : Array α} : zipWith f xs xs = xs.map fun a => f a a := by cases xs simp @@ -74,31 +74,31 @@ theorem getElem?_zip_eq_some {as : Array α} {bs : Array β} {z : α × β} {i : exact ⟨_, _, h₀, h₁, rfl⟩ @[simp] -theorem zipWith_map {μ} (f : γ → δ → μ) (g : α → γ) (h : β → δ) (as : Array α) (bs : Array β) : +theorem zipWith_map {μ} {f : γ → δ → μ} {g : α → γ} {h : β → δ} {as : Array α} {bs : Array β} : zipWith f (as.map g) (bs.map h) = zipWith (fun a b => f (g a) (h b)) as bs := by cases as cases bs simp [List.zipWith_map] -theorem zipWith_map_left (as : Array α) (bs : Array β) (f : α → α') (g : α' → β → γ) : +theorem zipWith_map_left {as : Array α} {bs : Array β} {f : α → α'} {g : α' → β → γ} : zipWith g (as.map f) bs = zipWith (fun a b => g (f a) b) as bs := by cases as cases bs simp [List.zipWith_map_left] -theorem zipWith_map_right (as : Array α) (bs : Array β) (f : β → β') (g : α → β' → γ) : +theorem zipWith_map_right {as : Array α} {bs : Array β} {f : β → β'} {g : α → β' → γ} : zipWith g as (bs.map f) = zipWith (fun a b => g a (f b)) as bs := by cases as cases bs simp [List.zipWith_map_right] -theorem zipWith_foldr_eq_zip_foldr {f : α → β → γ} (i : δ): +theorem zipWith_foldr_eq_zip_foldr {f : α → β → γ} {i : δ} : (zipWith f as bs).foldr g i = (zip as bs).foldr (fun p r => g (f p.1 p.2) r) i := by cases as cases bs simp [List.zipWith_foldr_eq_zip_foldr] -theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} (i : δ): +theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} {i : δ} : (zipWith f as bs).foldl g i = (zip as bs).foldl (fun r p => g r (f p.1 p.2)) i := by cases as cases bs @@ -108,7 +108,7 @@ theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} (i : δ): theorem zipWith_eq_empty_iff {f : α → β → γ} {as : Array α} {bs : Array β} : zipWith f as bs = #[] ↔ as = #[] ∨ bs = #[] := by cases as <;> cases bs <;> simp -theorem map_zipWith {δ : Type _} (f : α → β) (g : γ → δ → α) (cs : Array γ) (ds : Array δ) : +theorem map_zipWith {δ : Type _} {f : α → β} {g : γ → δ → α} {cs : Array γ} {ds : Array δ} : map f (zipWith g cs ds) = zipWith (fun x y => f (g x y)) cs ds := by cases cs cases ds @@ -124,7 +124,7 @@ theorem extract_zipWith : (zipWith f as bs).extract i j = zipWith f (as.extract cases bs simp [List.drop_zipWith, List.take_zipWith] -theorem zipWith_append (f : α → β → γ) (as as' : Array α) (bs bs' : Array β) +theorem zipWith_append {f : α → β → γ} {as as' : Array α} {bs bs' : Array β} (h : as.size = bs.size) : zipWith f (as ++ as') (bs ++ bs') = zipWith f as bs ++ zipWith f as' bs' := by cases as @@ -156,13 +156,13 @@ theorem zipWith_eq_append_iff {f : α → β → γ} {as : Array α} {bs : Array @[deprecated zipWith_replicate (since := "2025-03-18")] abbrev zipWith_mkArray := @zipWith_replicate -theorem map_uncurry_zip_eq_zipWith (f : α → β → γ) (as : Array α) (bs : Array β) : +theorem map_uncurry_zip_eq_zipWith {f : α → β → γ} {as : Array α} {bs : Array β} : map (Function.uncurry f) (as.zip bs) = zipWith f as bs := by cases as cases bs simp [List.map_uncurry_zip_eq_zipWith] -theorem map_zip_eq_zipWith (f : α × β → γ) (as : Array α) (bs : Array β) : +theorem map_zip_eq_zipWith {f : α × β → γ} {as : Array α} {bs : Array β} : map f (as.zip bs) = zipWith (Function.curry f) as bs := by cases as cases bs @@ -203,21 +203,21 @@ theorem getElem_zip {as : Array α} {bs : Array β} {i : Nat} {h : i < (zip as b (as[i]'(lt_size_left_of_zip h), bs[i]'(lt_size_right_of_zip h)) := getElem_zipWith (hi := by simpa using h) -theorem zip_eq_zipWith (as : Array α) (bs : Array β) : zip as bs = zipWith Prod.mk as bs := by +theorem zip_eq_zipWith {as : Array α} {bs : Array β} : zip as bs = zipWith Prod.mk as bs := by cases as cases bs simp [List.zip_eq_zipWith] -theorem zip_map (f : α → γ) (g : β → δ) (as : Array α) (bs : Array β) : +theorem zip_map {f : α → γ} {g : β → δ} {as : Array α} {bs : Array β} : zip (as.map f) (bs.map g) = (zip as bs).map (Prod.map f g) := by cases as cases bs simp [List.zip_map] -theorem zip_map_left (f : α → γ) (as : Array α) (bs : Array β) : +theorem zip_map_left {f : α → γ} {as : Array α} {bs : Array β} : zip (as.map f) bs = (zip as bs).map (Prod.map f id) := by rw [← zip_map, map_id] -theorem zip_map_right (f : β → γ) (as : Array α) (bs : Array β) : +theorem zip_map_right {f : β → γ} {as : Array α} {bs : Array β} : zip as (bs.map f) = (zip as bs).map (Prod.map id f) := by rw [← zip_map, map_id] theorem zip_append {as bs : Array α} {cs ds : Array β} (_h : as.size = cs.size) : @@ -228,7 +228,7 @@ theorem zip_append {as bs : Array α} {cs ds : Array β} (_h : as.size = cs.size cases ds simp_all [List.zip_append] -theorem zip_map' (f : α → β) (g : α → γ) (xs : Array α) : +theorem zip_map' {f : α → β} {g : α → γ} {xs : Array α} : zip (xs.map f) (xs.map g) = xs.map fun a => (f a, g a) := by cases xs simp [List.zip_map'] @@ -238,25 +238,25 @@ theorem of_mem_zip {a b} {as : Array α} {bs : Array β} : (a, b) ∈ zip as bs cases bs simpa using List.of_mem_zip -theorem map_fst_zip (as : Array α) (bs : Array β) (h : as.size ≤ bs.size) : +theorem map_fst_zip {as : Array α} {bs : Array β} (h : as.size ≤ bs.size) : map Prod.fst (zip as bs) = as := by cases as cases bs simp_all [List.map_fst_zip] -theorem map_snd_zip (as : Array α) (bs : Array β) (h : bs.size ≤ as.size) : +theorem map_snd_zip {as : Array α} {bs : Array β} (h : bs.size ≤ as.size) : map Prod.snd (zip as bs) = bs := by cases as cases bs simp_all [List.map_snd_zip] -theorem map_prod_left_eq_zip {xs : Array α} (f : α → β) : +theorem map_prod_left_eq_zip {xs : Array α} {f : α → β} : (xs.map fun x => (x, f x)) = xs.zip (xs.map f) := by rw [← zip_map'] congr simp -theorem map_prod_right_eq_zip {xs : Array α} (f : α → β) : +theorem map_prod_right_eq_zip {xs : Array α} {f : α → β} : (xs.map fun x => (f x, x)) = (xs.map f).zip xs := by rw [← zip_map'] congr @@ -280,7 +280,7 @@ theorem zip_eq_append_iff {as : Array α} {bs : Array β} : @[deprecated zip_replicate (since := "2025-03-18")] abbrev zip_mkArray := @zip_replicate -theorem zip_eq_zip_take_min (as : Array α) (bs : Array β) : +theorem zip_eq_zip_take_min {as : Array α} {bs : Array β} : zip as bs = zip (as.take (min as.size bs.size)) (bs.take (min as.size bs.size)) := by cases as cases bs @@ -298,25 +298,25 @@ theorem getElem?_zipWithAll {f : Option α → Option β → γ} {i : Nat} : simp [List.getElem?_zipWithAll] rfl -theorem zipWithAll_map {μ} (f : Option γ → Option δ → μ) (g : α → γ) (h : β → δ) (as : Array α) (bs : Array β) : +theorem zipWithAll_map {μ} {f : Option γ → Option δ → μ} {g : α → γ} {h : β → δ} {as : Array α} {bs : Array β} : zipWithAll f (as.map g) (bs.map h) = zipWithAll (fun a b => f (g <$> a) (h <$> b)) as bs := by cases as cases bs simp [List.zipWithAll_map] -theorem zipWithAll_map_left (as : Array α) (bs : Array β) (f : α → α') (g : Option α' → Option β → γ) : +theorem zipWithAll_map_left {as : Array α} {bs : Array β} {f : α → α'} {g : Option α' → Option β → γ} : zipWithAll g (as.map f) bs = zipWithAll (fun a b => g (f <$> a) b) as bs := by cases as cases bs simp [List.zipWithAll_map_left] -theorem zipWithAll_map_right (as : Array α) (bs : Array β) (f : β → β') (g : Option α → Option β' → γ) : +theorem zipWithAll_map_right {as : Array α} {bs : Array β} {f : β → β'} {g : Option α → Option β' → γ} : zipWithAll g as (bs.map f) = zipWithAll (fun a b => g a (f <$> b)) as bs := by cases as cases bs simp [List.zipWithAll_map_right] -theorem map_zipWithAll {δ : Type _} (f : α → β) (g : Option γ → Option δ → α) (cs : Array γ) (ds : Array δ) : +theorem map_zipWithAll {δ : Type _} {f : α → β} {g : Option γ → Option δ → α} {cs : Array γ} {ds : Array δ} : map f (zipWithAll g cs ds) = zipWithAll (fun x y => f (g x y)) cs ds := by cases cs cases ds @@ -337,10 +337,11 @@ abbrev zipWithAll_mkArray := @zipWithAll_replicate @[simp] theorem unzip_snd : (unzip l).snd = l.map Prod.snd := by induction l <;> simp_all -theorem unzip_eq_map (xs : Array (α × β)) : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by +theorem unzip_eq_map {xs : Array (α × β)} : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by cases xs simp [List.unzip_eq_map] +-- The argument `xs` is explicit so we can rewrite from right to left. theorem zip_unzip (xs : Array (α × β)) : zip (unzip xs).1 (unzip xs).2 = xs := by cases xs simp only [List.unzip_toArray, Prod.map_fst, Prod.map_snd, List.zip_toArray, List.zip_unzip] diff --git a/src/Init/Data/List/Attach.lean b/src/Init/Data/List/Attach.lean index 101ebd61f9..90c55a182b 100644 --- a/src/Init/Data/List/Attach.lean +++ b/src/Init/Data/List/Attach.lean @@ -65,9 +65,9 @@ well-founded recursion mechanism to prove that the function terminates. | cons _ l', hL' => congrArg _ <| go l' fun _ hx => hL' (.tail _ hx) exact go l h' -@[simp] theorem pmap_nil {P : α → Prop} (f : ∀ a, P a → β) : pmap f [] (by simp) = [] := rfl +@[simp] theorem pmap_nil {P : α → Prop} {f : ∀ a, P a → β} : pmap f [] (by simp) = [] := rfl -@[simp] theorem pmap_cons {P : α → Prop} (f : ∀ a, P a → β) (a : α) (l : List α) (h : ∀ b ∈ a :: l, P b) : +@[simp] theorem pmap_cons {P : α → Prop} {f : ∀ a, P a → β} {a : α} {l : List α} (h : ∀ b ∈ a :: l, P b) : pmap f (a :: l) h = f a (forall_mem_cons.1 h).1 :: pmap f l (forall_mem_cons.1 h).2 := rfl @[simp] theorem attach_nil : ([] : List α).attach = [] := rfl @@ -75,7 +75,7 @@ well-founded recursion mechanism to prove that the function terminates. @[simp] theorem attachWith_nil : ([] : List α).attachWith P H = [] := rfl @[simp] -theorem pmap_eq_map (p : α → Prop) (f : α → β) (l : List α) (H) : +theorem pmap_eq_map {p : α → Prop} {f : α → β} {l : List α} (H) : @pmap _ _ p (fun a _ => f a) l H = map f l := by induction l · rfl @@ -86,18 +86,18 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a, induction l with | nil => rfl | cons x l ih => - rw [pmap, pmap, h _ (mem_cons_self _ _), ih fun a ha => h a (mem_cons_of_mem _ ha)] + rw [pmap, pmap, h _ mem_cons_self, ih fun a ha => h a (mem_cons_of_mem _ ha)] @[deprecated pmap_congr_left (since := "2024-09-06")] abbrev pmap_congr := @pmap_congr_left -theorem map_pmap {p : α → Prop} (g : β → γ) (f : ∀ a, p a → β) (l H) : +theorem map_pmap {p : α → Prop} {g : β → γ} {f : ∀ a, p a → β} {l : List α} (H) : map g (pmap f l H) = pmap (fun a h => g (f a h)) l H := by induction l · rfl · simp only [*, pmap, map] -theorem pmap_map {p : β → Prop} (g : ∀ b, p b → γ) (f : α → β) (l H) : - pmap g (map f l) H = pmap (fun a h => g (f a) h) l fun _ h => H _ (mem_map_of_mem _ h) := by +theorem pmap_map {p : β → Prop} {g : ∀ b, p b → γ} {f : α → β} {l : List α} (H) : + pmap g (map f l) H = pmap (fun a h => g (f a) h) l fun _ h => H _ (mem_map_of_mem h) := by induction l · rfl · simp only [*, pmap, map] @@ -114,7 +114,7 @@ theorem attachWith_congr {l₁ l₂ : List α} (w : l₁ = l₂) {P : α → Pro @[simp] theorem attach_cons {x : α} {xs : List α} : (x :: xs).attach = - ⟨x, mem_cons_self x xs⟩ :: xs.attach.map fun ⟨y, h⟩ => ⟨y, mem_cons_of_mem x h⟩ := by + ⟨x, mem_cons_self⟩ :: xs.attach.map fun ⟨y, h⟩ => ⟨y, mem_cons_of_mem x h⟩ := by simp only [attach, attachWith, pmap, map_pmap, cons.injEq, true_and] apply pmap_congr_left intros a _ m' _ @@ -122,42 +122,43 @@ theorem attachWith_congr {l₁ l₂ : List α} (w : l₁ = l₂) {P : α → Pro @[simp] theorem attachWith_cons {x : α} {xs : List α} {p : α → Prop} (h : ∀ a ∈ x :: xs, p a) : - (x :: xs).attachWith p h = ⟨x, h x (mem_cons_self x xs)⟩ :: + (x :: xs).attachWith p h = ⟨x, h x (mem_cons_self)⟩ :: xs.attachWith p (fun a ha ↦ h a (mem_cons_of_mem x ha)) := rfl -theorem pmap_eq_map_attach {p : α → Prop} (f : ∀ a, p a → β) (l H) : +theorem pmap_eq_map_attach {p : α → Prop} {f : ∀ a, p a → β} {l : List α} (H) : pmap f l H = l.attach.map fun x => f x.1 (H _ x.2) := by rw [attach, attachWith, map_pmap]; exact pmap_congr_left l fun _ _ _ _ => rfl @[simp] -theorem pmap_eq_attachWith {p q : α → Prop} (f : ∀ a, p a → q a) (l H) : +theorem pmap_eq_attachWith {p q : α → Prop} {f : ∀ a, p a → q a} {l : List α} (H) : pmap (fun a h => ⟨a, f a h⟩) l H = l.attachWith q (fun x h => f x (H x h)) := by induction l with | nil => rfl | cons a l ih => simp [pmap, attachWith, ih] -theorem attach_map_val (l : List α) (f : α → β) : +theorem attach_map_val {l : List α} {f : α → β} : (l.attach.map fun (i : {i // i ∈ l}) => f i) = l.map f := by - rw [attach, attachWith, map_pmap]; exact pmap_eq_map _ _ _ _ + rw [attach, attachWith, map_pmap]; exact pmap_eq_map _ @[deprecated attach_map_val (since := "2025-02-17")] abbrev attach_map_coe := @attach_map_val +-- The argument `l : List α` is explicit to allow rewriting from right to left. theorem attach_map_subtype_val (l : List α) : l.attach.map Subtype.val = l := - (attach_map_val _ _).trans (List.map_id _) + attach_map_val.trans (List.map_id _) -theorem attachWith_map_val {p : α → Prop} (f : α → β) (l : List α) (H : ∀ a ∈ l, p a) : +theorem attachWith_map_val {p : α → Prop} {f : α → β} {l : List α} (H : ∀ a ∈ l, p a) : ((l.attachWith p H).map fun (i : { i // p i}) => f i) = l.map f := by - rw [attachWith, map_pmap]; exact pmap_eq_map _ _ _ _ + rw [attachWith, map_pmap]; exact pmap_eq_map _ @[deprecated attachWith_map_val (since := "2025-02-17")] abbrev attachWith_map_coe := @attachWith_map_val -theorem attachWith_map_subtype_val {p : α → Prop} (l : List α) (H : ∀ a ∈ l, p a) : +theorem attachWith_map_subtype_val {p : α → Prop} {l : List α} (H : ∀ a ∈ l, p a) : (l.attachWith p H).map Subtype.val = l := - (attachWith_map_val _ _ _).trans (List.map_id _) + (attachWith_map_val _).trans (List.map_id _) @[simp] theorem mem_attach (l : List α) : ∀ x, x ∈ l.attach @@ -167,7 +168,7 @@ theorem mem_attach (l : List α) : ∀ x, x ∈ l.attach exact m @[simp] -theorem mem_attachWith (l : List α) {q : α → Prop} (H) (x : {x // q x}) : +theorem mem_attachWith {l : List α} {q : α → Prop} (H) (x : {x // q x}) : x ∈ l.attachWith q H ↔ x.1 ∈ l := by induction l with | nil => simp @@ -240,7 +241,7 @@ theorem attachWith_ne_nil_iff {l : List α} {P : α → Prop} {H : ∀ a ∈ l, @[deprecated attach_ne_nil_iff (since := "2024-09-06")] abbrev attach_ne_nil := @attach_ne_nil_iff @[simp] -theorem getElem?_pmap {p : α → Prop} (f : ∀ a, p a → β) {l : List α} (h : ∀ a ∈ l, p a) (i : Nat) : +theorem getElem?_pmap {p : α → Prop} {f : ∀ a, p a → β} {l : List α} (h : ∀ a ∈ l, p a) (i : Nat) : (pmap f l h)[i]? = Option.pmap f l[i]? fun x H => h x (mem_of_getElem? H) := by induction l generalizing i with | nil => simp @@ -257,6 +258,7 @@ theorem get?_pmap {p : α → Prop} (f : ∀ a, p a → β) {l : List α} (h : simp only [get?_eq_getElem?] simp [getElem?_pmap, h] +-- The argument `f` is explicit to allow rewriting from right to left. @[simp] theorem getElem_pmap {p : α → Prop} (f : ∀ a, p a → β) {l : List α} (h : ∀ a ∈ l, p a) {i : Nat} (hn : i < (pmap f l h).length) : @@ -302,19 +304,19 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) : xs.attach[i] = ⟨xs[i]'(by simpa using h), getElem_mem (by simpa using h)⟩ := getElem_attachWith h -@[simp] theorem pmap_attach (l : List α) {p : {x // x ∈ l} → Prop} (f : ∀ a, p a → β) (H) : +@[simp] theorem pmap_attach {l : List α} {p : {x // x ∈ l} → Prop} {f : ∀ a, p a → β} (H) : pmap f l.attach H = l.pmap (P := fun a => ∃ h : a ∈ l, p ⟨a, h⟩) (fun a h => f ⟨a, h.1⟩ h.2) (fun a h => ⟨h, H ⟨a, h⟩ (by simp)⟩) := by apply ext_getElem <;> simp -@[simp] theorem pmap_attachWith (l : List α) {p : {x // q x} → Prop} (f : ∀ a, p a → β) (H₁ H₂) : +@[simp] theorem pmap_attachWith {l : List α} {p : {x // q x} → Prop} {f : ∀ a, p a → β} (H₁ H₂) : pmap f (l.attachWith q H₁) H₂ = l.pmap (P := fun a => ∃ h : q a, p ⟨a, h⟩) (fun a h => f ⟨a, h.1⟩ h.2) (fun a h => ⟨H₁ _ h, H₂ ⟨a, H₁ _ h⟩ (by simpa)⟩) := by apply ext_getElem <;> simp -@[simp] theorem head?_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : List α) +@[simp] theorem head?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : List α} (H : ∀ (a : α), a ∈ xs → P a) : (xs.pmap f H).head? = xs.attach.head?.map fun ⟨a, m⟩ => f a (H a m) := by induction xs with @@ -323,7 +325,7 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) : simp at ih simp [head?_pmap, ih] -@[simp] theorem head_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : List α) +@[simp] theorem head_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : List α} (H : ∀ (a : α), a ∈ xs → P a) (h : xs.pmap f H ≠ []) : (xs.pmap f H).head h = f (xs.head (by simpa using h)) (H _ (head_mem _)) := by induction xs with @@ -342,7 +344,7 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) : | nil => simp at h | cons x xs => simp [head_attachWith, h] -@[simp] theorem head?_attach (xs : List α) : +@[simp] theorem head?_attach {xs : List α} : xs.attach.head? = xs.head?.pbind (fun a h => some ⟨a, mem_of_mem_head? h⟩) := by cases xs <;> simp_all @@ -352,7 +354,7 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) : | nil => simp at h | cons x xs => simp [head_attach, h] -@[simp] theorem tail_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : List α) +@[simp] theorem tail_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : List α} (H : ∀ (a : α), a ∈ xs → P a) : (xs.pmap f H).tail = xs.tail.pmap f (fun a h => H a (mem_of_mem_tail h)) := by cases xs <;> simp @@ -362,29 +364,29 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) : (xs.attachWith P H).tail = xs.tail.attachWith P (fun a h => H a (mem_of_mem_tail h)) := by cases xs <;> simp -@[simp] theorem tail_attach (xs : List α) : +@[simp] theorem tail_attach {xs : List α} : xs.attach.tail = xs.tail.attach.map (fun ⟨x, h⟩ => ⟨x, mem_of_mem_tail h⟩) := by cases xs <;> simp -theorem foldl_pmap (l : List α) {P : α → Prop} (f : (a : α) → P a → β) - (H : ∀ (a : α), a ∈ l → P a) (g : γ → β → γ) (x : γ) : +theorem foldl_pmap {l : List α} {P : α → Prop} {f : (a : α) → P a → β} + (H : ∀ (a : α), a ∈ l → P a) (g : γ → β → γ) (x : γ) : (l.pmap f H).foldl g x = l.attach.foldl (fun acc a => g acc (f a.1 (H _ a.2))) x := by rw [pmap_eq_map_attach, foldl_map] -theorem foldr_pmap (l : List α) {P : α → Prop} (f : (a : α) → P a → β) - (H : ∀ (a : α), a ∈ l → P a) (g : β → γ → γ) (x : γ) : +theorem foldr_pmap {l : List α} {P : α → Prop} {f : (a : α) → P a → β} + (H : ∀ (a : α), a ∈ l → P a) (g : β → γ → γ) (x : γ) : (l.pmap f H).foldr g x = l.attach.foldr (fun a acc => g (f a.1 (H _ a.2)) acc) x := by rw [pmap_eq_map_attach, foldr_map] @[simp] theorem foldl_attachWith - (l : List α) {q : α → Prop} (H : ∀ a, a ∈ l → q a) {f : β → { x // q x} → β} {b} : + {l : List α} {q : α → Prop} (H : ∀ a, a ∈ l → q a) {f : β → { x // q x } → β} {b} : (l.attachWith q H).foldl f b = l.attach.foldl (fun b ⟨a, h⟩ => f b ⟨a, H _ h⟩) b := by induction l generalizing b with | nil => simp | cons a l ih => simp [ih, foldl_map] @[simp] theorem foldr_attachWith - (l : List α) {q : α → Prop} (H : ∀ a, a ∈ l → q a) {f : { x // q x} → β → β} {b} : + {l : List α} {q : α → Prop} (H : ∀ a, a ∈ l → q a) {f : { x // q x } → β → β} {b} : (l.attachWith q H).foldr f b = l.attach.foldr (fun a acc => f ⟨a.1, H _ a.2⟩ acc) b := by induction l generalizing b with | nil => simp @@ -400,7 +402,7 @@ Unfortunately this can't be applied by `simp` because of the higher order unific and even when rewriting we need to specify the function explicitly. See however `foldl_subtype` below. -/ -theorem foldl_attach (l : List α) (f : β → α → β) (b : β) : +theorem foldl_attach {l : List α} {f : β → α → β} {b : β} : l.attach.foldl (fun acc t => f acc t.1) b = l.foldl f b := by induction l generalizing b with | nil => simp @@ -416,28 +418,28 @@ Unfortunately this can't be applied by `simp` because of the higher order unific and even when rewriting we need to specify the function explicitly. See however `foldr_subtype` below. -/ -theorem foldr_attach (l : List α) (f : α → β → β) (b : β) : +theorem foldr_attach {l : List α} {f : α → β → β} {b : β} : l.attach.foldr (fun t acc => f t.1 acc) b = l.foldr f b := by induction l generalizing b with | nil => simp | cons a l ih => rw [foldr_cons, attach_cons, foldr_cons, foldr_map, ih] -theorem attach_map {l : List α} (f : α → β) : - (l.map f).attach = l.attach.map (fun ⟨x, h⟩ => ⟨f x, mem_map_of_mem f h⟩) := by +theorem attach_map {l : List α} {f : α → β} : + (l.map f).attach = l.attach.map (fun ⟨x, h⟩ => ⟨f x, mem_map_of_mem h⟩) := by induction l <;> simp [*] -theorem attachWith_map {l : List α} (f : α → β) {P : β → Prop} {H : ∀ (b : β), b ∈ l.map f → P b} : - (l.map f).attachWith P H = (l.attachWith (P ∘ f) (fun _ h => H _ (mem_map_of_mem f h))).map +theorem attachWith_map {l : List α} {f : α → β} {P : β → Prop} (H : ∀ (b : β), b ∈ l.map f → P b) : + (l.map f).attachWith P H = (l.attachWith (P ∘ f) (fun _ h => H _ (mem_map_of_mem h))).map fun ⟨x, h⟩ => ⟨f x, h⟩ := by induction l <;> simp [*] @[simp] theorem map_attachWith {l : List α} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a} - (f : { x // P x } → β) : + {f : { x // P x } → β} : (l.attachWith P H).map f = l.attach.map fun ⟨x, h⟩ => f ⟨x, H _ h⟩ := by induction l <;> simp_all theorem map_attachWith_eq_pmap {l : List α} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a} - (f : { x // P x } → β) : + {f : { x // P x } → β} : (l.attachWith P H).map f = l.pmap (fun a (h : a ∈ l ∧ P a) => f ⟨a, H _ h.1⟩) (fun a h => ⟨h, H a h⟩) := by induction l with @@ -448,7 +450,7 @@ theorem map_attachWith_eq_pmap {l : List α} {P : α → Prop} {H : ∀ (a : α) simp /-- See also `pmap_eq_map_attach` for writing `pmap` in terms of `map` and `attach`. -/ -theorem map_attach_eq_pmap {l : List α} (f : { x // x ∈ l } → β) : +theorem map_attach_eq_pmap {l : List α} {f : { x // x ∈ l } → β} : l.attach.map f = l.pmap (fun a h => f ⟨a, h⟩) (fun _ => id) := by induction l with | nil => rfl @@ -494,7 +496,7 @@ theorem attach_filterMap {l : List α} {f : α → Option β} : theorem attach_filter {l : List α} (p : α → Bool) : (l.filter p).attach = l.attach.filterMap fun x => if w : p x.1 then some ⟨x.1, mem_filter.mpr ⟨x.2, w⟩⟩ else none := by - rw [attach_congr (congrFun (filterMap_eq_filter _).symm _), attach_filterMap, map_filterMap] + rw [attach_congr (congrFun filterMap_eq_filter.symm _), attach_filterMap, map_filterMap] simp only [Option.guard] congr ext1 @@ -521,13 +523,13 @@ theorem filter_attachWith {q : α → Prop} {l : List α} {p : {x // q x} → Bo simp only [attachWith_cons, filter_cons] split <;> simp_all [Function.comp_def, filter_map] -theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f : ∀ b, q b → γ) (l H₁ H₂) : +theorem pmap_pmap {p : α → Prop} {q : β → Prop} {g : ∀ a, p a → β} {f : ∀ b, q b → γ} {l} (H₁ H₂) : pmap f (pmap g l H₁) H₂ = pmap (α := { x // x ∈ l }) (fun a h => f (g a h) (H₂ (g a h) (mem_pmap_of_mem a.2))) l.attach (fun a _ => H₁ a a.2) := by simp [pmap_eq_map_attach, attach_map] -@[simp] theorem pmap_append {p : ι → Prop} (f : ∀ a : ι, p a → α) (l₁ l₂ : List ι) +@[simp] theorem pmap_append {p : ι → Prop} {f : ∀ a : ι, p a → α} {l₁ l₂ : List ι} (h : ∀ a ∈ l₁ ++ l₂, p a) : (l₁ ++ l₂).pmap f h = (l₁.pmap f fun a ha => h a (mem_append_left l₂ ha)) ++ @@ -538,13 +540,13 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f dsimp only [pmap, cons_append] rw [ih] -theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (l₁ l₂ : List α) +theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {l₁ l₂ : List α} (h₁ : ∀ a ∈ l₁, p a) (h₂ : ∀ a ∈ l₂, p a) : ((l₁ ++ l₂).pmap f fun a ha => (List.mem_append.1 ha).elim (h₁ a) (h₂ a)) = l₁.pmap f h₁ ++ l₂.pmap f h₂ := - pmap_append f l₁ l₂ _ + pmap_append _ -@[simp] theorem attach_append (xs ys : List α) : +@[simp] theorem attach_append {xs ys : List α} : (xs ++ ys).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨x, mem_append_left ys h⟩) ++ ys.attach.map fun ⟨x, h⟩ => ⟨x, mem_append_right xs h⟩ := by simp only [attach, attachWith, pmap, map_pmap, pmap_append] @@ -557,12 +559,12 @@ theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (l₁ l₂ : ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by simp only [attachWith, attach_append, map_pmap, pmap_append] -@[simp] theorem pmap_reverse {P : α → Prop} (f : (a : α) → P a → β) (xs : List α) +@[simp] theorem pmap_reverse {P : α → Prop} {f : (a : α) → P a → β} {xs : List α} (H : ∀ (a : α), a ∈ xs.reverse → P a) : xs.reverse.pmap f H = (xs.pmap f (fun a h => H a (by simpa using h))).reverse := by induction xs <;> simp_all -theorem reverse_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : List α) +theorem reverse_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : List α} (H : ∀ (a : α), a ∈ xs → P a) : (xs.pmap f H).reverse = xs.reverse.pmap f (fun a h => H a (by simpa using h)) := by rw [pmap_reverse] @@ -578,21 +580,21 @@ theorem reverse_attachWith {P : α → Prop} {xs : List α} (xs.attachWith P H).reverse = (xs.reverse.attachWith P (fun a h => H a (by simpa using h))) := reverse_pmap .. -@[simp] theorem attach_reverse (xs : List α) : +@[simp] theorem attach_reverse {xs : List α} : xs.reverse.attach = xs.attach.reverse.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by simp only [attach, attachWith, reverse_pmap, map_pmap] apply pmap_congr_left intros rfl -theorem reverse_attach (xs : List α) : +theorem reverse_attach {xs : List α} : xs.attach.reverse = xs.reverse.attach.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by simp only [attach, attachWith, reverse_pmap, map_pmap] apply pmap_congr_left intros rfl -@[simp] theorem getLast?_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : List α) +@[simp] theorem getLast?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : List α} (H : ∀ (a : α), a ∈ xs → P a) : (xs.pmap f H).getLast? = xs.attach.getLast?.map fun ⟨a, m⟩ => f a (H a m) := by simp only [getLast?_eq_head?_reverse] @@ -600,7 +602,7 @@ theorem reverse_attach (xs : List α) : simp only [Option.map_map] congr -@[simp] theorem getLast_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : List α) +@[simp] theorem getLast_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : List α} (H : ∀ (a : α), a ∈ xs → P a) (h : xs.pmap f H ≠ []) : (xs.pmap f H).getLast h = f (xs.getLast (by simpa using h)) (H _ (getLast_mem _)) := by simp only [getLast_eq_head_reverse] @@ -629,26 +631,26 @@ theorem getLast_attach {xs : List α} (h : xs.attach ≠ []) : simp only [getLast_eq_head_reverse, reverse_attach, head_map, head_attach] @[simp] -theorem countP_attach (l : List α) (p : α → Bool) : +theorem countP_attach {l : List α} {p : α → Bool} : l.attach.countP (fun a : {x // x ∈ l} => p a) = l.countP p := by simp only [← Function.comp_apply (g := Subtype.val), ← countP_map, attach_map_subtype_val] @[simp] -theorem countP_attachWith {p : α → Prop} (l : List α) (H : ∀ a ∈ l, p a) (q : α → Bool) : +theorem countP_attachWith {p : α → Prop} {q : α → Bool} {l : List α} (H : ∀ a ∈ l, p a) : (l.attachWith p H).countP (fun a : {x // p x} => q a) = l.countP q := by simp only [← Function.comp_apply (g := Subtype.val), ← countP_map, attachWith_map_subtype_val] @[simp] -theorem count_attach [DecidableEq α] (l : List α) (a : {x // x ∈ l}) : +theorem count_attach [DecidableEq α] {l : List α} {a : {x // x ∈ l}} : l.attach.count a = l.count ↑a := - Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attach _ _ + Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attach @[simp] -theorem count_attachWith [DecidableEq α] {p : α → Prop} (l : List α) (H : ∀ a ∈ l, p a) (a : {x // p x}) : +theorem count_attachWith [DecidableEq α] {p : α → Prop} {l : List α} (H : ∀ a ∈ l, p a) {a : {x // p x}} : (l.attachWith p H).count a = l.count ↑a := - Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attachWith _ _ _ + Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attachWith _ -@[simp] theorem countP_pmap {p : α → Prop} (g : ∀ a, p a → β) (f : β → Bool) (l : List α) (H₁) : +@[simp] theorem countP_pmap {p : α → Prop} {g : ∀ a, p a → β} {f : β → Bool} {l : List α} (H₁) : (l.pmap g H₁).countP f = l.attach.countP (fun ⟨a, m⟩ => f (g a (H₁ a m))) := by simp [pmap_eq_map_attach, countP_map, Function.comp_def] @@ -835,62 +837,62 @@ and simplifies these to the function directly taking the value. /-! ### Well-founded recursion preprocessing setup -/ -@[wf_preprocess] theorem map_wfParam (xs : List α) (f : α → β) : +@[wf_preprocess] theorem map_wfParam {xs : List α} {f : α → β} : (wfParam xs).map f = xs.attach.unattach.map f := by simp [wfParam] -@[wf_preprocess] theorem map_unattach (P : α → Prop) (xs : List (Subtype P)) (f : α → β) : +@[wf_preprocess] theorem map_unattach {P : α → Prop} {xs : List (Subtype P)} {f : α → β} : xs.unattach.map f = xs.map fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] -@[wf_preprocess] theorem foldl_wfParam (xs : List α) (f : β → α → β) (x : β) : +@[wf_preprocess] theorem foldl_wfParam {xs : List α} {f : β → α → β} {x : β} : (wfParam xs).foldl f x = xs.attach.unattach.foldl f x := by simp [wfParam] -@[wf_preprocess] theorem foldl_unattach (P : α → Prop) (xs : List (Subtype P)) (f : β → α → β) (x : β): +@[wf_preprocess] theorem foldl_unattach {P : α → Prop} {xs : List (Subtype P)} {f : β → α → β} {x : β} : xs.unattach.foldl f x = xs.foldl (fun s ⟨x, h⟩ => binderNameHint s f <| binderNameHint x (f s) <| binderNameHint h () <| f s (wfParam x)) x := by simp [wfParam] -@[wf_preprocess] theorem foldr_wfParam (xs : List α) (f : α → β → β) (x : β) : +@[wf_preprocess] theorem foldr_wfParam {xs : List α} {f : α → β → β} {x : β} : (wfParam xs).foldr f x = xs.attach.unattach.foldr f x := by simp [wfParam] -@[wf_preprocess] theorem foldr_unattach (P : α → Prop) (xs : List (Subtype P)) (f : α → β → β) (x : β): +@[wf_preprocess] theorem foldr_unattach {P : α → Prop} {xs : List (Subtype P)} {f : α → β → β} {x : β} : xs.unattach.foldr f x = xs.foldr (fun ⟨x, h⟩ s => binderNameHint x f <| binderNameHint s (f x) <| binderNameHint h () <| f (wfParam x) s) x := by simp [wfParam] -@[wf_preprocess] theorem filter_wfParam (xs : List α) (f : α → Bool) : +@[wf_preprocess] theorem filter_wfParam {xs : List α} {f : α → Bool} : (wfParam xs).filter f = xs.attach.unattach.filter f:= by simp [wfParam] -@[wf_preprocess] theorem filter_unattach (P : α → Prop) (xs : List (Subtype P)) (f : α → Bool) : +@[wf_preprocess] theorem filter_unattach {P : α → Prop} {xs : List (Subtype P)} {f : α → Bool} : xs.unattach.filter f = (xs.filter (fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x))).unattach := by simp [wfParam] -@[wf_preprocess] theorem reverse_wfParam (xs : List α) : +@[wf_preprocess] theorem reverse_wfParam {xs : List α} : (wfParam xs).reverse = xs.attach.unattach.reverse := by simp [wfParam] -@[wf_preprocess] theorem reverse_unattach (P : α → Prop) (xs : List (Subtype P)) : +@[wf_preprocess] theorem reverse_unattach {P : α → Prop} {xs : List (Subtype P)} : xs.unattach.reverse = xs.reverse.unattach := by simp -@[wf_preprocess] theorem filterMap_wfParam (xs : List α) (f : α → Option β) : +@[wf_preprocess] theorem filterMap_wfParam {xs : List α} {f : α → Option β} : (wfParam xs).filterMap f = xs.attach.unattach.filterMap f := by simp [wfParam] -@[wf_preprocess] theorem filterMap_unattach (P : α → Prop) (xs : List (Subtype P)) (f : α → Option β) : +@[wf_preprocess] theorem filterMap_unattach {P : α → Prop} {xs : List (Subtype P)} {f : α → Option β} : xs.unattach.filterMap f = xs.filterMap fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] -@[wf_preprocess] theorem flatMap_wfParam (xs : List α) (f : α → List β) : +@[wf_preprocess] theorem flatMap_wfParam {xs : List α} {f : α → List β} : (wfParam xs).flatMap f = xs.attach.unattach.flatMap f := by simp [wfParam] -@[wf_preprocess] theorem flatMap_unattach (P : α → Prop) (xs : List (Subtype P)) (f : α → List β) : +@[wf_preprocess] theorem flatMap_unattach {P : α → Prop} {xs : List (Subtype P)} {f : α → List β} : xs.unattach.flatMap f = xs.flatMap fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] diff --git a/src/Init/Data/List/Basic.lean b/src/Init/Data/List/Basic.lean index 3f54c30571..14269b0d0e 100644 --- a/src/Init/Data/List/Basic.lean +++ b/src/Init/Data/List/Basic.lean @@ -76,14 +76,14 @@ namespace List @[simp] theorem length_nil : length ([] : List α) = 0 := rfl -@[simp] theorem length_singleton (a : α) : length [a] = 1 := rfl +@[simp] theorem length_singleton {a : α} : length [a] = 1 := rfl -@[simp] theorem length_cons {α} (a : α) (as : List α) : (cons a as).length = as.length + 1 := +@[simp] theorem length_cons {a : α} {as : List α} : (cons a as).length = as.length + 1 := rfl /-! ### set -/ -@[simp] theorem length_set (as : List α) (i : Nat) (a : α) : (as.set i a).length = as.length := by +@[simp] theorem length_set {as : List α} {i : Nat} {a : α} : (as.set i a).length = as.length := by induction as generalizing i with | nil => rfl | cons x xs ih => @@ -95,11 +95,11 @@ namespace List -- As `List.foldl` is defined in `Init.Prelude`, we write the basic simplification lemmas here. @[simp] theorem foldl_nil : [].foldl f b = b := rfl -@[simp] theorem foldl_cons (l : List α) (b : β) : (a :: l).foldl f b = l.foldl f (f b a) := rfl +@[simp] theorem foldl_cons {l : List α} {f : β → α → β} {b : β} : (a :: l).foldl f b = l.foldl f (f b a) := rfl /-! ### concat -/ -theorem length_concat (as : List α) (a : α) : (concat as a).length = as.length + 1 := by +theorem length_concat {as : List α} {a : α} : (concat as a).length = as.length + 1 := by induction as with | nil => rfl | cons _ xs ih => simp [concat, ih] @@ -125,9 +125,9 @@ protected def beq [BEq α] : List α → List α → Bool | _, _ => false @[simp] theorem beq_nil_nil [BEq α] : List.beq ([] : List α) ([] : List α) = true := rfl -@[simp] theorem beq_cons_nil [BEq α] (a : α) (as : List α) : List.beq (a::as) [] = false := rfl -@[simp] theorem beq_nil_cons [BEq α] (a : α) (as : List α) : List.beq [] (a::as) = false := rfl -theorem beq_cons₂ [BEq α] (a b : α) (as bs : List α) : List.beq (a::as) (b::bs) = (a == b && List.beq as bs) := rfl +@[simp] theorem beq_cons_nil [BEq α] {a : α} {as : List α} : List.beq (a::as) [] = false := rfl +@[simp] theorem beq_nil_cons [BEq α] {a : α} {as : List α} : List.beq [] (a::as) = false := rfl +theorem beq_cons₂ [BEq α] {a b : α} {as bs : List α} : List.beq (a::as) (b::bs) = (a == b && List.beq as bs) := rfl instance [BEq α] : BEq (List α) := ⟨List.beq⟩ @@ -344,8 +344,8 @@ def getLastD : (as : List α) → (fallback : α) → α | a::as, _ => getLast (a::as) (fun h => List.noConfusion h) -- These aren't `simp` lemmas since we always simplify `getLastD` in terms of `getLast?`. -theorem getLastD_nil (a) : @getLastD α [] a = a := rfl -theorem getLastD_cons (a b l) : @getLastD α (b::l) a = getLastD l b := by cases l <;> rfl +theorem getLastD_nil {a : α} : getLastD [] a = a := rfl +theorem getLastD_cons {a b : α} {l} : getLastD (b::l) a = getLastD l b := by cases l <;> rfl /-! ## Head and tail -/ @@ -357,7 +357,7 @@ Returns the first element of a non-empty list. def head : (as : List α) → as ≠ [] → α | a::_, _ => a -@[simp] theorem head_cons : @head α (a::l) h = a := rfl +@[simp] theorem head_cons {a : α} {l : List α} {h} : head (a::l) h = a := rfl /-! ### head? -/ @@ -375,8 +375,8 @@ def head? : List α → Option α | [] => none | a::_ => some a -@[simp] theorem head?_nil : @head? α [] = none := rfl -@[simp] theorem head?_cons : @head? α (a::l) = some a := rfl +@[simp] theorem head?_nil : head? ([] : List α) = none := rfl +@[simp] theorem head?_cons {a : α} {l : List α} : head? (a::l) = some a := rfl /-! ### headD -/ @@ -394,8 +394,8 @@ def headD : (as : List α) → (fallback : α) → α | [], fallback => fallback | a::_, _ => a -@[simp] theorem headD_nil : @headD α [] d = d := rfl -@[simp] theorem headD_cons : @headD α (a::l) d = a := rfl +@[simp] theorem headD_nil {d : α} : headD [] d = d := rfl +@[simp] theorem headD_cons {a : α} {l : List α} {d : α} : headD (a::l) d = a := rfl /-! ### tail -/ @@ -412,8 +412,8 @@ def tail : List α → List α | [] => [] | _::as => as -@[simp] theorem tail_nil : @tail α [] = [] := rfl -@[simp] theorem tail_cons : @tail α (a::as) = as := rfl +@[simp] theorem tail_nil : tail ([] : List α) = [] := rfl +@[simp] theorem tail_cons {a : α} {as : List α} : tail (a::as) = as := rfl /-! ### tail? -/ @@ -433,8 +433,8 @@ def tail? : List α → Option (List α) | [] => none | _::as => some as -@[simp] theorem tail?_nil : @tail? α [] = none := rfl -@[simp] theorem tail?_cons : @tail? α (a::l) = some l := rfl +@[simp] theorem tail?_nil : tail? ([] : List α) = none := rfl +@[simp] theorem tail?_cons {a : α} {l : List α} : tail? (a::l) = some l := rfl /-! ### tailD -/ @@ -456,8 +456,8 @@ def tailD (l fallback : List α) : List α := | [] => fallback | _ :: tl => tl -@[simp] theorem tailD_nil : @tailD α [] l' = l' := rfl -@[simp] theorem tailD_cons : @tailD α (a::l) l' = l := rfl +@[simp] theorem tailD_nil {l' : List α} : tailD [] l' = l' := rfl +@[simp] theorem tailD_cons {a : α} {l : List α} {l' : List α} : tailD (a::l) l' = l := rfl /-! ## Basic `List` operations. @@ -483,7 +483,7 @@ Examples: | a::as => f a :: map f as @[simp] theorem map_nil {f : α → β} : map f [] = [] := rfl -@[simp] theorem map_cons (f : α → β) a l : map f (a :: l) = f a :: map f l := rfl +@[simp] theorem map_cons {f : α → β} {a : α} {l : List α} : map f (a :: l) = f a :: map f l := rfl /-! ### filter -/ @@ -503,7 +503,7 @@ def filter (p : α → Bool) : (l : List α) → List α | true => a :: filter p as | false => filter p as -@[simp] theorem filter_nil (p : α → Bool) : filter p [] = [] := rfl +@[simp] theorem filter_nil {p : α → Bool} : filter p [] = [] := rfl /-! ### filterMap -/ @@ -529,8 +529,8 @@ Example: | none => filterMap f as | some b => b :: filterMap f as -@[simp] theorem filterMap_nil (f : α → Option β) : filterMap f [] = [] := rfl -theorem filterMap_cons (f : α → Option β) (a : α) (l : List α) : +@[simp] theorem filterMap_nil {f : α → Option β} : filterMap f [] = [] := rfl +theorem filterMap_cons {f : α → Option β} {a : α} {l : List α} : filterMap f (a :: l) = match f a with | none => filterMap f l @@ -554,7 +554,8 @@ Examples: | a :: l => f a (foldr f init l) @[simp] theorem foldr_nil : [].foldr f b = b := rfl -@[simp] theorem foldr_cons (l : List α) : (a :: l).foldr f b = f a (l.foldr f b) := rfl +@[simp] theorem foldr_cons {a} {l : List α} {f : α → β → β} {b} : + (a :: l).foldr f b = f a (l.foldr f b) := rfl /-! ### reverse -/ @@ -584,10 +585,11 @@ def reverse (as : List α) : List α := @[simp] theorem reverse_nil : reverse ([] : List α) = [] := rfl -theorem reverseAux_reverseAux (as bs cs : List α) : reverseAux (reverseAux as bs) cs = reverseAux bs (reverseAux (reverseAux as []) cs) := by +theorem reverseAux_reverseAux {as bs cs : List α} : + reverseAux (reverseAux as bs) cs = reverseAux bs (reverseAux (reverseAux as []) cs) := by induction as generalizing bs cs with | nil => rfl - | cons a as ih => simp [reverseAux, ih (a::bs), ih [a]] + | cons a as ih => simp [reverseAux, ih (bs := a::bs), ih (bs := [a])] /-! ### append -/ @@ -633,10 +635,10 @@ def appendTR (as bs : List α) : List α := instance : Append (List α) := ⟨List.append⟩ -@[simp] theorem append_eq (as bs : List α) : List.append as bs = as ++ bs := rfl +@[simp] theorem append_eq {as bs : List α} : List.append as bs = as ++ bs := rfl @[simp] theorem nil_append (as : List α) : [] ++ as = as := rfl -@[simp] theorem cons_append (a : α) (as bs : List α) : (a::as) ++ bs = a::(as ++ bs) := rfl +@[simp] theorem cons_append {a : α} {as bs : List α} : (a::as) ++ bs = a::(as ++ bs) := rfl @[simp] theorem append_nil (as : List α) : as ++ [] = as := by induction as with @@ -648,7 +650,7 @@ instance : Std.LawfulIdentity (α := List α) (· ++ ·) [] where left_id := nil_append right_id := append_nil -@[simp] theorem length_append (as bs : List α) : (as ++ bs).length = as.length + bs.length := by +@[simp] theorem length_append {as bs : List α} : (as ++ bs).length = as.length + bs.length := by induction as with | nil => simp | cons _ as ih => simp [ih, Nat.succ_add] @@ -660,21 +662,22 @@ instance : Std.LawfulIdentity (α := List α) (· ++ ·) [] where instance : Std.Associative (α := List α) (· ++ ·) := ⟨append_assoc⟩ +-- Arguments are explicit as there is often ambiguity inferring the arguments. theorem append_cons (as : List α) (b : α) (bs : List α) : as ++ b :: bs = as ++ [b] ++ bs := by simp -@[simp] theorem concat_eq_append (as : List α) (a : α) : as.concat a = as ++ [a] := by +@[simp] theorem concat_eq_append {as : List α} {a : α} : as.concat a = as ++ [a] := by induction as <;> simp [concat, *] -theorem reverseAux_eq_append (as bs : List α) : reverseAux as bs = reverseAux as [] ++ bs := by +theorem reverseAux_eq_append {as bs : List α} : reverseAux as bs = reverseAux as [] ++ bs := by induction as generalizing bs with | nil => simp [reverseAux] | cons a as ih => simp [reverseAux] - rw [ih (a :: bs), ih [a], append_assoc] + rw [ih (bs := a :: bs), ih (bs := [a]), append_assoc] rfl -@[simp] theorem reverse_cons (a : α) (as : List α) : reverse (a :: as) = reverse as ++ [a] := by +@[simp] theorem reverse_cons {a : α} {as : List α} : reverse (a :: as) = reverse as ++ [a] := by simp [reverse, reverseAux] rw [← reverseAux_eq_append] @@ -725,8 +728,8 @@ Examples: -/ @[inline] def flatMap {α : Type u} {β : Type v} (b : α → List β) (as : List α) : List β := flatten (map b as) -@[simp] theorem flatMap_nil (f : α → List β) : List.flatMap f [] = [] := by simp [flatten, List.flatMap] -@[simp] theorem flatMap_cons x xs (f : α → List β) : +@[simp] theorem flatMap_nil {f : α → List β} : List.flatMap f [] = [] := by simp [flatten, List.flatMap] +@[simp] theorem flatMap_cons {x : α} {xs : List α} {f : α → List β} : List.flatMap f (x :: xs) = f x ++ List.flatMap f xs := by simp [flatten, List.flatMap] set_option linter.missingDocs false in @@ -749,10 +752,10 @@ def replicate : (n : Nat) → (a : α) → List α | 0, _ => [] | n+1, a => a :: replicate n a -@[simp] theorem replicate_zero : replicate 0 a = [] := rfl -theorem replicate_succ (a : α) (n) : replicate (n+1) a = a :: replicate n a := rfl +@[simp] theorem replicate_zero {a : α} : replicate 0 a = [] := rfl +theorem replicate_succ {a : α} {n : Nat} : replicate (n+1) a = a :: replicate n a := rfl -@[simp] theorem length_replicate (n : Nat) (a : α) : (replicate n a).length = n := by +@[simp] theorem length_replicate {n : Nat} {a : α} : (replicate n a).length = n := by induction n with | zero => simp | succ n ih => simp only [ih, replicate_succ, length_cons, Nat.succ_eq_add_one] @@ -911,7 +914,7 @@ theorem mem_append_left {a : α} {as : List α} (bs : List α) : a ∈ as → a | head => apply Mem.head | tail => apply Mem.tail; assumption -theorem mem_append_right {b : α} {bs : List α} (as : List α) : b ∈ bs → b ∈ as ++ bs := by +theorem mem_append_right {b : α} (as : List α) {bs : List α} : b ∈ bs → b ∈ as ++ bs := by intro h induction as with | nil => simp [h] @@ -959,9 +962,9 @@ def take : (n : Nat) → (xs : List α) → List α | _+1, [] => [] | n+1, a::as => a :: take n as -@[simp] theorem take_nil : ([] : List α).take i = [] := by cases i <;> rfl -@[simp] theorem take_zero (l : List α) : l.take 0 = [] := rfl -@[simp] theorem take_succ_cons : (a::as).take (i+1) = a :: as.take i := rfl +@[simp] theorem take_nil {i : Nat} : ([] : List α).take i = [] := by cases i <;> rfl +@[simp] theorem take_zero {l : List α} : l.take 0 = [] := rfl +@[simp] theorem take_succ_cons {a : α} {as : List α} {i : Nat} : (a::as).take (i+1) = a :: as.take i := rfl /-! ### drop -/ @@ -983,8 +986,8 @@ def drop : (n : Nat) → (xs : List α) → List α @[simp] theorem drop_nil : ([] : List α).drop i = [] := by cases i <;> rfl -@[simp] theorem drop_zero (l : List α) : l.drop 0 = l := rfl -@[simp] theorem drop_succ_cons : (a :: l).drop (i + 1) = l.drop i := rfl +@[simp] theorem drop_zero {l : List α} : l.drop 0 = l := rfl +@[simp] theorem drop_succ_cons {a : α} {l : List α} {i : Nat} : (a :: l).drop (i + 1) = l.drop i := rfl theorem drop_eq_nil_of_le {as : List α} {i : Nat} (h : as.length ≤ i) : as.drop i = [] := by match as, i with @@ -1009,7 +1012,7 @@ Examples: abbrev extract (l : List α) (start : Nat := 0) (stop : Nat := l.length) : List α := (l.drop start).take (stop - start) -@[simp] theorem extract_eq_drop_take (l : List α) (start stop : Nat) : +@[simp] theorem extract_eq_drop_take {l : List α} {start stop : Nat} : l.extract start stop = (l.drop start).take (stop - start) := rfl /-! ### takeWhile -/ @@ -1102,12 +1105,10 @@ def dropLast {α} : List α → List α -- Later this can be proved by `simp` via `[List.length_dropLast, List.length_cons, Nat.add_sub_cancel]`, -- but we need this while bootstrapping `Array`. -@[simp] theorem length_dropLast_cons (a : α) (as : List α) : (a :: as).dropLast.length = as.length := by +@[simp] theorem length_dropLast_cons {a : α} {as : List α} : (a :: as).dropLast.length = as.length := by match as with | [] => rfl - | b::bs => - have ih := length_dropLast_cons b bs - simp [dropLast, ih] + | b::bs => simp [dropLast, length_dropLast_cons] /-! ### Subset -/ @@ -1500,8 +1501,8 @@ Examples: | [] => [] | a :: l => f a :: l -@[simp] theorem modifyHead_nil (f : α → α) : [].modifyHead f = [] := by rw [modifyHead] -@[simp] theorem modifyHead_cons (a : α) (l : List α) (f : α → α) : +@[simp] theorem modifyHead_nil {f : α → α} : [].modifyHead f = [] := by rw [modifyHead] +@[simp] theorem modifyHead_cons {a : α} {l : List α} {f : α → α} : (a :: l).modifyHead f = f a :: l := by rw [modifyHead] /-- @@ -1566,7 +1567,7 @@ protected def erase {α} [BEq α] : List α → α → List α | false => a :: List.erase as b @[simp] theorem erase_nil [BEq α] (a : α) : [].erase a = [] := rfl -theorem erase_cons [BEq α] (a b : α) (l : List α) : +theorem erase_cons [BEq α] {a b : α} {l : List α} : (b :: l).erase a = if b == a then l else b :: l.erase a := by simp only [List.erase]; split <;> simp_all @@ -1668,7 +1669,7 @@ Examples: | [], n => n | a :: l, n => bif p a then n else go l (n + 1) -@[simp] theorem findIdx_nil {α : Type _} (p : α → Bool) : [].findIdx p = 0 := rfl +@[simp] theorem findIdx_nil {p : α → Bool} : [].findIdx p = 0 := rfl /-! ### idxOf -/ @@ -1805,14 +1806,14 @@ Examples: * `[(1, "one"), (3, "three"), (3, "other")].lookup 2 = none` -/ def lookup [BEq α] : α → List (α × β) → Option β - | _, [] => none - | a, (k,b)::as => match a == k with + | _, [] => none + | a, (k, b) :: as => match a == k with | true => some b | false => lookup a as @[simp] theorem lookup_nil [BEq α] : ([] : List (α × β)).lookup a = none := rfl theorem lookup_cons [BEq α] {k : α} : - ((k,b)::as).lookup a = match a == k with | true => some b | false => as.lookup a := + ((k, b)::as).lookup a = match a == k with | true => some b | false => as.lookup a := rfl /-! ## Permutations -/ @@ -2220,9 +2221,9 @@ def intersperse (sep : α) : (l : List α) → List α | [x] => [x] | x::xs => x :: sep :: intersperse sep xs -@[simp] theorem intersperse_nil (sep : α) : ([] : List α).intersperse sep = [] := rfl -@[simp] theorem intersperse_single (sep : α) : [x].intersperse sep = [x] := rfl -@[simp] theorem intersperse_cons₂ (sep : α) : +@[simp] theorem intersperse_nil {sep : α} : ([] : List α).intersperse sep = [] := rfl +@[simp] theorem intersperse_single {x : α} {sep : α} : [x].intersperse sep = [x] := rfl +@[simp] theorem intersperse_cons₂ {x : α} {y : α} {zs : List α} {sep : α} : (x::y::zs).intersperse sep = x::sep::((y::zs).intersperse sep) := rfl /-! ### intercalate -/ @@ -2368,7 +2369,7 @@ then at runtime you will get non tail-recursive versions. /-! ### length -/ -theorem length_add_eq_lengthTRAux (as : List α) (n : Nat) : as.length + n = as.lengthTRAux n := by +theorem length_add_eq_lengthTRAux {as : List α} {n : Nat} : as.length + n = as.lengthTRAux n := by induction as generalizing n with | nil => simp [length, lengthTRAux] | cons a as ih => @@ -2399,13 +2400,13 @@ where | [], bs => bs.reverse | a::as, bs => loop as (f a :: bs) -theorem mapTR_loop_eq (f : α → β) (as : List α) (bs : List β) : +theorem mapTR_loop_eq {f : α → β} {as : List α} {bs : List β} : mapTR.loop f as bs = bs.reverse ++ map f as := by induction as generalizing bs with | nil => simp [mapTR.loop, map] | cons a as ih => simp only [mapTR.loop, map] - rw [ih (f a :: bs), reverse_cons, append_assoc] + rw [ih (bs := f a :: bs), reverse_cons, append_assoc] rfl @[csimp] theorem map_eq_mapTR : @map = @mapTR := @@ -2433,7 +2434,7 @@ where | true => loop as (a::acc) | false => loop as acc -theorem filterTR_loop_eq (p : α → Bool) (as bs : List α) : +theorem filterTR_loop_eq {p : α → Bool} {as : List α} {bs : List α} : filterTR.loop p as bs = bs.reverse ++ filter p as := by induction as generalizing bs with | nil => simp [filterTR.loop, filter] @@ -2462,19 +2463,19 @@ def replicateTR {α : Type u} (n : Nat) (a : α) : List α := | n+1, as => loop n (a::as) loop n [] -theorem replicateTR_loop_replicate_eq (a : α) (m n : Nat) : +theorem replicateTR_loop_replicate_eq {a : α} {m n : Nat} : replicateTR.loop a n (replicate m a) = replicate (n + m) a := by induction n generalizing m with simp [replicateTR.loop] - | succ n ih => simp [Nat.succ_add]; exact ih (m+1) + | succ n ih => simp [Nat.succ_add]; exact ih (m := m+1) theorem replicateTR_loop_eq : ∀ n, replicateTR.loop a n acc = replicate n a ++ acc | 0 => rfl - | n+1 => by rw [← replicateTR_loop_replicate_eq _ 1 n, replicate, replicate, + | n+1 => by rw [← replicateTR_loop_replicate_eq, replicate, replicate, replicateTR.loop, replicateTR_loop_eq n, replicateTR_loop_eq n, append_assoc]; rfl @[csimp] theorem replicate_eq_replicateTR : @List.replicate = @List.replicateTR := by apply funext; intro α; apply funext; intro n; apply funext; intro a - exact (replicateTR_loop_replicate_eq _ 0 n).symm + exact (replicateTR_loop_replicate_eq (m := 0)).symm /-! ## Additional functions -/ diff --git a/src/Init/Data/List/Control.lean b/src/Init/Data/List/Control.lean index b678e7a65e..7a69c675ad 100644 --- a/src/Init/Data/List/Control.lean +++ b/src/Init/Data/List/Control.lean @@ -236,8 +236,8 @@ def foldlM {m : Type u → Type v} [Monad m] {s : Type u} {α : Type w} : (f : s let s' ← f s a List.foldlM f s' as -@[simp] theorem foldlM_nil [Monad m] (f : β → α → m β) (b) : [].foldlM f b = pure b := rfl -@[simp] theorem foldlM_cons [Monad m] (f : β → α → m β) (b) (a) (l : List α) : +@[simp] theorem foldlM_nil [Monad m] {f : β → α → m β} {b : β} : [].foldlM f b = pure b := rfl +@[simp] theorem foldlM_cons [Monad m] {f : β → α → m β} {b : β} {a : α} {l : List α} : (a :: l).foldlM f b = f b a >>= l.foldlM f := by simp [List.foldlM] @@ -260,7 +260,7 @@ example [Monad m] (f : α → β → m β) : def foldrM {m : Type u → Type v} [Monad m] {s : Type u} {α : Type w} (f : α → s → m s) (init : s) (l : List α) : m s := l.reverse.foldlM (fun s a => f a s) init -@[simp] theorem foldrM_nil [Monad m] (f : α → β → m β) (b) : [].foldrM f b = pure b := rfl +@[simp] theorem foldrM_nil [Monad m] {f : α → β → m β} {b : β} : [].foldrM f b = pure b := rfl /-- Maps `f` over the list and collects the results with `<|>`. The result for the end of the list is @@ -382,7 +382,7 @@ def findSomeM? {m : Type u → Type v} [Monad m] {α : Type w} {β : Type u} (f | none => findSomeM? f as @[simp] -theorem findSomeM?_pure [Monad m] [LawfulMonad m] (f : α → Option β) (as : List α) : +theorem findSomeM?_pure [Monad m] [LawfulMonad m] {f : α → Option β} {as : List α} : findSomeM? (m := m) (pure <| f ·) as = pure (as.findSome? f) := by induction as with | nil => rfl @@ -393,10 +393,10 @@ theorem findSomeM?_pure [Monad m] [LawfulMonad m] (f : α → Option β) (as : L | none => simp [ih] @[simp] -theorem findSomeM?_id (f : α → Option β) (as : List α) : findSomeM? (m := Id) f as = as.findSome? f := - findSomeM?_pure _ _ +theorem findSomeM?_id {f : α → Option β} {as : List α} : findSomeM? (m := Id) f as = as.findSome? f := + findSomeM?_pure -theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] (p : α → m Bool) (as : List α) : +theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] {p : α → m Bool} {as : List α} : as.findM? p = as.findSomeM? fun a => return if (← p a) then some a else none := by induction as with | nil => rfl @@ -420,7 +420,7 @@ theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] (p : α → m Bool) (as : match (← f a this b) with | ForInStep.done b => pure b | ForInStep.yield b => - have : Exists (fun bs => bs ++ as' = as) := have ⟨bs, h⟩ := h; ⟨bs ++ [a], by rw [← h, append_cons bs a as']⟩ + have : Exists (fun bs => bs ++ as' = as) := have ⟨bs, h⟩ := h; ⟨bs ++ [a], by rw [← h, append_cons (bs := as')]⟩ loop as' b this loop as init ⟨[], rfl⟩ @@ -432,10 +432,10 @@ instance : ForIn' m (List α) α inferInstance where -- We simplify `List.forIn'` to `forIn'`. @[simp] theorem forIn'_eq_forIn' [Monad m] : @List.forIn' α β m _ = forIn' := rfl -@[simp] theorem forIn'_nil [Monad m] (f : (a : α) → a ∈ [] → β → m (ForInStep β)) (b : β) : forIn' [] b f = pure b := +@[simp] theorem forIn'_nil [Monad m] {f : (a : α) → a ∈ [] → β → m (ForInStep β)} {b : β} : forIn' [] b f = pure b := rfl -@[simp] theorem forIn_nil [Monad m] (f : α → β → m (ForInStep β)) (b : β) : forIn [] b f = pure b := +@[simp] theorem forIn_nil [Monad m] {f : α → β → m (ForInStep β)} {b : β} : forIn [] b f = pure b := rfl instance : ForM m (List α) α where @@ -444,9 +444,9 @@ instance : ForM m (List α) α where -- We simplify `List.forM` to `forM`. @[simp] theorem forM_eq_forM [Monad m] : @List.forM m _ α = forM := rfl -@[simp] theorem forM_nil [Monad m] (f : α → m PUnit) : forM [] f = pure ⟨⟩ := +@[simp] theorem forM_nil [Monad m] {f : α → m PUnit} : forM [] f = pure ⟨⟩ := rfl -@[simp] theorem forM_cons [Monad m] (f : α → m PUnit) (a : α) (as : List α) : forM (a::as) f = f a >>= fun _ => forM as f := +@[simp] theorem forM_cons [Monad m] {f : α → m PUnit} {a : α} {as : List α} : forM (a::as) f = f a >>= fun _ => forM as f := rfl instance : Functor List where diff --git a/src/Init/Data/List/Count.lean b/src/Init/Data/List/Count.lean index 15e2c8a811..5ae3eca97d 100644 --- a/src/Init/Data/List/Count.lean +++ b/src/Init/Data/List/Count.lean @@ -20,11 +20,11 @@ open Nat /-! ### countP -/ section countP -variable (p q : α → Bool) +variable {p q : α → Bool} @[simp] theorem countP_nil : countP p [] = 0 := rfl -protected theorem countP_go_eq_add (l) : countP.go p l n = n + countP.go p l 0 := by +protected theorem countP_go_eq_add {l} : countP.go p l n = n + countP.go p l 0 := by induction l generalizing n with | nil => rfl | cons hd _ ih => @@ -32,40 +32,40 @@ protected theorem countP_go_eq_add (l) : countP.go p l n = n + countP.go p l 0 : rw [ih (n := n + 1), ih (n := n), ih (n := 1)] if h : p hd then simp [h, Nat.add_assoc] else simp [h] -@[simp] theorem countP_cons_of_pos (l) (pa : p a) : countP p (a :: l) = countP p l + 1 := by +@[simp] theorem countP_cons_of_pos {l} (pa : p a) : countP p (a :: l) = countP p l + 1 := by have : countP.go p (a :: l) 0 = countP.go p l 1 := show cond .. = _ by rw [pa]; rfl unfold countP rw [this, Nat.add_comm, List.countP_go_eq_add] -@[simp] theorem countP_cons_of_neg (l) (pa : ¬p a) : countP p (a :: l) = countP p l := by +@[simp] theorem countP_cons_of_neg {l} (pa : ¬p a) : countP p (a :: l) = countP p l := by simp [countP, countP.go, pa] -theorem countP_cons (a : α) (l) : countP p (a :: l) = countP p l + if p a then 1 else 0 := by +theorem countP_cons {a : α} {l : List α} : countP p (a :: l) = countP p l + if p a then 1 else 0 := by by_cases h : p a <;> simp [h] -@[simp] theorem countP_singleton (a : α) : countP p [a] = if p a then 1 else 0 := by +@[simp] theorem countP_singleton {a : α} : countP p [a] = if p a then 1 else 0 := by simp [countP_cons] -theorem length_eq_countP_add_countP (l) : length l = countP p l + countP (fun a => ¬p a) l := by +theorem length_eq_countP_add_countP (p : α → Bool) {l : List α} : length l = countP p l + countP (fun a => ¬p a) l := by induction l with | nil => rfl | cons hd _ ih => if h : p hd then - rw [countP_cons_of_pos _ _ h, countP_cons_of_neg _ _ _, length, ih] + rw [countP_cons_of_pos h, countP_cons_of_neg _, length, ih] · rw [Nat.add_assoc, Nat.add_comm _ 1, Nat.add_assoc] · simp [h] else - rw [countP_cons_of_pos (fun a => ¬p a) _ _, countP_cons_of_neg _ _ h, length, ih] + rw [countP_cons_of_pos (p := fun a => ¬p a), countP_cons_of_neg h, length, ih] · rfl · simp [h] -theorem countP_eq_length_filter (l) : countP p l = length (filter p l) := by +theorem countP_eq_length_filter {l : List α} : countP p l = length (filter p l) := by induction l with | nil => rfl | cons x l ih => if h : p x - then rw [countP_cons_of_pos p l h, ih, filter_cons_of_pos h, length] - else rw [countP_cons_of_neg p l h, ih, filter_cons_of_neg h] + then rw [countP_cons_of_pos h, ih, filter_cons_of_pos h, length] + else rw [countP_cons_of_neg h, ih, filter_cons_of_neg h] theorem countP_eq_length_filter' : countP p = length ∘ filter p := by funext l @@ -75,7 +75,7 @@ theorem countP_le_length : countP p l ≤ l.length := by simp only [countP_eq_length_filter] apply length_filter_le -@[simp] theorem countP_append (l₁ l₂) : countP p (l₁ ++ l₂) = countP p l₁ + countP p l₂ := by +@[simp] theorem countP_append {l₁ l₂ : List α} : countP p (l₁ ++ l₂) = countP p l₁ + countP p l₂ := by simp only [countP_eq_length_filter, filter_append, length_append] @[simp] theorem countP_pos_iff {p} : 0 < countP p l ↔ ∃ a ∈ l, p a := by @@ -92,12 +92,12 @@ theorem countP_le_length : countP p l ≤ l.length := by @[simp] theorem countP_eq_length {p} : countP p l = l.length ↔ ∀ a ∈ l, p a := by rw [countP_eq_length_filter, length_filter_eq_length_iff] -theorem countP_replicate (p : α → Bool) (a : α) (n : Nat) : +theorem countP_replicate {p : α → Bool} {a : α} {n : Nat} : countP p (replicate n a) = if p a then n else 0 := by simp only [countP_eq_length_filter, filter_replicate] split <;> simp -theorem boole_getElem_le_countP (p : α → Bool) (l : List α) (i : Nat) (h : i < l.length) : +theorem boole_getElem_le_countP {p : α → Bool} {l : List α} {i : Nat} (h : i < l.length) : (if p l[i] then 1 else 0) ≤ l.countP p := by induction l generalizing i with | nil => simp at h @@ -107,25 +107,25 @@ theorem boole_getElem_le_countP (p : α → Bool) (l : List α) (i : Nat) (h : i | succ i => simp only [length_cons, add_one_lt_add_one_iff] at h simp only [getElem_cons_succ, countP_cons] - specialize ih _ h + specialize ih h exact le_add_right_of_le ih theorem Sublist.countP_le (s : l₁ <+ l₂) : countP p l₁ ≤ countP p l₂ := by simp only [countP_eq_length_filter] apply s.filter _ |>.length_le -theorem IsPrefix.countP_le (s : l₁ <+: l₂) : countP p l₁ ≤ countP p l₂ := s.sublist.countP_le _ -theorem IsSuffix.countP_le (s : l₁ <:+ l₂) : countP p l₁ ≤ countP p l₂ := s.sublist.countP_le _ -theorem IsInfix.countP_le (s : l₁ <:+: l₂) : countP p l₁ ≤ countP p l₂ := s.sublist.countP_le _ +theorem IsPrefix.countP_le (s : l₁ <+: l₂) : countP p l₁ ≤ countP p l₂ := s.sublist.countP_le +theorem IsSuffix.countP_le (s : l₁ <:+ l₂) : countP p l₁ ≤ countP p l₂ := s.sublist.countP_le +theorem IsInfix.countP_le (s : l₁ <:+: l₂) : countP p l₁ ≤ countP p l₂ := s.sublist.countP_le -- See `Init.Data.List.Nat.Count` for `Sublist.le_countP : countP p l₂ - (l₂.length - l₁.length) ≤ countP p l₁`. theorem countP_tail_le (l) : countP p l.tail ≤ countP p l := - (tail_sublist l).countP_le _ + (tail_sublist l).countP_le -- See `Init.Data.List.Nat.Count` for `le_countP_tail : countP p l - 1 ≤ countP p l.tail`. -theorem countP_filter (l : List α) : +theorem countP_filter {l : List α} : countP p (filter q l) = countP (fun a => p a && q a) l := by simp only [countP_eq_length_filter, filter_filter] @@ -137,12 +137,12 @@ theorem countP_filter (l : List α) : funext l simp -@[simp] theorem countP_map (p : β → Bool) (f : α → β) : - ∀ l, countP p (map f l) = countP (p ∘ f) l +@[simp] theorem countP_map {p : β → Bool} {f : α → β} : + ∀ {l}, countP p (map f l) = countP (p ∘ f) l | [] => rfl - | a :: l => by rw [map_cons, countP_cons, countP_cons, countP_map p f l]; rfl + | a :: l => by rw [map_cons, countP_cons, countP_cons, countP_map]; rfl -theorem length_filterMap_eq_countP (f : α → Option β) (l : List α) : +theorem length_filterMap_eq_countP {f : α → Option β} {l : List α} : (filterMap f l).length = countP (fun a => (f a).isSome) l := by induction l with | nil => rfl @@ -150,7 +150,7 @@ theorem length_filterMap_eq_countP (f : α → Option β) (l : List α) : simp only [filterMap_cons, countP_cons] split <;> simp [ih, *] -theorem countP_filterMap (p : β → Bool) (f : α → Option β) (l : List α) : +theorem countP_filterMap {p : β → Bool} {f : α → Option β} {l : List α} : countP p (filterMap f l) = countP (fun a => ((f a).map p).getD false) l := by simp only [countP_eq_length_filter, filter_filterMap, ← filterMap_eq_filter] simp only [length_filterMap_eq_countP] @@ -158,22 +158,20 @@ theorem countP_filterMap (p : β → Bool) (f : α → Option β) (l : List α) ext a simp +contextual [Option.getD_eq_iff, Option.isSome_eq_isSome] -@[simp] theorem countP_flatten (l : List (List α)) : +@[simp] theorem countP_flatten {l : List (List α)} : countP p l.flatten = (l.map (countP p)).sum := by simp only [countP_eq_length_filter, filter_flatten] simp [countP_eq_length_filter'] @[deprecated countP_flatten (since := "2024-10-14")] abbrev countP_join := @countP_flatten -theorem countP_flatMap (p : β → Bool) (l : List α) (f : α → List β) : +theorem countP_flatMap {p : β → Bool} {l : List α} {f : α → List β} : countP p (l.flatMap f) = sum (map (countP p ∘ f) l) := by rw [List.flatMap, countP_flatten, map_map] -@[simp] theorem countP_reverse (l : List α) : countP p l.reverse = countP p l := by +@[simp] theorem countP_reverse {l : List α} : countP p l.reverse = countP p l := by simp [countP_eq_length_filter, filter_reverse] -variable {p q} - theorem countP_mono_left (h : ∀ x ∈ l, p x → q x) : countP p l ≤ countP q l := by induction l with | nil => apply Nat.le_refl @@ -200,70 +198,69 @@ section count variable [BEq α] -@[simp] theorem count_nil (a : α) : count a [] = 0 := rfl +@[simp] theorem count_nil {a : α} : count a [] = 0 := rfl -theorem count_cons (a b : α) (l : List α) : +theorem count_cons {a b : α} {l : List α} : count a (b :: l) = count a l + if b == a then 1 else 0 := by simp [count, countP_cons] -theorem count_eq_countP (a : α) (l : List α) : count a l = countP (· == a) l := rfl +theorem count_eq_countP {a : α} {l : List α} : count a l = countP (· == a) l := rfl theorem count_eq_countP' {a : α} : count a = countP (· == a) := by funext l apply count_eq_countP -theorem count_tail : ∀ (l : List α) (a : α) (h : l ≠ []), +theorem count_tail : ∀ {l : List α} {a : α} (h : l ≠ []), l.tail.count a = l.count a - if l.head h == a then 1 else 0 | _ :: _, a, _ => by simp [count_cons] -theorem count_le_length (a : α) (l : List α) : count a l ≤ l.length := countP_le_length _ +theorem count_le_length {a : α} {l : List α} : count a l ≤ l.length := countP_le_length -theorem Sublist.count_le (h : l₁ <+ l₂) (a : α) : count a l₁ ≤ count a l₂ := h.countP_le _ +theorem Sublist.count_le (a : α) (h : l₁ <+ l₂) : count a l₁ ≤ count a l₂ := h.countP_le -theorem IsPrefix.count_le (h : l₁ <+: l₂) (a : α) : count a l₁ ≤ count a l₂ := h.sublist.count_le _ -theorem IsSuffix.count_le (h : l₁ <:+ l₂) (a : α) : count a l₁ ≤ count a l₂ := h.sublist.count_le _ -theorem IsInfix.count_le (h : l₁ <:+: l₂) (a : α) : count a l₁ ≤ count a l₂ := h.sublist.count_le _ +theorem IsPrefix.count_le (a : α) (h : l₁ <+: l₂) : count a l₁ ≤ count a l₂ := h.sublist.count_le a +theorem IsSuffix.count_le (a : α) (h : l₁ <:+ l₂) : count a l₁ ≤ count a l₂ := h.sublist.count_le a +theorem IsInfix.count_le (a : α) (h : l₁ <:+: l₂) : count a l₁ ≤ count a l₂ := h.sublist.count_le a -- See `Init.Data.List.Nat.Count` for `Sublist.le_count : count a l₂ - (l₂.length - l₁.length) ≤ countP a l₁`. -theorem count_tail_le (a : α) (l) : count a l.tail ≤ count a l := - (tail_sublist l).count_le _ +theorem count_tail_le {a : α} {l : List α} : count a l.tail ≤ count a l := + (tail_sublist l).count_le a -- See `Init.Data.List.Nat.Count` for `le_count_tail : count a l - 1 ≤ count a l.tail`. -theorem count_le_count_cons (a b : α) (l : List α) : count a l ≤ count a (b :: l) := - (sublist_cons_self _ _).count_le _ +theorem count_le_count_cons {a b : α} {l : List α} : count a l ≤ count a (b :: l) := + (sublist_cons_self _ _).count_le a -theorem count_singleton (a b : α) : count a [b] = if b == a then 1 else 0 := by +theorem count_singleton {a b : α} : count a [b] = if b == a then 1 else 0 := by simp [count_cons] -@[simp] theorem count_append (a : α) : ∀ l₁ l₂, count a (l₁ ++ l₂) = count a l₁ + count a l₂ := - countP_append _ +@[simp] theorem count_append {a : α} {l₁ l₂ : List α} : count a (l₁ ++ l₂) = count a l₁ + count a l₂ := + countP_append -theorem count_flatten (a : α) (l : List (List α)) : count a l.flatten = (l.map (count a)).sum := by +theorem count_flatten {a : α} {l : List (List α)} : count a l.flatten = (l.map (count a)).sum := by simp only [count_eq_countP, countP_flatten, count_eq_countP'] @[deprecated count_flatten (since := "2024-10-14")] abbrev count_join := @count_flatten -@[simp] theorem count_reverse (a : α) (l : List α) : count a l.reverse = count a l := by +@[simp] theorem count_reverse {a : α} {l : List α} : count a l.reverse = count a l := by simp only [count_eq_countP, countP_eq_length_filter, filter_reverse, length_reverse] -theorem boole_getElem_le_count (a : α) (l : List α) (i : Nat) (h : i < l.length) : +theorem boole_getElem_le_count {a : α} {l : List α} {i : Nat} (h : i < l.length) : (if l[i] == a then 1 else 0) ≤ l.count a := by rw [count_eq_countP] - apply boole_getElem_le_countP (· == a) + apply boole_getElem_le_countP (p := (· == a)) variable [LawfulBEq α] -@[simp] theorem count_cons_self (a : α) (l : List α) : count a (a :: l) = count a l + 1 := by +@[simp] theorem count_cons_self {a : α} {l : List α} : count a (a :: l) = count a l + 1 := by simp [count_cons] -@[simp] theorem count_cons_of_ne (h : b ≠ a) (l : List α) : count a (b :: l) = count a l := by +@[simp] theorem count_cons_of_ne (h : b ≠ a) {l : List α} : count a (b :: l) = count a l := by simp [count_cons, h] -theorem count_singleton_self (a : α) : count a [a] = 1 := by simp +theorem count_singleton_self {a : α} : count a [a] = 1 := by simp -theorem count_concat_self (a : α) (l : List α) : - count a (concat l a) = (count a l) + 1 := by simp +theorem count_concat_self {a : α} {l : List α} : count a (concat l a) = count a l + 1 := by simp @[simp] theorem count_pos_iff {a : α} {l : List α} : 0 < count a l ↔ a ∈ l := by @@ -289,41 +286,40 @@ theorem count_eq_length {l : List α} : count a l = l.length ↔ ∀ b ∈ l, a · simpa using h b hb · rw [h b hb, beq_self_eq_true] -@[simp] theorem count_replicate_self (a : α) (n : Nat) : count a (replicate n a) = n := +@[simp] theorem count_replicate_self {a : α} {n : Nat} : count a (replicate n a) = n := (count_eq_length.2 <| fun _ h => (eq_of_mem_replicate h).symm).trans (length_replicate ..) -theorem count_replicate (a b : α) (n : Nat) : count a (replicate n b) = if b == a then n else 0 := by +theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by split <;> (rename_i h; simp only [beq_iff_eq] at h) · exact ‹b = a› ▸ count_replicate_self .. · exact count_eq_zero.2 <| mt eq_of_mem_replicate (Ne.symm h) -theorem filter_beq (l : List α) (a : α) : l.filter (· == a) = replicate (count a l) a := by +theorem filter_beq {l : List α} (a : α) : l.filter (· == a) = replicate (count a l) a := by simp only [count, countP_eq_length_filter, eq_replicate_iff, mem_filter, beq_iff_eq] exact ⟨trivial, fun _ h => h.2⟩ -theorem filter_eq {α} [DecidableEq α] (l : List α) (a : α) : l.filter (· = a) = replicate (count a l) a := - filter_beq l a +theorem filter_eq {α} [DecidableEq α] {l : List α} (a : α) : l.filter (· = a) = replicate (count a l) a := + filter_beq a theorem le_count_iff_replicate_sublist {l : List α} : n ≤ count a l ↔ replicate n a <+ l := by refine ⟨fun h => ?_, fun h => ?_⟩ - · exact ((replicate_sublist_replicate a).2 h).trans <| filter_beq l a ▸ filter_sublist _ + · exact ((replicate_sublist_replicate a).2 h).trans <| filter_beq a ▸ filter_sublist · simpa only [count_replicate_self] using h.count_le a theorem replicate_count_eq_of_count_eq_length {l : List α} (h : count a l = length l) : replicate (count a l) a = l := - (le_count_iff_replicate_sublist.mp (Nat.le_refl _)).eq_of_length <| - (length_replicate (count a l) a).trans h + (le_count_iff_replicate_sublist.mp (Nat.le_refl _)).eq_of_length <| length_replicate.trans h @[simp] theorem count_filter {l : List α} (h : p a) : count a (filter p l) = count a l := by rw [count, countP_filter]; congr; funext b simp; rintro rfl; exact h -theorem count_le_count_map [DecidableEq β] (l : List α) (f : α → β) (x : α) : +theorem count_le_count_map [DecidableEq β] {l : List α} {f : α → β} {x : α} : count x l ≤ count (f x) (map f l) := by rw [count, count, countP_map] apply countP_mono_left; simp +contextual -theorem count_filterMap {α} [BEq β] (b : β) (f : α → Option β) (l : List α) : +theorem count_filterMap {α} [BEq β] {b : β} {f : α → Option β} {l : List α} : count b (filterMap f l) = countP (fun a => f a == some b) l := by rw [count_eq_countP, countP_filterMap] congr @@ -332,11 +328,11 @@ theorem count_filterMap {α} [BEq β] (b : β) (f : α → Option β) (l : List · simp · simp -theorem count_flatMap {α} [BEq β] (l : List α) (f : α → List β) (x : β) : - count x (l.flatMap f) = sum (map (count x ∘ f) l) := countP_flatMap _ _ _ +theorem count_flatMap {α} [BEq β] {l : List α} {f : α → List β} {x : β} : + count x (l.flatMap f) = sum (map (count x ∘ f) l) := countP_flatMap -theorem count_erase (a b : α) : - ∀ l : List α, count a (l.erase b) = count a l - if b == a then 1 else 0 +theorem count_erase {a b : α} : + ∀ {l : List α}, count a (l.erase b) = count a l - if b == a then 1 else 0 | [] => by simp | c :: l => by rw [erase_cons] @@ -345,17 +341,17 @@ theorem count_erase (a b : α) : rw [if_pos hc_beq, hc, count_cons, Nat.add_sub_cancel] else have hc_beq := beq_false_of_ne hc - simp only [hc_beq, if_false, count_cons, count_cons, count_erase a b l, reduceCtorEq] + simp only [hc_beq, if_false, count_cons, count_cons, count_erase, reduceCtorEq] if ha : b = a then rw [ha, eq_comm] at hc rw [if_pos (beq_iff_eq.2 ha), if_neg (by simpa using Ne.symm hc), Nat.add_zero, Nat.add_zero] else rw [if_neg (by simpa using ha), Nat.sub_zero, Nat.sub_zero] -@[simp] theorem count_erase_self (a : α) (l : List α) : +@[simp] theorem count_erase_self {a : α} {l : List α} : count a (List.erase l a) = count a l - 1 := by rw [count_erase, if_pos (by simp)] -@[simp] theorem count_erase_of_ne (ab : a ≠ b) (l : List α) : count a (l.erase b) = count a l := by +@[simp] theorem count_erase_of_ne (ab : a ≠ b) {l : List α} : count a (l.erase b) = count a l := by rw [count_erase, if_neg (by simpa using ab.symm), Nat.sub_zero] end count diff --git a/src/Init/Data/List/Erase.lean b/src/Init/Data/List/Erase.lean index 8cfa2ac8f8..834e34084c 100644 --- a/src/Init/Data/List/Erase.lean +++ b/src/Init/Data/List/Erase.lean @@ -23,7 +23,7 @@ open Nat @[simp] theorem eraseP_nil : [].eraseP p = [] := rfl -theorem eraseP_cons (a : α) (l : List α) : +theorem eraseP_cons {a : α} {l : List α} : (a :: l).eraseP p = bif p a then l else a :: l.eraseP p := rfl @[simp] theorem eraseP_cons_of_pos {l : List α} {p} (h : p a) : (a :: l).eraseP p = l := by @@ -75,6 +75,7 @@ theorem exists_of_eraseP : ∀ {l : List α} {a} (_ : a ∈ l) (_ : p a), ⟨c, b::l₁, l₂, (forall_mem_cons ..).2 ⟨pb, h₁⟩, h₂, by rw [h₃, cons_append], by simp [pb, h₄]⟩ +-- The arguments are explicit here, so this lemma can be used as a case split. theorem exists_or_eq_self_of_eraseP (p) (l : List α) : l.eraseP p = l ∨ ∃ a l₁ l₂, (∀ b ∈ l₁, ¬p b) ∧ p a ∧ l = l₁ ++ a :: l₂ ∧ l.eraseP p = l₁ ++ l₂ := @@ -98,32 +99,32 @@ theorem length_eraseP {l : List α} : (l.eraseP p).length = if l.any p then l.le rw [eraseP_of_forall_not] simp_all -theorem eraseP_sublist (l : List α) : l.eraseP p <+ l := by +theorem eraseP_sublist {l : List α} : l.eraseP p <+ l := by match exists_or_eq_self_of_eraseP p l with | .inl h => rw [h]; apply Sublist.refl | .inr ⟨c, l₁, l₂, _, _, h₃, h₄⟩ => rw [h₄, h₃]; simp -theorem eraseP_subset (l : List α) : l.eraseP p ⊆ l := (eraseP_sublist l).subset +theorem eraseP_subset {l : List α} : l.eraseP p ⊆ l := eraseP_sublist.subset protected theorem Sublist.eraseP : l₁ <+ l₂ → l₁.eraseP p <+ l₂.eraseP p | .slnil => Sublist.refl _ | .cons a s => by by_cases h : p a - · simpa [h] using s.eraseP.trans (eraseP_sublist _) + · simpa [h] using s.eraseP.trans eraseP_sublist · simpa [h] using s.eraseP.cons _ | .cons₂ a s => by by_cases h : p a · simpa [h] using s · simpa [h] using s.eraseP -theorem length_eraseP_le (l : List α) : (l.eraseP p).length ≤ l.length := - l.eraseP_sublist.length_le +theorem length_eraseP_le {l : List α} : (l.eraseP p).length ≤ l.length := + eraseP_sublist.length_le -theorem le_length_eraseP (l : List α) : l.length - 1 ≤ (l.eraseP p).length := by +theorem le_length_eraseP {l : List α} : l.length - 1 ≤ (l.eraseP p).length := by rw [length_eraseP] split <;> simp -theorem mem_of_mem_eraseP {l : List α} : a ∈ l.eraseP p → a ∈ l := (eraseP_subset _ ·) +theorem mem_of_mem_eraseP {l : List α} : a ∈ l.eraseP p → a ∈ l := (eraseP_subset ·) @[simp] theorem mem_eraseP_of_neg {l : List α} (pa : ¬p a) : a ∈ l.eraseP p ↔ a ∈ l := by refine ⟨mem_of_mem_eraseP, fun al => ?_⟩ @@ -135,7 +136,7 @@ theorem mem_of_mem_eraseP {l : List α} : a ∈ l.eraseP p → a ∈ l := (erase simp [this] at al; simp [al] @[simp] theorem eraseP_eq_self_iff {p} {l : List α} : l.eraseP p = l ↔ ∀ a ∈ l, ¬ p a := by - rw [← Sublist.length_eq (eraseP_sublist l), length_eraseP] + rw [← Sublist.length_eq eraseP_sublist, length_eraseP] split <;> rename_i h · simp only [any_eq_true, length_eq_zero_iff] at h constructor @@ -143,11 +144,11 @@ theorem mem_of_mem_eraseP {l : List α} : a ∈ l.eraseP p → a ∈ l := (erase · intro; obtain ⟨x, m, h⟩ := h; simp_all · simp_all -theorem eraseP_map (f : β → α) : ∀ (l : List β), (map f l).eraseP p = map f (l.eraseP (p ∘ f)) +theorem eraseP_map {f : β → α} : ∀ {l : List β}, (map f l).eraseP p = map f (l.eraseP (p ∘ f)) | [] => rfl - | b::l => by by_cases h : p (f b) <;> simp [h, eraseP_map f l, eraseP_cons_of_pos] + | b::l => by by_cases h : p (f b) <;> simp [h, eraseP_map, eraseP_cons_of_pos] -theorem eraseP_filterMap (f : α → Option β) : ∀ (l : List α), +theorem eraseP_filterMap {f : α → Option β} : ∀ {l : List α}, (filterMap f l).eraseP p = filterMap f (l.eraseP (fun x => match f x with | some y => p y | none => false)) | [] => rfl | a::l => by @@ -161,7 +162,7 @@ theorem eraseP_filterMap (f : α → Option β) : ∀ (l : List α), · simp only [w, cond_false] rw [filterMap_cons_some h, eraseP_filterMap] -theorem eraseP_filter (f : α → Bool) (l : List α) : +theorem eraseP_filter {f : α → Bool} {l : List α} : (filter f l).eraseP p = filter f (l.eraseP (fun x => p x && f x)) := by rw [← filterMap_eq_filter, eraseP_filterMap] congr @@ -182,7 +183,7 @@ theorem eraseP_append_right : | _ :: _, _, h => by simp [(forall_mem_cons.1 h).1, eraseP_append_right _ (forall_mem_cons.1 h).2] -theorem eraseP_append (l₁ l₂ : List α) : +theorem eraseP_append {l₁ l₂ : List α} : (l₁ ++ l₂).eraseP p = if l₁.any p then l₁.eraseP p ++ l₂ else l₁ ++ l₂.eraseP p := by split <;> rename_i h · simp only [any_eq_true] at h @@ -192,7 +193,7 @@ theorem eraseP_append (l₁ l₂ : List α) : rw [eraseP_append_right _] simp_all -theorem eraseP_replicate (n : Nat) (a : α) (p : α → Bool) : +theorem eraseP_replicate {n : Nat} {a : α} {p : α → Bool} : (replicate n a).eraseP p = if p a then replicate (n - 1) a else replicate n a := by induction n with | zero => simp @@ -255,7 +256,7 @@ theorem eraseP_eq_iff {p} {l : List α} : simp_all theorem Pairwise.eraseP (q) : Pairwise p l → Pairwise p (l.eraseP q) := - Pairwise.sublist <| eraseP_sublist _ + Pairwise.sublist <| eraseP_sublist theorem Nodup.eraseP (p) : Nodup l → Nodup (l.eraseP p) := Pairwise.eraseP p @@ -274,11 +275,11 @@ theorem eraseP_comm {l : List α} (h : ∀ a ∈ l, ¬ p a ∨ ¬ q a) : · simp [h₁, h₂, ih (fun b m => h b (mem_cons_of_mem _ m))] · simp [h₁, h₂, ih (fun b m => h b (mem_cons_of_mem _ m))] -theorem head_eraseP_mem (xs : List α) (p : α → Bool) (h) : (xs.eraseP p).head h ∈ xs := - (eraseP_sublist xs).head_mem h +theorem head_eraseP_mem {xs : List α} {p : α → Bool} (h) : (xs.eraseP p).head h ∈ xs := + eraseP_sublist.head_mem h -theorem getLast_eraseP_mem (xs : List α) (p : α → Bool) (h) : (xs.eraseP p).getLast h ∈ xs := - (eraseP_sublist xs).getLast_mem h +theorem getLast_eraseP_mem {xs : List α} {p : α → Bool} (h) : (xs.eraseP p).getLast h ∈ xs := + eraseP_sublist.getLast_mem h theorem eraseP_eq_eraseIdx {xs : List α} {p : α → Bool} : xs.eraseP p = match xs.findIdx? p with @@ -299,6 +300,8 @@ theorem eraseP_eq_eraseIdx {xs : List α} {p : α → Bool} : section erase variable [BEq α] +-- The arguments are explicit to allow determining the type, +-- and to allow rewriting from right to left. @[simp] theorem erase_cons_head [LawfulBEq α] (a : α) (l : List α) : (a :: l).erase a = l := by simp [erase_cons] @@ -311,6 +314,7 @@ theorem erase_of_not_mem [LawfulBEq α] {a : α} : ∀ {l : List α}, a ∉ l rw [mem_cons, not_or] at h simp only [erase_cons, if_neg, erase_of_not_mem h.2, beq_iff_eq, Ne.symm h.1, not_false_eq_true] +-- The arguments are intentionally explicit. theorem erase_eq_eraseP' (a : α) (l : List α) : l.erase a = l.eraseP (· == a) := by induction l · simp @@ -318,10 +322,11 @@ theorem erase_eq_eraseP' (a : α) (l : List α) : l.erase a = l.eraseP (· == a) rw [erase_cons, eraseP_cons, ih] if h : b == a then simp [h] else simp [h] -theorem erase_eq_eraseP [LawfulBEq α] (a : α) : ∀ l : List α, l.erase a = l.eraseP (a == ·) +-- The arguments are intentionally explicit. +theorem erase_eq_eraseP [LawfulBEq α] (a : α) : ∀ (l : List α), l.erase a = l.eraseP (a == ·) | [] => rfl | b :: l => by - if h : a = b then simp [h] else simp [h, Ne.symm h, erase_eq_eraseP a l] + if h : a = b then simp [h] else simp [h, Ne.symm h, erase_eq_eraseP (l := l)] @[simp] theorem erase_eq_nil_iff [LawfulBEq α] {xs : List α} {a : α} : xs.erase a = [] ↔ xs = [] ∨ xs = [a] := by @@ -348,15 +353,15 @@ theorem exists_erase_eq [LawfulBEq α] {a : α} {l : List α} (h : a ∈ l) : length (l.erase a) = length l - 1 := by rw [erase_eq_eraseP]; exact length_eraseP_of_mem h (beq_self_eq_true a) -theorem length_erase [LawfulBEq α] (a : α) (l : List α) : +theorem length_erase [LawfulBEq α] {a : α} {l : List α} : length (l.erase a) = if a ∈ l then length l - 1 else length l := by rw [erase_eq_eraseP, length_eraseP] split <;> split <;> simp_all -theorem erase_sublist (a : α) (l : List α) : l.erase a <+ l := +theorem erase_sublist {a : α} {l : List α} : l.erase a <+ l := erase_eq_eraseP' a l ▸ eraseP_sublist .. -theorem erase_subset (a : α) (l : List α) : l.erase a ⊆ l := (erase_sublist a l).subset +theorem erase_subset {a : α} {l : List α} : l.erase a ⊆ l := erase_sublist.subset theorem Sublist.erase (a : α) {l₁ l₂ : List α} (h : l₁ <+ l₂) : l₁.erase a <+ l₂.erase a := by simp only [erase_eq_eraseP']; exact h.eraseP @@ -364,14 +369,14 @@ theorem Sublist.erase (a : α) {l₁ l₂ : List α} (h : l₁ <+ l₂) : l₁.e theorem IsPrefix.erase (a : α) {l₁ l₂ : List α} (h : l₁ <+: l₂) : l₁.erase a <+: l₂.erase a := by simp only [erase_eq_eraseP']; exact h.eraseP -theorem length_erase_le (a : α) (l : List α) : (l.erase a).length ≤ l.length := - (erase_sublist a l).length_le +theorem length_erase_le {a : α} {l : List α} : (l.erase a).length ≤ l.length := + erase_sublist.length_le -theorem le_length_erase [LawfulBEq α] (a : α) (l : List α) : l.length - 1 ≤ (l.erase a).length := by +theorem le_length_erase [LawfulBEq α] {a : α} {l : List α} : l.length - 1 ≤ (l.erase a).length := by rw [length_erase] split <;> simp -theorem mem_of_mem_erase {a b : α} {l : List α} (h : a ∈ l.erase b) : a ∈ l := erase_subset _ _ h +theorem mem_of_mem_erase {a b : α} {l : List α} (h : a ∈ l.erase b) : a ∈ l := erase_subset h @[simp] theorem mem_erase_of_ne [LawfulBEq α] {a b : α} {l : List α} (ab : a ≠ b) : a ∈ l.erase b ↔ a ∈ l := @@ -381,7 +386,7 @@ theorem mem_of_mem_erase {a b : α} {l : List α} (h : a ∈ l.erase b) : a ∈ rw [erase_eq_eraseP', eraseP_eq_self_iff] simp [forall_mem_ne'] -theorem erase_filter [LawfulBEq α] (f : α → Bool) (l : List α) : +theorem erase_filter [LawfulBEq α] {f : α → Bool} {l : List α} : (filter f l).erase a = filter f (l.erase a) := by induction l with | nil => rfl @@ -412,12 +417,14 @@ theorem erase_append [LawfulBEq α] {a : α} {l₁ l₂ : List α} : (l₁ ++ l₂).erase a = if a ∈ l₁ then l₁.erase a ++ l₂ else l₁ ++ l₂.erase a := by simp [erase_eq_eraseP, eraseP_append] -theorem erase_replicate [LawfulBEq α] (n : Nat) (a b : α) : +theorem erase_replicate [LawfulBEq α] {n : Nat} {a b : α} : (replicate n a).erase b = if b == a then replicate (n - 1) a else replicate n a := by rw [erase_eq_eraseP] simp [eraseP_replicate] -theorem erase_comm [LawfulBEq α] (a b : α) (l : List α) : +-- The arguments `a b` are explicit, +-- so they can be specified to prevent `simp` repeatedly applying the lemma. +theorem erase_comm [LawfulBEq α] (a b : α) {l : List α} : (l.erase a).erase b = (l.erase b).erase a := by if ab : a == b then rw [eq_of_beq ab] else ?_ if ha : a ∈ l then ?_ else @@ -457,7 +464,7 @@ theorem erase_eq_iff [LawfulBEq α] {a : α} {l : List α} : simp_all theorem Pairwise.erase [LawfulBEq α] {l : List α} (a) : Pairwise p l → Pairwise p (l.erase a) := - Pairwise.sublist <| erase_sublist _ _ + Pairwise.sublist <| erase_sublist theorem Nodup.erase_eq_filter [LawfulBEq α] {l} (d : Nodup l) (a : α) : l.erase a = l.filter (· != a) := by induction d with @@ -482,10 +489,10 @@ theorem Nodup.erase [LawfulBEq α] (a : α) : Nodup l → Nodup (l.erase a) := Pairwise.erase a theorem head_erase_mem (xs : List α) (a : α) (h) : (xs.erase a).head h ∈ xs := - (erase_sublist a xs).head_mem h + erase_sublist.head_mem h theorem getLast_erase_mem (xs : List α) (a : α) (h) : (xs.erase a).getLast h ∈ xs := - (erase_sublist a xs).getLast_mem h + erase_sublist.getLast_mem h theorem erase_eq_eraseIdx (l : List α) (a : α) : l.erase a = match l.idxOf? a with @@ -504,7 +511,7 @@ end erase /-! ### eraseIdx -/ -theorem length_eraseIdx (l : List α) (i : Nat) : +theorem length_eraseIdx {l : List α} {i : Nat} : (l.eraseIdx i).length = if i < l.length then l.length - 1 else l.length := by induction l generalizing i with | nil => simp @@ -521,7 +528,7 @@ theorem length_eraseIdx_of_lt {l : List α} {i} (h : i < length l) : (l.eraseIdx i).length = length l - 1 := by simp [length_eraseIdx, h] -@[simp] theorem eraseIdx_zero (l : List α) : eraseIdx l 0 = tail l := by cases l <;> rfl +@[simp] theorem eraseIdx_zero {l : List α} : eraseIdx l 0 = l.tail := by cases l <;> rfl theorem eraseIdx_eq_take_drop_succ : ∀ (l : List α) (i : Nat), l.eraseIdx i = l.take i ++ l.drop (i + 1) @@ -552,12 +559,13 @@ abbrev eraseIdx_ne_nil := @eraseIdx_ne_nil_iff theorem eraseIdx_sublist : ∀ (l : List α) (k : Nat), eraseIdx l k <+ l | [], _ => by simp | a::l, 0 => by simp - | a::l, k + 1 => by simp [eraseIdx_sublist l k] + | a::l, k + 1 => by simp [eraseIdx_sublist] theorem mem_of_mem_eraseIdx {l : List α} {i : Nat} {a : α} (h : a ∈ l.eraseIdx i) : a ∈ l := (eraseIdx_sublist _ _).mem h -theorem eraseIdx_subset (l : List α) (k : Nat) : eraseIdx l k ⊆ l := (eraseIdx_sublist l k).subset +theorem eraseIdx_subset {l : List α} {k : Nat} : eraseIdx l k ⊆ l := + (eraseIdx_sublist _ _).subset @[simp] theorem eraseIdx_eq_self : ∀ {l : List α} {k : Nat}, eraseIdx l k = l ↔ length l ≤ k @@ -568,9 +576,11 @@ theorem eraseIdx_eq_self : ∀ {l : List α} {k : Nat}, eraseIdx l k = l ↔ len theorem eraseIdx_of_length_le {l : List α} {k : Nat} (h : length l ≤ k) : eraseIdx l k = l := by rw [eraseIdx_eq_self.2 h] +-- Arguments are intentionally explicit. theorem length_eraseIdx_le (l : List α) (i : Nat) : length (l.eraseIdx i) ≤ length l := - (eraseIdx_sublist l i).length_le + (eraseIdx_sublist _ _).length_le +-- Arguments are intentionally explicit. theorem le_length_eraseIdx (l : List α) (i : Nat) : length l - 1 ≤ length (l.eraseIdx i) := by rw [length_eraseIdx] split <;> simp @@ -623,7 +633,7 @@ protected theorem IsPrefix.eraseIdx {l l' : List α} (h : l <+: l') (k : Nat) : -- `Init/Data/List/Nat/Basic.lean`. theorem erase_eq_eraseIdx_of_idxOf [BEq α] [LawfulBEq α] - (l : List α) (a : α) (i : Nat) (w : l.idxOf a = i) : + {l : List α} {a : α} {i : Nat} (w : l.idxOf a = i) : l.erase a = l.eraseIdx i := by subst w rw [erase_eq_iff] diff --git a/src/Init/Data/List/FinRange.lean b/src/Init/Data/List/FinRange.lean index 79d3624844..818501e0fb 100644 --- a/src/Init/Data/List/FinRange.lean +++ b/src/Init/Data/List/FinRange.lean @@ -20,19 +20,19 @@ Examples: -/ def finRange (n : Nat) : List (Fin n) := ofFn fun i => i -@[simp] theorem length_finRange (n) : (List.finRange n).length = n := by +@[simp] theorem length_finRange {n : Nat} : (List.finRange n).length = n := by simp [List.finRange] -@[simp] theorem getElem_finRange (i : Nat) (h : i < (List.finRange n).length) : - (finRange n)[i] = Fin.cast (length_finRange n) ⟨i, h⟩ := by +@[simp] theorem getElem_finRange {i : Nat} (h : i < (List.finRange n).length) : + (finRange n)[i] = Fin.cast length_finRange ⟨i, h⟩ := by simp [List.finRange] @[simp] theorem finRange_zero : finRange 0 = [] := by simp [finRange, ofFn] -theorem finRange_succ (n) : finRange (n+1) = 0 :: (finRange n).map Fin.succ := by +theorem finRange_succ {n} : finRange (n+1) = 0 :: (finRange n).map Fin.succ := by apply List.ext_getElem; simp; intro i; cases i <;> simp -theorem finRange_succ_last (n) : +theorem finRange_succ_last {n} : finRange (n+1) = (finRange n).map Fin.castSucc ++ [Fin.last n] := by apply List.ext_getElem · simp @@ -43,7 +43,7 @@ theorem finRange_succ_last (n) : · rfl · next h => exact Fin.eq_last_of_not_lt h -theorem finRange_reverse (n) : (finRange n).reverse = (finRange n).map Fin.rev := by +theorem finRange_reverse {n} : (finRange n).reverse = (finRange n).map Fin.rev := by induction n with | zero => simp | succ n ih => diff --git a/src/Init/Data/List/Find.lean b/src/Init/Data/List/Find.lean index 0605cbe862..9f559fc9cd 100644 --- a/src/Init/Data/List/Find.lean +++ b/src/Init/Data/List/Find.lean @@ -25,11 +25,11 @@ open Nat /-! ### findSome? -/ -@[simp] theorem findSome?_cons_of_isSome (l) (h : (f a).isSome) : findSome? f (a :: l) = f a := by +@[simp] theorem findSome?_cons_of_isSome {l} (h : (f a).isSome) : findSome? f (a :: l) = f a := by simp only [findSome?] split <;> simp_all -@[simp] theorem findSome?_cons_of_isNone (l) (h : (f a).isNone) : findSome? f (a :: l) = findSome? f l := by +@[simp] theorem findSome?_cons_of_isNone {l} (h : (f a).isNone) : findSome? f (a :: l) = findSome? f l := by simp only [findSome?] split <;> simp_all @@ -89,7 +89,7 @@ theorem findSome?_eq_some_iff {f : α → Option β} {l : List α} {b : β} : obtain ⟨⟨rfl, rfl⟩, rfl⟩ := h₁ exact ⟨l₁, a, l₂, rfl, h₂, fun a' w => h₃ a' (mem_cons_of_mem p w)⟩ -@[simp] theorem findSome?_guard (l : List α) : findSome? (Option.guard fun x => p x) l = find? p l := by +@[simp] theorem findSome?_guard {l : List α} : findSome? (Option.guard fun x => p x) l = find? p l := by induction l with | nil => simp | cons x xs ih => @@ -101,33 +101,33 @@ theorem findSome?_eq_some_iff {f : α → Option β} {l : List α} {b : β} : · simp only [Option.guard_eq_none] at h simp [ih, h] -theorem find?_eq_findSome?_guard (l : List α) : find? p l = findSome? (Option.guard fun x => p x) l := - (findSome?_guard l).symm +theorem find?_eq_findSome?_guard {l : List α} : find? p l = findSome? (Option.guard fun x => p x) l := + findSome?_guard.symm -@[simp] theorem head?_filterMap (f : α → Option β) (l : List α) : (l.filterMap f).head? = l.findSome? f := by +@[simp] theorem head?_filterMap {f : α → Option β} {l : List α} : (l.filterMap f).head? = l.findSome? f := by induction l with | nil => simp | cons x xs ih => simp only [filterMap_cons, findSome?_cons] split <;> simp [*] -@[simp] theorem head_filterMap (f : α → Option β) (l : List α) (h) : +@[simp] theorem head_filterMap {f : α → Option β} {l : List α} (h) : (l.filterMap f).head h = (l.findSome? f).get (by simp_all [Option.isSome_iff_ne_none]) := by simp [head_eq_iff_head?_eq_some] -@[simp] theorem getLast?_filterMap (f : α → Option β) (l : List α) : (l.filterMap f).getLast? = l.reverse.findSome? f := by +@[simp] theorem getLast?_filterMap {f : α → Option β} {l : List α} : (l.filterMap f).getLast? = l.reverse.findSome? f := by rw [getLast?_eq_head?_reverse] simp [← filterMap_reverse] -@[simp] theorem getLast_filterMap (f : α → Option β) (l : List α) (h) : +@[simp] theorem getLast_filterMap {f : α → Option β} {l : List α} (h) : (l.filterMap f).getLast h = (l.reverse.findSome? f).get (by simp_all [Option.isSome_iff_ne_none]) := by simp [getLast_eq_iff_getLast?_eq_some] -@[simp] theorem map_findSome? (f : α → Option β) (g : β → γ) (l : List α) : +@[simp] theorem map_findSome? {f : α → Option β} {g : β → γ} {l : List α} : (l.findSome? f).map g = l.findSome? (Option.map g ∘ f) := by induction l <;> simp [findSome?_cons]; split <;> simp [*] -theorem findSome?_map (f : β → γ) (l : List β) : findSome? p (l.map f) = l.findSome? (p ∘ f) := by +theorem findSome?_map {f : β → γ} {l : List β} : findSome? p (l.map f) = l.findSome? (p ∘ f) := by induction l with | nil => simp | cons x xs ih => @@ -202,14 +202,14 @@ theorem IsInfix.findSome?_eq_none {l₁ l₂ : List α} {f : α → Option β} ( /-! ### find? -/ -@[simp] theorem find?_singleton (a : α) (p : α → Bool) : [a].find? p = if p a then some a else none := by +@[simp] theorem find?_singleton {a : α} {p : α → Bool} : [a].find? p = if p a then some a else none := by simp only [find?] split <;> simp_all -@[simp] theorem find?_cons_of_pos (l) (h : p a) : find? p (a :: l) = some a := by +@[simp] theorem find?_cons_of_pos {l} (h : p a) : find? p (a :: l) = some a := by simp [find?, h] -@[simp] theorem find?_cons_of_neg (l) (h : ¬p a) : find? p (a :: l) = find? p l := by +@[simp] theorem find?_cons_of_neg {l} (h : ¬p a) : find? p (a :: l) = find? p l := by simp [find?, h] @[simp] theorem find?_eq_none : find? p l = none ↔ ∀ x ∈ l, ¬ p x := by @@ -230,7 +230,7 @@ theorem find?_eq_some_iff_append : cases as with | nil => simp_all | cons a as => - specialize h₂ a (mem_cons_self _ _) + specialize h₂ a mem_cons_self simp only [cons_append] at h₁ obtain ⟨rfl, -⟩ := h₁ simp_all @@ -279,7 +279,7 @@ theorem mem_of_find?_eq_some : ∀ {l}, find? p l = some a → a ∈ l · exact H ▸ .head _ · exact .tail _ (mem_of_find?_eq_some H) -theorem get_find?_mem (xs : List α) (p : α → Bool) (h) : (xs.find? p).get h ∈ xs := by +theorem get_find?_mem {xs : List α} {p : α → Bool} (h) : (xs.find? p).get h ∈ xs := by induction xs with | nil => simp at h | cons x xs ih => @@ -290,7 +290,7 @@ theorem get_find?_mem (xs : List α) (p : α → Bool) (h) : (xs.find? p).get h right apply ih -@[simp] theorem find?_filter (xs : List α) (p : α → Bool) (q : α → Bool) : +@[simp] theorem find?_filter {xs : List α} {p : α → Bool} {q : α → Bool} : (xs.filter p).find? q = xs.find? (fun a => p a ∧ q a) := by induction xs with | nil => simp @@ -300,22 +300,22 @@ theorem get_find?_mem (xs : List α) (p : α → Bool) (h) : (xs.find? p).get h · simp only [find?_cons] split <;> simp_all -@[simp] theorem head?_filter (p : α → Bool) (l : List α) : (l.filter p).head? = l.find? p := by +@[simp] theorem head?_filter {p : α → Bool} {l : List α} : (l.filter p).head? = l.find? p := by rw [← filterMap_eq_filter, head?_filterMap, findSome?_guard] -@[simp] theorem head_filter (p : α → Bool) (l : List α) (h) : +@[simp] theorem head_filter {p : α → Bool} {l : List α} (h) : (l.filter p).head h = (l.find? p).get (by simp_all [Option.isSome_iff_ne_none]) := by simp [head_eq_iff_head?_eq_some] -@[simp] theorem getLast?_filter (p : α → Bool) (l : List α) : (l.filter p).getLast? = l.reverse.find? p := by +@[simp] theorem getLast?_filter {p : α → Bool} {l : List α} : (l.filter p).getLast? = l.reverse.find? p := by rw [getLast?_eq_head?_reverse] simp [← filter_reverse] -@[simp] theorem getLast_filter (p : α → Bool) (l : List α) (h) : +@[simp] theorem getLast_filter {p : α → Bool} {l : List α} (h) : (l.filter p).getLast h = (l.reverse.find? p).get (by simp_all [Option.isSome_iff_ne_none]) := by simp [getLast_eq_iff_getLast?_eq_some] -@[simp] theorem find?_filterMap (xs : List α) (f : α → Option β) (p : β → Bool) : +@[simp] theorem find?_filterMap {xs : List α} {f : α → Option β} {p : β → Bool} : (xs.filterMap f).find? p = (xs.find? (fun a => (f a).any p)).bind f := by induction xs with | nil => simp @@ -325,7 +325,7 @@ theorem get_find?_mem (xs : List α) (p : α → Bool) (h) : (xs.find? p).get h · simp only [find?_cons] split <;> simp_all -@[simp] theorem find?_map (f : β → α) (l : List β) : find? p (l.map f) = (l.find? (p ∘ f)).map f := by +@[simp] theorem find?_map {f : β → α} {l : List β} : find? p (l.map f) = (l.find? (p ∘ f)).map f := by induction l with | nil => simp | cons x xs ih => @@ -339,7 +339,7 @@ theorem get_find?_mem (xs : List α) (p : α → Bool) (h) : (xs.find? p).get h simp only [cons_append, find?] by_cases h : p x <;> simp [h, ih] -@[simp] theorem find?_flatten (xss : List (List α)) (p : α → Bool) : +@[simp] theorem find?_flatten {xss : List (List α)} {p : α → Bool} : xss.flatten.find? p = xss.findSome? (·.find? p) := by induction xss with | nil => simp @@ -397,7 +397,7 @@ theorem find?_flatten_eq_some_iff {xs : List (List α)} {p : α → Bool} {a : @[deprecated find?_flatten_eq_some_iff (since := "2025-02-03")] abbrev find?_flatten_eq_some := @find?_flatten_eq_some_iff -@[simp] theorem find?_flatMap (xs : List α) (f : α → List β) (p : β → Bool) : +@[simp] theorem find?_flatMap {xs : List α} {f : α → List β} {p : β → Bool} : (xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by simp [flatMap_def, findSome?_map]; rfl @@ -441,7 +441,7 @@ abbrev find?_replicate_eq_none := @find?_replicate_eq_none_iff @[deprecated find?_replicate_eq_some_iff (since := "2025-02-03")] abbrev find?_replicate_eq_some := @find?_replicate_eq_some_iff -@[simp] theorem get_find?_replicate (n : Nat) (a : α) (p : α → Bool) (h) : ((replicate n a).find? p).get h = a := by +@[simp] theorem get_find?_replicate {n : Nat} {a : α} {p : α → Bool} (h) : ((replicate n a).find? p).get h = a := by cases n with | zero => simp at h | succ n => simp @@ -476,8 +476,8 @@ theorem IsInfix.find?_eq_none {l₁ l₂ : List α} {p : α → Bool} (h : l₁ List.find? p l₂ = none → List.find? p l₁ = none := h.sublist.find?_eq_none -theorem find?_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : List α) - (H : ∀ (a : α), a ∈ xs → P a) (p : β → Bool) : +theorem find?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : List α} + (H : ∀ (a : α), a ∈ xs → P a) {p : β → Bool} : (xs.pmap f H).find? p = (xs.attach.find? (fun ⟨a, m⟩ => p (f a (H a m)))).map fun ⟨a, m⟩ => f a (H a m) := by simp only [pmap_eq_map_attach, find?_map] rfl @@ -516,7 +516,7 @@ private theorem findIdx?_go_eq {p : α → Bool} {xs : List α} {i : Nat} : /-! ### findIdx -/ -theorem findIdx_cons (p : α → Bool) (b : α) (l : List α) : +theorem findIdx_cons {p : α → Bool} {b : α} {l : List α} : (b :: l).findIdx p = bif p b then 0 else (l.findIdx p) + 1 := by cases H : p b with | true => simp [H, findIdx, findIdx.go] @@ -572,7 +572,7 @@ theorem findIdx_eq_length_of_false {p : α → Bool} {xs : List α} (h : ∀ x rw [findIdx_eq_length] exact h -theorem findIdx_le_length (p : α → Bool) {xs : List α} : xs.findIdx p ≤ xs.length := by +theorem findIdx_le_length {p : α → Bool} {xs : List α} : xs.findIdx p ≤ xs.length := by by_cases e : ∃ x ∈ xs, p x · exact Nat.le_of_lt (findIdx_lt_length_of_exists e) · simp at e @@ -589,7 +589,7 @@ theorem findIdx_lt_length {p : α → Bool} {xs : List α} : /-- `p` does not hold for elements with indices less than `xs.findIdx p`. -/ theorem not_of_lt_findIdx {p : α → Bool} {xs : List α} {i : Nat} (h : i < xs.findIdx p) : - p (xs[i]'(Nat.le_trans h (findIdx_le_length p))) = false := by + p (xs[i]'(Nat.le_trans h findIdx_le_length)) = false := by revert i induction xs with | nil => intro i h; rw [findIdx_nil] at h; simp at h @@ -638,7 +638,7 @@ theorem findIdx_eq {p : α → Bool} {xs : List α} {i : Nat} (h : i < xs.length simp at h3 simp_all [not_of_lt_findIdx h3] -theorem findIdx_append (p : α → Bool) (l₁ l₂ : List α) : +theorem findIdx_append {p : α → Bool} {l₁ l₂ : List α} : (l₁ ++ l₂).findIdx p = if l₁.findIdx p < l₁.length then l₁.findIdx p else l₂.findIdx p + l₁.length := by induction l₁ with @@ -813,7 +813,7 @@ theorem of_findIdx?_eq_none {xs : List α} {p : α → Bool} (w : xs.findIdx? p @[deprecated of_findIdx?_eq_none (since := "2025-02-02")] abbrev findIdx?_of_eq_none := @of_findIdx?_eq_none -@[simp] theorem findIdx?_map (f : β → α) (l : List β) : findIdx? p (l.map f) = l.findIdx? (p ∘ f) := by +@[simp] theorem findIdx?_map {f : β → α} {l : List β} : findIdx? p (l.map f) = l.findIdx? (p ∘ f) := by induction l with | nil => simp | cons x xs ih => @@ -1066,7 +1066,7 @@ theorem idxOf?_eq_map_finIdxOf?_val [BEq α] {xs : List α} {a : α} : @[simp] theorem finIdxOf?_nil [BEq α] : ([] : List α).finIdxOf? a = none := rfl -@[simp] theorem finIdxOf?_cons [BEq α] (a : α) (xs : List α) : +@[simp] theorem finIdxOf?_cons [BEq α] {a : α} {xs : List α} : (a :: xs).finIdxOf? b = if a == b then some ⟨0, by simp⟩ else (xs.finIdxOf? b).map (·.succ) := by simp [finIdxOf?] @@ -1092,7 +1092,7 @@ The lemmas below should be made consistent with those for `findIdx?` (and proved @[simp] theorem idxOf?_nil [BEq α] : ([] : List α).idxOf? a = none := rfl -theorem idxOf?_cons [BEq α] (a : α) (xs : List α) (b : α) : +theorem idxOf?_cons [BEq α] {a : α} {xs : List α} {b : α} : (a :: xs).idxOf? b = if a == b then some 0 else (xs.idxOf? b).map (· + 1) := by simp [idxOf?] @@ -1117,7 +1117,7 @@ variable [BEq α] [LawfulBEq α] @[simp] theorem lookup_cons_self {k : α} : ((k,b) :: es).lookup k = some b := by simp [lookup_cons] -theorem lookup_eq_findSome? (l : List (α × β)) (k : α) : +theorem lookup_eq_findSome? {l : List (α × β)} {k : α} : l.lookup k = l.findSome? fun p => if k == p.1 then some p.2 else none := by induction l with | nil => rfl diff --git a/src/Init/Data/List/Lemmas.lean b/src/Init/Data/List/Lemmas.lean index eeaf6a0220..a4410addbd 100644 --- a/src/Init/Data/List/Lemmas.lean +++ b/src/Init/Data/List/Lemmas.lean @@ -146,6 +146,7 @@ abbrev length_eq_one := @length_eq_one_iff /-! ### cons -/ +-- The arguments here are intentionally explicit. theorem cons_ne_nil (a : α) (l : List α) : a :: l ≠ [] := nofun @[simp] @@ -184,7 +185,7 @@ theorem singleton_inj {α : Type _} {a b : α} : [a] = [b] ↔ a = b := by We simplify `l.get i` to `l[i.1]'i.2` and `l.get? i` to `l[i]?`. -/ -@[simp] theorem get_eq_getElem (l : List α) (i : Fin l.length) : l.get i = l[i.1]'i.2 := rfl +@[simp] theorem get_eq_getElem {l : List α} {i : Fin l.length} : l.get i = l[i.1]'i.2 := rfl set_option linter.deprecated false in @[deprecated "Use `a[i]?` instead." (since := "2025-02-12")] @@ -213,7 +214,7 @@ theorem get?_eq_none_iff : l.get? n = none ↔ length l ≤ n := set_option linter.deprecated false in @[deprecated "Use `a[i]?` instead." (since := "2025-02-12"), simp] -theorem get?_eq_getElem? (l : List α) (i : Nat) : l.get? i = l[i]? := by +theorem get?_eq_getElem? {l : List α} {i : Nat} : l.get? i = l[i]? := by simp only [getElem?_def]; split · exact (get?_eq_get ‹_›) · exact (get?_eq_none_iff.2 <| Nat.not_lt.1 ‹_›) @@ -223,7 +224,7 @@ theorem get?_eq_getElem? (l : List α) (i : Nat) : l.get? i = l[i]? := by We simplify `l[i]!` to `(l[i]?).getD default`. -/ -@[simp] theorem getElem!_eq_getElem?_getD [Inhabited α] (l : List α) (i : Nat) : +@[simp] theorem getElem!_eq_getElem?_getD [Inhabited α] {l : List α} {i : Nat} : l[i]! = (l[i]?).getD (default : α) := by simp only [getElem!_def] match l[i]? with @@ -259,23 +260,23 @@ theorem getElem?_eq_some_iff {l : List α} : l[i]? = some a ↔ ∃ h : i < l.le theorem some_eq_getElem?_iff {l : List α} : some a = l[i]? ↔ ∃ h : i < l.length, l[i] = a := by rw [eq_comm, getElem?_eq_some_iff] -@[simp] theorem some_getElem_eq_getElem?_iff (xs : List α) (i : Nat) (h : i < xs.length) : +@[simp] theorem some_getElem_eq_getElem?_iff {xs : List α} {i : Nat} (h : i < xs.length) : (some xs[i] = xs[i]?) ↔ True := by simp [h] -@[simp] theorem getElem?_eq_some_getElem_iff (xs : List α) (i : Nat) (h : i < xs.length) : +@[simp] theorem getElem?_eq_some_getElem_iff {xs : List α} {i : Nat} (h : i < xs.length) : (xs[i]? = some xs[i]) ↔ True := by simp [h] -theorem getElem_eq_iff {l : List α} {i : Nat} {h : i < l.length} : l[i] = x ↔ l[i]? = some x := by +theorem getElem_eq_iff {l : List α} {i : Nat} (h : i < l.length) : l[i] = x ↔ l[i]? = some x := by simp only [getElem?_eq_some_iff] exact ⟨fun w => ⟨h, w⟩, fun h => h.2⟩ -theorem getElem_eq_getElem?_get (l : List α) (i : Nat) (h : i < l.length) : +theorem getElem_eq_getElem?_get {l : List α} {i : Nat} (h : i < l.length) : l[i] = l[i]?.get (by simp [getElem?_eq_getElem, h]) := by simp [getElem_eq_iff] -theorem getD_getElem? (l : List α) (i : Nat) (d : α) : +theorem getD_getElem? {l : List α} {i : Nat} {d : α} : l[i]?.getD d = if p : i < l.length then l[i]'p else d := by if h : i < l.length then simp [h, getElem?_def] @@ -283,11 +284,11 @@ theorem getD_getElem? (l : List α) (i : Nat) (d : α) : have p : i ≥ l.length := Nat.le_of_not_gt h simp [getElem?_eq_none p, h] -@[simp] theorem getElem_singleton (a : α) (h : i < 1) : [a][i] = a := +@[simp] theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : [a][i] = a := match i, h with | 0, _ => rfl -theorem getElem?_singleton (a : α) (i : Nat) : [a][i]? = if i = 0 then some a else none := by +theorem getElem?_singleton {a : α} {i : Nat} : [a][i]? = if i = 0 then some a else none := by simp [getElem?_cons] /-- @@ -321,11 +322,11 @@ theorem ext_getElem {l₁ l₂ : List α} (hl : length l₁ = length l₂) have h₁ := Nat.le_of_not_lt h₁ rw [getElem?_eq_none h₁, getElem?_eq_none]; rwa [← hl] -@[simp] theorem getElem_concat_length : ∀ (l : List α) (a : α) (i) (_ : i = l.length) (w), (l ++ [a])[i]'w = a - | [], a, _, h, _ => by subst h; simp - | _ :: l, a, _, h, _ => by simp [getElem_concat_length, h] +@[simp] theorem getElem_concat_length {l : List α} {a : α} {i : Nat} (h : i = l.length) (w) : + (l ++ [a])[i]'w = a := by + subst h; simp -theorem getElem?_concat_length (l : List α) (a : α) : (l ++ [a])[l.length]? = some a := by +theorem getElem?_concat_length {l : List α} {a : α} : (l ++ [a])[l.length]? = some a := by simp /-! ### getD @@ -334,7 +335,7 @@ We simplify away `getD`, replacing `getD l n a` with `(l[n]?).getD a`. Because of this, there is only minimal API for `getD`. -/ -@[simp] theorem getD_eq_getElem?_getD (l) (i) (a : α) : getD l i a = (l[i]?).getD a := by +@[simp] theorem getD_eq_getElem?_getD {l : List α} {i : Nat} {a : α} : getD l i a = (l[i]?).getD a := by simp [getD] theorem getD_cons_zero : getD (x :: xs) 0 d = x := by simp @@ -359,18 +360,18 @@ theorem get!_eq_getElem! [Inhabited α] (l : List α) (i) : l.get! i = l[i]! := /-! ### mem -/ -@[simp] theorem not_mem_nil (a : α) : ¬ a ∈ [] := nofun +@[simp] theorem not_mem_nil {a : α} : ¬ a ∈ [] := nofun @[simp] theorem mem_cons : a ∈ (b :: l) ↔ a = b ∨ a ∈ l := ⟨fun h => by cases h <;> simp [Membership.mem, *], fun | Or.inl rfl => by constructor | Or.inr h => by constructor; assumption⟩ -theorem mem_cons_self (a : α) (l : List α) : a ∈ a :: l := .head .. +theorem mem_cons_self {a : α} {l : List α} : a ∈ a :: l := .head .. -theorem mem_concat_self (xs : List α) (a : α) : a ∈ xs ++ [a] := - mem_append_right xs (mem_cons_self a _) +theorem mem_concat_self {xs : List α} {a : α} : a ∈ xs ++ [a] := + mem_append_right xs mem_cons_self -theorem mem_append_cons_self : a ∈ xs ++ a :: ys := mem_append_right _ (mem_cons_self _ _) +theorem mem_append_cons_self : a ∈ xs ++ a :: ys := mem_append_right _ mem_cons_self theorem eq_append_cons_of_mem {a : α} {xs : List α} (h : a ∈ xs) : ∃ as bs, xs = as ++ a :: bs ∧ a ∉ as := by @@ -389,6 +390,8 @@ theorem eq_append_cons_of_mem {a : α} {xs : List α} (h : a ∈ xs) : theorem mem_cons_of_mem (y : α) {a : α} {l : List α} : a ∈ l → a ∈ y :: l := .tail _ +-- The argument `l : List α` is intentionally explicit, +-- as a tactic may generate `h` without determining `l`. theorem exists_mem_of_ne_nil (l : List α) (h : l ≠ []) : ∃ x, x ∈ l := exists_mem_of_length_pos (length_pos_iff.2 h) @@ -440,7 +443,7 @@ theorem forall_mem_singleton {p : α → Prop} {a : α} : (∀ (x) (_ : x ∈ [a theorem mem_nil_iff (a : α) : a ∈ ([] : List α) ↔ False := by simp -theorem mem_singleton_self (a : α) : a ∈ [a] := mem_cons_self _ _ +theorem mem_singleton_self (a : α) : a ∈ [a] := mem_cons_self theorem mem_of_mem_cons_of_mem : ∀ {a b : α} {l : List α}, a ∈ b :: l → b ∈ l → a ∈ l | _, _, _, .head .., h | _, _, _, .tail _ h, _ => h @@ -595,10 +598,10 @@ theorem all_bne' [BEq α] [PartialEquivBEq α] {l : List α} : /-! ### set -/ -- As `List.set` is defined in `Init.Prelude`, we write the basic simplification lemmas here. -@[simp] theorem set_nil (i : Nat) (a : α) : [].set i a = [] := rfl -@[simp] theorem set_cons_zero (x : α) (xs : List α) (a : α) : +@[simp] theorem set_nil {i : Nat} {a : α} : [].set i a = [] := rfl +@[simp] theorem set_cons_zero {x : α} {xs : List α} {a : α} : (x :: xs).set 0 a = a :: xs := rfl -@[simp] theorem set_cons_succ (x : α) (xs : List α) (i : Nat) (a : α) : +@[simp] theorem set_cons_succ {x : α} {xs : List α} {i : Nat} {a : α} : (x :: xs).set (i + 1) a = x :: xs.set i a := rfl @[simp] theorem getElem_set_self {l : List α} {i : Nat} {a : α} (h : i < (l.set i a).length) : @@ -689,21 +692,21 @@ theorem set_eq_of_length_le {l : List α} {i : Nat} (h : l.length ≤ i) {a : α @[simp] theorem set_eq_nil_iff {l : List α} (i : Nat) (a : α) : l.set i a = [] ↔ l = [] := by cases l <;> cases i <;> simp [set] -theorem set_comm (a b : α) : ∀ {i j : Nat} (l : List α), i ≠ j → +theorem set_comm (a b : α) : ∀ {i j : Nat} {l : List α}, i ≠ j → (l.set i a).set j b = (l.set j b).set i a | _, _, [], _ => by simp | _+1, 0, _ :: _, _ => by simp [set] | 0, _+1, _ :: _, _ => by simp [set] | _+1, _+1, _ :: t, h => - congrArg _ <| set_comm a b t fun h' => h <| Nat.succ_inj'.mpr h' + congrArg _ <| set_comm a b fun h' => h <| Nat.succ_inj'.mpr h' @[simp] -theorem set_set (a b : α) : ∀ (l : List α) (i : Nat), (l.set i a).set i b = l.set i b +theorem set_set (a : α) {b : α} : ∀ {l : List α} {i : Nat}, (l.set i a).set i b = l.set i b | [], _ => by simp | _ :: _, 0 => by simp [set] | _ :: _, _+1 => by simp [set, set_set] -theorem mem_set (l : List α) (i : Nat) (h : i < l.length) (a : α) : +theorem mem_set {l : List α} {i : Nat} (h : i < l.length) (a : α) : a ∈ l.set i a := by simp [mem_iff_getElem] exact ⟨i, (by simpa using h), by simp⟩ @@ -802,7 +805,7 @@ theorem length_eq_of_beq [BEq α] {l₁ l₂ : List α} (h : l₁ == l₂) : l /-! ### getLast -/ -theorem getLast_eq_getElem : ∀ (l : List α) (h : l ≠ []), +theorem getLast_eq_getElem : ∀ {l : List α} (h : l ≠ []), getLast l h = l[l.length - 1]'(by match l with | [] => contradiction @@ -811,7 +814,7 @@ theorem getLast_eq_getElem : ∀ (l : List α) (h : l ≠ []), | _ :: _ :: _, _ => by simp [getLast, Nat.succ_sub_succ, getLast_eq_getElem] -theorem getElem_length_sub_one_eq_getLast (l : List α) (h : l.length - 1 < l.length) : +theorem getElem_length_sub_one_eq_getLast {l : List α} (h : l.length - 1 < l.length) : l[l.length - 1] = getLast l (by cases l; simp at h; simp) := by rw [← getLast_eq_getElem] @@ -819,13 +822,13 @@ theorem getLast_cons {a : α} {l : List α} : ∀ (h : l ≠ nil), getLast (a :: l) (cons_ne_nil a l) = getLast l h := by induction l <;> intros; {contradiction}; rfl -theorem getLast_eq_getLastD (a l h) : @getLast α (a::l) h = getLastD l a := by +theorem getLast_eq_getLastD {a l} (h) : @getLast α (a::l) h = getLastD l a := by cases l <;> rfl -@[simp] theorem getLastD_eq_getLast? (a l) : @getLastD α l a = (getLast? l).getD a := by +@[simp] theorem getLastD_eq_getLast? {a l} : @getLastD α l a = (getLast? l).getD a := by cases l <;> rfl -@[simp] theorem getLast_singleton (a h) : @getLast α [a] h = a := rfl +@[simp] theorem getLast_singleton {a} (h) : @getLast α [a] h = a := rfl theorem getLast!_cons_eq_getLastD [Inhabited α] : @getLast! α _ (a::l) = getLastD l a := by simp [getLast!, getLast_eq_getLastD] @@ -839,30 +842,31 @@ theorem getLast_mem_getLast? : ∀ {l : List α} (h : l ≠ []), getLast l h ∈ | [], h => by contradiction | _ :: _, _ => rfl -theorem getLastD_mem_cons : ∀ (l : List α) (a : α), getLastD l a ∈ a::l +theorem getLastD_mem_cons : ∀ {l : List α} {a : α}, getLastD l a ∈ a::l | [], _ => .head .. | _::_, _ => .tail _ <| getLast_mem _ -theorem getElem_cons_length (x : α) (xs : List α) (i : Nat) (h : i = xs.length) : +theorem getElem_cons_length {x : α} {xs : List α} {i : Nat} (h : i = xs.length) : (x :: xs)[i]'(by simp [h]) = (x :: xs).getLast (cons_ne_nil x xs) := by rw [getLast_eq_getElem]; cases h; rfl /-! ### getLast? -/ -@[simp] theorem getLast?_singleton (a : α) : getLast? [a] = a := rfl +@[simp] theorem getLast?_singleton {a : α} : getLast? [a] = a := rfl -theorem getLast?_eq_getLast : ∀ l h, @getLast? α l = some (getLast l h) +-- The `l : List α` argument is intentionally explicit. +theorem getLast?_eq_getLast : ∀ {l : List α} h, l.getLast? = some (l.getLast h) | [], h => nomatch h rfl | _ :: _, _ => rfl -theorem getLast?_eq_getElem? : ∀ (l : List α), getLast? l = l[l.length - 1]? +theorem getLast?_eq_getElem? : ∀ {l : List α}, l.getLast? = l[l.length - 1]? | [] => rfl | a::l => by - rw [getLast?_eq_getLast (a::l) nofun, getLast_eq_getElem, getElem?_eq_getElem] + rw [getLast?_eq_getLast (l := a :: l) nofun, getLast_eq_getElem, getElem?_eq_getElem] theorem getLast_eq_iff_getLast?_eq_some {xs : List α} (h) : xs.getLast h = a ↔ xs.getLast? = some a := by - rw [getLast?_eq_getLast _ h] + rw [getLast?_eq_getLast h] simp -- `getLast?_eq_none_iff`, `getLast?_eq_some_iff`, `getLast?_isSome`, and `getLast_mem` @@ -874,10 +878,10 @@ theorem getLast?_cons {a : α} : (a::l).getLast? = l.getLast?.getD a := by @[simp] theorem getLast?_cons_cons : (a :: b :: l).getLast? = (b :: l).getLast? := by simp [getLast?_cons] -theorem getLast?_concat (l : List α) : getLast? (l ++ [a]) = some a := by +theorem getLast?_concat {l : List α} {a : α} : (l ++ [a]).getLast? = some a := by simp [getLast?_eq_getElem?, Nat.succ_sub_succ] -theorem getLastD_concat (a b l) : @getLastD α (l ++ [b]) a = b := by +theorem getLastD_concat {a b} {l : List α} : (l ++ [b]).getLastD a = b := by rw [getLastD_eq_getLast?, getLast?_concat]; rfl /-! ### getLast! -/ @@ -904,25 +908,25 @@ theorem getLast!_eq_getElem! [Inhabited α] {l : List α} : l.getLast! = l[l.len /-! ### head -/ -theorem head?_singleton (a : α) : head? [a] = some a := by simp +theorem head?_singleton {a : α} : head? [a] = some a := by simp set_option linter.unusedVariables false in -- See https://github.com/leanprover/lean4/issues/5259 theorem head!_of_head? [Inhabited α] : ∀ {l : List α}, head? l = some a → head! l = a | _ :: _, rfl => rfl -theorem head?_eq_head : ∀ {l} h, @head? α l = some (head l h) +theorem head?_eq_head : ∀ {l : List α} h, l.head? = some (head l h) | _ :: _, _ => rfl -theorem head?_eq_getElem? : ∀ l : List α, head? l = l[0]? +theorem head?_eq_getElem? : ∀ {l : List α}, l.head? = l[0]? | [] => rfl | a :: l => by simp -theorem head_eq_getElem (l : List α) (h : l ≠ []) : head l h = l[0]'(length_pos_iff.mpr h) := by +theorem head_eq_getElem {l : List α} (h : l ≠ []) : head l h = l[0]'(length_pos_iff.mpr h) := by cases l with | nil => simp at h | cons _ _ => simp -theorem getElem_zero_eq_head (l : List α) (h : 0 < l.length) : +theorem getElem_zero_eq_head {l : List α} (h : 0 < l.length) : l[0] = head l (by simpa [length_pos_iff] using h) := by cases l with | nil => simp at h @@ -956,7 +960,7 @@ theorem mem_of_mem_head? : ∀ {l : List α} {a : α}, a ∈ l.head? → a ∈ l | cons b l => simp at h cases h - exact mem_cons_self a l + exact mem_cons_self theorem head_mem_head? : ∀ {l : List α} (h : l ≠ []), head l h ∈ head? l | [], h => by contradiction @@ -977,16 +981,16 @@ theorem head?_concat_concat : (l ++ [a, b]).head? = (l ++ [a]).head? := by /-! ### tailD -/ /-- `simp` unfolds `tailD` in terms of `tail?` and `Option.getD`. -/ -@[simp] theorem tailD_eq_tail? (l l' : List α) : tailD l l' = (tail? l).getD l' := by +@[simp] theorem tailD_eq_tail? {l l' : List α} : tailD l l' = (tail? l).getD l' := by cases l <;> rfl /-! ### tail -/ -@[simp] theorem length_tail (l : List α) : length (tail l) = length l - 1 := by cases l <;> rfl +@[simp] theorem length_tail {l : List α} : l.tail.length = l.length - 1 := by cases l <;> rfl -theorem tail_eq_tailD (l) : @tail α l = tailD l [] := by cases l <;> rfl +theorem tail_eq_tailD {l : List α} : l.tail = tailD l [] := by cases l <;> rfl -theorem tail_eq_tail? (l) : @tail α l = (tail? l).getD [] := by simp [tail_eq_tailD] +theorem tail_eq_tail? {l : List α} : l.tail = (tail? l).getD [] := by simp [tail_eq_tailD] theorem mem_of_mem_tail {a : α} {l : List α} (h : a ∈ tail l) : a ∈ l := by induction l <;> simp_all @@ -994,17 +998,17 @@ theorem mem_of_mem_tail {a : α} {l : List α} (h : a ∈ tail l) : a ∈ l := b theorem ne_nil_of_tail_ne_nil {l : List α} : l.tail ≠ [] → l ≠ [] := by cases l <;> simp -@[simp] theorem getElem_tail (l : List α) (i : Nat) (h : i < l.tail.length) : +@[simp] theorem getElem_tail {l : List α} {i : Nat} (h : i < l.tail.length) : (tail l)[i] = l[i + 1]'(add_lt_of_lt_sub (by simpa using h)) := by cases l with | nil => simp at h | cons _ l => simp -@[simp] theorem getElem?_tail (l : List α) (i : Nat) : +@[simp] theorem getElem?_tail {l : List α} {i : Nat} : (tail l)[i]? = l[i + 1]? := by cases l <;> simp -@[simp] theorem set_tail (l : List α) (i : Nat) (a : α) : +@[simp] theorem set_tail {l : List α} {i : Nat} {a : α} : l.tail.set i a = (l.set (i + 1) a).tail := by cases l <;> simp @@ -1015,23 +1019,23 @@ theorem one_lt_length_of_tail_ne_nil {l : List α} (h : l.tail ≠ []) : 1 < l.l simp only [tail_cons, ne_eq] at h exact Nat.lt_add_of_pos_left (length_pos_iff.mpr h) -@[simp] theorem head_tail (l : List α) (h : l.tail ≠ []) : +@[simp] theorem head_tail {l : List α} (h : l.tail ≠ []) : (tail l).head h = l[1]'(one_lt_length_of_tail_ne_nil h) := by cases l with | nil => simp at h | cons _ l => simp [head_eq_getElem] -@[simp] theorem head?_tail (l : List α) : (tail l).head? = l[1]? := by +@[simp] theorem head?_tail {l : List α} : (tail l).head? = l[1]? := by simp [head?_eq_getElem?] -@[simp] theorem getLast_tail (l : List α) (h : l.tail ≠ []) : +@[simp] theorem getLast_tail {l : List α} (h : l.tail ≠ []) : (tail l).getLast h = l.getLast (ne_nil_of_tail_ne_nil h) := by simp only [getLast_eq_getElem, length_tail, getElem_tail] congr match l with | _ :: _ :: l => simp -theorem getLast?_tail (l : List α) : (tail l).getLast? = if l.length = 1 then none else l.getLast? := by +theorem getLast?_tail {l : List α} : (tail l).getLast? = if l.length = 1 then none else l.getLast? := by match l with | [] => simp | [a] => simp @@ -1044,18 +1048,19 @@ theorem getLast?_tail (l : List α) : (tail l).getLast? = if l.length = 1 then n /-! ### map -/ -@[simp] theorem length_map (as : List α) (f : α → β) : (as.map f).length = as.length := by +@[simp] theorem length_map {as : List α} (f : α → β) : (as.map f).length = as.length := by induction as with | nil => simp [List.map] | cons _ as ih => simp [List.map, ih] -@[simp] theorem getElem?_map (f : α → β) : ∀ (l : List α) (i : Nat), (map f l)[i]? = Option.map f l[i]? +@[simp] theorem getElem?_map {f : α → β} : ∀ {l : List α} {i : Nat}, (map f l)[i]? = Option.map f l[i]? | [], _ => rfl | _ :: _, 0 => by simp - | _ :: l, i+1 => by simp [getElem?_map f l i] + | _ :: l, i+1 => by simp [getElem?_map] +-- The argument `f : α → β` is explicit, to facilitate rewriting from right to left. @[simp] theorem getElem_map (f : α → β) {l} {i : Nat} {h : i < (map f l).length} : - (map f l)[i] = f (l[i]'(length_map l f ▸ h)) := + (map f l)[i] = f (l[i]'(length_map f ▸ h)) := Option.some.inj <| by rw [← getElem?_eq_getElem, getElem?_map, getElem?_eq_getElem]; rfl @[simp] theorem map_id_fun : map (id : α → α) = id := by @@ -1066,18 +1071,21 @@ theorem getLast?_tail (l : List α) : (tail l).getLast? = if l.length = 1 then n @[simp] theorem map_id_fun' : map (fun (a : α) => a) = id := map_id_fun -- This is not a `@[simp]` lemma because `map_id_fun` will apply. +-- The argument `l : List α` is explicit to allow rewriting from right to left. theorem map_id (l : List α) : map (id : α → α) l = l := by induction l <;> simp_all /-- `map_id'` differs from `map_id` by representing the identity function as a lambda, rather than `id`. -/ -- This is not a `@[simp]` lemma because `map_id_fun'` will apply. +-- The argument `l : List α` is explicit to allow rewriting from right to left. theorem map_id' (l : List α) : map (fun (a : α) => a) l = l := map_id l /-- Variant of `map_id`, with a side condition that the function is pointwise the identity. -/ +-- The argument `l : List α` is explicit to allow rewriting from right to left. theorem map_id'' {f : α → α} (h : ∀ x, f x = x) (l : List α) : map f l = l := by simp [show f = id from funext h] -theorem map_singleton (f : α → β) (a : α) : map f [a] = [f a] := rfl +theorem map_singleton {f : α → β} {a : α} : map f [a] = [f a] := rfl -- We use a lower priority here as there are more specific lemmas in downstream libraries -- which should be able to fire first. @@ -1087,7 +1095,7 @@ theorem map_singleton (f : α → β) (a : α) : map f [a] = [f a] := rfl theorem exists_of_mem_map (h : b ∈ map f l) : ∃ a, a ∈ l ∧ f a = b := mem_map.1 h -theorem mem_map_of_mem (f : α → β) (h : a ∈ l) : f a ∈ map f l := mem_map.2 ⟨_, h, rfl⟩ +theorem mem_map_of_mem {f : α → β} (h : a ∈ l) : f a ∈ map f l := mem_map.2 ⟨_, h, rfl⟩ theorem forall_mem_map {f : α → β} {l : List α} {P : β → Prop} : (∀ (i) (_ : i ∈ l.map f), P i) ↔ ∀ (j) (_ : j ∈ l), P (f j) := by @@ -1161,7 +1169,7 @@ theorem map_eq_iff : map f l = l' ↔ ∀ i : Nat, l'[i]? = l[i]?.map f := by ext1 i simp_all -theorem map_eq_foldr (f : α → β) (l : List α) : map f l = foldr (fun a bs => f a :: bs) [] l := by +theorem map_eq_foldr {f : α → β} {l : List α} : map f l = foldr (fun a bs => f a :: bs) [] l := by induction l <;> simp [*] @[simp] theorem map_set {f : α → β} {l : List α} {i : Nat} {a : α} : @@ -1175,48 +1183,48 @@ theorem set_map {f : α → β} {l : List α} {i : Nat} {a : α} : (map f l).set i (f a) = map f (l.set i a) := by simp -@[simp] theorem head_map (f : α → β) (l : List α) (w) : +@[simp] theorem head_map {f : α → β} {l : List α} (w) : (map f l).head w = f (l.head (by simpa using w)) := by cases l · simp at w · simp_all -@[simp] theorem head?_map (f : α → β) (l : List α) : (map f l).head? = l.head?.map f := by +@[simp] theorem head?_map {f : α → β} {l : List α} : (map f l).head? = l.head?.map f := by cases l <;> rfl -@[simp] theorem map_tail? (f : α → β) (l : List α) : (tail? l).map (map f) = tail? (map f l) := by +@[simp] theorem map_tail? {f : α → β} {l : List α} : (tail? l).map (map f) = tail? (map f l) := by cases l <;> rfl -@[simp] theorem map_tail (f : α → β) (l : List α) : +@[simp] theorem map_tail {f : α → β} {l : List α} : map f l.tail = (map f l).tail := by cases l <;> simp_all -theorem headD_map (f : α → β) (l : List α) (a : α) : headD (map f l) (f a) = f (headD l a) := by +theorem headD_map {f : α → β} {l : List α} {a : α} : (map f l).headD (f a) = f (l.headD a) := by cases l <;> rfl -theorem tailD_map (f : α → β) (l : List α) (l' : List α) : +theorem tailD_map {f : α → β} {l l' : List α} : tailD (map f l) (map f l') = map f (tailD l l') := by simp [← map_tail?] -@[simp] theorem getLast_map (f : α → β) (l : List α) (h) : +@[simp] theorem getLast_map {f : α → β} {l : List α} (h) : getLast (map f l) h = f (getLast l (by simpa using h)) := by cases l · simp at h - · simp only [← getElem_cons_length _ _ _ rfl] + · simp only [← getElem_cons_length rfl] simp only [map_cons] - simp only [← getElem_cons_length _ _ _ rfl] + simp only [← getElem_cons_length rfl] simp only [← map_cons, getElem_map] simp -@[simp] theorem getLast?_map (f : α → β) (l : List α) : getLast? (map f l) = (getLast? l).map f := by +@[simp] theorem getLast?_map {f : α → β} {l : List α} : (map f l).getLast? = l.getLast?.map f := by cases l · simp · rw [getLast?_eq_getLast, getLast?_eq_getLast, getLast_map] <;> simp -theorem getLastD_map (f : α → β) (l : List α) (a : α) : getLastD (map f l) (f a) = f (getLastD l a) := by +theorem getLastD_map {f : α → β} {l : List α} {a : α} : (map f l).getLastD (f a) = f (l.getLastD a) := by simp -@[simp] theorem map_map (g : β → γ) (f : α → β) (l : List α) : - map g (map f l) = map (g ∘ f) l := by induction l <;> simp_all +@[simp] theorem map_map {g : β → γ} {f : α → β} {l : List α} : + map g (map f l) = map (g ∘ f) l := by induction l <;> simp_all /-! ### filter -/ @@ -1230,6 +1238,7 @@ theorem filter_cons : (x :: xs : List α).filter p = if p x then x :: (xs.filter p) else xs.filter p := by split <;> simp [*] +-- The `l : List α` argument is intentionally explicit. theorem length_filter_le (p : α → Bool) (l : List α) : (l.filter p).length ≤ l.length := by induction l with @@ -1279,11 +1288,11 @@ theorem forall_mem_filter {l : List α} {p : α → Bool} {P : α → Prop} : (∀ (i) (_ : i ∈ l.filter p), P i) ↔ ∀ (j) (_ : j ∈ l), p j → P j := by simp -@[simp] theorem filter_filter (q) : ∀ l, filter p (filter q l) = filter (fun a => p a && q a) l +@[simp] theorem filter_filter : ∀ {l}, filter p (filter q l) = filter (fun a => p a && q a) l | [] => rfl - | a :: l => by by_cases hp : p a <;> by_cases hq : q a <;> simp [hp, hq, filter_filter _ l] + | a :: l => by by_cases hp : p a <;> by_cases hq : q a <;> simp [hp, hq, filter_filter] -theorem foldl_filter (p : α → Bool) (f : β → α → β) (l : List α) (init : β) : +theorem foldl_filter {p : α → Bool} {f : β → α → β} {l : List α} {init : β} : (l.filter p).foldl f init = l.foldl (fun x y => if p y then f x y else x) init := by induction l generalizing init with | nil => rfl @@ -1291,7 +1300,7 @@ theorem foldl_filter (p : α → Bool) (f : β → α → β) (l : List α) (ini simp only [filter_cons, foldl_cons] split <;> simp [ih] -theorem foldr_filter (p : α → Bool) (f : α → β → β) (l : List α) (init : β) : +theorem foldr_filter {p : α → Bool} {f : α → β → β} {l : List α} {init : β} : (l.filter p).foldr f init = l.foldr (fun x y => if p x then f x y else y) init := by induction l generalizing init with | nil => rfl @@ -1299,12 +1308,13 @@ theorem foldr_filter (p : α → Bool) (f : α → β → β) (l : List α) (ini simp only [filter_cons, foldr_cons] split <;> simp [ih] -theorem filter_map (f : β → α) (l : List β) : filter p (map f l) = map f (filter (p ∘ f) l) := by +theorem filter_map {f : β → α} {p : α → Bool} {l : List β} : + filter p (map f l) = map f (filter (p ∘ f) l) := by induction l with | nil => rfl | cons a l IH => by_cases h : p (f a) <;> simp [*] -theorem map_filter_eq_foldr (f : α → β) (p : α → Bool) (as : List α) : +theorem map_filter_eq_foldr {f : α → β} {p : α → Bool} {as : List α} : map f (filter p as) = foldr (fun a bs => bif p a then f a :: bs else bs) [] as := by induction as with | nil => rfl @@ -1356,9 +1366,9 @@ theorem head_filter_of_pos {p : α → Bool} {l : List α} (w : l ≠ []) (h : p simp only [head_cons] at h simp [filter_cons, h] -@[simp] theorem filter_sublist {p : α → Bool} : ∀ (l : List α), filter p l <+ l +@[simp] theorem filter_sublist {p : α → Bool} : ∀ {l : List α}, filter p l <+ l | [] => .slnil - | a :: l => by rw [filter]; split <;> simp [Sublist.cons, Sublist.cons₂, filter_sublist l] + | a :: l => by rw [filter]; split <;> simp [Sublist.cons, Sublist.cons₂, filter_sublist] /-! ### filterMap -/ @@ -1369,29 +1379,30 @@ theorem head_filter_of_pos {p : α → Bool} {l : List α} (w : l ≠ []) (h : p filterMap f (a :: l) = b :: filterMap f l := by simp only [filterMap, h] @[simp] -theorem filterMap_eq_map (f : α → β) : filterMap (some ∘ f) = map f := by +theorem filterMap_eq_map {f : α → β} : filterMap (some ∘ f) = map f := by funext l; induction l <;> simp [*, filterMap_cons] /-- Variant of `filterMap_eq_map` with `some ∘ f` expanded out to a lambda. -/ @[simp] -theorem filterMap_eq_map' (f : α → β) : filterMap (fun x => some (f x)) = map f := - filterMap_eq_map f +theorem filterMap_eq_map' {f : α → β} : filterMap (fun x => some (f x)) = map f := + filterMap_eq_map @[simp] theorem filterMap_some_fun : filterMap (some : α → Option α) = id := by funext l erw [filterMap_eq_map] simp -theorem filterMap_some (l : List α) : filterMap some l = l := by +theorem filterMap_some {l : List α} : filterMap some l = l := by rw [filterMap_some_fun, id] -theorem map_filterMap_some_eq_filter_map_isSome (f : α → Option β) (l : List α) : +theorem map_filterMap_some_eq_filter_map_isSome {f : α → Option β} {l : List α} : (l.filterMap f).map some = (l.map f).filter fun b => b.isSome := by induction l <;> simp [filterMap_cons]; split <;> simp [*] +-- The arguments are intentionally explicit. theorem length_filterMap_le (f : α → Option β) (l : List α) : (filterMap f l).length ≤ l.length := by - rw [← length_map _ some, map_filterMap_some_eq_filter_map_isSome, ← length_map _ f] + rw [← length_map some, map_filterMap_some_eq_filter_map_isSome, ← length_map f] apply length_filter_le @[simp] @@ -1407,34 +1418,34 @@ theorem filterMap_length_eq_length {l} : · simp_all [Nat.add_one_inj] -- Why does the simproc not fire here? @[simp] -theorem filterMap_eq_filter (p : α → Bool) : +theorem filterMap_eq_filter {p : α → Bool} : filterMap (Option.guard (p ·)) = filter p := by funext l induction l with | nil => rfl | cons a l IH => by_cases pa : p a <;> simp [filterMap_cons, Option.guard, pa, ← IH] -theorem filterMap_filterMap (f : α → Option β) (g : β → Option γ) (l : List α) : +theorem filterMap_filterMap {f : α → Option β} {g : β → Option γ} {l : List α} : filterMap g (filterMap f l) = filterMap (fun x => (f x).bind g) l := by induction l with | nil => rfl | cons a l IH => cases h : f a <;> simp [filterMap_cons, *] -theorem map_filterMap (f : α → Option β) (g : β → γ) (l : List α) : +theorem map_filterMap {f : α → Option β} {g : β → γ} {l : List α} : map g (filterMap f l) = filterMap (fun x => (f x).map g) l := by simp only [← filterMap_eq_map, filterMap_filterMap, Option.map_eq_bind] @[simp] -theorem filterMap_map (f : α → β) (g : β → Option γ) (l : List α) : +theorem filterMap_map {f : α → β} {g : β → Option γ} {l : List α} : filterMap g (map f l) = filterMap (g ∘ f) l := by rw [← filterMap_eq_map, filterMap_filterMap]; rfl -theorem filter_filterMap (f : α → Option β) (p : β → Bool) (l : List α) : +theorem filter_filterMap {f : α → Option β} {p : β → Bool} {l : List α} : filter p (filterMap f l) = filterMap (fun x => (f x).filter p) l := by rw [← filterMap_eq_filter, filterMap_filterMap] congr; funext x; cases f x <;> simp [Option.filter, Option.guard] -theorem filterMap_filter (p : α → Bool) (f : α → Option β) (l : List α) : +theorem filterMap_filter {p : α → Bool} {f : α → Option β} {l : List α} : filterMap f (filter p l) = filterMap (fun x => if p x then f x else none) l := by rw [← filterMap_eq_filter, filterMap_filterMap] congr; funext x; by_cases h : p x <;> simp [Option.guard, h] @@ -1451,12 +1462,13 @@ theorem forall_mem_filterMap {f : α → Option β} {l : List α} {P : β → Pr intro a rw [forall_comm] -@[simp] theorem filterMap_append {α β : Type _} (l l' : List α) (f : α → Option β) : +@[simp] theorem filterMap_append {l l' : List α} {f : α → Option β} : filterMap f (l ++ l') = filterMap f l ++ filterMap f l' := by induction l <;> simp [filterMap_cons]; split <;> simp [*] -theorem map_filterMap_of_inv (f : α → Option β) (g : β → α) (H : ∀ x : α, (f x).map g = some x) - (l : List α) : map g (filterMap f l) = l := by simp only [map_filterMap, H, filterMap_some, id] +theorem map_filterMap_of_inv + {f : α → Option β} {g : β → α} (H : ∀ x : α, (f x).map g = some x) {l : List α} : + map g (filterMap f l) = l := by simp only [map_filterMap, H, filterMap_some, id] theorem head_filterMap_of_eq_some {f : α → Option β} {l : List α} (w : l ≠ []) {b : β} (h : f (l.head w) = some b) : (filterMap f l).head ((ne_nil_of_mem (mem_filterMap.2 ⟨_, head_mem w, h⟩))) = @@ -1522,7 +1534,7 @@ theorem filterMap_eq_cons_iff {l} {b} {bs} : @[simp] theorem nil_append_fun : (([] : List α) ++ ·) = id := rfl -@[simp] theorem cons_append_fun (a : α) (as : List α) : +@[simp] theorem cons_append_fun {a : α} {as : List α} : (fun bs => ((a :: as) ++ bs)) = fun bs => a :: (as ++ bs) := rfl @[simp] theorem mem_append {a : α} {s t : List α} : a ∈ s ++ t ↔ a ∈ s ∨ a ∈ t := by @@ -1532,7 +1544,7 @@ theorem not_mem_append {a : α} {s t : List α} (h₁ : a ∉ s) (h₂ : a ∉ t mt mem_append.1 $ not_or.mpr ⟨h₁, h₂⟩ @[deprecated mem_append (since := "2025-01-13")] -theorem mem_append_eq (a : α) (s t : List α) : (a ∈ s ++ t) = (a ∈ s ∨ a ∈ t) := +theorem mem_append_eq {a : α} {s t : List α} : (a ∈ s ++ t) = (a ∈ s ∨ a ∈ t) := propext mem_append @[deprecated mem_append_left (since := "2024-11-20")] abbrev mem_append_of_mem_left := @mem_append_left @@ -1553,7 +1565,7 @@ theorem forall_mem_append {p : α → Prop} {l₁ l₂ : List α} : (∀ (x) (_ : x ∈ l₁ ++ l₂), p x) ↔ (∀ (x) (_ : x ∈ l₁), p x) ∧ (∀ (x) (_ : x ∈ l₂), p x) := by simp only [mem_append, or_imp, forall_and] -theorem getElem_append {l₁ l₂ : List α} (i : Nat) (h : i < (l₁ ++ l₂).length) : +theorem getElem_append {l₁ l₂ : List α} {i : Nat} (h : i < (l₁ ++ l₂).length) : (l₁ ++ l₂)[i] = if h' : i < l₁.length then l₁[i] else l₂[i - l₁.length]'(by simp at h h'; exact Nat.sub_lt_left_of_lt_add h' h) := by split <;> rename_i h' · rw [getElem_append_left h'] @@ -1579,7 +1591,7 @@ theorem getElem?_append {l₁ l₂ : List α} {i : Nat} : · exact getElem?_append_right (by simpa using h) /-- Variant of `getElem_append_left` useful for rewriting from the small list to the big list. -/ -theorem getElem_append_left' (l₂ : List α) {l₁ : List α} {i : Nat} (hi : i < l₁.length) : +theorem getElem_append_left' {l₁ : List α} {i : Nat} (hi : i < l₁.length) (l₂ : List α) : l₁[i] = (l₁ ++ l₂)[i]'(by simpa using Nat.lt_add_right l₂.length hi) := by rw [getElem_append_left] <;> simp @@ -1638,10 +1650,10 @@ theorem append_left_inj {s₁ s₂ : List α} (t) : s₁ ++ t = s₂ ++ t ↔ s @[simp] theorem self_eq_append_right {xs ys : List α} : xs = xs ++ ys ↔ ys = [] := by rw [eq_comm, append_right_eq_self] -theorem getLast_concat {a : α} : ∀ (l : List α), getLast (l ++ [a]) (by simp) = a +theorem getLast_concat {a : α} : ∀ {l : List α}, getLast (l ++ [a]) (by simp) = a | [] => rfl | a::t => by - simp [getLast_cons _, getLast_concat t] + simp [getLast_cons _, getLast_concat] @[simp] theorem append_eq_nil_iff : p ++ q = [] ↔ p = [] ∧ q = [] := by cases p <;> simp @@ -1788,7 +1800,7 @@ theorem append_eq_filter_iff {p : α → Bool} : @[deprecated append_eq_filter_iff (since := "2024-09-05")] abbrev append_eq_filter := @append_eq_filter_iff -@[simp] theorem map_append (f : α → β) : ∀ l₁ l₂, map f (l₁ ++ l₂) = map f l₁ ++ map f l₂ := by +@[simp] theorem map_append {f : α → β} : ∀ {l₁ l₂}, map f (l₁ ++ l₂) = map f l₁ ++ map f l₂ := by intro l₁; induction l₁ <;> intros <;> simp_all theorem map_eq_append_iff {f : α → β} : @@ -1809,9 +1821,9 @@ As such there's no need for a thorough set of lemmas describing `concat`. -/ -- As `List.concat` is defined in `Init.Prelude`, we write the basic simplification lemmas here. -theorem concat_nil (a : α) : concat [] a = [a] := +theorem concat_nil {a : α} : concat [] a = [a] := rfl -theorem concat_cons (a b : α) (l : List α) : concat (a :: l) b = a :: concat l b := +theorem concat_cons {a b : α} {l : List α} : concat (a :: l) b = a :: concat l b := rfl theorem init_eq_of_concat_eq {a b : α} {l₁ l₂ : List α} : concat l₁ a = concat l₂ b → l₁ = l₂ := by @@ -1835,11 +1847,11 @@ theorem concat_inj_right {l : List α} {a a' : α} : concat l a = concat l a' @[deprecated concat_inj (since := "2024-09-05")] abbrev concat_eq_concat := @concat_inj -theorem concat_append (a : α) (l₁ l₂ : List α) : concat l₁ a ++ l₂ = l₁ ++ a :: l₂ := by simp +theorem concat_append {a : α} {l₁ l₂ : List α} : concat l₁ a ++ l₂ = l₁ ++ a :: l₂ := by simp -theorem append_concat (a : α) (l₁ l₂ : List α) : l₁ ++ concat l₂ a = concat (l₁ ++ l₂) a := by simp +theorem append_concat {a : α} {l₁ l₂ : List α} : l₁ ++ concat l₂ a = concat (l₁ ++ l₂) a := by simp -theorem map_concat (f : α → β) (a : α) (l : List α) : map f (concat l a) = concat (map f l) (f a) := by +theorem map_concat {f : α → β} {a : α} {l : List α} : map f (concat l a) = concat (map f l) (f a) := by induction l with | nil => rfl | cons x xs ih => simp [ih] @@ -1852,13 +1864,13 @@ theorem eq_nil_or_concat : ∀ l : List α, l = [] ∨ ∃ l' b, l = concat l' b /-! ### flatten -/ -@[simp] theorem length_flatten (L : List (List α)) : L.flatten.length = (L.map length).sum := by +@[simp] theorem length_flatten {L : List (List α)} : L.flatten.length = (L.map length).sum := by induction L with | nil => rfl | cons => simp [flatten, length_append, *] -theorem flatten_singleton (l : List α) : [l].flatten = l := by simp +theorem flatten_singleton {l : List α} : [l].flatten = l := by simp @[simp] theorem mem_flatten : ∀ {L : List (List α)}, a ∈ L.flatten ↔ ∃ l, l ∈ L ∧ a ∈ l | [] => by simp @@ -1895,15 +1907,15 @@ theorem head?_flatten {L : List (List α)} : (flatten L).head? = L.findSome? fun -- `getLast?_flatten` is proved later, after the `reverse` section. -- `head_flatten` and `getLast_flatten` are proved in `Init.Data.List.Find`. -@[simp] theorem map_flatten (f : α → β) (L : List (List α)) : +@[simp] theorem map_flatten {f : α → β} {L : List (List α)} : (flatten L).map f = (map (map f) L).flatten := by induction L <;> simp_all -@[simp] theorem filterMap_flatten (f : α → Option β) (L : List (List α)) : +@[simp] theorem filterMap_flatten {f : α → Option β} {L : List (List α)} : filterMap f (flatten L) = flatten (map (filterMap f) L) := by induction L <;> simp [*, filterMap_append] -@[simp] theorem filter_flatten (p : α → Bool) (L : List (List α)) : +@[simp] theorem filter_flatten {p : α → Bool} {L : List (List α)} : filter p (flatten L) = flatten (map (filter p) L) := by induction L <;> simp [*, filter_append] @@ -1919,10 +1931,10 @@ theorem flatten_filter_ne_nil [DecidablePred fun l : List α => l ≠ []] {L : L simp only [ne_eq, ← isEmpty_iff, Bool.not_eq_true, Bool.decide_eq_false, flatten_filter_not_isEmpty] -@[simp] theorem flatten_append (L₁ L₂ : List (List α)) : flatten (L₁ ++ L₂) = flatten L₁ ++ flatten L₂ := by +@[simp] theorem flatten_append {L₁ L₂ : List (List α)} : flatten (L₁ ++ L₂) = flatten L₁ ++ flatten L₂ := by induction L₁ <;> simp_all -theorem flatten_concat (L : List (List α)) (l : List α) : flatten (L ++ [l]) = flatten L ++ l := by +theorem flatten_concat {L : List (List α)} {l : List α} : flatten (L ++ [l]) = flatten L ++ l := by simp theorem flatten_flatten {L : List (List (List α))} : flatten (flatten L) = flatten (map flatten L) := by @@ -2022,14 +2034,14 @@ theorem eq_iff_flatten_eq : ∀ {L L' : List (List α)}, /-! ### flatMap -/ -theorem flatMap_def (l : List α) (f : α → List β) : l.flatMap f = flatten (map f l) := by rfl +theorem flatMap_def {l : List α} {f : α → List β} : l.flatMap f = flatten (map f l) := by rfl -@[simp] theorem flatMap_id (L : List (List α)) : L.flatMap id = L.flatten := by simp [flatMap_def] +@[simp] theorem flatMap_id {L : List (List α)} : L.flatMap id = L.flatten := by simp [flatMap_def] -@[simp] theorem flatMap_id' (L : List (List α)) : L.flatMap (fun as => as) = L.flatten := by simp [flatMap_def] +@[simp] theorem flatMap_id' {L : List (List α)} : L.flatMap (fun as => as) = L.flatten := by simp [flatMap_def] @[simp] -theorem length_flatMap (l : List α) (f : α → List β) : +theorem length_flatMap {l : List α} {f : α → List β} : length (l.flatMap f) = sum (map (fun a => (f a).length) l) := by rw [List.flatMap, length_flatten, map_map, Function.comp_def] @@ -2058,6 +2070,7 @@ theorem forall_mem_flatMap {p : β → Prop} {l : List α} {f : α → List β} theorem flatMap_singleton (f : α → List β) (x : α) : [x].flatMap f = f x := append_nil (f x) +-- The argument `l : List α` is intentionally explicit, to allow rewriting from right to left. @[simp] theorem flatMap_singleton' (l : List α) : (l.flatMap fun x => [x]) = l := by induction l <;> simp [*] @@ -2069,36 +2082,36 @@ theorem head?_flatMap {l : List α} {f : α → List β} : simp only [findSome?_cons] split <;> simp_all -@[simp] theorem flatMap_append (xs ys : List α) (f : α → List β) : +@[simp] theorem flatMap_append {xs ys : List α} {f : α → List β} : (xs ++ ys).flatMap f = xs.flatMap f ++ ys.flatMap f := by induction xs; {rfl}; simp_all [flatMap_cons, append_assoc] -theorem flatMap_assoc {α β} (l : List α) (f : α → List β) (g : β → List γ) : +theorem flatMap_assoc {l : List α} {f : α → List β} {g : β → List γ} : (l.flatMap f).flatMap g = l.flatMap fun x => (f x).flatMap g := by induction l <;> simp [*] -theorem map_flatMap (f : β → γ) (g : α → List β) : - ∀ l : List α, (l.flatMap g).map f = l.flatMap fun a => (g a).map f +theorem map_flatMap {f : β → γ} {g : α → List β} : + ∀ {l : List α}, (l.flatMap g).map f = l.flatMap fun a => (g a).map f | [] => rfl - | a::l => by simp only [flatMap_cons, map_append, map_flatMap _ _ l] + | a::l => by simp only [flatMap_cons, map_append, map_flatMap] theorem flatMap_map (f : α → β) (g : β → List γ) (l : List α) : (map f l).flatMap g = l.flatMap (fun a => g (f a)) := by induction l <;> simp [flatMap_cons, *] -theorem map_eq_flatMap {α β} (f : α → β) (l : List α) : map f l = l.flatMap fun x => [f x] := by +theorem map_eq_flatMap {f : α → β} {l : List α} : map f l = l.flatMap fun x => [f x] := by simp only [← map_singleton] rw [← flatMap_singleton' l, map_flatMap, flatMap_singleton'] -theorem filterMap_flatMap {β γ} (l : List α) (g : α → List β) (f : β → Option γ) : +theorem filterMap_flatMap {l : List α} {g : α → List β} {f : β → Option γ} : (l.flatMap g).filterMap f = l.flatMap fun a => (g a).filterMap f := by induction l <;> simp [*] -theorem filter_flatMap (l : List α) (g : α → List β) (f : β → Bool) : +theorem filter_flatMap {l : List α} {g : α → List β} {f : β → Bool} : (l.flatMap g).filter f = l.flatMap fun a => (g a).filter f := by induction l <;> simp [*] -theorem flatMap_eq_foldl (f : α → List β) (l : List α) : +theorem flatMap_eq_foldl {f : α → List β} {l : List α} : l.flatMap f = l.foldl (fun acc a => acc ++ f a) [] := by suffices ∀ l', l' ++ l.flatMap f = l.foldl (fun acc a => acc ++ f a) l' by simpa using this [] intro l' @@ -2139,7 +2152,7 @@ theorem forall_mem_replicate {p : α → Prop} {a : α} {n} : (∀ b, b ∈ replicate n a → p b) ↔ n = 0 ∨ p a := by cases n <;> simp [mem_replicate] -@[simp] theorem replicate_succ_ne_nil (n : Nat) (a : α) : replicate (n+1) a ≠ [] := by +@[simp] theorem replicate_succ_ne_nil {n : Nat} {a : α} : replicate (n+1) a ≠ [] := by simp [replicate_succ] @[simp] theorem replicate_eq_nil_iff {n : Nat} (a : α) : replicate n a = [] ↔ n = 0 := by @@ -2147,7 +2160,7 @@ theorem forall_mem_replicate {p : α → Prop} {a : α} {n} : @[deprecated replicate_eq_nil_iff (since := "2024-09-05")] abbrev replicate_eq_nil := @replicate_eq_nil_iff -@[simp] theorem getElem_replicate (a : α) {n : Nat} {i} (h : i < (replicate n a).length) : +@[simp] theorem getElem_replicate {a : α} {n : Nat} {i : Nat} (h : i < (replicate n a).length) : (replicate n a)[i] = a := eq_of_mem_replicate (getElem_mem _) @@ -2159,7 +2172,7 @@ theorem getElem?_replicate : (replicate n a)[i]? = if i < n then some a else non @[simp] theorem getElem?_replicate_of_lt {n : Nat} {i : Nat} (h : i < n) : (replicate n a)[i]? = some a := by simp [getElem?_replicate, h] -theorem head?_replicate (a : α) (n : Nat) : (replicate n a).head? = if n = 0 then none else some a := by +theorem head?_replicate {a : α} {n : Nat} : (replicate n a).head? = if n = 0 then none else some a := by cases n <;> simp [replicate_succ] @[simp] theorem head_replicate (w : replicate n a ≠ []) : (replicate n a).head w = a := by @@ -2170,7 +2183,7 @@ theorem head?_replicate (a : α) (n : Nat) : (replicate n a).head? = if n = 0 th -- `getLast?_replicate` and `getLast_replicate` appear below, -- after more `reverse` lemmas are available. -@[simp] theorem tail_replicate (n : Nat) (a : α) : (replicate n a).tail = replicate (n - 1) a := by +@[simp] theorem tail_replicate {n : Nat} {a : α} : (replicate n a).tail = replicate (n - 1) a := by cases n <;> simp [replicate_succ] @[simp] theorem replicate_inj : replicate n a = replicate m b ↔ n = m ∧ (n = 0 ∨ a = b) := @@ -2204,17 +2217,17 @@ theorem map_eq_replicate_iff {l : List α} {f : α → β} {b : β} : l.map f = replicate l.length b ↔ ∀ x ∈ l, f x = b := by simp [eq_replicate_iff] -@[simp] theorem map_const (l : List α) (b : β) : map (Function.const α b) l = replicate l.length b := +@[simp] theorem map_const {l : List α} {b : β} : map (Function.const α b) l = replicate l.length b := map_eq_replicate_iff.mpr fun _ _ => rfl -@[simp] theorem map_const_fun (x : β) : map (Function.const α x) = (replicate ·.length x) := by +@[simp] theorem map_const_fun {x : β} : map (Function.const α x) = (replicate ·.length x) := by funext l simp /-- Variant of `map_const` using a lambda rather than `Function.const`. -/ -- This can not be a `@[simp]` lemma because it would fire on every `List.map`. -theorem map_const' (l : List α) (b : β) : map (fun _ => b) l = replicate l.length b := - map_const l b +theorem map_const' {l : List α} {b : β} : map (fun _ => b) l = replicate l.length b := + map_const @[simp] theorem set_replicate_self : (replicate n a).set i a = replicate n a := by apply ext_getElem @@ -2302,7 +2315,7 @@ theorem filterMap_replicate_of_some {f : α → Option β} (h : f a = some b) : simp only [replicate_succ, flatten_cons, ih, replicate_append_replicate, replicate_inj, or_true, and_true, add_one_mul, Nat.add_comm] -theorem flatMap_replicate {β} (f : α → List β) : (replicate n a).flatMap f = (replicate n (f a)).flatten := by +theorem flatMap_replicate {β} {f : α → List β} : (replicate n a).flatMap f = (replicate n (f a)).flatten := by induction n with | zero => simp | succ n ih => simp only [replicate_succ, flatMap_cons, ih, flatten_cons] @@ -2351,12 +2364,12 @@ theorem replicateRecOn {α : Type _} {p : List α → Prop} (l : List α) exact hi _ _ _ _ h hn (replicateRecOn (b :: l') h0 hr hi) termination_by l.length -@[simp] theorem sum_replicate_nat (n : Nat) (a : Nat) : (replicate n a).sum = n * a := by +@[simp] theorem sum_replicate_nat {n : Nat} {a : Nat} : (replicate n a).sum = n * a := by induction n <;> simp_all [replicate_succ, Nat.add_mul, Nat.add_comm] /-! ### reverse -/ -@[simp] theorem length_reverse (as : List α) : (as.reverse).length = as.length := by +@[simp] theorem length_reverse {as : List α} : (as.reverse).length = as.length := by induction as with | nil => rfl | cons a as ih => simp [ih] @@ -2380,19 +2393,19 @@ theorem reverse_ne_nil_iff {xs : List α} : xs.reverse ≠ [] ↔ xs ≠ [] := cases xs <;> simp /-- Variant of `getElem?_reverse` with a hypothesis giving the linear relation between the indices. -/ -theorem getElem?_reverse' : ∀ {l : List α} (i j), i + j + 1 = length l → +theorem getElem?_reverse' : ∀ {l : List α} {i j}, i + j + 1 = length l → l.reverse[i]? = l[j]? | [], _, _, _ => rfl | a::l, i, 0, h => by simp [Nat.succ.injEq] at h; simp [h, getElem?_append_right, Nat.succ.injEq] | a::l, i, j+1, h => by have := Nat.succ.inj h; simp at this ⊢ - rw [getElem?_append_left, getElem?_reverse' _ _ this] + rw [getElem?_append_left, getElem?_reverse' this] rw [length_reverse, ← this]; apply Nat.lt_add_of_pos_right (Nat.succ_pos _) @[simp] theorem getElem?_reverse {l : List α} {i} (h : i < length l) : l.reverse[i]? = l[l.length - 1 - i]? := - getElem?_reverse' _ _ <| by + getElem?_reverse' <| by rw [Nat.add_sub_of_le (Nat.le_sub_one_of_lt h), Nat.sub_add_cancel (Nat.lt_of_le_of_lt (Nat.zero_le _) h)] @@ -2403,11 +2416,12 @@ theorem getElem_reverse {l : List α} {i} (h : i < l.reverse.length) : rw [← getElem?_eq_getElem, ← getElem?_eq_getElem] rw [getElem?_reverse (by simpa using h)] -theorem reverseAux_reverseAux_nil (as bs : List α) : reverseAux (reverseAux as bs) [] = reverseAux bs as := by +theorem reverseAux_reverseAux_nil {as bs : List α} : reverseAux (reverseAux as bs) [] = reverseAux bs as := by induction as generalizing bs with | nil => rfl | cons a as ih => simp [reverseAux, ih] +-- The argument `as : List α` is explicit to allow rewriting from right to left. @[simp] theorem reverse_reverse (as : List α) : as.reverse.reverse = as := by simp only [reverse]; rw [reverseAux_reverseAux_nil]; rfl @@ -2423,10 +2437,10 @@ theorem reverse_eq_iff {as bs : List α} : as.reverse = bs ↔ as = bs.reverse : @[deprecated reverse_eq_cons_iff (since := "2024-09-05")] abbrev reverse_eq_cons := @reverse_eq_cons_iff -@[simp] theorem getLast?_reverse (l : List α) : l.reverse.getLast? = l.head? := by +@[simp] theorem getLast?_reverse {l : List α} : l.reverse.getLast? = l.head? := by cases l <;> simp [getLast?_concat] -@[simp] theorem head?_reverse (l : List α) : l.reverse.head? = l.getLast? := by +@[simp] theorem head?_reverse {l : List α} : l.reverse.head? = l.getLast? := by rw [← getLast?_reverse, reverse_reverse] theorem getLast?_eq_head?_reverse {xs : List α} : xs.getLast? = xs.reverse.head? := by @@ -2440,24 +2454,24 @@ theorem mem_of_mem_getLast? {l : List α} {a : α} (h : a ∈ getLast? l) : a rw [← mem_reverse] exact mem_of_mem_head? h -@[simp] theorem map_reverse (f : α → β) (l : List α) : l.reverse.map f = (l.map f).reverse := by +@[simp] theorem map_reverse {f : α → β} {l : List α} : l.reverse.map f = (l.map f).reverse := by induction l <;> simp [*] -@[simp] theorem filter_reverse (p : α → Bool) (l : List α) : (l.reverse.filter p) = (l.filter p).reverse := by +@[simp] theorem filter_reverse {p : α → Bool} {l : List α} : (l.reverse.filter p) = (l.filter p).reverse := by induction l with | nil => simp | cons a l ih => simp only [reverse_cons, filter_append, filter_cons, ih] split <;> simp_all -@[simp] theorem filterMap_reverse (f : α → Option β) (l : List α) : (l.reverse.filterMap f) = (l.filterMap f).reverse := by +@[simp] theorem filterMap_reverse {f : α → Option β} {l : List α} : (l.reverse.filterMap f) = (l.filterMap f).reverse := by induction l with | nil => simp | cons a l ih => simp only [reverse_cons, filterMap_append, filterMap_cons, ih] split <;> simp_all -@[simp] theorem reverse_append (as bs : List α) : (as ++ bs).reverse = bs.reverse ++ as.reverse := by +@[simp] theorem reverse_append {as bs : List α} : (as ++ bs).reverse = bs.reverse ++ as.reverse := by induction as <;> simp_all @[simp] theorem reverse_eq_append_iff {xs ys zs : List α} : @@ -2466,7 +2480,7 @@ theorem mem_of_mem_getLast? {l : List α} {a : α} (h : a ∈ getLast? l) : a @[deprecated reverse_eq_append_iff (since := "2024-09-05")] abbrev reverse_eq_append := @reverse_eq_append_iff -theorem reverse_concat (l : List α) (a : α) : (l ++ [a]).reverse = a :: l.reverse := by +theorem reverse_concat {l : List α} {a : α} : (l ++ [a]).reverse = a :: l.reverse := by rw [reverse_append]; rfl theorem reverse_eq_concat {xs ys : List α} {a : α} : @@ -2474,25 +2488,25 @@ theorem reverse_eq_concat {xs ys : List α} {a : α} : rw [reverse_eq_iff, reverse_concat] /-- Reversing a flatten is the same as reversing the order of parts and reversing all parts. -/ -theorem reverse_flatten (L : List (List α)) : +theorem reverse_flatten {L : List (List α)} : L.flatten.reverse = (L.map reverse).reverse.flatten := by induction L <;> simp_all /-- Flattening a reverse is the same as reversing all parts and reversing the flattened result. -/ -theorem flatten_reverse (L : List (List α)) : +theorem flatten_reverse {L : List (List α)} : L.reverse.flatten = (L.map reverse).flatten.reverse := by induction L <;> simp_all -theorem reverse_flatMap {β} (l : List α) (f : α → List β) : (l.flatMap f).reverse = l.reverse.flatMap (reverse ∘ f) := by +theorem reverse_flatMap {β} {l : List α} {f : α → List β} : (l.flatMap f).reverse = l.reverse.flatMap (reverse ∘ f) := by induction l <;> simp_all -theorem flatMap_reverse {β} (l : List α) (f : α → List β) : (l.reverse.flatMap f) = (l.flatMap (reverse ∘ f)).reverse := by +theorem flatMap_reverse {β} {l : List α} {f : α → List β} : (l.reverse.flatMap f) = (l.flatMap (reverse ∘ f)).reverse := by induction l <;> simp_all -@[simp] theorem reverseAux_eq (as bs : List α) : reverseAux as bs = reverse as ++ bs := +@[simp] theorem reverseAux_eq {as bs : List α} : reverseAux as bs = reverse as ++ bs := reverseAux_eq_append .. -@[simp] theorem reverse_replicate (n) (a : α) : reverse (replicate n a) = replicate n a := +@[simp] theorem reverse_replicate {n : Nat} {a : α} : reverse (replicate n a) = replicate n a := eq_replicate_iff.2 ⟨by rw [length_reverse, length_replicate], fun _ h => eq_of_mem_replicate (mem_reverse.1 h)⟩ @@ -2500,88 +2514,88 @@ theorem flatMap_reverse {β} (l : List α) (f : α → List β) : (l.reverse.fla /-! ### foldlM and foldrM -/ -@[simp] theorem foldlM_append [Monad m] [LawfulMonad m] (f : β → α → m β) (b) (l l' : List α) : +@[simp] theorem foldlM_append [Monad m] [LawfulMonad m] {f : β → α → m β} {b : β} {l l' : List α} : (l ++ l').foldlM f b = l.foldlM f b >>= l'.foldlM f := by induction l generalizing b <;> simp [*] -@[simp] theorem foldrM_cons [Monad m] [LawfulMonad m] (a : α) (l) (f : α → β → m β) (b) : +@[simp] theorem foldrM_cons [Monad m] [LawfulMonad m] {a : α} {l : List α} {f : α → β → m β} {b : β} : (a :: l).foldrM f b = l.foldrM f b >>= f a := by simp only [foldrM] induction l <;> simp_all -@[simp] theorem foldlM_pure [Monad m] [LawfulMonad m] (f : β → α → β) (b) (l : List α) : +@[simp] theorem foldlM_pure [Monad m] [LawfulMonad m] {f : β → α → β} {b : β} {l : List α} : l.foldlM (m := m) (pure <| f · ·) b = pure (l.foldl f b) := by induction l generalizing b <;> simp [*] -@[simp] theorem foldrM_pure [Monad m] [LawfulMonad m] (f : α → β → β) (b) (l : List α) : +@[simp] theorem foldrM_pure [Monad m] [LawfulMonad m] {f : α → β → β} {b : β} {l : List α} : l.foldrM (m := m) (pure <| f · ·) b = pure (l.foldr f b) := by induction l generalizing b <;> simp [*] -theorem foldl_eq_foldlM (f : β → α → β) (b) (l : List α) : +theorem foldl_eq_foldlM {f : β → α → β} {b : β} {l : List α} : l.foldl f b = l.foldlM (m := Id) f b := by induction l generalizing b <;> simp [*, foldl] -theorem foldr_eq_foldrM (f : α → β → β) (b) (l : List α) : +theorem foldr_eq_foldrM {f : α → β → β} {b : β} {l : List α} : l.foldr f b = l.foldrM (m := Id) f b := by induction l <;> simp [*, foldr] -@[simp] theorem id_run_foldlM (f : β → α → Id β) (b) (l : List α) : - Id.run (l.foldlM f b) = l.foldl f b := (foldl_eq_foldlM f b l).symm +@[simp] theorem id_run_foldlM {f : β → α → Id β} {b : β} {l : List α} : + Id.run (l.foldlM f b) = l.foldl f b := foldl_eq_foldlM.symm -@[simp] theorem id_run_foldrM (f : α → β → Id β) (b) (l : List α) : - Id.run (l.foldrM f b) = l.foldr f b := (foldr_eq_foldrM f b l).symm +@[simp] theorem id_run_foldrM {f : α → β → Id β} {b : β} {l : List α} : + Id.run (l.foldrM f b) = l.foldr f b := foldr_eq_foldrM.symm -@[simp] theorem foldlM_reverse [Monad m] (l : List α) (f : β → α → m β) (b) : +@[simp] theorem foldlM_reverse [Monad m] {l : List α} {f : β → α → m β} {b : β} : l.reverse.foldlM f b = l.foldrM (fun x y => f y x) b := rfl -@[simp] theorem foldrM_reverse [Monad m] (l : List α) (f : α → β → m β) (b) : +@[simp] theorem foldrM_reverse [Monad m] {l : List α} {f : α → β → m β} {b : β} : l.reverse.foldrM f b = l.foldlM (fun x y => f y x) b := (foldlM_reverse ..).symm.trans <| by simp /-! ### foldl and foldr -/ -@[simp] theorem foldr_cons_eq_append (l : List α) (f : α → β) (l' : List β) : +@[simp] theorem foldr_cons_eq_append {l : List α} {f : α → β} {l' : List β} : l.foldr (fun x ys => f x :: ys) l' = l.map f ++ l' := by induction l <;> simp [*] /-- Variant of `foldr_cons_eq_append` specalized to `f = id`. -/ -@[simp] theorem foldr_cons_eq_append' (l l' : List β) : +@[simp] theorem foldr_cons_eq_append' {l l' : List β} : l.foldr cons l' = l ++ l' := by induction l <;> simp [*] -@[simp] theorem foldl_flip_cons_eq_append (l : List α) (f : α → β) (l' : List β) : +@[simp] theorem foldl_flip_cons_eq_append {l : List α} {f : α → β} {l' : List β} : l.foldl (fun xs y => f y :: xs) l' = (l.map f).reverse ++ l' := by induction l generalizing l' <;> simp [*] -@[simp] theorem foldr_append_eq_append (l : List α) (f : α → List β) (l' : List β) : +@[simp] theorem foldr_append_eq_append {l : List α} {f : α → List β} {l' : List β} : l.foldr (f · ++ ·) l' = (l.map f).flatten ++ l' := by induction l <;> simp [*] -@[simp] theorem foldl_append_eq_append (l : List α) (f : α → List β) (l' : List β) : +@[simp] theorem foldl_append_eq_append {l : List α} {f : α → List β} {l' : List β} : l.foldl (· ++ f ·) l' = l' ++ (l.map f).flatten := by induction l generalizing l'<;> simp [*] -@[simp] theorem foldr_flip_append_eq_append (l : List α) (f : α → List β) (l' : List β) : +@[simp] theorem foldr_flip_append_eq_append {l : List α} {f : α → List β} {l' : List β} : l.foldr (fun x ys => ys ++ f x) l' = l' ++ (l.map f).reverse.flatten := by induction l generalizing l' <;> simp [*] -@[simp] theorem foldl_flip_append_eq_append (l : List α) (f : α → List β) (l' : List β) : +@[simp] theorem foldl_flip_append_eq_append {l : List α} {f : α → List β} {l' : List β} : l.foldl (fun xs y => f y ++ xs) l' = (l.map f).reverse.flatten ++ l' := by induction l generalizing l' <;> simp [*] -theorem foldr_cons_nil (l : List α) : l.foldr cons [] = l := by simp +theorem foldr_cons_nil {l : List α} : l.foldr cons [] = l := by simp @[deprecated foldr_cons_nil (since := "2024-09-04")] abbrev foldr_self := @foldr_cons_nil -theorem foldl_map (f : β₁ → β₂) (g : α → β₂ → α) (l : List β₁) (init : α) : +theorem foldl_map {f : β₁ → β₂} {g : α → β₂ → α} {l : List β₁} {init : α} : (l.map f).foldl g init = l.foldl (fun x y => g x (f y)) init := by induction l generalizing init <;> simp [*] -theorem foldr_map (f : α₁ → α₂) (g : α₂ → β → β) (l : List α₁) (init : β) : +theorem foldr_map {f : α₁ → α₂} {g : α₂ → β → β} {l : List α₁} {init : β} : (l.map f).foldr g init = l.foldr (fun x y => g (f x) y) init := by induction l generalizing init <;> simp [*] -theorem foldl_filterMap (f : α → Option β) (g : γ → β → γ) (l : List α) (init : γ) : +theorem foldl_filterMap {f : α → Option β} {g : γ → β → γ} {l : List α} {init : γ} : (l.filterMap f).foldl g init = l.foldl (fun x y => match f y with | some b => g x b | none => x) init := by induction l generalizing init with | nil => rfl @@ -2589,7 +2603,7 @@ theorem foldl_filterMap (f : α → Option β) (g : γ → β → γ) (l : List simp only [filterMap_cons, foldl_cons] cases f a <;> simp [ih] -theorem foldr_filterMap (f : α → Option β) (g : β → γ → γ) (l : List α) (init : γ) : +theorem foldr_filterMap {f : α → Option β} {g : β → γ → γ} {l : List α} {init : γ} : (l.filterMap f).foldr g init = l.foldr (fun x y => match f x with | some b => g b y | none => y) init := by induction l generalizing init with | nil => rfl @@ -2597,7 +2611,7 @@ theorem foldr_filterMap (f : α → Option β) (g : β → γ → γ) (l : List simp only [filterMap_cons, foldr_cons] cases f a <;> simp [ih] -theorem foldl_map_hom (g : α → β) (f : α → α → α) (f' : β → β → β) (a : α) (l : List α) +theorem foldl_map_hom {g : α → β} {f : α → α → α} {f' : β → β → β} {a : α} {l : List α} (h : ∀ x y, f' (g x) (g y) = g (f x y)) : (l.map g).foldl f' (g a) = g (l.foldl f a) := by induction l generalizing a @@ -2606,7 +2620,7 @@ theorem foldl_map_hom (g : α → β) (f : α → α → α) (f' : β → β → @[deprecated foldl_map_hom (since := "2025-01-20")] abbrev foldl_map' := @foldl_map_hom -theorem foldr_map_hom (g : α → β) (f : α → α → α) (f' : β → β → β) (a : α) (l : List α) +theorem foldr_map_hom {g : α → β} {f : α → α → α} {f' : β → β → β} {a : α} {l : List α} (h : ∀ x y, f' (g x) (g y) = g (f x y)) : (l.map g).foldr f' (g a) = g (l.foldr f a) := by induction l generalizing a @@ -2615,35 +2629,35 @@ theorem foldr_map_hom (g : α → β) (f : α → α → α) (f' : β → β → @[deprecated foldr_map_hom (since := "2025-01-20")] abbrev foldr_map' := @foldr_map_hom -@[simp] theorem foldrM_append [Monad m] [LawfulMonad m] (f : α → β → m β) (b) (l l' : List α) : +@[simp] theorem foldrM_append [Monad m] [LawfulMonad m] {f : α → β → m β} {b : β} {l l' : List α} : (l ++ l').foldrM f b = l'.foldrM f b >>= l.foldrM f := by induction l <;> simp [*] -@[simp] theorem foldl_append {β : Type _} (f : β → α → β) (b) (l l' : List α) : +@[simp] theorem foldl_append {β : Type _} {f : β → α → β} {b : β} {l l' : List α} : (l ++ l').foldl f b = l'.foldl f (l.foldl f b) := by simp [foldl_eq_foldlM] -@[simp] theorem foldr_append (f : α → β → β) (b) (l l' : List α) : +@[simp] theorem foldr_append {f : α → β → β} {b : β} {l l' : List α} : (l ++ l').foldr f b = l.foldr f (l'.foldr f b) := by simp [foldr_eq_foldrM] -theorem foldl_flatten (f : β → α → β) (b : β) (L : List (List α)) : +theorem foldl_flatten {f : β → α → β} {b : β} {L : List (List α)} : (flatten L).foldl f b = L.foldl (fun b l => l.foldl f b) b := by induction L generalizing b <;> simp_all -theorem foldr_flatten (f : α → β → β) (b : β) (L : List (List α)) : +theorem foldr_flatten {f : α → β → β} {b : β} {L : List (List α)} : (flatten L).foldr f b = L.foldr (fun l b => l.foldr f b) b := by induction L <;> simp_all -@[simp] theorem foldl_reverse (l : List α) (f : β → α → β) (b) : +@[simp] theorem foldl_reverse {l : List α} {f : β → α → β} {b : β} : l.reverse.foldl f b = l.foldr (fun x y => f y x) b := by simp [foldl_eq_foldlM, foldr_eq_foldrM] -@[simp] theorem foldr_reverse (l : List α) (f : α → β → β) (b) : +@[simp] theorem foldr_reverse {l : List α} {f : α → β → β} {b : β} : l.reverse.foldr f b = l.foldl (fun x y => f y x) b := (foldl_reverse ..).symm.trans <| by simp -theorem foldl_eq_foldr_reverse (l : List α) (f : β → α → β) (b) : +theorem foldl_eq_foldr_reverse {l : List α} {f : β → α → β} {b : β} : l.foldl f b = l.reverse.foldr (fun x y => f y x) b := by simp -theorem foldr_eq_foldl_reverse (l : List α) (f : α → β → β) (b) : +theorem foldr_eq_foldl_reverse {l : List α} {f : α → β → β} {b : β} : l.foldr f b = l.reverse.foldl (fun x y => f y x) b := by simp theorem foldl_assoc {op : α → α → α} [ha : Std.Associative op] : @@ -2660,11 +2674,13 @@ theorem foldr_assoc {op : α → α → α} [ha : Std.Associative op] : simp only [foldr_cons, ha.assoc] rw [foldr_assoc] -theorem foldl_hom (f : α₁ → α₂) (g₁ : α₁ → β → α₁) (g₂ : α₂ → β → α₂) (l : List β) (init : α₁) +-- The argument `f : α₁ → α₂` is intentionally explicit, as it is sometimes not found by unification. +theorem foldl_hom (f : α₁ → α₂) {g₁ : α₁ → β → α₁} {g₂ : α₂ → β → α₂} {l : List β} {init : α₁} (H : ∀ x y, g₂ (f x) y = f (g₁ x y)) : l.foldl g₂ (f init) = f (l.foldl g₁ init) := by induction l generalizing init <;> simp [*, H] -theorem foldr_hom (f : β₁ → β₂) (g₁ : α → β₁ → β₁) (g₂ : α → β₂ → β₂) (l : List α) (init : β₁) +-- The argument `f : β₁ → β₂` is intentionally explicit, as it is sometimes not found by unification. +theorem foldr_hom (f : β₁ → β₂) {g₁ : α → β₁ → β₁} {g₂ : α → β₂ → β₂} {l : List α} {init : β₁} (H : ∀ x y, g₂ x (f y) = f (g₁ x y)) : l.foldr g₂ (f init) = f (l.foldr g₁ init) := by induction l <;> simp [*, H] @@ -2684,21 +2700,21 @@ example {xs : List Nat} : xs.foldl (· + ·) 1 > 0 := by intros; omega ``` -/ -def foldlRecOn {motive : β → Sort _} : ∀ (l : List α) (op : β → α → β) (b : β) (_ : motive b) +def foldlRecOn {motive : β → Sort _} : ∀ (l : List α) (op : β → α → β) {b : β} (_ : motive b) (_ : ∀ (b : β) (_ : motive b) (a : α) (_ : a ∈ l), motive (op b a)), motive (List.foldl op b l) | [], _, _, hb, _ => hb | hd :: tl, op, b, hb, hl => - foldlRecOn tl op (op b hd) (hl b hb hd (mem_cons_self hd tl)) + foldlRecOn tl op (hl b hb hd mem_cons_self) fun y hy x hx => hl y hy x (mem_cons_of_mem hd hx) -@[simp] theorem foldlRecOn_nil {motive : β → Sort _} (hb : motive b) +@[simp] theorem foldlRecOn_nil {motive : β → Sort _} {op : β → α → β} (hb : motive b) (hl : ∀ (b : β) (_ : motive b) (a : α) (_ : a ∈ []), motive (op b a)) : - foldlRecOn [] op b hb hl = hb := rfl + foldlRecOn [] op hb hl = hb := rfl -@[simp] theorem foldlRecOn_cons {motive : β → Sort _} (hb : motive b) +@[simp] theorem foldlRecOn_cons {motive : β → Sort _} {op : β → α → β} (hb : motive b) (hl : ∀ (b : β) (_ : motive b) (a : α) (_ : a ∈ x :: l), motive (op b a)) : - foldlRecOn (x :: l) op b hb hl = - foldlRecOn l op (op b x) (hl b hb x (mem_cons_self x l)) + foldlRecOn (x :: l) op hb hl = + foldlRecOn l op (hl b hb x mem_cons_self) (fun b c a m => hl b c a (mem_cons_of_mem x m)) := rfl @@ -2718,22 +2734,22 @@ example {xs : List Nat} : xs.foldr (· + ·) 1 > 0 := by intros; omega ``` -/ -def foldrRecOn {motive : β → Sort _} : ∀ (l : List α) (op : α → β → β) (b : β) (_ : motive b) +def foldrRecOn {motive : β → Sort _} : ∀ (l : List α) (op : α → β → β) {b : β} (_ : motive b) (_ : ∀ (b : β) (_ : motive b) (a : α) (_ : a ∈ l), motive (op a b)), motive (List.foldr op b l) | nil, _, _, hb, _ => hb | x :: l, op, b, hb, hl => hl (foldr op b l) - (foldrRecOn l op b hb fun b c a m => hl b c a (mem_cons_of_mem x m)) x (mem_cons_self x l) + (foldrRecOn l op hb fun b c a m => hl b c a (mem_cons_of_mem x m)) x mem_cons_self -@[simp] theorem foldrRecOn_nil {motive : β → Sort _} (hb : motive b) +@[simp] theorem foldrRecOn_nil {motive : β → Sort _} {op : α → β → β} (hb : motive b) (hl : ∀ (b : β) (_ : motive b) (a : α) (_ : a ∈ []), motive (op a b)) : - foldrRecOn [] op b hb hl = hb := rfl + foldrRecOn [] op hb hl = hb := rfl -@[simp] theorem foldrRecOn_cons {motive : β → Sort _} (hb : motive b) +@[simp] theorem foldrRecOn_cons {motive : β → Sort _} {op : α → β → β} (hb : motive b) (hl : ∀ (b : β) (_ : motive b) (a : α) (_ : a ∈ x :: l), motive (op a b)) : - foldrRecOn (x :: l) op b hb hl = - hl _ (foldrRecOn l op b hb fun b c a m => hl b c a (mem_cons_of_mem x m)) - x (mem_cons_self x l) := + foldrRecOn (x :: l) op hb hl = + hl _ (foldrRecOn l op hb fun b c a m => hl b c a (mem_cons_of_mem x m)) + x mem_cons_self := rfl /-- @@ -2741,7 +2757,7 @@ We can prove that two folds over the same list are related (by some arbitrary re if we know that the initial elements are related and the folding function, for each element of the list, preserves the relation. -/ -theorem foldl_rel {l : List α} {f g : β → α → β} {a b : β} (r : β → β → Prop) +theorem foldl_rel {l : List α} {f g : β → α → β} {a b : β} {r : β → β → Prop} (h : r a b) (h' : ∀ (a : α), a ∈ l → ∀ (c c' : β), r c c' → r (f c a) (g c' a)) : r (l.foldl (fun acc a => f acc a) a) (l.foldl (fun acc a => g acc a) b) := by induction l generalizing a b with @@ -2757,7 +2773,7 @@ We can prove that two folds over the same list are related (by some arbitrary re if we know that the initial elements are related and the folding function, for each element of the list, preserves the relation. -/ -theorem foldr_rel {l : List α} {f g : α → β → β} {a b : β} (r : β → β → Prop) +theorem foldr_rel {l : List α} {f g : α → β → β} {a b : β} {r : β → β → Prop} (h : r a b) (h' : ∀ (a : α), a ∈ l → ∀ (c c' : β), r c c' → r (f a c) (g a c')) : r (l.foldr (fun a acc => f a acc) a) (l.foldr (fun a acc => g a acc) b) := by induction l generalizing a b with @@ -2768,7 +2784,7 @@ theorem foldr_rel {l : List α} {f g : α → β → β} {a b : β} (r : β → · simp · exact ih h fun a m c c' h => h' _ (by simp_all) _ _ h -@[simp] theorem foldl_add_const (l : List α) (a b : Nat) : +@[simp] theorem foldl_add_const {l : List α} {a b : Nat} : l.foldl (fun x _ => x + a) b = b + a * l.length := by induction l generalizing b with | nil => simp @@ -2776,7 +2792,7 @@ theorem foldr_rel {l : List α} {f g : α → β → β} {a b : β} (r : β → simp only [foldl_cons, ih, length_cons, Nat.mul_add, Nat.mul_one, Nat.add_assoc, Nat.add_comm a] -@[simp] theorem foldr_add_const (l : List α) (a b : Nat) : +@[simp] theorem foldr_add_const {l : List α} {a b : Nat} : l.foldr (fun _ x => x + a) b = b + a * l.length := by induction l generalizing b with | nil => simp @@ -2818,7 +2834,7 @@ theorem getLast?_eq_some_iff {xs : List α} {a : α} : xs.getLast? = some a ↔ theorem mem_of_getLast? {xs : List α} {a : α} (h : xs.getLast? = some a) : a ∈ xs := by obtain ⟨ys, rfl⟩ := getLast?_eq_some_iff.1 h - exact mem_concat_self ys a + exact mem_concat_self @[deprecated mem_of_getLast? (since := "2024-10-21")] abbrev mem_of_getLast?_eq_some := @mem_of_getLast? @@ -2830,7 +2846,7 @@ theorem head_eq_getLast_reverse {l : List α} (h : l ≠ []) : l.head h = l.reverse.getLast (by simp_all) := by rw [← getLast_reverse] -@[simp] theorem getLast_append_of_ne_nil {l : List α} {h₁} (h₂ : l' ≠ []) : +@[simp] theorem getLast_append_of_ne_nil {l : List α} (h₁) (h₂ : l' ≠ []) : (l ++ l').getLast h₁ = l'.getLast h₂ := by simp only [getLast_eq_head_reverse, reverse_append] rw [head_append_of_ne_nil] @@ -2865,7 +2881,7 @@ theorem getLast_filter_of_pos {p : α → Bool} {l : List α} (w : l ≠ []) (h rw [head_filter_of_pos] simp_all -theorem getLast_filterMap_of_eq_some {f : α → Option β} {l : List α} {w : l ≠ []} {b : β} (h : f (l.getLast w) = some b) : +theorem getLast_filterMap_of_eq_some {f : α → Option β} {l : List α} (w : l ≠ []) {b : β} (h : f (l.getLast w) = some b) : (filterMap f l).getLast (ne_nil_of_mem (mem_filterMap.2 ⟨_, getLast_mem w, h⟩)) = b := by simp only [getLast_eq_head_reverse, ← filterMap_reverse] rw [head_filterMap_of_eq_some (by simp_all)] @@ -2881,7 +2897,7 @@ theorem getLast?_flatten {L : List (List α)} : (flatten L).getLast? = L.reverse.findSome? fun l => l.getLast? := by simp [← flatMap_id, getLast?_flatMap] -theorem getLast?_replicate (a : α) (n : Nat) : (replicate n a).getLast? = if n = 0 then none else some a := by +theorem getLast?_replicate {a : α} {n : Nat} : (replicate n a).getLast? = if n = 0 then none else some a := by simp only [← head?_reverse, reverse_replicate, head?_replicate] @[simp] theorem getLast_replicate (w : replicate n a ≠ []) : (replicate n a).getLast w = a := by @@ -2896,12 +2912,12 @@ attribute [simp] leftpad rightpad -- `length_leftpad` and `length_rightpad` are in `Init.Data.List.Nat.Basic`. -theorem leftpad_prefix (n : Nat) (a : α) (l : List α) : +theorem leftpad_prefix {n : Nat} {a : α} {l : List α} : replicate (n - length l) a <+: leftpad n a l := by simp only [IsPrefix, leftpad] exact Exists.intro l rfl -theorem leftpad_suffix (n : Nat) (a : α) (l : List α) : l <:+ (leftpad n a l) := by +theorem leftpad_suffix {n : Nat} {a : α} {l : List α} : l <:+ (leftpad n a l) := by simp only [IsSuffix, leftpad] exact Exists.intro (replicate (n - length l) a) rfl @@ -2911,7 +2927,7 @@ theorem leftpad_suffix (n : Nat) (a : α) (l : List α) : l <:+ (leftpad n a l) theorem elem_cons_self [BEq α] [LawfulBEq α] {a : α} : (a::as).elem a = true := by simp -theorem contains_eq_any_beq [BEq α] (l : List α) (a : α) : l.contains a = l.any (a == ·) := by +theorem contains_eq_any_beq [BEq α] {l : List α} {a : α} : l.contains a = l.any (a == ·) := by induction l with simp | cons b l => cases b == a <;> simp [*] theorem contains_iff_exists_mem_beq [BEq α] {l : List α} {a : α} : @@ -2930,7 +2946,7 @@ Because we immediately simplify `partition` into two `filter`s for verification we do not separately develop much theory about it. -/ -@[simp] theorem partition_eq_filter_filter (p : α → Bool) (l : List α) : +@[simp] theorem partition_eq_filter_filter {p : α → Bool} {l : List α} : partition p l = (filter p l, filter (not ∘ p) l) := by simp [partition, aux] where aux : ∀ l {as bs}, partition.loop p l (as, bs) = @@ -2947,23 +2963,23 @@ theorem mem_partition : a ∈ l ↔ a ∈ (partition p l).1 ∨ a ∈ (partition are often used for theorems about `Array.pop`. -/ -@[simp] theorem length_dropLast : ∀ (xs : List α), xs.dropLast.length = xs.length - 1 +@[simp] theorem length_dropLast : ∀ {xs : List α}, xs.dropLast.length = xs.length - 1 | [] => rfl | x::xs => by simp -@[simp] theorem getElem_dropLast : ∀ (xs : List α) (i : Nat) (h : i < xs.dropLast.length), +@[simp] theorem getElem_dropLast : ∀ {xs : List α} {i : Nat} (h : i < xs.dropLast.length), xs.dropLast[i] = xs[i]'(Nat.lt_of_lt_of_le h (length_dropLast .. ▸ Nat.pred_le _)) - | _::_::_, 0, _ => rfl - | _::_::_, i+1, h => getElem_dropLast _ i (Nat.add_one_lt_add_one_iff.mp h) + | _ :: _ :: _, 0, _ => rfl + | _ :: _ :: _, _ + 1, h => getElem_dropLast (Nat.add_one_lt_add_one_iff.mp h) -theorem getElem?_dropLast (xs : List α) (i : Nat) : +theorem getElem?_dropLast {xs : List α} {i : Nat} : xs.dropLast[i]? = if i < xs.length - 1 then xs[i]? else none := by split · rw [getElem?_eq_getElem, getElem?_eq_getElem, getElem_dropLast] simpa · simp_all -theorem head_dropLast (xs : List α) (h) : +theorem head_dropLast {xs : List α} (h) : xs.dropLast.head h = xs.head (by rintro rfl; simp at h) := by cases xs with | nil => rfl @@ -2972,7 +2988,7 @@ theorem head_dropLast (xs : List α) (h) : | nil => simp at h | cons y ys => rfl -theorem head?_dropLast (xs : List α) : xs.dropLast.head? = if 1 < xs.length then xs.head? else none := by +theorem head?_dropLast {xs : List α} : xs.dropLast.head? = if 1 < xs.length then xs.head? else none := by cases xs with | nil => rfl | cons x xs => @@ -3012,16 +3028,16 @@ theorem dropLast_concat_getLast : ∀ {l : List α} (h : l ≠ []), dropLast l + congr exact dropLast_concat_getLast (cons_ne_nil b l) -@[simp] theorem map_dropLast (f : α → β) (l : List α) : l.dropLast.map f = (l.map f).dropLast := by +@[simp] theorem map_dropLast {f : α → β} {l : List α} : l.dropLast.map f = (l.map f).dropLast := by induction l with | nil => rfl | cons x xs ih => cases xs <;> simp [ih] @[simp] theorem dropLast_append_of_ne_nil {α : Type u} {l : List α} : - ∀ (l' : List α) (_ : l ≠ []), (l' ++ l).dropLast = l' ++ l.dropLast + ∀ {l' : List α} (_ : l ≠ []), (l' ++ l).dropLast = l' ++ l.dropLast | [], _ => by simp only [nil_append] | a :: l', h => by - rw [cons_append, dropLast, dropLast_append_of_ne_nil l' h, cons_append] + rw [cons_append, dropLast, dropLast_append_of_ne_nil h, cons_append] simp [h] theorem dropLast_append {l₁ l₂ : List α} : @@ -3033,7 +3049,7 @@ theorem dropLast_append_cons : dropLast (l₁ ++ b :: l₂) = l₁ ++ dropLast ( @[simp] theorem dropLast_concat : dropLast (l₁ ++ [b]) = l₁ := by simp -@[simp] theorem dropLast_replicate (n) (a : α) : dropLast (replicate n a) = replicate (n - 1) a := by +@[simp] theorem dropLast_replicate {n : Nat} {a : α} : dropLast (replicate n a) = replicate (n - 1) a := by match n with | 0 => simp | 1 => simp [replicate_succ] @@ -3042,11 +3058,11 @@ theorem dropLast_append_cons : dropLast (l₁ ++ b :: l₂) = l₁ ++ dropLast ( · simp [replicate_succ] · simp -@[simp] theorem dropLast_cons_self_replicate (n) (a : α) : +@[simp] theorem dropLast_cons_self_replicate {n : Nat} {a : α} : dropLast (a :: replicate n a) = replicate n a := by rw [← replicate_succ, dropLast_replicate, Nat.add_sub_cancel] -@[simp] theorem tail_reverse (l : List α) : l.reverse.tail = l.dropLast.reverse := by +@[simp] theorem tail_reverse {l : List α} : l.reverse.tail = l.dropLast.reverse := by apply ext_getElem · simp · intro i h₁ h₂ @@ -3060,7 +3076,7 @@ We don't provide any API for `splitAt`, beyond the `@[simp]` lemma which is proved in `Init.Data.List.TakeDrop`. -/ -theorem splitAt_go (i : Nat) (l acc : List α) : +theorem splitAt_go {i : Nat} {l acc : List α} : splitAt.go l xs i acc = if i < xs.length then (acc.reverse ++ xs.take i, xs.drop i) else (l, []) := by induction xs generalizing i acc with @@ -3069,8 +3085,8 @@ theorem splitAt_go (i : Nat) (l acc : List α) : cases i with | zero => simp [splitAt.go] | succ i => - rw [splitAt.go, take_succ_cons, drop_succ_cons, ih i (x :: acc), - reverse_cons, append_assoc, singleton_append, length_cons] + rw [splitAt.go, take_succ_cons, drop_succ_cons, ih, reverse_cons, append_assoc, + singleton_append, length_cons] simp only [Nat.succ_lt_succ_iff] /-! ## Manipulating elements -/ @@ -3120,7 +3136,7 @@ theorem getElem_replace_of_ne [LawfulBEq α] {l : List α} {i : Nat} {h : i < l. rw [getElem_replace h] simp [h'] -theorem head?_replace (l : List α) (a b : α) : +theorem head?_replace {l : List α} {a b : α} : (l.replace a b).head? = match l.head? with | none => none | some x => some (if a == x then b else x) := by @@ -3130,7 +3146,7 @@ theorem head?_replace (l : List α) (a b : α) : simp [replace_cons] split <;> simp_all -theorem head_replace (l : List α) (a b : α) (w) : +theorem head_replace {l : List α} {a b : α} (w) : (l.replace a b).head w = if a == l.head (by rintro rfl; simp_all) then b @@ -3201,7 +3217,7 @@ variable [LawfulBEq α] | Or.inr h' => exact h' else rw [insert_of_not_mem h, mem_cons] -@[simp] theorem mem_insert_self (a : α) (l : List α) : a ∈ l.insert a := +@[simp] theorem mem_insert_self {a : α} {l : List α} : a ∈ l.insert a := mem_insert_iff.2 (Or.inl rfl) theorem mem_insert_of_mem {l : List α} (h : a ∈ l) : a ∈ l.insert b := @@ -3233,23 +3249,23 @@ theorem length_insert_pos {l : List α} {a : α} : 0 < (l.insert a).length := by theorem insert_eq {l : List α} {a : α} : l.insert a = if a ∈ l then l else a :: l := by simp [List.insert] -theorem getElem?_insert_zero (l : List α) (a : α) : +theorem getElem?_insert_zero {l : List α} {a : α} : (l.insert a)[0]? = if a ∈ l then l[0]? else some a := by simp only [insert_eq] split <;> simp -theorem getElem?_insert_succ (l : List α) (a : α) (i : Nat) : +theorem getElem?_insert_succ {l : List α} {a : α} {i : Nat} : (l.insert a)[i+1]? = if a ∈ l then l[i+1]? else l[i]? := by simp only [insert_eq] split <;> simp -theorem getElem?_insert (l : List α) (a : α) (i : Nat) : +theorem getElem?_insert {l : List α} {a : α} {i : Nat} : (l.insert a)[i]? = if a ∈ l then l[i]? else if i = 0 then some a else l[i-1]? := by cases i · simp [getElem?_insert_zero] · simp [getElem?_insert_succ] -theorem getElem_insert (l : List α) (a : α) (i : Nat) (h : i < l.length) : +theorem getElem_insert {l : List α} {a : α} {i : Nat} (h : i < l.length) : (l.insert a)[i]'(Nat.lt_of_lt_of_le h length_le_length_insert) = if a ∈ l then l[i] else if i = 0 then a else l[i-1]'(Nat.lt_of_le_of_lt (Nat.pred_le _) h) := by apply Option.some.inj @@ -3261,14 +3277,14 @@ theorem getElem_insert (l : List α) (a : α) (i : Nat) (h : i < l.length) : · have h' : i - 1 < l.length := Nat.lt_of_le_of_lt (Nat.pred_le _) h simp [getElem?_eq_getElem, h'] -theorem head?_insert (l : List α) (a : α) : +theorem head?_insert {l : List α} {a : α} : (l.insert a).head? = some (if h : a ∈ l then l.head (ne_nil_of_mem h) else a) := by simp only [insert_eq] split <;> rename_i h · simp [head?_eq_head (ne_nil_of_mem h)] · rfl -theorem head_insert (l : List α) (a : α) (w) : +theorem head_insert {l : List α} {a : α} (w) : (l.insert a).head w = if h : a ∈ l then l.head (ne_nil_of_mem h) else a := by apply Option.some.inj rw [← head?_eq_head, head?_insert] @@ -3300,32 +3316,32 @@ end insert /-! ### any / all -/ -theorem not_any_eq_all_not (l : List α) (p : α → Bool) : (!l.any p) = l.all fun a => !p a := by +theorem not_any_eq_all_not {l : List α} {p : α → Bool} : (!l.any p) = l.all fun a => !p a := by induction l with simp | cons _ _ ih => rw [ih] -theorem not_all_eq_any_not (l : List α) (p : α → Bool) : (!l.all p) = l.any fun a => !p a := by +theorem not_all_eq_any_not {l : List α} {p : α → Bool} : (!l.all p) = l.any fun a => !p a := by induction l with simp | cons _ _ ih => rw [ih] -theorem and_any_distrib_left (l : List α) (p : α → Bool) (q : Bool) : +theorem and_any_distrib_left {l : List α} {p : α → Bool} {q : Bool} : (q && l.any p) = l.any fun a => q && p a := by induction l with simp | cons _ _ ih => rw [Bool.and_or_distrib_left, ih] -theorem and_any_distrib_right (l : List α) (p : α → Bool) (q : Bool) : +theorem and_any_distrib_right {l : List α} {p : α → Bool} {q : Bool} : (l.any p && q) = l.any fun a => p a && q := by induction l with simp | cons _ _ ih => rw [Bool.and_or_distrib_right, ih] -theorem or_all_distrib_left (l : List α) (p : α → Bool) (q : Bool) : +theorem or_all_distrib_left {l : List α} {p : α → Bool} {q : Bool} : (q || l.all p) = l.all fun a => q || p a := by induction l with simp | cons _ _ ih => rw [Bool.or_and_distrib_left, ih] -theorem or_all_distrib_right (l : List α) (p : α → Bool) (q : Bool) : +theorem or_all_distrib_right {l : List α} {p : α → Bool} {q : Bool} : (l.all p || q) = l.all fun a => p a || q := by induction l with simp | cons _ _ ih => rw [Bool.or_and_distrib_right, ih] -theorem any_eq_not_all_not (l : List α) (p : α → Bool) : l.any p = !l.all (!p .) := by +theorem any_eq_not_all_not {l : List α} {p : α → Bool} : l.any p = !l.all (!p .) := by simp only [not_all_eq_any_not, Bool.not_not] -theorem all_eq_not_any_not (l : List α) (p : α → Bool) : l.all p = !l.any (!p .) := by +theorem all_eq_not_any_not {l : List α} {p : α → Bool} : l.all p = !l.any (!p .) := by simp only [not_any_eq_all_not, Bool.not_not] @[simp] theorem any_map {l : List α} {p : β → Bool} : (l.map f).any p = l.any (p ∘ f) := by diff --git a/src/Init/Data/List/Lex.lean b/src/Init/Data/List/Lex.lean index bf05b4255f..d342273779 100644 --- a/src/Init/Data/List/Lex.lean +++ b/src/Init/Data/List/Lex.lean @@ -14,11 +14,11 @@ namespace List /-! ### Lexicographic ordering -/ -@[simp] theorem lex_lt [LT α] (l₁ l₂ : List α) : Lex (· < ·) l₁ l₂ ↔ l₁ < l₂ := Iff.rfl -@[simp] theorem not_lex_lt [LT α] (l₁ l₂ : List α) : ¬ Lex (· < ·) l₁ l₂ ↔ l₂ ≤ l₁ := Iff.rfl +@[simp] theorem lex_lt [LT α] {l₁ l₂ : List α} : Lex (· < ·) l₁ l₂ ↔ l₁ < l₂ := Iff.rfl +@[simp] theorem not_lex_lt [LT α] {l₁ l₂ : List α} : ¬ Lex (· < ·) l₁ l₂ ↔ l₂ ≤ l₁ := Iff.rfl -protected theorem not_lt_iff_ge [LT α] (l₁ l₂ : List α) : ¬ l₁ < l₂ ↔ l₂ ≤ l₁ := Iff.rfl -protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] (l₁ l₂ : List α) : +protected theorem not_lt_iff_ge [LT α] {l₁ l₂ : List α} : ¬ l₁ < l₂ ↔ l₂ ≤ l₁ := Iff.rfl +protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {l₁ l₂ : List α} : ¬ l₁ ≤ l₂ ↔ l₂ < l₁ := Decidable.not_not @@ -49,7 +49,7 @@ instance ltIrrefl [LT α] [Std.Irrefl (· < · : α → α → Prop)] : Std.Irre · rintro rfl exact not_lex_nil -@[simp] theorem le_nil [LT α] (l : List α) : l ≤ [] ↔ l = [] := not_nil_lex_iff +@[simp] theorem le_nil [LT α] {l : List α} : l ≤ [] ↔ l = [] := not_nil_lex_iff -- This is named with a prime to avoid conflict with `lex [] (b :: bs) lt = true`. -- Better naming for the `Lex` vs `lex` distinction would be welcome. diff --git a/src/Init/Data/List/MapIdx.lean b/src/Init/Data/List/MapIdx.lean index 571475274a..318f63237c 100644 --- a/src/Init/Data/List/MapIdx.lean +++ b/src/Init/Data/List/MapIdx.lean @@ -490,9 +490,9 @@ theorem mapIdx_eq_mapIdx_iff {l : List α} : cases l with | nil => simp at h | cons _ _ => - simp only [← getElem_cons_length _ _ _ rfl] + simp only [← getElem_cons_length rfl] simp only [mapIdx_cons] - simp only [← getElem_cons_length _ _ _ rfl] + simp only [← getElem_cons_length rfl] simp only [← mapIdx_cons, getElem_mapIdx] simp diff --git a/src/Init/Data/List/MinMax.lean b/src/Init/Data/List/MinMax.lean index 4a883b7c2f..0a9ceb72d1 100644 --- a/src/Init/Data/List/MinMax.lean +++ b/src/Init/Data/List/MinMax.lean @@ -37,19 +37,19 @@ theorem min?_cons' [Min α] {xs : List α} : (x :: xs).min? = foldl min x xs := theorem isSome_min?_of_mem {l : List α} [Min α] {a : α} (h : a ∈ l) : l.min?.isSome := by - cases l <;> simp_all [List.min?_cons'] + cases l <;> simp_all [min?_cons'] theorem min?_eq_head? {α : Type u} [Min α] {l : List α} (h : l.Pairwise (fun a b => min a b = a)) : l.min? = l.head? := by cases l with | nil => rfl | cons x l => - rw [List.head?_cons, List.min?_cons', Option.some.injEq] + rw [head?_cons, min?_cons', Option.some.injEq] induction l generalizing x with | nil => simp | cons y l ih => - have hx : min x y = x := List.rel_of_pairwise_cons h (List.mem_cons_self _ _) - rw [List.foldl_cons, ih _ (hx.symm ▸ h.sublist (by simp)), hx] + have hx : min x y = x := rel_of_pairwise_cons h mem_cons_self + rw [foldl_cons, ih _ (hx.symm ▸ h.sublist (by simp)), hx] theorem min?_mem [Min α] (min_eq_or : ∀ a b : α, min a b = a ∨ min a b = b) : {xs : List α} → xs.min? = some a → a ∈ xs := by @@ -57,7 +57,7 @@ theorem min?_mem [Min α] (min_eq_or : ∀ a b : α, min a b = a ∨ min a b = b match xs with | nil => simp | x :: xs => - simp only [min?_cons', Option.some.injEq, List.mem_cons] + simp only [min?_cons', Option.some.injEq, mem_cons] intro eq induction xs generalizing x with | nil => @@ -138,7 +138,7 @@ theorem max?_cons' [Max α] {xs : List α} : (x :: xs).max? = foldl max x xs := theorem isSome_max?_of_mem {l : List α} [Max α] {a : α} (h : a ∈ l) : l.max?.isSome := by - cases l <;> simp_all [List.max?_cons'] + cases l <;> simp_all [max?_cons'] theorem max?_mem [Max α] (min_eq_or : ∀ a b : α, max a b = a ∨ max a b = b) : {xs : List α} → xs.max? = some a → a ∈ xs diff --git a/src/Init/Data/List/Monadic.lean b/src/Init/Data/List/Monadic.lean index 7528cebdbe..6f0057fe59 100644 --- a/src/Init/Data/List/Monadic.lean +++ b/src/Init/Data/List/Monadic.lean @@ -48,29 +48,29 @@ def mapM' [Monad m] (f : α → m β) : List α → m (List β) mapM' f (a :: l) = return ((← f a) :: (← l.mapM' f)) := rfl -theorem mapM'_eq_mapM [Monad m] [LawfulMonad m] (f : α → m β) (l : List α) : +theorem mapM'_eq_mapM [Monad m] [LawfulMonad m] {f : α → m β} {l : List α} : mapM' f l = mapM f l := by simp [go, mapM] where go : ∀ l acc, mapM.loop f l acc = return acc.reverse ++ (← mapM' f l) | [], acc => by simp [mapM.loop, mapM'] | a::l, acc => by simp [go l, mapM.loop, mapM'] -@[simp] theorem mapM_nil [Monad m] (f : α → m β) : [].mapM f = pure [] := rfl +@[simp] theorem mapM_nil [Monad m] {f : α → m β} : [].mapM f = pure [] := rfl -@[simp] theorem mapM_cons [Monad m] [LawfulMonad m] (f : α → m β) : +@[simp] theorem mapM_cons [Monad m] [LawfulMonad m] {f : α → m β} : (a :: l).mapM f = (return (← f a) :: (← l.mapM f)) := by simp [← mapM'_eq_mapM, mapM'] -@[simp] theorem mapM_pure [Monad m] [LawfulMonad m] (l : List α) (f : α → β) : +@[simp] theorem mapM_pure [Monad m] [LawfulMonad m] {l : List α} {f : α → β} : l.mapM (m := m) (pure <| f ·) = pure (l.map f) := by induction l <;> simp_all @[simp] theorem mapM_id {l : List α} {f : α → Id β} : l.mapM f = l.map f := - mapM_pure _ _ + mapM_pure -@[simp] theorem mapM_append [Monad m] [LawfulMonad m] (f : α → m β) {l₁ l₂ : List α} : +@[simp] theorem mapM_append [Monad m] [LawfulMonad m] {f : α → m β} {l₁ l₂ : List α} : (l₁ ++ l₂).mapM f = (return (← l₁.mapM f) ++ (← l₂.mapM f)) := by induction l₁ <;> simp [*] /-- Auxiliary lemma for `mapM_eq_reverse_foldlM_cons`. -/ -theorem foldlM_cons_eq_append [Monad m] [LawfulMonad m] (f : α → m β) (as : List α) (b : β) (bs : List β) : +theorem foldlM_cons_eq_append [Monad m] [LawfulMonad m] {f : α → m β} {as : List α} {b : β} {bs : List β} : (as.foldlM (init := b :: bs) fun acc a => return ((← f a) :: acc)) = (· ++ b :: bs) <$> as.foldlM (init := []) fun acc a => return ((← f a) :: acc) := by induction as generalizing b bs with @@ -79,7 +79,7 @@ theorem foldlM_cons_eq_append [Monad m] [LawfulMonad m] (f : α → m β) (as : simp only [bind_pure_comp] at ih simp [ih, _root_.map_bind, Functor.map_map, Function.comp_def] -theorem mapM_eq_reverse_foldlM_cons [Monad m] [LawfulMonad m] (f : α → m β) (l : List α) : +theorem mapM_eq_reverse_foldlM_cons [Monad m] [LawfulMonad m] {f : α → m β} {l : List α} : mapM f l = reverse <$> (l.foldlM (fun acc a => return ((← f a) :: acc)) []) := by rw [← mapM'_eq_mapM] induction l with @@ -92,10 +92,9 @@ theorem mapM_eq_reverse_foldlM_cons [Monad m] [LawfulMonad m] (f : α → m β) /-! ### filterMapM -/ -@[simp] theorem filterMapM_nil [Monad m] (f : α → m (Option β)) : [].filterMapM f = pure [] := rfl +@[simp] theorem filterMapM_nil [Monad m] {f : α → m (Option β)} : [].filterMapM f = pure [] := rfl -theorem filterMapM_loop_eq [Monad m] [LawfulMonad m] - (f : α → m (Option β)) (l : List α) (acc : List β) : +theorem filterMapM_loop_eq [Monad m] [LawfulMonad m] {f : α → m (Option β)} {l : List α} {acc : List β} : filterMapM.loop f l acc = (acc.reverse ++ ·) <$> filterMapM.loop f l [] := by induction l generalizing acc with | nil => simp [filterMapM.loop] @@ -105,10 +104,10 @@ theorem filterMapM_loop_eq [Monad m] [LawfulMonad m] funext b? split <;> rename_i b · apply ih - · rw [ih, ih [b]] + · rw [ih, ih (acc := [b])] simp -@[simp] theorem filterMapM_cons [Monad m] [LawfulMonad m] (f : α → m (Option β)) : +@[simp] theorem filterMapM_cons [Monad m] [LawfulMonad m] {f : α → m (Option β)} : (a :: l).filterMapM f = do match (← f a) with | none => filterMapM f l @@ -124,9 +123,9 @@ theorem filterMapM_loop_eq [Monad m] [LawfulMonad m] /-! ### flatMapM -/ -@[simp] theorem flatMapM_nil [Monad m] (f : α → m (List β)) : [].flatMapM f = pure [] := rfl +@[simp] theorem flatMapM_nil [Monad m] {f : α → m (List β)} : [].flatMapM f = pure [] := rfl -theorem flatMapM_loop_eq [Monad m] [LawfulMonad m] (f : α → m (List β)) (l : List α) (acc : List (List β)) : +theorem flatMapM_loop_eq [Monad m] [LawfulMonad m] {f : α → m (List β)} {l : List α} {acc : List (List β)} : flatMapM.loop f l acc = (acc.reverse.flatten ++ ·) <$> flatMapM.loop f l [] := by induction l generalizing acc with | nil => simp [flatMapM.loop] @@ -134,10 +133,10 @@ theorem flatMapM_loop_eq [Monad m] [LawfulMonad m] (f : α → m (List β)) (l : simp only [flatMapM.loop, append_nil, _root_.map_bind] congr funext bs - rw [ih, ih [bs]] + rw [ih, ih (acc := [bs])] simp -@[simp] theorem flatMapM_cons [Monad m] [LawfulMonad m] (f : α → m (List β)) : +@[simp] theorem flatMapM_cons [Monad m] [LawfulMonad m] {f : α → m (List β)} : (a :: l).flatMapM f = do let bs ← f a return (bs ++ (← l.flatMapM f)) := by @@ -149,15 +148,15 @@ theorem flatMapM_loop_eq [Monad m] [LawfulMonad m] (f : α → m (List β)) (l : /-! ### foldlM and foldrM -/ -theorem foldlM_map [Monad m] (f : β₁ → β₂) (g : α → β₂ → m α) (l : List β₁) (init : α) : +theorem foldlM_map [Monad m] {f : β₁ → β₂} {g : α → β₂ → m α} {l : List β₁} {init : α} : (l.map f).foldlM g init = l.foldlM (fun x y => g x (f y)) init := by induction l generalizing g init <;> simp [*] -theorem foldrM_map [Monad m] [LawfulMonad m] (f : β₁ → β₂) (g : β₂ → α → m α) (l : List β₁) - (init : α) : (l.map f).foldrM g init = l.foldrM (fun x y => g (f x) y) init := by +theorem foldrM_map [Monad m] [LawfulMonad m] {f : β₁ → β₂} {g : β₂ → α → m α} {l : List β₁} {init : α} : + (l.map f).foldrM g init = l.foldrM (fun x y => g (f x) y) init := by induction l generalizing g init <;> simp [*] -theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : γ → β → m γ) (l : List α) (init : γ) : +theorem foldlM_filterMap [Monad m] [LawfulMonad m] {f : α → Option β} {g : γ → β → m γ} {l : List α} {init : γ} : (l.filterMap f).foldlM g init = l.foldlM (fun x y => match f y with | some b => g x b | none => pure x) init := by induction l generalizing init with @@ -166,7 +165,7 @@ theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : simp only [filterMap_cons, foldlM_cons] cases f a <;> simp [ih] -theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : β → γ → m γ) (l : List α) (init : γ) : +theorem foldrM_filterMap [Monad m] [LawfulMonad m] {f : α → Option β} {g : β → γ → m γ} {l : List α} {init : γ} : (l.filterMap f).foldrM g init = l.foldrM (fun x y => match f x with | some b => g b y | none => pure y) init := by induction l generalizing init with @@ -175,7 +174,7 @@ theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : simp only [filterMap_cons, foldrM_cons] cases f a <;> simp [ih] -theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : β → α → m β) (l : List α) (init : β) : +theorem foldlM_filter [Monad m] [LawfulMonad m] {p : α → Bool} {g : β → α → m β} {l : List α} {init : β} : (l.filter p).foldlM g init = l.foldlM (fun x y => if p y then g x y else pure x) init := by induction l generalizing init with @@ -184,7 +183,7 @@ theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : β → α simp only [filter_cons, foldlM_cons] split <;> simp [ih] -theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β → m β) (l : List α) (init : β) : +theorem foldrM_filter [Monad m] [LawfulMonad m] {p : α → Bool} {g : α → β → m β} {l : List α} {init : β} : (l.filter p).foldrM g init = l.foldrM (fun x y => if p x then g x y else pure y) init := by induction l generalizing init with @@ -194,14 +193,14 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β split <;> simp [ih] @[simp] theorem foldlM_attachWith [Monad m] - (l : List α) {q : α → Prop} (H : ∀ a, a ∈ l → q a) {f : β → { x // q x} → m β} {b} : + {l : List α} {q : α → Prop} (H : ∀ a, a ∈ l → q a) {f : β → { x // q x} → m β} {b} : (l.attachWith q H).foldlM f b = l.attach.foldlM (fun b ⟨a, h⟩ => f b ⟨a, H _ h⟩) b := by induction l generalizing b with | nil => simp | cons a l ih => simp [ih, foldlM_map] @[simp] theorem foldrM_attachWith [Monad m] [LawfulMonad m] - (l : List α) {q : α → Prop} (H : ∀ a, a ∈ l → q a) {f : { x // q x} → β → m β} {b} : + {l : List α} {q : α → Prop} (H : ∀ a, a ∈ l → q a) {f : { x // q x} → β → m β} {b} : (l.attachWith q H).foldrM f b = l.attach.foldrM (fun a acc => f ⟨a.1, H _ a.2⟩ acc) b := by induction l generalizing b with | nil => simp @@ -215,13 +214,13 @@ theorem forM_nil' [Monad m] : ([] : List α).forM f = (pure .unit : m PUnit) := @[deprecated forM_cons (since := "2025-01-31")] theorem forM_cons' [Monad m] : (a::as).forM f = (f a >>= fun _ => as.forM f : m PUnit) := - List.forM_cons _ _ _ + List.forM_cons -@[simp] theorem forM_append [Monad m] [LawfulMonad m] (l₁ l₂ : List α) (f : α → m PUnit) : +@[simp] theorem forM_append [Monad m] [LawfulMonad m] {l₁ l₂ : List α} {f : α → m PUnit} : forM (l₁ ++ l₂) f = (do forM l₁ f; forM l₂ f) := by induction l₁ <;> simp [*] -@[simp] theorem forM_map [Monad m] [LawfulMonad m] (l : List α) (g : α → β) (f : β → m PUnit) : +@[simp] theorem forM_map [Monad m] [LawfulMonad m] {l : List α} {g : α → β} {f : β → m PUnit} : forM (l.map g) f = forM l (fun a => f (g a)) := by induction l <;> simp [*] @@ -246,7 +245,7 @@ theorem forIn'_loop_congr [Monad m] {as bs : List α} @[simp] theorem forIn'_cons [Monad m] {a : α} {as : List α} (f : (a' : α) → a' ∈ a :: as → β → m (ForInStep β)) (b : β) : - forIn' (a::as) b f = f a (mem_cons_self a as) b >>= + forIn' (a::as) b f = f a mem_cons_self b >>= fun | ForInStep.done b => pure b | ForInStep.yield b => forIn' as b fun a' m b => f a' (mem_cons_of_mem a m) b := by simp only [forIn', List.forIn', forIn'.loop] congr 1 @@ -294,7 +293,7 @@ We can express a for loop over a list as a fold, in which whenever we reach `.done b` we keep that value through the rest of the fold. -/ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m] - (l : List α) (f : (a : α) → a ∈ l → β → m (ForInStep β)) (init : β) : + {l : List α} (f : (a : α) → a ∈ l → β → m (ForInStep β)) (init : β) : forIn' l init f = ForInStep.value <$> l.attach.foldlM (fun b ⟨a, m⟩ => match b with | .yield b => f a m b @@ -324,29 +323,29 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m] /-- We can express a for loop over a list which always yields as a fold. -/ @[simp] theorem forIn'_yield_eq_foldlM [Monad m] [LawfulMonad m] - (l : List α) (f : (a : α) → a ∈ l → β → m γ) (g : (a : α) → a ∈ l → β → γ → β) (init : β) : + {l : List α} (f : (a : α) → a ∈ l → β → m γ) (g : (a : α) → a ∈ l → β → γ → β) (init : β) : forIn' l init (fun a m b => (fun c => .yield (g a m b c)) <$> f a m b) = l.attach.foldlM (fun b ⟨a, m⟩ => g a m b <$> f a m b) init := by simp only [forIn'_eq_foldlM] induction l.attach generalizing init <;> simp_all @[simp] theorem forIn'_pure_yield_eq_foldl [Monad m] [LawfulMonad m] - (l : List α) (f : (a : α) → a ∈ l → β → β) (init : β) : + {l : List α} (f : (a : α) → a ∈ l → β → β) (init : β) : forIn' l init (fun a m b => pure (.yield (f a m b))) = pure (f := m) (l.attach.foldl (fun b ⟨a, h⟩ => f a h b) init) := by simp only [forIn'_eq_foldlM] induction l.attach generalizing init <;> simp_all @[simp] theorem forIn'_yield_eq_foldl - (l : List α) (f : (a : α) → a ∈ l → β → β) (init : β) : + {l : List α} (f : (a : α) → a ∈ l → β → β) (init : β) : forIn' (m := Id) l init (fun a m b => .yield (f a m b)) = l.attach.foldl (fun b ⟨a, h⟩ => f a h b) init := by simp only [forIn'_eq_foldlM] induction l.attach generalizing init <;> simp_all @[simp] theorem forIn'_map [Monad m] [LawfulMonad m] - (l : List α) (g : α → β) (f : (b : β) → b ∈ l.map g → γ → m (ForInStep γ)) : - forIn' (l.map g) init f = forIn' l init fun a h y => f (g a) (mem_map_of_mem g h) y := by + {l : List α} (g : α → β) (f : (b : β) → b ∈ l.map g → γ → m (ForInStep γ)) : + forIn' (l.map g) init f = forIn' l init fun a h y => f (g a) (mem_map_of_mem h) y := by induction l generalizing init <;> simp_all /-- @@ -354,7 +353,7 @@ We can express a for loop over a list as a fold, in which whenever we reach `.done b` we keep that value through the rest of the fold. -/ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m] - (f : α → β → m (ForInStep β)) (init : β) (l : List α) : + {l : List α} (f : α → β → m (ForInStep β)) (init : β) : forIn l init f = ForInStep.value <$> l.foldlM (fun b a => match b with | .yield b => f a b @@ -377,34 +376,34 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m] /-- We can express a for loop over a list which always yields as a fold. -/ @[simp] theorem forIn_yield_eq_foldlM [Monad m] [LawfulMonad m] - (l : List α) (f : α → β → m γ) (g : α → β → γ → β) (init : β) : + {l : List α} (f : α → β → m γ) (g : α → β → γ → β) (init : β) : forIn l init (fun a b => (fun c => .yield (g a b c)) <$> f a b) = l.foldlM (fun b a => g a b <$> f a b) init := by simp only [forIn_eq_foldlM] induction l generalizing init <;> simp_all @[simp] theorem forIn_pure_yield_eq_foldl [Monad m] [LawfulMonad m] - (l : List α) (f : α → β → β) (init : β) : + {l : List α} (f : α → β → β) (init : β) : forIn l init (fun a b => pure (.yield (f a b))) = pure (f := m) (l.foldl (fun b a => f a b) init) := by simp only [forIn_eq_foldlM] induction l generalizing init <;> simp_all @[simp] theorem forIn_yield_eq_foldl - (l : List α) (f : α → β → β) (init : β) : + {l : List α} (f : α → β → β) (init : β) : forIn (m := Id) l init (fun a b => .yield (f a b)) = l.foldl (fun b a => f a b) init := by simp only [forIn_eq_foldlM] induction l generalizing init <;> simp_all @[simp] theorem forIn_map [Monad m] [LawfulMonad m] - (l : List α) (g : α → β) (f : β → γ → m (ForInStep γ)) : + {l : List α} {g : α → β} {f : β → γ → m (ForInStep γ)} : forIn (l.map g) init f = forIn l init fun a y => f (g a) y := by induction l generalizing init <;> simp_all /-! ### allM and anyM -/ -theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] (p : α → m Bool) (as : List α) : +theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] {p : α → m Bool} {as : List α} : allM p as = (! ·) <$> anyM ((! ·) <$> p ·) as := by induction as with | nil => simp @@ -414,7 +413,7 @@ theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] (p : α → m Bool) (as : funext b split <;> simp_all -@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] (p : α → Bool) (as : List α) : +@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] {p : α → Bool} {as : List α} : as.anyM (m := m) (pure <| p ·) = pure (as.any p) := by induction as with | nil => simp @@ -422,7 +421,7 @@ theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] (p : α → m Bool) (as : simp only [anyM, ih, pure_bind, all_cons] split <;> simp_all -@[simp] theorem allM_pure [Monad m] [LawfulMonad m] (p : α → Bool) (as : List α) : +@[simp] theorem allM_pure [Monad m] [LawfulMonad m] {p : α → Bool} {as : List α} : as.allM (m := m) (pure <| p ·) = pure (as.all p) := by simp [allM_eq_not_anyM_not, all_eq_not_any_not] @@ -441,11 +440,11 @@ and simplifies these to the function directly taking the value. | nil => simp | cons a l ih => simp [ih, hf] -@[wf_preprocess] theorem foldlM_wfParam [Monad m] (xs : List α) (f : β → α → m β) (init : β) : +@[wf_preprocess] theorem foldlM_wfParam [Monad m] {xs : List α} {f : β → α → m β} {init : β} : (wfParam xs).foldlM f init = xs.attach.unattach.foldlM f init := by simp [wfParam] -@[wf_preprocess] theorem foldlM_unattach [Monad m] (P : α → Prop) (xs : List (Subtype P)) (f : β → α → m β) (init : β): +@[wf_preprocess] theorem foldlM_unattach [Monad m] {P : α → Prop} {xs : List (Subtype P)} {f : β → α → m β} {init : β} : xs.unattach.foldlM f init = xs.foldlM (init := init) fun b ⟨x, h⟩ => binderNameHint b f <| binderNameHint x (f b) <| binderNameHint h () <| f b (wfParam x) := by @@ -468,11 +467,11 @@ and simplifies these to the function directly taking the value. funext b simp [hf] -@[wf_preprocess] theorem foldrM_wfParam [Monad m] [LawfulMonad m] (xs : List α) (f : α → β → m β) (init : β) : +@[wf_preprocess] theorem foldrM_wfParam [Monad m] [LawfulMonad m] {xs : List α} {f : α → β → m β} {init : β} : (wfParam xs).foldrM f init = xs.attach.unattach.foldrM f init := by simp [wfParam] -@[wf_preprocess] theorem foldrM_unattach [Monad m] [LawfulMonad m] (P : α → Prop) (xs : List (Subtype P)) (f : α → β → m β) (init : β) : +@[wf_preprocess] theorem foldrM_unattach [Monad m] [LawfulMonad m] {P : α → Prop} {xs : List (Subtype P)} {f : α → β → m β} {init : β} : xs.unattach.foldrM f init = xs.foldrM (init := init) fun ⟨x, h⟩ b => binderNameHint x f <| binderNameHint h () <| binderNameHint b (f x) <| f (wfParam x) b := by @@ -491,11 +490,11 @@ and simplifies these to the function directly taking the value. | nil => simp | cons a l ih => simp [ih, hf] -@[wf_preprocess] theorem mapM_wfParam [Monad m] [LawfulMonad m] (xs : List α) (f : α → m β) : +@[wf_preprocess] theorem mapM_wfParam [Monad m] [LawfulMonad m] {xs : List α} {f : α → m β} : (wfParam xs).mapM f = xs.attach.unattach.mapM f := by simp [wfParam] -@[wf_preprocess] theorem mapM_unattach [Monad m] [LawfulMonad m] (P : α → Prop) (xs : List (Subtype P)) (f : α → m β) : +@[wf_preprocess] theorem mapM_unattach [Monad m] [LawfulMonad m] {P : α → Prop} {xs : List (Subtype P)} {f : α → m β} : xs.unattach.mapM f = xs.mapM fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] @@ -509,12 +508,12 @@ and simplifies these to the function directly taking the value. | cons a l ih => simp [ih, hf, filterMapM_cons] @[wf_preprocess] theorem filterMapM_wfParam [Monad m] [LawfulMonad m] - (xs : List α) (f : α → m (Option β)) : + {xs : List α} {f : α → m (Option β)} : (wfParam xs).filterMapM f = xs.attach.unattach.filterMapM f := by simp [wfParam] @[wf_preprocess] theorem filterMapM_unattach [Monad m] [LawfulMonad m] - (P : α → Prop) (xs : List (Subtype P)) (f : α → m (Option β)) : + {P : α → Prop} {xs : List (Subtype P)} {f : α → m (Option β)} : xs.unattach.filterMapM f = xs.filterMapM fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] @@ -528,12 +527,12 @@ and simplifies these to the function directly taking the value. | cons a l ih => simp [ih, hf] @[wf_preprocess] theorem flatMapM_wfParam [Monad m] [LawfulMonad m] - (xs : List α) (f : α → m (List β)) : + {xs : List α} {f : α → m (List β)} : (wfParam xs).flatMapM f = xs.attach.unattach.flatMapM f := by simp [wfParam] @[wf_preprocess] theorem flatMapM_unattach [Monad m] [LawfulMonad m] - (P : α → Prop) (xs : List (Subtype P)) (f : α → m (List β)) : + {P : α → Prop} {xs : List (Subtype P)} {f : α → m (List β)} : xs.unattach.flatMapM f = xs.flatMapM fun ⟨x, h⟩ => binderNameHint x f <| binderNameHint h () <| f (wfParam x) := by simp [wfParam] diff --git a/src/Init/Data/List/Nat/BEq.lean b/src/Init/Data/List/Nat/BEq.lean index d592bb62bc..fd8f61f6a4 100644 --- a/src/Init/Data/List/Nat/BEq.lean +++ b/src/Init/Data/List/Nat/BEq.lean @@ -14,7 +14,7 @@ namespace List /-! ### isEqv -/ -theorem isEqv_eq_decide (as bs : List α) (r) : +theorem isEqv_eq_decide {as bs : List α} {r : α → α → Bool} : isEqv as bs r = if h : as.length = bs.length then decide (∀ (i : Nat) (h' : i < as.length), r (as[i]'(h ▸ h')) (bs[i]'(h ▸ h'))) else false := by induction as generalizing bs with @@ -29,7 +29,7 @@ theorem isEqv_eq_decide (as bs : List α) (r) : /-! ### beq -/ -theorem beq_eq_isEqv [BEq α] (as bs : List α) : as.beq bs = isEqv as bs (· == ·) := by +theorem beq_eq_isEqv [BEq α] {as bs : List α} : as.beq bs = isEqv as bs (· == ·) := by induction as generalizing bs with | nil => cases bs <;> simp @@ -42,7 +42,7 @@ theorem beq_eq_isEqv [BEq α] (as bs : List α) : as.beq bs = isEqv as bs (· == Bool.decide_eq_true] split <;> simp -theorem beq_eq_decide [BEq α] (as bs : List α) : +theorem beq_eq_decide [BEq α] {as bs : List α} : (as == bs) = if h : as.length = bs.length then decide (∀ (i : Nat) (h' : i < as.length), as[i] == bs[i]'(h ▸ h')) else false := by simp [BEq.beq, beq_eq_isEqv, isEqv_eq_decide] diff --git a/src/Init/Data/List/Nat/Basic.lean b/src/Init/Data/List/Nat/Basic.lean index b96cdaa4f7..336a17f7b4 100644 --- a/src/Init/Data/List/Nat/Basic.lean +++ b/src/Init/Data/List/Nat/Basic.lean @@ -24,7 +24,7 @@ namespace List /-! ### dropLast -/ -theorem tail_dropLast (l : List α) : tail (dropLast l) = dropLast (tail l) := by +theorem tail_dropLast {l : List α} : tail (dropLast l) = dropLast (tail l) := by ext1 simp only [getElem?_tail, getElem?_dropLast, length_tail] split <;> split @@ -33,7 +33,7 @@ theorem tail_dropLast (l : List α) : tail (dropLast l) = dropLast (tail l) := b · omega · rfl -@[simp] theorem dropLast_reverse (l : List α) : l.reverse.dropLast = l.tail.reverse := by +@[simp] theorem dropLast_reverse {l : List α} : l.reverse.dropLast = l.tail.reverse := by apply ext_getElem · simp · intro i h₁ h₂ @@ -47,13 +47,13 @@ theorem tail_dropLast (l : List α) : tail (dropLast l) = dropLast (tail l) := b @[simp] theorem length_filter_pos_iff {l : List α} {p : α → Bool} : 0 < (filter p l).length ↔ ∃ x ∈ l, p x := by - simpa [length_eq_countP_add_countP p l, countP_eq_length_filter] using + simpa [length_eq_countP_add_countP, countP_eq_length_filter] using countP_pos_iff (p := p) @[simp] theorem length_filter_lt_length_iff_exists {l} : (filter p l).length < l.length ↔ ∃ x ∈ l, ¬p x := by - simp [length_eq_countP_add_countP p l, countP_eq_length_filter] + simp [length_eq_countP_add_countP p (l := l), countP_eq_length_filter] /-! ### filterMap -/ @@ -95,14 +95,14 @@ theorem getElem_eq_getElem_reverse {l : List α} {i} (h : i < l.length) : to the larger of `n` and `l.length` -/ -- We don't mark this as a `@[simp]` lemma since we allow `simp` to unfold `leftpad`, -- so the left hand side simplifies directly to `n - l.length + l.length`. -theorem length_leftpad (n : Nat) (a : α) (l : List α) : +theorem length_leftpad {n : Nat} {a : α} {l : List α} : (leftpad n a l).length = max n l.length := by simp only [leftpad, length_append, length_replicate, Nat.sub_add_eq_max] @[deprecated length_leftpad (since := "2025-02-24")] abbrev leftpad_length := @length_leftpad -theorem length_rightpad (n : Nat) (a : α) (l : List α) : +theorem length_rightpad {n : Nat} {a : α} {l : List α} : (rightpad n a l).length = max n l.length := by simp [rightpad] omega diff --git a/src/Init/Data/List/Nat/Count.lean b/src/Init/Data/List/Nat/Count.lean index 86c457156a..15c82921e3 100644 --- a/src/Init/Data/List/Nat/Count.lean +++ b/src/Init/Data/List/Nat/Count.lean @@ -14,7 +14,7 @@ namespace List open Nat -theorem countP_set (p : α → Bool) (l : List α) (i : Nat) (a : α) (h : i < l.length) : +theorem countP_set {p : α → Bool} {l : List α} {i : Nat} {a : α} (h : i < l.length) : (l.set i a).countP p = l.countP p - (if p l[i] then 1 else 0) + (if p a then 1 else 0) := by induction l generalizing i with | nil => simp at h @@ -23,11 +23,11 @@ theorem countP_set (p : α → Bool) (l : List α) (i : Nat) (a : α) (h : i < l | zero => simp [countP_cons] | succ i => simp [add_one_lt_add_one_iff] at h - simp [countP_cons, ih _ h] - have : (if p l[i] = true then 1 else 0) ≤ l.countP p := boole_getElem_le_countP p l i h + simp [countP_cons, ih h] + have : (if p l[i] = true then 1 else 0) ≤ l.countP p := boole_getElem_le_countP (p := p) h omega -theorem count_set [BEq α] (a b : α) (l : List α) (i : Nat) (h : i < l.length) : +theorem count_set [BEq α] {a b : α} {l : List α} {i : Nat} (h : i < l.length) : (l.set i a).count b = l.count b - (if l[i] == b then 1 else 0) + (if a == b then 1 else 0) := by simp [count_eq_countP, countP_set, h] @@ -64,7 +64,7 @@ theorem IsInfix.le_countP (s : l₁ <:+: l₂) : countP p l₂ - (l₂.length - The number of elements satisfying a predicate in the tail of a list is at least one less than the number of elements satisfying the predicate in the list. -/ -theorem le_countP_tail (l) : countP p l - 1 ≤ countP p l.tail := by +theorem le_countP_tail {l} : countP p l - 1 ≤ countP p l.tail := by have := (tail_sublist l).le_countP p simp only [length_tail] at this omega @@ -83,7 +83,7 @@ theorem IsSuffix.le_count (s : l₁ <:+ l₂) (a : α) : count a l₂ - (l₂.le theorem IsInfix.le_count (s : l₁ <:+: l₂) (a : α) : count a l₂ - (l₂.length - l₁.length) ≤ count a l₁ := s.sublist.le_count _ -theorem le_count_tail (a : α) (l) : count a l - 1 ≤ count a l.tail := - le_countP_tail _ +theorem le_count_tail {a : α} {l : List α} : count a l - 1 ≤ count a l.tail := + le_countP_tail end List diff --git a/src/Init/Data/List/Nat/Erase.lean b/src/Init/Data/List/Nat/Erase.lean index 7508a3a5dd..6f1c561d7f 100644 --- a/src/Init/Data/List/Nat/Erase.lean +++ b/src/Init/Data/List/Nat/Erase.lean @@ -12,7 +12,7 @@ set_option linter.indexVariables true -- Enforce naming conventions for index va namespace List -theorem getElem?_eraseIdx (l : List α) (i : Nat) (j : Nat) : +theorem getElem?_eraseIdx {l : List α} {i : Nat} {j : Nat} : (l.eraseIdx i)[j]? = if j < i then l[j]? else l[j + 1]? := by rw [eraseIdx_eq_take_drop_succ, getElem?_append] split <;> rename_i h @@ -35,19 +35,19 @@ theorem getElem?_eraseIdx (l : List α) (i : Nat) (j : Nat) : omega · rw [getElem?_eq_none, getElem?_eq_none] <;> omega -theorem getElem?_eraseIdx_of_lt (l : List α) (i : Nat) (j : Nat) (h : j < i) : +theorem getElem?_eraseIdx_of_lt {l : List α} {i : Nat} {j : Nat} (h : j < i) : (l.eraseIdx i)[j]? = l[j]? := by rw [getElem?_eraseIdx] simp [h] -theorem getElem?_eraseIdx_of_ge (l : List α) (i : Nat) (j : Nat) (h : i ≤ j) : +theorem getElem?_eraseIdx_of_ge {l : List α} {i : Nat} {j : Nat} (h : i ≤ j) : (l.eraseIdx i)[j]? = l[j + 1]? := by rw [getElem?_eraseIdx] simp only [dite_eq_ite, ite_eq_right_iff] intro h' omega -theorem getElem_eraseIdx (l : List α) (i : Nat) (j : Nat) (h : j < (l.eraseIdx i).length) : +theorem getElem_eraseIdx {l : List α} {i : Nat} {j : Nat} (h : j < (l.eraseIdx i).length) : (l.eraseIdx i)[j] = if h' : j < i then l[j]'(by have := length_eraseIdx_le l i; omega) else @@ -56,19 +56,19 @@ theorem getElem_eraseIdx (l : List α) (i : Nat) (j : Nat) (h : j < (l.eraseIdx rw [← getElem?_eq_getElem, getElem?_eraseIdx] split <;> simp -theorem getElem_eraseIdx_of_lt (l : List α) (i : Nat) (j : Nat) (h : j < (l.eraseIdx i).length) (h' : j < i) : +theorem getElem_eraseIdx_of_lt {l : List α} {i : Nat} {j : Nat} (h : j < (l.eraseIdx i).length) (h' : j < i) : (l.eraseIdx i)[j] = l[j]'(by have := length_eraseIdx_le l i; omega) := by rw [getElem_eraseIdx] simp only [dite_eq_left_iff, Nat.not_lt] intro h' omega -theorem getElem_eraseIdx_of_ge (l : List α) (i : Nat) (j : Nat) (h : j < (l.eraseIdx i).length) (h' : i ≤ j) : +theorem getElem_eraseIdx_of_ge {l : List α} {i : Nat} {j : Nat} (h : j < (l.eraseIdx i).length) (h' : i ≤ j) : (l.eraseIdx i)[j] = l[j + 1]'(by rw [length_eraseIdx] at h; split at h <;> omega) := by rw [getElem_eraseIdx, dif_neg] omega -theorem eraseIdx_eq_dropLast (l : List α) (i : Nat) (h : i + 1 = l.length) : +theorem eraseIdx_eq_dropLast {l : List α} {i : Nat} (h : i + 1 = l.length) : l.eraseIdx i = l.dropLast := by simp [eraseIdx_eq_take_drop_succ, h] rw [take_eq_dropLast h] @@ -141,7 +141,7 @@ theorem eraseIdx_set_gt {l : List α} {i : Nat} {j : Nat} {a : α} (h : i < j) : · have t : ¬ n < i := by omega simp [t] -@[simp] theorem eraseIdx_length_sub_one (l : List α) : +@[simp] theorem eraseIdx_length_sub_one {l : List α} : (l.eraseIdx (l.length - 1)) = l.dropLast := by apply ext_getElem · simp [length_eraseIdx] diff --git a/src/Init/Data/List/Nat/InsertIdx.lean b/src/Init/Data/List/Nat/InsertIdx.lean index 5ae2fe8404..e5f0930b77 100644 --- a/src/Init/Data/List/Nat/InsertIdx.lean +++ b/src/Init/Data/List/Nat/InsertIdx.lean @@ -29,19 +29,19 @@ section InsertIdx variable {a : α} @[simp] -theorem insertIdx_zero (xs : List α) (x : α) : xs.insertIdx 0 x = x :: xs := +theorem insertIdx_zero {xs : List α} {x : α} : xs.insertIdx 0 x = x :: xs := rfl @[simp] -theorem insertIdx_succ_nil (n : Nat) (a : α) : ([] : List α).insertIdx (n + 1) a = [] := +theorem insertIdx_succ_nil {n : Nat} {a : α} : ([] : List α).insertIdx (n + 1) a = [] := rfl @[simp] -theorem insertIdx_succ_cons (xs : List α) (hd x : α) (i : Nat) : +theorem insertIdx_succ_cons {xs : List α} {hd x : α} {i : Nat} : (hd :: xs).insertIdx (i + 1) x = hd :: xs.insertIdx i x := rfl -theorem length_insertIdx : ∀ i (as : List α), (as.insertIdx i a).length = if i ≤ as.length then as.length + 1 else as.length +theorem length_insertIdx : ∀ {i} {as : List α}, (as.insertIdx i a).length = if i ≤ as.length then as.length + 1 else as.length | 0, _ => by simp | n + 1, [] => by simp | n + 1, a :: as => by @@ -55,37 +55,37 @@ theorem length_insertIdx_of_length_lt (h : length as < i) : (as.insertIdx i a).l simp [length_insertIdx, h] @[simp] -theorem eraseIdx_insertIdx (i : Nat) (l : List α) : (l.insertIdx i a).eraseIdx i = l := by +theorem eraseIdx_insertIdx {i : Nat} {l : List α} : (l.insertIdx i a).eraseIdx i = l := by rw [eraseIdx_eq_modifyTailIdx, insertIdx, modifyTailIdx_modifyTailIdx_self] exact modifyTailIdx_id _ _ theorem insertIdx_eraseIdx_of_ge : - ∀ i m as, + ∀ {i m as}, i < length as → i ≤ m → (as.eraseIdx i).insertIdx m a = (as.insertIdx (m + 1) a).eraseIdx i | 0, 0, [], has, _ => (Nat.lt_irrefl _ has).elim | 0, 0, _ :: as, _, _ => by simp [eraseIdx, insertIdx] | 0, _ + 1, _ :: _, _, _ => rfl | n + 1, m + 1, a :: as, has, hmn => congrArg (cons a) <| - insertIdx_eraseIdx_of_ge n m as (Nat.lt_of_succ_lt_succ has) (Nat.le_of_succ_le_succ hmn) + insertIdx_eraseIdx_of_ge (Nat.lt_of_succ_lt_succ has) (Nat.le_of_succ_le_succ hmn) theorem insertIdx_eraseIdx_of_le : - ∀ i j as, + ∀ {i j as}, i < length as → j ≤ i → (as.eraseIdx i).insertIdx j a = (as.insertIdx j a).eraseIdx (i + 1) | _, 0, _ :: _, _, _ => rfl - | n + 1, m + 1, a :: as, has, hmn => + | _ + 1, _ + 1, a :: _, has, hmn => congrArg (cons a) <| - insertIdx_eraseIdx_of_le n m as (Nat.lt_of_succ_lt_succ has) (Nat.le_of_succ_le_succ hmn) + insertIdx_eraseIdx_of_le (Nat.lt_of_succ_lt_succ has) (Nat.le_of_succ_le_succ hmn) theorem insertIdx_comm (a b : α) : - ∀ (i j : Nat) (l : List α) (_ : i ≤ j) (_ : j ≤ length l), + ∀ {i j : Nat} {l : List α} (_ : i ≤ j) (_ : j ≤ length l), (l.insertIdx i a).insertIdx (j + 1) b = (l.insertIdx j b).insertIdx i a | 0, j, l => by simp [insertIdx] | _ + 1, 0, _ => fun h => (Nat.not_lt_zero _ h).elim | i + 1, j + 1, [] => by simp | i + 1, j + 1, c :: l => fun h₀ h₁ => by simp only [insertIdx_succ_cons, cons.injEq, true_and] - exact insertIdx_comm a b i j l (Nat.le_of_succ_le_succ h₀) (Nat.le_of_succ_le_succ h₁) + exact insertIdx_comm a b (Nat.le_of_succ_le_succ h₀) (Nat.le_of_succ_le_succ h₁) theorem mem_insertIdx {a b : α} : ∀ {i : Nat} {l : List α} (_ : i ≤ l.length), a ∈ l.insertIdx i b ↔ a = b ∨ a ∈ l @@ -95,7 +95,7 @@ theorem mem_insertIdx {a b : α} : rw [List.insertIdx_succ_cons, mem_cons, mem_insertIdx (Nat.le_of_succ_le_succ h), ← or_assoc, @or_comm (a = a'), or_assoc, mem_cons] -theorem insertIdx_of_length_lt (l : List α) (x : α) (i : Nat) (h : l.length < i) : +theorem insertIdx_of_length_lt {l : List α} {x : α} {i : Nat} (h : l.length < i) : l.insertIdx i x = l := by induction l generalizing i with | nil => @@ -106,20 +106,20 @@ theorem insertIdx_of_length_lt (l : List α) (x : α) (i : Nat) (h : l.length < cases i · simp at h · simp only [Nat.succ_lt_succ_iff, length] at h - simpa using ih _ h + simpa using ih h @[simp] -theorem insertIdx_length_self (l : List α) (x : α) : l.insertIdx l.length x = l ++ [x] := by +theorem insertIdx_length_self {l : List α} {x : α} : l.insertIdx l.length x = l ++ [x] := by induction l with | nil => simp | cons x l ih => simpa using ih -theorem length_le_length_insertIdx (l : List α) (x : α) (i : Nat) : +theorem length_le_length_insertIdx {l : List α} {x : α} {i : Nat} : l.length ≤ (l.insertIdx i x).length := by simp only [length_insertIdx] split <;> simp -theorem length_insertIdx_le_succ (l : List α) (x : α) (i : Nat) : +theorem length_insertIdx_le_succ {l : List α} {x : α} {i : Nat} : (l.insertIdx i x).length ≤ l.length + 1 := by simp only [length_insertIdx] split <;> simp diff --git a/src/Init/Data/List/Nat/Perm.lean b/src/Init/Data/List/Nat/Perm.lean index 114b6d2243..5bc7a88440 100644 --- a/src/Init/Data/List/Nat/Perm.lean +++ b/src/Init/Data/List/Nat/Perm.lean @@ -47,7 +47,7 @@ theorem set_set_perm {as : List α} {i j : Nat} (h₁ : i < as.length) (h₂ : j subst t exact set_set_perm' _ _ (by omega) else - rw [set_comm _ _ _ (by omega)] + rw [set_comm _ _ (by omega)] let i' := i - j have t : i = j + i' := by omega generalize i' = i' at t diff --git a/src/Init/Data/List/Nat/Range.lean b/src/Init/Data/List/Nat/Range.lean index 2111287ffc..2c5cb1e383 100644 --- a/src/Init/Data/List/Nat/Range.lean +++ b/src/Init/Data/List/Nat/Range.lean @@ -30,7 +30,7 @@ open Nat fun ⟨i, h, e⟩ => e ▸ ⟨Nat.le_add_right .., Nat.add_lt_add_left h _⟩, fun ⟨h₁, h₂⟩ => ⟨m - s, Nat.sub_lt_left_of_lt_add h₁ h₂, (Nat.add_sub_cancel' h₁).symm⟩⟩ -theorem getLast?_range' (n : Nat) : (range' s n).getLast? = if n = 0 then none else some (s + n - 1) := by +theorem getLast?_range' {n : Nat} : (range' s n).getLast? = if n = 0 then none else some (s + n - 1) := by induction n generalizing s with | zero => simp | succ n ih => @@ -42,12 +42,12 @@ theorem getLast?_range' (n : Nat) : (range' s n).getLast? = if n = 0 then none e simp omega -@[simp] theorem getLast_range' (n : Nat) (h) : (range' s n).getLast h = s + n - 1 := by +@[simp] theorem getLast_range' {n : Nat} (h) : (range' s n).getLast h = s + n - 1 := by cases n with | zero => simp at h | succ n => simp [getLast?_range', getLast_eq_iff_getLast?_eq_some] -theorem pairwise_lt_range' s n (step := 1) (pos : 0 < step := by simp) : +theorem pairwise_lt_range' {s n} (step := 1) (pos : 0 < step := by simp) : Pairwise (· < ·) (range' s n step) := match s, n, step, pos with | _, 0, _, _ => Pairwise.nil @@ -57,9 +57,9 @@ theorem pairwise_lt_range' s n (step := 1) (pos : 0 < step := by simp) : · intros n m rw [mem_range'] at m omega - · exact pairwise_lt_range' (s + step) n step pos + · exact pairwise_lt_range' (s := s + step) step pos -theorem pairwise_le_range' s n (step := 1) : +theorem pairwise_le_range' {s n} (step := 1) : Pairwise (· ≤ ·) (range' s n step) := match s, n, step with | _, 0, _ => Pairwise.nil @@ -69,12 +69,12 @@ theorem pairwise_le_range' s n (step := 1) : · intros n m rw [mem_range'] at m omega - · exact pairwise_le_range' (s + step) n step + · exact pairwise_le_range' (s := s + step) step -theorem nodup_range' (s n : Nat) (step := 1) (h : 0 < step := by simp) : Nodup (range' s n step) := - (pairwise_lt_range' s n step h).imp Nat.ne_of_lt +theorem nodup_range' {s n : Nat} (step := 1) (h : 0 < step := by simp) : Nodup (range' s n step) := + (pairwise_lt_range' step h).imp Nat.ne_of_lt -theorem map_sub_range' (a s n : Nat) (h : a ≤ s) : +theorem map_sub_range' {a s n : Nat} (h : a ≤ s) : map (· - a) (range' s n step) = range' (s - a) n step := by conv => lhs; rw [← Nat.add_sub_cancel' h] rw [← map_add_range', map_map, (?_ : _∘_ = _), map_id] @@ -159,7 +159,7 @@ theorem erase_range' : /-! ### range -/ -theorem reverse_range' : ∀ s n : Nat, reverse (range' s n) = map (s + n - 1 - ·) (range n) +theorem reverse_range' : ∀ {s n : Nat}, reverse (range' s n) = map (s + n - 1 - ·) (range n) | _, 0 => rfl | s, n + 1 => by rw [range'_1_concat, reverse_append, range_succ_eq_map, @@ -172,20 +172,20 @@ theorem mem_range {m n : Nat} : m ∈ range n ↔ m < n := by theorem not_mem_range_self {n : Nat} : n ∉ range n := by simp -theorem self_mem_range_succ (n : Nat) : n ∈ range (n + 1) := by simp +theorem self_mem_range_succ {n : Nat} : n ∈ range (n + 1) := by simp -theorem pairwise_lt_range (n : Nat) : Pairwise (· < ·) (range n) := by +theorem pairwise_lt_range {n : Nat} : Pairwise (· < ·) (range n) := by simp +decide only [range_eq_range', pairwise_lt_range'] -theorem pairwise_le_range (n : Nat) : Pairwise (· ≤ ·) (range n) := - Pairwise.imp Nat.le_of_lt (pairwise_lt_range _) +theorem pairwise_le_range {n : Nat} : Pairwise (· ≤ ·) (range n) := + Pairwise.imp Nat.le_of_lt pairwise_lt_range -@[simp] theorem take_range (i n : Nat) : take i (range n) = range (min i n) := by +@[simp] theorem take_range {i n : Nat} : take i (range n) = range (min i n) := by apply List.ext_getElem · simp · simp +contextual [getElem_take, Nat.lt_min] -theorem nodup_range (n : Nat) : Nodup (range n) := by +theorem nodup_range {n : Nat} : Nodup (range n) := by simp +decide only [range_eq_range', nodup_range'] @[simp] theorem find?_range_eq_some {n : Nat} {i : Nat} {p : Nat → Bool} : @@ -263,7 +263,7 @@ theorem iota_eq_append_iff : iota n = xs ++ ys ↔ ∃ k, k ≤ n ∧ xs = (rang @[deprecated "Use `(List.range' 1 n).reverse` instead of `iota n`." (since := "2025-01-20")] theorem pairwise_gt_iota (n : Nat) : Pairwise (· > ·) (iota n) := by - simpa only [iota_eq_reverse_range', pairwise_reverse] using pairwise_lt_range' 1 n + simpa only [iota_eq_reverse_range', pairwise_reverse] using pairwise_lt_range' @[deprecated "Use `(List.range' 1 n).reverse` instead of `iota n`." (since := "2025-01-20")] theorem nodup_iota (n : Nat) : Nodup (iota n) := @@ -348,14 +348,14 @@ end /-! ### zipIdx -/ @[simp] -theorem zipIdx_singleton (x : α) (k : Nat) : zipIdx [x] k = [(x, k)] := +theorem zipIdx_singleton {x : α} {k : Nat} : zipIdx [x] k = [(x, k)] := rfl -@[simp] theorem head?_zipIdx (l : List α) (k : Nat) : +@[simp] theorem head?_zipIdx {l : List α} {k : Nat} : (zipIdx l k).head? = l.head?.map fun a => (a, k) := by simp [head?_eq_getElem?] -@[simp] theorem getLast?_zipIdx (l : List α) (k : Nat) : +@[simp] theorem getLast?_zipIdx {l : List α} {k : Nat} : (zipIdx l k).getLast? = l.getLast?.map fun a => (a, k + l.length - 1) := by simp [getLast?_eq_getElem?] cases l <;> simp; omega @@ -401,12 +401,12 @@ theorem snd_lt_add_of_mem_zipIdx {x : α × Nat} {l : List α} {k : Nat} (h : x theorem snd_lt_of_mem_zipIdx {x : α × Nat} {l : List α} {k : Nat} (h : x ∈ l.zipIdx k) : x.2 < l.length + k := by simpa [Nat.add_comm] using snd_lt_add_of_mem_zipIdx h -theorem map_zipIdx (f : α → β) (l : List α) (k : Nat) : +theorem map_zipIdx {f : α → β} {l : List α} {k : Nat} : map (Prod.map f id) (zipIdx l k) = zipIdx (l.map f) k := by induction l generalizing k <;> simp_all theorem fst_mem_of_mem_zipIdx {x : α × Nat} {l : List α} {k : Nat} (h : x ∈ zipIdx l k) : x.1 ∈ l := - zipIdx_map_fst k l ▸ mem_map_of_mem _ h + zipIdx_map_fst k l ▸ mem_map_of_mem h theorem fst_eq_of_mem_zipIdx {x : α × Nat} {l : List α} {k : Nat} (h : x ∈ zipIdx l k) : x.1 = l[x.2 - k]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) := by @@ -432,7 +432,7 @@ theorem mem_zipIdx' {x : α} {i : Nat} {xs : List α} (h : (x, i) ∈ xs.zipIdx) i < xs.length ∧ x = xs[i]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) := ⟨by simpa using snd_lt_add_of_mem_zipIdx h, fst_eq_of_mem_zipIdx h⟩ -theorem zipIdx_map (l : List α) (k : Nat) (f : α → β) : +theorem zipIdx_map {l : List α} {k : Nat} {f : α → β} : zipIdx (l.map f) k = (zipIdx l k).map (Prod.map f id) := by induction l with | nil => rfl @@ -440,7 +440,7 @@ theorem zipIdx_map (l : List α) (k : Nat) (f : α → β) : rw [map_cons, zipIdx_cons', zipIdx_cons', map_cons, map_map, IH, map_map] rfl -theorem zipIdx_append (xs ys : List α) (k : Nat) : +theorem zipIdx_append {xs ys : List α} {k : Nat} : zipIdx (xs ++ ys) k = zipIdx xs k ++ zipIdx ys (k + xs.length) := by induction xs generalizing ys k with | nil => simp @@ -532,7 +532,7 @@ theorem map_enumFrom (f : α → β) (n : Nat) (l : List α) : @[deprecated fst_mem_of_mem_zipIdx (since := "2025-01-21")] theorem snd_mem_of_mem_enumFrom {x : Nat × α} {n : Nat} {l : List α} (h : x ∈ enumFrom n l) : x.2 ∈ l := - enumFrom_map_snd n l ▸ mem_map_of_mem _ h + enumFrom_map_snd n l ▸ mem_map_of_mem h @[deprecated fst_eq_of_mem_zipIdx (since := "2025-01-21")] theorem snd_eq_of_mem_enumFrom {x : Nat × α} {n : Nat} {l : List α} (h : x ∈ enumFrom n l) : diff --git a/src/Init/Data/List/Nat/TakeDrop.lean b/src/Init/Data/List/Nat/TakeDrop.lean index f04e01e3be..fb12d4c661 100644 --- a/src/Init/Data/List/Nat/TakeDrop.lean +++ b/src/Init/Data/List/Nat/TakeDrop.lean @@ -25,7 +25,7 @@ open Nat /-! ### take -/ -@[simp] theorem length_take : ∀ (i : Nat) (l : List α), length (take i l) = min i (length l) +@[simp] theorem length_take : ∀ {i : Nat} {l : List α}, (take i l).length = min i l.length | 0, l => by simp [Nat.zero_min] | succ n, [] => by simp [Nat.min_zero] | succ n, _ :: l => by simp [Nat.succ_min_succ, length_take] @@ -39,16 +39,16 @@ theorem length_take_of_le (h : i ≤ length l) : length (take i l) = i := by sim /-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of length `> i`. Version designed to rewrite from the big list to the small list. -/ -theorem getElem_take' (xs : List α) {i j : Nat} (hi : i < xs.length) (hj : i < j) : +theorem getElem_take' {xs : List α} {i j : Nat} (hi : i < xs.length) (hj : i < j) : xs[i] = (xs.take j)[i]'(length_take .. ▸ Nat.lt_min.mpr ⟨hj, hi⟩) := getElem_of_eq (take_append_drop j xs).symm _ ▸ getElem_append_left .. /-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of length `> i`. Version designed to rewrite from the small list to the big list. -/ -@[simp] theorem getElem_take (xs : List α) {j i : Nat} {h : i < (xs.take j).length} : +@[simp] theorem getElem_take {xs : List α} {j i : Nat} {h : i < (xs.take j).length} : (xs.take j)[i] = xs[i]'(Nat.lt_of_lt_of_le h (length_take_le' _ _)) := by - rw [length_take, Nat.lt_min] at h; rw [getElem_take' xs _ h.1] + rw [length_take, Nat.lt_min] at h; rw [getElem_take' (xs := xs) _ h.1] theorem getElem?_take_eq_none {l : List α} {i j : Nat} (h : i ≤ j) : (l.take i)[j]? = none := @@ -97,14 +97,14 @@ theorem getLast_take {l : List α} (h : l.take i ≠ []) : · rw [getElem?_eq_none (by omega), getLast_eq_getElem] simp -theorem take_take : ∀ (i j) (l : List α), take i (take j l) = take (min i j) l +theorem take_take : ∀ {i j} {l : List α}, take i (take j l) = take (min i j) l | n, 0, l => by rw [Nat.min_zero, take_zero, take_nil] | 0, m, l => by rw [Nat.zero_min, take_zero, take_zero] | succ n, succ m, nil => by simp only [take_nil] | succ n, succ m, a :: l => by - simp only [take, succ_min_succ, take_take n m l] + simp only [take, succ_min_succ, take_take] -theorem take_set_of_le (a : α) {i j : Nat} (l : List α) (h : j ≤ i) : +theorem take_set_of_le {a : α} {i j : Nat} {l : List α} (h : j ≤ i) : (l.set i a).take j = l.take j := List.ext_getElem? fun i => by rw [getElem?_take, getElem?_take] @@ -115,12 +115,12 @@ theorem take_set_of_le (a : α) {i j : Nat} (l : List α) (h : j ≤ i) : @[deprecated take_set_of_le (since := "2025-02-04")] abbrev take_set_of_lt := @take_set_of_le -@[simp] theorem take_replicate (a : α) : ∀ i n : Nat, take i (replicate n a) = replicate (min i n) a +@[simp] theorem take_replicate {a : α} : ∀ {i n : Nat}, take i (replicate n a) = replicate (min i n) a | n, 0 => by simp [Nat.min_zero] | 0, m => by simp [Nat.zero_min] | succ n, succ m => by simp [replicate_succ, succ_min_succ, take_replicate] -@[simp] theorem drop_replicate (a : α) : ∀ i n : Nat, drop i (replicate n a) = replicate (n - i) a +@[simp] theorem drop_replicate {a : α} : ∀ {i n : Nat}, drop i (replicate n a) = replicate (n - i) a | n, 0 => by simp | 0, m => by simp | succ n, succ m => by simp [replicate_succ, succ_sub_succ, drop_replicate] @@ -160,7 +160,7 @@ theorem take_eq_take_iff : @[deprecated take_eq_take_iff (since := "2025-02-16")] abbrev take_eq_take := @take_eq_take_iff -theorem take_add (l : List α) (i j : Nat) : l.take (i + j) = l.take i ++ (l.drop i).take j := by +theorem take_add {l : List α} {i j : Nat} : l.take (i + j) = l.take i ++ (l.drop i).take j := by suffices take (i + j) (take i l ++ drop i l) = take i l ++ take j (drop i l) by rw [take_append_drop] at this assumption @@ -198,22 +198,22 @@ theorem take_eq_dropLast {l : List α} {i : Nat} (h : i + 1 = l.length) : rw [ih] simpa using h -theorem take_prefix_take_left (l : List α) {i j : Nat} (h : i ≤ j) : take i l <+: take j l := by +theorem take_prefix_take_left {l : List α} {i j : Nat} (h : i ≤ j) : take i l <+: take j l := by rw [isPrefix_iff] intro i w rw [getElem?_take_of_lt, getElem_take, getElem?_eq_getElem] simp only [length_take] at w exact Nat.lt_of_lt_of_le (Nat.lt_of_lt_of_le w (Nat.min_le_left _ _)) h -theorem take_sublist_take_left (l : List α) {i j : Nat} (h : i ≤ j) : take i l <+ take j l := - (take_prefix_take_left l h).sublist +theorem take_sublist_take_left {l : List α} {i j : Nat} (h : i ≤ j) : take i l <+ take j l := + (take_prefix_take_left h).sublist theorem take_subset_take_left (l : List α) {i j : Nat} (h : i ≤ j) : take i l ⊆ take j l := - (take_sublist_take_left l h).subset + (take_sublist_take_left h).subset /-! ### drop -/ -theorem lt_length_drop (xs : List α) {i j : Nat} (h : i + j < xs.length) : j < (xs.drop i).length := by +theorem lt_length_drop {xs : List α} {i j : Nat} (h : i + j < xs.length) : j < (xs.drop i).length := by have A : i < xs.length := Nat.lt_of_le_of_lt (Nat.le.intro rfl) h rw [(take_append_drop i xs).symm] at h simpa only [Nat.le_of_lt A, Nat.min_eq_left, Nat.add_lt_add_iff_left, length_take, @@ -221,8 +221,8 @@ theorem lt_length_drop (xs : List α) {i j : Nat} (h : i + j < xs.length) : j < /-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/ -theorem getElem_drop' (xs : List α) {i j : Nat} (h : i + j < xs.length) : - xs[i + j] = (xs.drop i)[j]'(lt_length_drop xs h) := by +theorem getElem_drop' {xs : List α} {i j : Nat} (h : i + j < xs.length) : + xs[i + j] = (xs.drop i)[j]'(lt_length_drop h) := by have : i ≤ xs.length := Nat.le_trans (Nat.le_add_right _ _) (Nat.le_of_lt h) rw [getElem_of_eq (take_append_drop i xs).symm h, getElem_append_right] · simp [Nat.min_eq_left this, Nat.add_sub_cancel_left] @@ -230,14 +230,14 @@ theorem getElem_drop' (xs : List α) {i j : Nat} (h : i + j < xs.length) : /-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by dropping the first `i` elements. Version designed to rewrite from the small list to the big list. -/ -@[simp] theorem getElem_drop (xs : List α) {i : Nat} {j : Nat} {h : j < (xs.drop i).length} : +@[simp] theorem getElem_drop {xs : List α} {i : Nat} {j : Nat} {h : j < (xs.drop i).length} : (xs.drop i)[j] = xs[i + j]'(by rw [Nat.add_comm] - exact Nat.add_lt_of_lt_sub (length_drop i xs ▸ h)) := by + exact Nat.add_lt_of_lt_sub (length_drop ▸ h)) := by rw [getElem_drop'] @[simp] -theorem getElem?_drop (xs : List α) (i j : Nat) : (xs.drop i)[j]? = xs[i + j]? := by +theorem getElem?_drop {xs : List α} {i j : Nat} : (xs.drop i)[j]? = xs[i + j]? := by ext simp only [getElem?_eq_some_iff, getElem_drop, Option.mem_def] constructor <;> intro ⟨h, ha⟩ @@ -267,7 +267,7 @@ theorem mem_drop_iff_getElem {l : List α} {a : α} : · rintro ⟨i, hm, rfl⟩ refine ⟨i, by simp; omega, by rw [getElem_drop]⟩ -@[simp] theorem head?_drop (l : List α) (i : Nat) : +@[simp] theorem head?_drop {l : List α} {i : Nat} : (l.drop i).head? = l[i]? := by rw [head?_eq_getElem?, getElem?_drop, Nat.add_zero] @@ -327,7 +327,7 @@ theorem drop_append {l₁ l₂ : List α} (i : Nat) : drop (l₁.length + i) (l rw [drop_append_eq_append_drop, drop_eq_nil_of_le] <;> simp [Nat.add_sub_cancel_left, Nat.le_add_right] -theorem set_eq_take_append_cons_drop (l : List α) (i : Nat) (a : α) : +theorem set_eq_take_append_cons_drop {l : List α} {i : Nat} {a : α} : l.set i a = if i < l.length then l.take i ++ a :: l.drop (i + 1) else l := by split <;> rename_i h · ext1 j @@ -354,16 +354,15 @@ theorem set_eq_take_append_cons_drop (l : List α) (i : Nat) (a : α) : · rw [set_eq_of_length_le] omega -theorem drop_set_of_lt (a : α) {i j : Nat} (l : List α) - (hnm : i < j) : drop j (l.set i a) = l.drop j := +theorem drop_set_of_lt {a : α} {i j : Nat} {l : List α} (hnm : i < j) : drop j (l.set i a) = l.drop j := ext_getElem? fun k => by simpa only [getElem?_drop] using getElem?_set_ne (by omega) -theorem drop_take : ∀ (i j : Nat) (l : List α), drop i (take j l) = take (j - i) (drop i l) +theorem drop_take : ∀ {i j : Nat} {l : List α}, drop i (take j l) = take (j - i) (drop i l) | 0, _, _ => by simp | _, 0, _ => by simp | _, _, [] => by simp | i+1, j+1, h :: t => by - simp [take_succ_cons, drop_succ_cons, drop_take i j t] + simp [take_succ_cons, drop_succ_cons, drop_take] congr 1 omega @@ -515,7 +514,7 @@ theorem dropWhile_eq_drop_findIdx_not {xs : List α} {p : α → Bool} : /-! ### rotateLeft -/ -@[simp] theorem rotateLeft_replicate (n) (a : α) : rotateLeft (replicate m a) n = replicate m a := by +@[simp] theorem rotateLeft_replicate {n} {a : α} : rotateLeft (replicate m a) n = replicate m a := by cases n with | zero => simp | succ n => @@ -528,7 +527,7 @@ theorem dropWhile_eq_drop_findIdx_not {xs : List α} {p : α → Bool} : /-! ### rotateRight -/ -@[simp] theorem rotateRight_replicate (n) (a : α) : rotateRight (replicate m a) n = replicate m a := by +@[simp] theorem rotateRight_replicate {n} {a : α} : rotateRight (replicate m a) n = replicate m a := by cases n with | zero => simp | succ n => @@ -541,7 +540,7 @@ theorem dropWhile_eq_drop_findIdx_not {xs : List α} {p : α → Bool} : /-! ### zipWith -/ -@[simp] theorem length_zipWith (f : α → β → γ) (l₁ l₂) : +@[simp] theorem length_zipWith {f : α → β → γ} {l₁ : List α} {l₂ : List β} : length (zipWith f l₁ l₂) = min (length l₁) (length l₂) := by induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all [succ_min_succ, Nat.zero_min, Nat.min_zero] @@ -563,11 +562,11 @@ theorem getElem_zipWith {f : α → β → γ} {l : List α} {l' : List β} ⟨l[i]'(lt_length_left_of_zipWith h), l'[i]'(lt_length_right_of_zipWith h), by rw [getElem?_eq_getElem], by rw [getElem?_eq_getElem]; exact ⟨rfl, rfl⟩⟩ -theorem zipWith_eq_zipWith_take_min : ∀ (l₁ : List α) (l₂ : List β), +theorem zipWith_eq_zipWith_take_min : ∀ {l₁ : List α} {l₂ : List β}, zipWith f l₁ l₂ = zipWith f (l₁.take (min l₁.length l₂.length)) (l₂.take (min l₁.length l₂.length)) | [], _ => by simp | _, [] => by simp - | a :: l₁, b :: l₂ => by simp [succ_min_succ, zipWith_eq_zipWith_take_min l₁ l₂] + | a :: l₁, b :: l₂ => by simp [succ_min_succ, zipWith_eq_zipWith_take_min (l₁ := l₁) (l₂ := l₂)] theorem reverse_zipWith (h : l.length = l'.length) : (zipWith f l l').reverse = zipWith f l.reverse l'.reverse := by @@ -579,7 +578,7 @@ theorem reverse_zipWith (h : l.length = l'.length) : | cons hd' tl' => simp only [Nat.add_right_cancel_iff, length] at h have : tl.reverse.length = tl'.reverse.length := by simp [h] - simp [hl h, zipWith_append _ _ _ _ _ this] + simp [hl h, zipWith_append this] @[simp] theorem zipWith_replicate {a : α} {b : β} {m n : Nat} : zipWith f (replicate m a) (replicate n b) = replicate (min m n) (f a b) := by @@ -588,7 +587,7 @@ theorem reverse_zipWith (h : l.length = l'.length) : /-! ### zip -/ -@[simp] theorem length_zip (l₁ : List α) (l₂ : List β) : +@[simp] theorem length_zip {l₁ : List α} {l₂ : List β} : length (zip l₁ l₂) = min (length l₁) (length l₂) := by simp [zip] @@ -606,11 +605,11 @@ theorem getElem_zip {l : List α} {l' : List β} {i : Nat} {h : i < (zip l l').l (l[i]'(lt_length_left_of_zip h), l'[i]'(lt_length_right_of_zip h)) := getElem_zipWith (h := h) -theorem zip_eq_zip_take_min : ∀ (l₁ : List α) (l₂ : List β), +theorem zip_eq_zip_take_min : ∀ {l₁ : List α} {l₂ : List β}, zip l₁ l₂ = zip (l₁.take (min l₁.length l₂.length)) (l₂.take (min l₁.length l₂.length)) | [], _ => by simp | _, [] => by simp - | a :: l₁, b :: l₂ => by simp [succ_min_succ, zip_eq_zip_take_min l₁ l₂] + | a :: l₁, b :: l₂ => by simp [succ_min_succ, zip_eq_zip_take_min (l₁ := l₁) (l₂ := l₂)] @[simp] theorem zip_replicate {a : α} {b : β} {m n : Nat} : zip (replicate m a) (replicate n b) = replicate (min m n) (a, b) := by diff --git a/src/Init/Data/List/OfFn.lean b/src/Init/Data/List/OfFn.lean index ffda1b18ec..580fb21c66 100644 --- a/src/Init/Data/List/OfFn.lean +++ b/src/Init/Data/List/OfFn.lean @@ -26,14 +26,14 @@ Examples: def ofFn {n} (f : Fin n → α) : List α := Fin.foldr n (f · :: ·) [] @[simp] -theorem length_ofFn (f : Fin n → α) : (ofFn f).length = n := by +theorem length_ofFn {f : Fin n → α} : (ofFn f).length = n := by simp only [ofFn] induction n with | zero => simp | succ n ih => simp [Fin.foldr_succ, ih] @[simp] -protected theorem getElem_ofFn (f : Fin n → α) (i : Nat) (h : i < (ofFn f).length) : +protected theorem getElem_ofFn {f : Fin n → α} (h : i < (ofFn f).length) : (ofFn f)[i] = f ⟨i, by simp_all⟩ := by simp only [ofFn] induction n generalizing i with @@ -47,7 +47,7 @@ protected theorem getElem_ofFn (f : Fin n → α) (i : Nat) (h : i < (ofFn f).le simp_all @[simp] -protected theorem getElem?_ofFn (f : Fin n → α) (i) : (ofFn f)[i]? = if h : i < n then some (f ⟨i, h⟩) else none := +protected theorem getElem?_ofFn {f : Fin n → α} : (ofFn f)[i]? = if h : i < n then some (f ⟨i, h⟩) else none := if h : i < (ofFn f).length then by rw [getElem?_eq_getElem h, List.getElem_ofFn] @@ -58,11 +58,11 @@ protected theorem getElem?_ofFn (f : Fin n → α) (i) : (ofFn f)[i]? = if h : i /-- `ofFn` on an empty domain is the empty list. -/ @[simp] -theorem ofFn_zero (f : Fin 0 → α) : ofFn f = [] := +theorem ofFn_zero {f : Fin 0 → α} : ofFn f = [] := ext_get (by simp) (fun i hi₁ hi₂ => by contradiction) @[simp] -theorem ofFn_succ {n} (f : Fin (n + 1) → α) : ofFn f = f 0 :: ofFn fun i => f i.succ := +theorem ofFn_succ {n} {f : Fin (n + 1) → α} : ofFn f = f 0 :: ofFn fun i => f i.succ := ext_get (by simp) (fun i hi₁ hi₂ => by cases i · simp @@ -73,7 +73,7 @@ theorem ofFn_eq_nil_iff {f : Fin n → α} : ofFn f = [] ↔ n = 0 := by cases n <;> simp only [ofFn_zero, ofFn_succ, eq_self_iff_true, Nat.succ_ne_zero, reduceCtorEq] @[simp 500] -theorem mem_ofFn {n} (f : Fin n → α) (a : α) : a ∈ ofFn f ↔ ∃ i, f i = a := by +theorem mem_ofFn {n} {f : Fin n → α} {a : α} : a ∈ ofFn f ↔ ∃ i, f i = a := by constructor · intro w obtain ⟨i, h, rfl⟩ := getElem_of_mem w @@ -81,12 +81,12 @@ theorem mem_ofFn {n} (f : Fin n → α) (a : α) : a ∈ ofFn f ↔ ∃ i, f i = · rintro ⟨i, rfl⟩ apply mem_of_getElem (i := i) <;> simp -theorem head_ofFn {n} (f : Fin n → α) (h : ofFn f ≠ []) : +theorem head_ofFn {n} {f : Fin n → α} (h : ofFn f ≠ []) : (ofFn f).head h = f ⟨0, Nat.pos_of_ne_zero (mt ofFn_eq_nil_iff.2 h)⟩ := by - rw [← getElem_zero (length_ofFn _ ▸ Nat.pos_of_ne_zero (mt ofFn_eq_nil_iff.2 h)), + rw [← getElem_zero (length_ofFn ▸ Nat.pos_of_ne_zero (mt ofFn_eq_nil_iff.2 h)), List.getElem_ofFn] -theorem getLast_ofFn {n} (f : Fin n → α) (h : ofFn f ≠ []) : +theorem getLast_ofFn {n} {f : Fin n → α} (h : ofFn f ≠ []) : (ofFn f).getLast h = f ⟨n - 1, Nat.sub_one_lt (mt ofFn_eq_nil_iff.2 h)⟩ := by simp [getLast_eq_getElem, length_ofFn, List.getElem_ofFn] diff --git a/src/Init/Data/List/Pairwise.lean b/src/Init/Data/List/Pairwise.lean index 4710d5dc22..e351121cbf 100644 --- a/src/Init/Data/List/Pairwise.lean +++ b/src/Init/Data/List/Pairwise.lean @@ -38,7 +38,8 @@ theorem rel_of_pairwise_cons (p : (a :: l).Pairwise R) : ∀ {a'}, a' ∈ l → theorem Pairwise.of_cons (p : (a :: l).Pairwise R) : Pairwise R l := (pairwise_cons.1 p).2 -theorem Pairwise.tail : ∀ {l : List α} (_p : Pairwise R l), Pairwise R l.tail +set_option linter.unusedVariables false in +theorem Pairwise.tail : ∀ {l : List α} (h : Pairwise R l), Pairwise R l.tail | [], h => h | _ :: _, h => h.of_cons @@ -93,7 +94,7 @@ theorem Pairwise.forall_of_forall_of_flip (h₁ : ∀ x ∈ l, R x x) (h₂ : Pa rw [pairwise_cons] at h₂ h₃ simp only [mem_cons] rintro x (rfl | hx) y (rfl | hy) - · exact h₁ _ (l.mem_cons_self _) + · exact h₁ _ l.mem_cons_self · exact h₂.1 _ hy · exact h₃.1 _ hx · exact ih (fun x hx => h₁ _ <| mem_cons_of_mem _ hx) h₂.2 h₃.2 hx hy @@ -143,7 +144,7 @@ theorem pairwise_filter {p : α → Prop} [DecidablePred p] {l : List α} : simp theorem Pairwise.filter (p : α → Bool) : Pairwise R l → Pairwise R (filter p l) := - Pairwise.sublist (filter_sublist _) + Pairwise.sublist filter_sublist theorem pairwise_append {l₁ l₂ : List α} : (l₁ ++ l₂).Pairwise R ↔ l₁.Pairwise R ∧ l₂.Pairwise R ∧ ∀ a ∈ l₁, ∀ b ∈ l₂, R a b := by diff --git a/src/Init/Data/List/Perm.lean b/src/Init/Data/List/Perm.lean index ae2a3cb56e..cb4ec8c202 100644 --- a/src/Init/Data/List/Perm.lean +++ b/src/Init/Data/List/Perm.lean @@ -191,7 +191,7 @@ theorem Perm.filterMap (f : α → Option β) {l₁ l₂ : List α} (p : l₁ ~ | trans _p₁ _p₂ IH₁ IH₂ => exact IH₁.trans IH₂ theorem Perm.map (f : α → β) {l₁ l₂ : List α} (p : l₁ ~ l₂) : map f l₁ ~ map f l₂ := - filterMap_eq_map f ▸ p.filterMap _ + filterMap_eq_map ▸ p.filterMap _ theorem Perm.pmap {p : α → Prop} (f : ∀ a, p a → β) {l₁ l₂ : List α} (p : l₁ ~ l₂) {H₁ H₂} : pmap f l₁ H₁ ~ pmap f l₂ H₂ := by @@ -384,7 +384,7 @@ theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.erase theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : List α} : a :: l₁ ~ l₂ ↔ a ∈ l₂ ∧ l₁ ~ l₂.erase a := by refine ⟨fun h => ?_, fun ⟨m, h⟩ => (h.cons a).trans (perm_cons_erase m).symm⟩ - have : a ∈ l₂ := h.subset (mem_cons_self a l₁) + have : a ∈ l₂ := h.subset mem_cons_self exact ⟨this, (h.trans <| perm_cons_erase this).cons_inv⟩ theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l₁ = count a l₂ := by @@ -435,7 +435,7 @@ theorem Perm.pairwise_iff {R : α → α → Prop} (S : ∀ {x y}, R x y → R y induction d generalizing l₂ with | nil => rw [← p.nil_eq]; constructor | cons h _ IH => - have : _ ∈ l₂ := p.subset (mem_cons_self _ _) + have : _ ∈ l₂ := p.subset mem_cons_self obtain ⟨s₂, t₂, rfl⟩ := append_of_mem this have p' := (p.trans perm_middle).cons_inv refine (pairwise_middle S).2 (pairwise_cons.2 ⟨fun b m => ?_, IH p'⟩) @@ -458,8 +458,8 @@ theorem Perm.eq_of_sorted : ∀ {l₁ l₂ : List α} | [], b :: l₂, _, _, _, h => by simp_all | a :: l₁, [], _, _, _, h => by simp_all | a :: l₁, b :: l₂, w, h₁, h₂, h => by - have am : a ∈ b :: l₂ := h.subset (mem_cons_self _ _) - have bm : b ∈ a :: l₁ := h.symm.subset (mem_cons_self _ _) + have am : a ∈ b :: l₂ := h.subset mem_cons_self + have bm : b ∈ a :: l₁ := h.symm.subset mem_cons_self have ab : a = b := by simp only [mem_cons] at am rcases am with rfl | am @@ -467,7 +467,7 @@ theorem Perm.eq_of_sorted : ∀ {l₁ l₂ : List α} · simp only [mem_cons] at bm rcases bm with rfl | bm · rfl - · exact w _ _ (mem_cons_self _ _) (mem_cons_self _ _) + · exact w _ _ mem_cons_self mem_cons_self (rel_of_pairwise_cons h₁ bm) (rel_of_pairwise_cons h₂ am) subst ab simp only [perm_cons] at h diff --git a/src/Init/Data/List/Range.lean b/src/Init/Data/List/Range.lean index 613d236f2c..0ce5797059 100644 --- a/src/Init/Data/List/Range.lean +++ b/src/Init/Data/List/Range.lean @@ -25,12 +25,12 @@ open Nat /-! ### range' -/ -theorem range'_succ (s n step) : range' s (n + 1) step = s :: range' (s + step) n step := by +theorem range'_succ {s n step} : range' s (n + 1) step = s :: range' (s + step) n step := by simp [range', Nat.add_succ, Nat.mul_succ] -@[simp] theorem length_range' (s step) : ∀ n : Nat, length (range' s n step) = n +@[simp] theorem length_range' {s step} : ∀ {n : Nat}, length (range' s n step) = n | 0 => rfl - | _ + 1 => congrArg succ (length_range' _ _ _) + | _ + 1 => congrArg succ length_range' @[simp] theorem range'_eq_nil_iff : range' s n step = [] ↔ n = 0 := by rw [← length_eq_zero_iff, length_range'] @@ -47,7 +47,7 @@ theorem range'_ne_nil_iff (s : Nat) {n step : Nat} : range' s n step ≠ [] ↔ @[simp] theorem range'_one {s step : Nat} : range' s 1 step = [s] := rfl -@[simp] theorem tail_range' (n : Nat) : (range' s n step).tail = range' (s + step) (n - 1) step := by +@[simp] theorem tail_range' : (range' s n step).tail = range' (s + step) (n - 1) step := by cases n with | zero => simp | succ n => simp [range'_succ] @@ -65,7 +65,7 @@ theorem range'_ne_nil_iff (s : Nat) {n step : Nat} : range' s n step ≠ [] ↔ simp_all · rintro ⟨rfl, rfl | rfl⟩ <;> simp -theorem mem_range' : ∀{n}, m ∈ range' s n step ↔ ∃ i < n, m = s + step * i +theorem mem_range' : ∀ {n}, m ∈ range' s n step ↔ ∃ i < n, m = s + step * i | 0 => by simp [range', Nat.not_lt_zero] | n + 1 => by have h (i) : i ≤ n ↔ i = 0 ∨ ∃ j, i = succ j ∧ j < n := by @@ -73,42 +73,42 @@ theorem mem_range' : ∀{n}, m ∈ range' s n step ↔ ∃ i < n, m = s + step * simp [range', mem_range', Nat.lt_succ, h]; simp only [← exists_and_right, and_assoc] rw [exists_comm]; simp [Nat.mul_succ, Nat.add_assoc, Nat.add_comm] -theorem getElem?_range' (s step) : +theorem getElem?_range' {s step} : ∀ {i n : Nat}, i < n → (range' s n step)[i]? = some (s + step * i) | 0, n + 1, _ => by simp [range'_succ] | m + 1, n + 1, h => by simp only [range'_succ, getElem?_cons_succ] - exact (getElem?_range' (s + step) step (by exact succ_lt_succ_iff.mp h)).trans <| by + exact (getElem?_range' (s := s + step) (by exact succ_lt_succ_iff.mp h)).trans <| by simp [Nat.mul_succ, Nat.add_assoc, Nat.add_comm] -@[simp] theorem getElem_range' {n m step} (i) (H : i < (range' n m step).length) : +@[simp] theorem getElem_range' {n m step} {i} (H : i < (range' n m step).length) : (range' n m step)[i] = n + step * i := - (getElem?_eq_some_iff.1 <| getElem?_range' n step (by simpa using H)).2 + (getElem?_eq_some_iff.1 <| getElem?_range' (by simpa using H)).2 -theorem head?_range' (n : Nat) : (range' s n).head? = if n = 0 then none else some s := by +theorem head?_range' : (range' s n).head? = if n = 0 then none else some s := by induction n <;> simp_all [range'_succ, head?_append] -@[simp] theorem head_range' (n : Nat) (h) : (range' s n).head h = s := by +@[simp] theorem head_range' (h) : (range' s n).head h = s := by repeat simp_all [head?_range', head_eq_iff_head?_eq_some] -theorem map_add_range' (a) : ∀ s n step, map (a + ·) (range' s n step) = range' (a + s) n step +theorem map_add_range' {a} : ∀ s n step, map (a + ·) (range' s n step) = range' (a + s) n step | _, 0, _ => rfl - | s, n + 1, step => by simp [range', map_add_range' _ (s + step) n step, Nat.add_assoc] + | s, n + 1, step => by simp [range', map_add_range' (s + step), Nat.add_assoc] theorem range'_succ_left : range' (s + 1) n step = (range' s n step).map (· + 1) := by apply ext_getElem · simp · simp [Nat.add_right_comm] -theorem range'_append : ∀ s m n step : Nat, +theorem range'_append : ∀ {s m n step : Nat}, range' s m step ++ range' (s + step * m) n step = range' s (m + n) step | _, 0, _, _ => by simp | s, m + 1, n, step => by simpa [range', Nat.mul_succ, Nat.add_assoc, Nat.add_comm] - using range'_append (s + step) m n step + using range'_append (s := s + step) -@[simp] theorem range'_append_1 (s m n : Nat) : - range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append s m n 1 +@[simp] theorem range'_append_1 {s m n : Nat} : + range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append (step := 1) theorem range'_sublist_right {s m n : Nat} : range' s m step <+ range' s n step ↔ m ≤ n := ⟨fun h => by simpa only [length_range'] using h.length_le, @@ -123,10 +123,10 @@ theorem range'_subset_right {s m n : Nat} (step0 : 0 < step) : theorem range'_subset_right_1 {s m n : Nat} : range' s m ⊆ range' s n ↔ m ≤ n := range'_subset_right (by decide) -theorem range'_concat (s n : Nat) : range' s (n + 1) step = range' s n step ++ [s + step * n] := by - exact (range'_append s n 1 step).symm +theorem range'_concat {s n : Nat} : range' s (n + 1) step = range' s n step ++ [s + step * n] := by + exact range'_append.symm -theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ [s + n] := by +theorem range'_1_concat {s n : Nat} : range' s (n + 1) = range' s n ++ [s + n] := by simp [range'_concat] theorem range'_eq_cons_iff : range' s n = a :: xs ↔ s = a ∧ 0 < n ∧ xs = range' (a + 1) (n - 1) := by @@ -140,27 +140,27 @@ theorem range'_eq_cons_iff : range' s n = a :: xs ↔ s = a ∧ 0 < n ∧ xs = r /-! ### range -/ -theorem range_loop_range' : ∀ s n : Nat, range.loop s (range' s n) = range' 0 (n + s) +theorem range_loop_range' : ∀ s n, range.loop s (range' s n) = range' 0 (n + s) | 0, _ => rfl | s + 1, n => by rw [← Nat.add_assoc, Nat.add_right_comm n s 1]; exact range_loop_range' s (n + 1) -theorem range_eq_range' (n : Nat) : range n = range' 0 n := +theorem range_eq_range' {n : Nat} : range n = range' 0 n := (range_loop_range' n 0).trans <| by rw [Nat.zero_add] theorem getElem?_range {i n : Nat} (h : i < n) : (range n)[i]? = some i := by - simp [range_eq_range', getElem?_range' _ _ h] + simp [range_eq_range', getElem?_range' h] -@[simp] theorem getElem_range {n : Nat} (j) (h : j < (range n).length) : (range n)[j] = j := by +@[simp] theorem getElem_range (h : j < (range n).length) : (range n)[j] = j := by simp [range_eq_range'] -theorem range_succ_eq_map (n : Nat) : range (n + 1) = 0 :: map succ (range n) := by +theorem range_succ_eq_map {n : Nat} : range (n + 1) = 0 :: map succ (range n) := by rw [range_eq_range', range_eq_range', range', Nat.add_comm, ← map_add_range'] congr; exact funext (Nat.add_comm 1) -theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) := by +theorem range'_eq_map_range {s n : Nat} : range' s n = map (s + ·) (range n) := by rw [range_eq_range', map_add_range']; rfl -@[simp] theorem length_range (n : Nat) : length (range n) = n := by +@[simp] theorem length_range {n : Nat} : (range n).length = n := by simp only [range_eq_range', length_range'] @[simp] theorem range_eq_nil {n : Nat} : range n = [] ↔ n = 0 := by @@ -169,7 +169,7 @@ theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) := theorem range_ne_nil {n : Nat} : range n ≠ [] ↔ n ≠ 0 := by cases n <;> simp -@[simp] theorem tail_range (n : Nat) : (range n).tail = range' 1 (n - 1) := by +@[simp] theorem tail_range : (range n).tail = range' 1 (n - 1) := by rw [range_eq_range', tail_range'] @[simp] @@ -180,33 +180,33 @@ theorem range_sublist {m n : Nat} : range m <+ range n ↔ m ≤ n := by theorem range_subset {m n : Nat} : range m ⊆ range n ↔ m ≤ n := by simp only [range_eq_range', range'_subset_right, lt_succ_self] -theorem range_succ (n : Nat) : range (succ n) = range n ++ [n] := by +theorem range_succ {n : Nat} : range (succ n) = range n ++ [n] := by simp only [range_eq_range', range'_1_concat, Nat.zero_add] -theorem range_add (n m : Nat) : range (n + m) = range n ++ (range m).map (n + ·) := by +theorem range_add {n m : Nat} : range (n + m) = range n ++ (range m).map (n + ·) := by rw [← range'_eq_map_range] - simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 n m).symm + simpa [range_eq_range', Nat.add_comm] using (range'_append_1 (s := 0)).symm -theorem head?_range (n : Nat) : (range n).head? = if n = 0 then none else some 0 := by +theorem head?_range {n : Nat} : (range n).head? = if n = 0 then none else some 0 := by induction n with | zero => simp | succ n ih => simp only [range_succ, head?_append, ih] split <;> simp_all -@[simp] theorem head_range (n : Nat) (h) : (range n).head h = 0 := by +@[simp] theorem head_range {n : Nat} (h) : (range n).head h = 0 := by cases n with | zero => simp at h | succ n => simp [head?_range, head_eq_iff_head?_eq_some] -theorem getLast?_range (n : Nat) : (range n).getLast? = if n = 0 then none else some (n - 1) := by +theorem getLast?_range {n : Nat} : (range n).getLast? = if n = 0 then none else some (n - 1) := by induction n with | zero => simp | succ n ih => simp only [range_succ, getLast?_append, ih] split <;> simp_all -@[simp] theorem getLast_range (n : Nat) (h) : (range n).getLast h = n - 1 := by +@[simp] theorem getLast_range {n : Nat} (h) : (range n).getLast h = n - 1 := by cases n with | zero => simp at h | succ n => simp [getLast?_range, getLast_eq_iff_getLast?_eq_some] @@ -223,15 +223,15 @@ theorem zipIdx_eq_nil_iff {l : List α} {i : Nat} : List.zipIdx l i = [] ↔ l = @[simp] theorem getElem?_zipIdx : - ∀ (l : List α) i j, (zipIdx l i)[j]? = l[j]?.map fun a => (a, i + j) + ∀ {l : List α} {i j}, (zipIdx l i)[j]? = l[j]?.map fun a => (a, i + j) | [], _, _ => rfl | _ :: _, _, 0 => by simp | _ :: l, n, m + 1 => by simp only [zipIdx_cons, getElem?_cons_succ] - exact (getElem?_zipIdx l (n + 1) m).trans <| by rw [Nat.add_right_comm]; rfl + exact getElem?_zipIdx.trans <| by rw [Nat.add_right_comm]; rfl @[simp] -theorem getElem_zipIdx (l : List α) (j) (i : Nat) (h : i < (l.zipIdx j).length) : +theorem getElem_zipIdx {l : List α} (h : i < (l.zipIdx j).length) : (l.zipIdx j)[i] = (l[i]'(by simpa [length_zipIdx] using h), j + i) := by simp only [length_zipIdx] at h rw [getElem_eq_getElem?_get] @@ -239,53 +239,55 @@ theorem getElem_zipIdx (l : List α) (j) (i : Nat) (h : i < (l.zipIdx j).length) simp @[simp] -theorem tail_zipIdx (l : List α) (i : Nat) : (zipIdx l i).tail = zipIdx l.tail (i + 1) := by +theorem tail_zipIdx {l : List α} {i : Nat} : (zipIdx l i).tail = zipIdx l.tail (i + 1) := by induction l generalizing i with | nil => simp | cons _ l ih => simp [ih, zipIdx_cons] -theorem map_snd_add_zipIdx_eq_zipIdx (l : List α) (n k : Nat) : +theorem map_snd_add_zipIdx_eq_zipIdx {l : List α} {n k : Nat} : map (Prod.map id (· + n)) (zipIdx l k) = zipIdx l (n + k) := ext_getElem? fun i ↦ by simp [(· ∘ ·), Nat.add_comm, Nat.add_left_comm]; rfl -theorem zipIdx_cons' (i : Nat) (x : α) (xs : List α) : +theorem zipIdx_cons' {i : Nat} {x : α} {xs : List α} : zipIdx (x :: xs) i = (x, i) :: (zipIdx xs i).map (Prod.map id (· + 1)) := by rw [zipIdx_cons, Nat.add_comm, ← map_snd_add_zipIdx_eq_zipIdx] +-- Arguments are explicit for parity with `zipIdx_map_fst`. @[simp] -theorem zipIdx_map_snd (i) : +theorem zipIdx_map_snd (i : Nat) : ∀ (l : List α), map Prod.snd (zipIdx l i) = range' i l.length | [] => rfl - | _ :: _ => congrArg (cons _) (zipIdx_map_snd _ _) + | _ :: _ => congrArg (cons _) (zipIdx_map_snd ..) +-- Arguments are explicit so we can rewrite from right to left. @[simp] -theorem zipIdx_map_fst : ∀ (i) (l : List α), map Prod.fst (zipIdx l i) = l +theorem zipIdx_map_fst : ∀ i (l : List α), map Prod.fst (zipIdx l i) = l | _, [] => rfl - | _, _ :: _ => congrArg (cons _) (zipIdx_map_fst _ _) + | _, _ :: _ => congrArg (cons _) (zipIdx_map_fst ..) -theorem zipIdx_eq_zip_range' (l : List α) {i : Nat} : l.zipIdx i = l.zip (range' i l.length) := - zip_of_prod (zipIdx_map_fst _ _) (zipIdx_map_snd _ _) +theorem zipIdx_eq_zip_range' {l : List α} {i : Nat} : l.zipIdx i = l.zip (range' i l.length) := + zip_of_prod (zipIdx_map_fst ..) (zipIdx_map_snd ..) @[simp] -theorem unzip_zipIdx_eq_prod (l : List α) {i : Nat} : +theorem unzip_zipIdx_eq_prod {l : List α} {i : Nat} : (l.zipIdx i).unzip = (l, range' i l.length) := by simp only [zipIdx_eq_zip_range', unzip_zip, length_range'] /-- Replace `zipIdx` with a starting index `n+1` with `zipIdx` starting from `n`, followed by a `map` increasing the indices by one. -/ -theorem zipIdx_succ (l : List α) (i : Nat) : +theorem zipIdx_succ {l : List α} {i : Nat} : l.zipIdx (i + 1) = (l.zipIdx i).map (fun ⟨a, i⟩ => (a, i + 1)) := by induction l generalizing i with | nil => rfl - | cons _ _ ih => simp only [zipIdx_cons, ih (i + 1), map_cons] + | cons _ _ ih => simp only [zipIdx_cons, ih, map_cons] /-- Replace `zipIdx` with a starting index with `zipIdx` starting from 0, followed by a `map` increasing the indices. -/ -theorem zipIdx_eq_map_add (l : List α) (i : Nat) : +theorem zipIdx_eq_map_add {l : List α} {i : Nat} : l.zipIdx i = l.zipIdx.map (fun ⟨a, j⟩ => (a, i + j)) := by induction l generalizing i with | nil => rfl - | cons _ _ ih => simp [ih (i+1), zipIdx_succ, Nat.add_assoc, Nat.add_comm 1] + | cons _ _ ih => simp [ih (i := i + 1), zipIdx_succ, Nat.add_assoc, Nat.add_comm 1] /-! ### enumFrom -/ diff --git a/src/Init/Data/List/Sort/Lemmas.lean b/src/Init/Data/List/Sort/Lemmas.lean index a018b37838..4c85aae7aa 100644 --- a/src/Init/Data/List/Sort/Lemmas.lean +++ b/src/Init/Data/List/Sort/Lemmas.lean @@ -243,7 +243,7 @@ theorem merge_of_le : ∀ {xs ys : List α} (_ : ∀ a b, a ∈ xs → b ∈ ys rw [if_pos, merge_of_le] · intro a b ma mb exact h a b (mem_cons_of_mem _ ma) mb - · exact h x y (mem_cons_self _ _) (mem_cons_self _ _) + · exact h x y mem_cons_self mem_cons_self variable (le) in theorem merge_perm_append : ∀ {xs ys : List α}, merge xs ys le ~ xs ++ ys @@ -367,9 +367,9 @@ theorem mergeSort_cons {le : α → α → Bool} ∀ b, b ∈ l₁ → !le a b := by rw [← mergeSort_zipIdx] rw [zipIdx_cons] - have nd : Nodup ((a :: l).zipIdx.map (·.2)) := by rw [zipIdx_map_snd]; exact nodup_range' _ _ + have nd : Nodup ((a :: l).zipIdx.map (·.2)) := by rw [zipIdx_map_snd]; exact nodup_range' _ have m₁ : (a, 0) ∈ mergeSort ((a :: l).zipIdx) (zipIdxLE le) := - mem_mergeSort.mpr (mem_cons_self _ _) + mem_mergeSort.mpr mem_cons_self obtain ⟨l₁, l₂, h⟩ := append_of_mem m₁ have s := sorted_mergeSort (zipIdxLE_trans trans) (zipIdxLE_total total) ((a :: l).zipIdx) rw [h] at s @@ -408,9 +408,9 @@ theorem mergeSort_cons {le : α → α → Bool} have nd' := nd.perm p.symm rw [map_append] at nd' have j0 := nd'.rel_of_mem_append - (mem_map_of_mem (·.2) m) (mem_map_of_mem _ (mem_cons_self _ _)) + (mem_map_of_mem m) (mem_map_of_mem mem_cons_self) simp only [ne_eq] at j0 - have r := s.rel_of_mem_append m (mem_cons_self _ _) + have r := s.rel_of_mem_append m mem_cons_self simp_all [zipIdxLE] /-- diff --git a/src/Init/Data/List/Sublist.lean b/src/Init/Data/List/Sublist.lean index e8b03beef4..327f4d8441 100644 --- a/src/Init/Data/List/Sublist.lean +++ b/src/Init/Data/List/Sublist.lean @@ -256,10 +256,10 @@ protected theorem Sublist.filter (p : α → Bool) {l₁ l₂} (s : l₁ <+ l₂ rw [← filterMap_eq_filter]; apply s.filterMap theorem head_filter_mem (xs : List α) (p : α → Bool) (h) : (xs.filter p).head h ∈ xs := - (filter_sublist xs).head_mem h + filter_sublist.head_mem h theorem getLast_filter_mem (xs : List α) (p : α → Bool) (h) : (xs.filter p).getLast h ∈ xs := - (filter_sublist xs).getLast_mem h + filter_sublist.getLast_mem h theorem sublist_filterMap_iff {l₁ : List β} {f : α → Option β} : l₁ <+ l₂.filterMap f ↔ ∃ l', l' <+ l₂ ∧ l₁ = l'.filterMap f := by @@ -991,10 +991,10 @@ theorem drop_subset_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l (drop_sublist_drop_left l h).subset theorem takeWhile_prefix (p : α → Bool) : l.takeWhile p <+: l := - ⟨l.dropWhile p, takeWhile_append_dropWhile p l⟩ + ⟨l.dropWhile p, takeWhile_append_dropWhile⟩ theorem dropWhile_suffix (p : α → Bool) : l.dropWhile p <:+ l := - ⟨l.takeWhile p, takeWhile_append_dropWhile p l⟩ + ⟨l.takeWhile p, takeWhile_append_dropWhile⟩ theorem takeWhile_sublist (p : α → Bool) : l.takeWhile p <+ l := (takeWhile_prefix p).sublist diff --git a/src/Init/Data/List/TakeDrop.lean b/src/Init/Data/List/TakeDrop.lean index d20481527c..ce1077b2d2 100644 --- a/src/Init/Data/List/TakeDrop.lean +++ b/src/Init/Data/List/TakeDrop.lean @@ -23,28 +23,29 @@ Further results on `List.take` and `List.drop`, which rely on stronger automatio are given in `Init.Data.List.TakeDrop`. -/ -theorem take_cons {l : List α} (h : 0 < i) : take i (a :: l) = a :: take (i - 1) l := by +theorem take_cons {l : List α} (h : 0 < i) : (a :: l).take i = a :: l.take (i - 1) := by cases i with | zero => exact absurd h (Nat.lt_irrefl _) | succ i => rfl @[simp] -theorem drop_one : ∀ l : List α, drop 1 l = tail l +theorem drop_one : ∀ {l : List α}, l.drop 1 = l.tail | [] | _ :: _ => rfl -@[simp] theorem take_append_drop : ∀ (i : Nat) (l : List α), take i l ++ drop i l = l +-- Arguments are explicit so we can rewrite from right to left. +@[simp] theorem take_append_drop : ∀ (i : Nat) (l : List α), l.take i ++ l.drop i = l | 0, _ => rfl - | _+1, [] => rfl - | i+1, x :: xs => congrArg (cons x) <| take_append_drop i xs + | _ + 1, [] => rfl + | _ + 1, x :: _ => congrArg (cons x) (take_append_drop ..) -@[simp] theorem length_drop : ∀ (i : Nat) (l : List α), length (drop i l) = length l - i +@[simp] theorem length_drop : ∀ {i : Nat} {l : List α}, (drop i l).length = l.length - i | 0, _ => rfl | succ i, [] => Eq.symm (Nat.zero_sub (succ i)) | succ i, x :: l => calc - length (drop (succ i) (x :: l)) = length l - i := length_drop i l + length (drop (i + 1) (x :: l)) = length l - i := length_drop (i := i) (l := l) _ = succ (length l) - succ i := (Nat.succ_sub_succ_eq_sub (length l) i).symm -theorem drop_of_length_le {l : List α} (h : l.length ≤ i) : drop i l = [] := +theorem drop_of_length_le {l : List α} (h : l.length ≤ i) : l.drop i = [] := length_eq_zero_iff.1 (length_drop .. ▸ Nat.sub_eq_zero_of_le h) theorem length_lt_of_drop_ne_nil {l : List α} {i} (h : drop i l ≠ []) : i < l.length := @@ -57,18 +58,18 @@ theorem take_of_length_le {l : List α} (h : l.length ≤ i) : take i l = l := b theorem lt_length_of_take_ne_self {l : List α} {i} (h : l.take i ≠ l) : i < l.length := gt_of_not_le (mt take_of_length_le h) -@[simp] theorem drop_length (l : List α) : drop l.length l = [] := drop_of_length_le (Nat.le_refl _) +@[simp] theorem drop_length {l : List α} : l.drop l.length = [] := drop_of_length_le (Nat.le_refl _) -@[simp] theorem take_length (l : List α) : take l.length l = l := take_of_length_le (Nat.le_refl _) +@[simp] theorem take_length {l : List α} : l.take l.length = l := take_of_length_le (Nat.le_refl _) @[simp] -theorem getElem_cons_drop : ∀ (l : List α) (i : Nat) (h : i < l.length), +theorem getElem_cons_drop : ∀ {l : List α} {i : Nat} (h : i < l.length), l[i] :: drop (i + 1) l = drop i l | _::_, 0, _ => rfl - | _::_, i+1, h => getElem_cons_drop _ i (Nat.add_one_lt_add_one_iff.mp h) + | _::_, _+1, h => getElem_cons_drop (Nat.add_one_lt_add_one_iff.mp h) theorem drop_eq_getElem_cons {i} {l : List α} (h : i < l.length) : drop i l = l[i] :: drop (i + 1) l := - (getElem_cons_drop _ i h).symm + (getElem_cons_drop h).symm @[simp] theorem getElem?_take_of_lt {l : List α} {i j : Nat} (h : i < j) : (l.take j)[i]? = l[i]? := by @@ -85,25 +86,25 @@ theorem getElem?_take_of_lt {l : List α} {i j : Nat} (h : i < j) : (l.take j)[i theorem getElem?_take_of_succ {l : List α} {i : Nat} : (l.take (i + 1))[i]? = l[i]? := by simp -@[simp] theorem drop_drop (i : Nat) : ∀ (j) (l : List α), drop i (drop j l) = drop (j + i) l +@[simp] theorem drop_drop {i : Nat} : ∀ {j} {l : List α}, drop i (drop j l) = drop (j + i) l | j, [] => by simp | 0, l => by simp | j + 1, a :: l => calc drop i (drop (j + 1) (a :: l)) = drop i (drop j l) := rfl - _ = drop (j + i) l := drop_drop i j l + _ = drop (j + i) l := drop_drop _ = drop ((j + 1) + i) (a :: l) := by rw [Nat.add_right_comm]; rfl -theorem drop_add_one_eq_tail_drop (l : List α) : l.drop (i + 1) = (l.drop i).tail := by +theorem drop_add_one_eq_tail_drop {l : List α} : l.drop (i + 1) = (l.drop i).tail := by rw [← drop_drop, drop_one] -theorem take_drop : ∀ (i j : Nat) (l : List α), take i (drop j l) = drop j (take (j + i) l) +theorem take_drop : ∀ {i j : Nat} {l : List α}, take i (drop j l) = drop j (take (j + i) l) | _, 0, _ => by simp | _, _, [] => by simp | _, _+1, _ :: _ => by simpa [Nat.succ_add, take_succ_cons, drop_succ_cons] using take_drop .. @[simp] -theorem tail_drop (l : List α) (i : Nat) : (l.drop i).tail = l.drop (i + 1) := by +theorem tail_drop {l : List α} {i : Nat} : (l.drop i).tail = l.drop (i + 1) := by induction l generalizing i with | nil => simp | cons hd tl hl => @@ -112,7 +113,7 @@ theorem tail_drop (l : List α) (i : Nat) : (l.drop i).tail = l.drop (i + 1) := · simp [hl] @[simp] -theorem drop_tail (l : List α) (i : Nat) : l.tail.drop i = l.drop (i + 1) := by +theorem drop_tail {l : List α} {i : Nat} : l.tail.drop i = l.drop (i + 1) := by rw [Nat.add_comm, ← drop_drop, drop_one] @[simp] @@ -177,18 +178,20 @@ theorem set_drop {l : List α} {i j : Nat} {a : α} : rw [drop_set, if_neg, add_sub_self_left] exact (Nat.not_lt).2 (le_add_right ..) -theorem take_concat_get (l : List α) (i : Nat) (h : i < l.length) : +theorem take_concat_get {l : List α} {i : Nat} (h : i < l.length) : (l.take i).concat l[i] = l.take (i+1) := Eq.symm <| (append_left_inj _).1 <| (take_append_drop (i+1) l).trans <| by rw [concat_eq_append, append_assoc, singleton_append, getElem_cons_drop_succ_eq_drop, take_append_drop] -@[simp] theorem take_append_getElem (l : List α) (i : Nat) (h : i < l.length) : +@[simp] theorem take_append_getElem {l : List α} {i : Nat} (h : i < l.length) : (l.take i) ++ [l[i]] = l.take (i+1) := by - simpa using take_concat_get l i h + simpa using take_concat_get h theorem take_succ_eq_append_getElem {i} {l : List α} (h : i < l.length) : l.take (i + 1) = l.take i ++ [l[i]] := - (take_append_getElem _ _ h).symm + (take_append_getElem h).symm +-- The argument `l : List α` is explicit +-- as `h` may be produced by a tactic that does not determine `l`. @[simp] theorem take_append_getLast (l : List α) (h : l ≠ []) : (l.take (l.length - 1)) ++ [l.getLast h] = l := by rw [getLast_eq_getElem] @@ -203,17 +206,17 @@ theorem take_succ_eq_append_getElem {i} {l : List α} (h : i < l.length) : l.tak | x :: xs => simpa using take_append_getLast (x :: xs) (by simp) -theorem drop_left : ∀ l₁ l₂ : List α, drop (length l₁) (l₁ ++ l₂) = l₂ +theorem drop_left : ∀ {l₁ l₂ : List α}, drop (length l₁) (l₁ ++ l₂) = l₂ | [], _ => rfl - | _ :: l₁, l₂ => drop_left l₁ l₂ + | _ :: l₁, _ => drop_left (l₁ := l₁) @[simp] theorem drop_left' {l₁ l₂ : List α} {i} (h : length l₁ = i) : drop i (l₁ ++ l₂) = l₂ := by rw [← h]; apply drop_left -theorem take_left : ∀ l₁ l₂ : List α, take (length l₁) (l₁ ++ l₂) = l₁ +theorem take_left : ∀ {l₁ l₂ : List α}, take (length l₁) (l₁ ++ l₂) = l₁ | [], _ => rfl - | a :: l₁, l₂ => congrArg (cons a) (take_left l₁ l₂) + | a :: _, _ => congrArg (cons a) take_left @[simp] theorem take_left' {l₁ l₂ : List α} {i} (h : length l₁ = i) : take i (l₁ ++ l₂) = l₁ := by @@ -228,29 +231,29 @@ theorem take_succ {l : List α} {i : Nat} : l.take (i + 1) = l.take i ++ l[i]?.t · simp only [take, Option.toList, getElem?_cons_zero, nil_append] · simp only [take, hl, getElem?_cons_succ, cons_append] -theorem dropLast_eq_take (l : List α) : l.dropLast = l.take (l.length - 1) := by +theorem dropLast_eq_take {l : List α} : l.dropLast = l.take (l.length - 1) := by cases l with | nil => simp [dropLast] | cons x l => induction l generalizing x <;> simp_all [dropLast] -@[simp] theorem map_take (f : α → β) : - ∀ (l : List α) (i : Nat), (l.take i).map f = (l.map f).take i +@[simp] theorem map_take {f : α → β} : + ∀ {l : List α} {i : Nat}, (l.take i).map f = (l.map f).take i | [], i => by simp | _, 0 => by simp - | _ :: tl, n + 1 => by dsimp; rw [map_take f tl n] + | _ :: tl, n + 1 => by dsimp; rw [map_take] -@[simp] theorem map_drop (f : α → β) : - ∀ (l : List α) (i : Nat), (l.drop i).map f = (l.map f).drop i +@[simp] theorem map_drop {f : α → β} : + ∀ {l : List α} {i : Nat}, (l.drop i).map f = (l.map f).drop i | [], i => by simp | l, 0 => by simp | _ :: tl, n + 1 => by dsimp - rw [map_drop f tl] + rw [map_drop] /-! ### takeWhile and dropWhile -/ -theorem takeWhile_cons (p : α → Bool) (a : α) (l : List α) : +theorem takeWhile_cons {p : α → Bool} {a : α} {l : List α} : (a :: l).takeWhile p = if p a then a :: l.takeWhile p else [] := by simp only [takeWhile] by_cases h: p a <;> simp [h] @@ -275,14 +278,14 @@ theorem dropWhile_cons : (a :: l).dropWhile p = a :: l := by simp [dropWhile_cons, h] -theorem head?_takeWhile (p : α → Bool) (l : List α) : (l.takeWhile p).head? = l.head?.filter p := by +theorem head?_takeWhile {p : α → Bool} {l : List α} : (l.takeWhile p).head? = l.head?.filter p := by cases l with | nil => rfl | cons x xs => simp only [takeWhile_cons, head?_cons, Option.filter_some] split <;> simp -theorem head_takeWhile (p : α → Bool) (l : List α) (w) : +theorem head_takeWhile {p : α → Bool} {l : List α} (w) : (l.takeWhile p).head w = l.head (by rintro rfl; simp_all) := by cases l with | nil => rfl @@ -299,11 +302,12 @@ theorem head?_dropWhile_not (p : α → Bool) (l : List α) : simp only [dropWhile_cons] split <;> rename_i h <;> split at h <;> simp_all -theorem head_dropWhile_not (p : α → Bool) (l : List α) (w) : +-- The argument `p` is explicit, as otherwise the head of the left hand side may be a metavariable. +theorem head_dropWhile_not (p : α → Bool) {l : List α} (w) : p ((l.dropWhile p).head w) = false := by simpa [head?_eq_head, w] using head?_dropWhile_not p l -theorem takeWhile_map (f : α → β) (p : β → Bool) (l : List α) : +theorem takeWhile_map {f : α → β} {p : β → Bool} {l : List α} : (l.map f).takeWhile p = (l.takeWhile (p ∘ f)).map f := by induction l with | nil => rfl @@ -311,7 +315,7 @@ theorem takeWhile_map (f : α → β) (p : β → Bool) (l : List α) : simp only [map_cons, takeWhile_cons] split <;> simp_all -theorem dropWhile_map (f : α → β) (p : β → Bool) (l : List α) : +theorem dropWhile_map {f : α → β} {p : β → Bool} {l : List α} : (l.map f).dropWhile p = (l.dropWhile (p ∘ f)).map f := by induction l with | nil => rfl @@ -319,7 +323,7 @@ theorem dropWhile_map (f : α → β) (p : β → Bool) (l : List α) : simp only [map_cons, dropWhile_cons] split <;> simp_all -theorem takeWhile_filterMap (f : α → Option β) (p : β → Bool) (l : List α) : +theorem takeWhile_filterMap {f : α → Option β} {p : β → Bool} {l : List α} : (l.filterMap f).takeWhile p = (l.takeWhile fun a => (f a).all p).filterMap f := by induction l with | nil => rfl @@ -331,7 +335,7 @@ theorem takeWhile_filterMap (f : α → Option β) (p : β → Bool) (l : List · simp [takeWhile_cons, h, ih] split <;> simp_all [filterMap_cons] -theorem dropWhile_filterMap (f : α → Option β) (p : β → Bool) (l : List α) : +theorem dropWhile_filterMap {f : α → Option β} {p : β → Bool} {l : List α} : (l.filterMap f).dropWhile p = (l.dropWhile fun a => (f a).all p).filterMap f := by induction l with | nil => rfl @@ -343,18 +347,18 @@ theorem dropWhile_filterMap (f : α → Option β) (p : β → Bool) (l : List · simp [dropWhile_cons, h, ih] split <;> simp_all [filterMap_cons] -theorem takeWhile_filter (p q : α → Bool) (l : List α) : +theorem takeWhile_filter {p q : α → Bool} {l : List α} : (l.filter p).takeWhile q = (l.takeWhile fun a => !p a || q a).filter p := by simp [← filterMap_eq_filter, takeWhile_filterMap] -theorem dropWhile_filter (p q : α → Bool) (l : List α) : +theorem dropWhile_filter {p q : α → Bool} {l : List α} : (l.filter p).dropWhile q = (l.dropWhile fun a => !p a || q a).filter p := by simp [← filterMap_eq_filter, dropWhile_filterMap] -@[simp] theorem takeWhile_append_dropWhile (p : α → Bool) : - ∀ (l : List α), takeWhile p l ++ dropWhile p l = l +@[simp] theorem takeWhile_append_dropWhile {p : α → Bool} : + ∀ {l : List α}, takeWhile p l ++ dropWhile p l = l | [] => rfl - | x :: xs => by simp [takeWhile, dropWhile]; cases p x <;> simp [takeWhile_append_dropWhile p xs] + | x :: xs => by simp [takeWhile, dropWhile]; cases p x <;> simp [takeWhile_append_dropWhile] theorem takeWhile_append {xs ys : List α} : (xs ++ ys).takeWhile p = @@ -389,7 +393,7 @@ theorem dropWhile_append {xs ys : List α} : | nil => simp | cons x xs ih => simp_all [dropWhile_cons] -@[simp] theorem takeWhile_replicate_eq_filter (p : α → Bool) : +@[simp] theorem takeWhile_replicate_eq_filter {p : α → Bool} : (replicate n a).takeWhile p = (replicate n a).filter p := by induction n with | zero => simp @@ -397,11 +401,11 @@ theorem dropWhile_append {xs ys : List α} : simp only [replicate_succ, takeWhile_cons] split <;> simp_all -theorem takeWhile_replicate (p : α → Bool) : +theorem takeWhile_replicate {p : α → Bool} : (replicate n a).takeWhile p = if p a then replicate n a else [] := by rw [takeWhile_replicate_eq_filter, filter_replicate] -@[simp] theorem dropWhile_replicate_eq_filter_not (p : α → Bool) : +@[simp] theorem dropWhile_replicate_eq_filter_not {p : α → Bool} : (replicate n a).dropWhile p = (replicate n a).filter (fun a => !p a) := by induction n with | zero => simp @@ -409,12 +413,12 @@ theorem takeWhile_replicate (p : α → Bool) : simp only [replicate_succ, dropWhile_cons] split <;> simp_all -theorem dropWhile_replicate (p : α → Bool) : +theorem dropWhile_replicate {p : α → Bool} : (replicate n a).dropWhile p = if p a then [] else replicate n a := by simp only [dropWhile_replicate_eq_filter_not, filter_replicate] split <;> simp_all -theorem take_takeWhile {l : List α} (p : α → Bool) i : +theorem take_takeWhile {l : List α} {p : α → Bool} : (l.takeWhile p).take i = (l.take i).takeWhile p := by induction l generalizing i with | nil => simp @@ -446,13 +450,13 @@ theorem replace_takeWhile [BEq α] [LawfulBEq α] {l : List α} {p : α → Bool /-! ### splitAt -/ -@[simp] theorem splitAt_eq (i : Nat) (l : List α) : splitAt i l = (l.take i, l.drop i) := by +@[simp] theorem splitAt_eq {i : Nat} {l : List α} : splitAt i l = (l.take i, l.drop i) := by rw [splitAt, splitAt_go, reverse_nil, nil_append] split <;> simp_all [take_of_length_le, drop_of_length_le] /-! ### rotateLeft -/ -@[simp] theorem rotateLeft_zero (l : List α) : rotateLeft l 0 = l := by +@[simp] theorem rotateLeft_zero {l : List α} : rotateLeft l 0 = l := by simp [rotateLeft] -- TODO Batteries defines its own `getElem?_rotate`, which we need to adapt. @@ -460,7 +464,7 @@ theorem replace_takeWhile [BEq α] [LawfulBEq α] {l : List α} {p : α → Bool /-! ### rotateRight -/ -@[simp] theorem rotateRight_zero (l : List α) : rotateRight l 0 = l := by +@[simp] theorem rotateRight_zero {l : List α} : rotateRight l 0 = l := by simp [rotateRight] -- TODO Batteries defines its own `getElem?_rotate`, which we need to adapt. diff --git a/src/Init/Data/List/ToArray.lean b/src/Init/Data/List/ToArray.lean index 64725a3332..192bfe7c79 100644 --- a/src/Init/Data/List/ToArray.lean +++ b/src/Init/Data/List/ToArray.lean @@ -619,15 +619,15 @@ private theorem insertIdx_loop_toArray (i : Nat) (l : List α) (j : Nat) (hj : j simp only [append_assoc, cons_append] rw [insertIdx_loop_toArray _ _ _ _ (by omega)] simp only [swap_toArray, w, append_assoc, cons_append, mk.injEq] - rw [take_set_of_le _ _ (by omega), drop_eq_getElem_cons (i := j) (by simpa), getElem_set_self, - drop_set_of_lt _ _ (by omega), drop_set_of_lt _ _ (by omega), getElem_set_ne (by omega), - getElem_set_self, take_set_of_le (j := j - 1) _ _ (by omega), - take_set_of_le (j := j - 1) _ _ (by omega), take_eq_append_getElem_of_pos (by omega) hj, + rw [take_set_of_le (by omega), drop_eq_getElem_cons (i := j) (by simpa), getElem_set_self, + drop_set_of_lt (by omega), drop_set_of_lt (by omega), getElem_set_ne (by omega), + getElem_set_self, take_set_of_le (j := j - 1) (by omega), + take_set_of_le (j := j - 1) (by omega), take_eq_append_getElem_of_pos (by omega) hj, drop_append_of_le_length (by simp; omega)] simp only [append_assoc, cons_append, nil_append, append_cancel_right_eq] cases i with | zero => simp - | succ i => rw [take_set_of_le _ _ (by omega)] + | succ i => rw [take_set_of_le (by omega)] · simp only [Nat.not_lt] at h' have : i = j := by omega subst this diff --git a/src/Init/Data/List/Zip.lean b/src/Init/Data/List/Zip.lean index e06fbb29c5..a6e0cc58a7 100644 --- a/src/Init/Data/List/Zip.lean +++ b/src/Init/Data/List/Zip.lean @@ -22,21 +22,21 @@ open Nat /-! ### zipWith -/ -theorem zipWith_comm (f : α → β → γ) : - ∀ (as : List α) (bs : List β), zipWith f as bs = zipWith (fun b a => f a b) bs as +theorem zipWith_comm {f : α → β → γ} : + ∀ {as : List α} {bs : List β}, zipWith f as bs = zipWith (fun b a => f a b) bs as | [], _ => List.zipWith_nil_right.symm | _ :: _, [] => rfl - | _ :: as, _ :: bs => congrArg _ (zipWith_comm f as bs) + | _ :: _, _ :: _ => congrArg _ zipWith_comm -theorem zipWith_comm_of_comm (f : α → α → β) (comm : ∀ x y : α, f x y = f y x) (l l' : List α) : +theorem zipWith_comm_of_comm {f : α → α → β} (comm : ∀ x y : α, f x y = f y x) {l l' : List α} : zipWith f l l' = zipWith f l' l := by rw [zipWith_comm] simp only [comm] @[simp] -theorem zipWith_self (f : α → α → δ) : ∀ l : List α, zipWith f l l = l.map fun a => f a a +theorem zipWith_self {f : α → α → δ} : ∀ {l : List α}, zipWith f l l = l.map fun a => f a a | [] => rfl - | _ :: xs => congrArg _ (zipWith_self f xs) + | _ :: _ => congrArg _ zipWith_self @[deprecated zipWith_self (since := "2025-01-29")] abbrev zipWith_same := @zipWith_self @@ -92,23 +92,23 @@ theorem head_zipWith {f : α → β → γ} (h): rw [← head?_eq_head, head?_zipWith, head?_eq_head, head?_eq_head] @[simp] -theorem zipWith_map {μ} (f : γ → δ → μ) (g : α → γ) (h : β → δ) (l₁ : List α) (l₂ : List β) : +theorem zipWith_map {μ} {f : γ → δ → μ} {g : α → γ} {h : β → δ} {l₁ : List α} {l₂ : List β} : zipWith f (l₁.map g) (l₂.map h) = zipWith (fun a b => f (g a) (h b)) l₁ l₂ := by induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all -theorem zipWith_map_left (l₁ : List α) (l₂ : List β) (f : α → α') (g : α' → β → γ) : +theorem zipWith_map_left {l₁ : List α} {l₂ : List β} {f : α → α'} {g : α' → β → γ} : zipWith g (l₁.map f) l₂ = zipWith (fun a b => g (f a) b) l₁ l₂ := by induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all -theorem zipWith_map_right (l₁ : List α) (l₂ : List β) (f : β → β') (g : α → β' → γ) : +theorem zipWith_map_right {l₁ : List α} {l₂ : List β} {f : β → β'} {g : α → β' → γ} : zipWith g l₁ (l₂.map f) = zipWith (fun a b => g a (f b)) l₁ l₂ := by induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all -theorem zipWith_foldr_eq_zip_foldr {f : α → β → γ} (i : δ): +theorem zipWith_foldr_eq_zip_foldr {f : α → β → γ} {i : δ} {g : γ → δ → δ} : (zipWith f l₁ l₂).foldr g i = (zip l₁ l₂).foldr (fun p r => g (f p.1 p.2) r) i := by induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all -theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} (i : δ): +theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} {i : δ} {g : δ → γ → δ} : (zipWith f l₁ l₂).foldl g i = (zip l₁ l₂).foldl (fun r p => g r (f p.1 p.2)) i := by induction l₁ generalizing i l₂ <;> cases l₂ <;> simp_all @@ -116,7 +116,7 @@ theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} (i : δ): theorem zipWith_eq_nil_iff {f : α → β → γ} {l l'} : zipWith f l l' = [] ↔ l = [] ∨ l' = [] := by cases l <;> cases l' <;> simp -theorem map_zipWith {δ : Type _} (f : α → β) (g : γ → δ → α) (l : List γ) (l' : List δ) : +theorem map_zipWith {δ : Type _} {f : α → β} {g : γ → δ → α} {l : List γ} {l' : List δ} : map f (zipWith g l l') = zipWith (fun x y => f (g x y)) l l' := by induction l generalizing l' with | nil => simp @@ -149,7 +149,7 @@ theorem drop_zipWith : (zipWith f l l').drop i = zipWith f (l.drop i) (l'.drop i theorem tail_zipWith : (zipWith f l l').tail = zipWith f l.tail l'.tail := by rw [← drop_one]; simp [drop_zipWith] -theorem zipWith_append (f : α → β → γ) (l₁ l₁' : List α) (l₂ l₂' : List β) +theorem zipWith_append {f : α → β → γ} {l₁ l₁' : List α} {l₂ l₂' : List β} (h : l₁.length = l₂.length) : zipWith f (l₁ ++ l₁') (l₂ ++ l₂') = zipWith f l₁ l₂ ++ zipWith f l₁' l₂' := by induction l₁ generalizing l₂ with @@ -161,7 +161,7 @@ theorem zipWith_append (f : α → β → γ) (l₁ l₁' : List α) (l₂ l₂' | nil => simp at h | cons _ _ => simp only [length_cons, Nat.succ.injEq] at h - simp [ih _ h] + simp [ih h] theorem zipWith_eq_cons_iff {f : α → β → γ} {l₁ : List α} {l₂ : List β} : zipWith f l₁ l₂ = g :: l ↔ @@ -229,7 +229,7 @@ theorem zipWith_eq_append_iff {f : α → β → γ} {l₁ : List α} {l₂ : Li | zero => rfl | succ n ih => simp [replicate_succ, ih] -theorem map_uncurry_zip_eq_zipWith (f : α → β → γ) (l : List α) (l' : List β) : +theorem map_uncurry_zip_eq_zipWith {f : α → β → γ} {l : List α} {l' : List β} : map (Function.uncurry f) (l.zip l') = zipWith f l l' := by rw [zip] induction l generalizing l' with @@ -237,7 +237,7 @@ theorem map_uncurry_zip_eq_zipWith (f : α → β → γ) (l : List α) (l' : Li | cons hl tl ih => cases l' <;> simp [ih] -theorem map_zip_eq_zipWith (f : α × β → γ) (l : List α) (l' : List β) : +theorem map_zip_eq_zipWith {f : α × β → γ} {l : List α} {l' : List β} : map f (l.zip l') = zipWith (Function.curry f) l l' := by rw [zip] induction l generalizing l' with @@ -247,24 +247,24 @@ theorem map_zip_eq_zipWith (f : α × β → γ) (l : List α) (l' : List β) : /-! ### zip -/ -theorem zip_eq_zipWith : ∀ (l₁ : List α) (l₂ : List β), zip l₁ l₂ = zipWith Prod.mk l₁ l₂ +theorem zip_eq_zipWith : ∀ {l₁ : List α} {l₂ : List β}, zip l₁ l₂ = zipWith Prod.mk l₁ l₂ | [], _ => rfl | _, [] => rfl - | a :: l₁, b :: l₂ => by simp [zip_cons_cons, zip_eq_zipWith l₁ l₂] + | a :: l₁, b :: l₂ => by simp [zip_cons_cons, zip_eq_zipWith (l₁ := l₁)] -theorem zip_map (f : α → γ) (g : β → δ) : - ∀ (l₁ : List α) (l₂ : List β), zip (l₁.map f) (l₂.map g) = (zip l₁ l₂).map (Prod.map f g) +theorem zip_map {f : α → γ} {g : β → δ} : + ∀ {l₁ : List α} {l₂ : List β}, zip (l₁.map f) (l₂.map g) = (zip l₁ l₂).map (Prod.map f g) | [], _ => rfl | _, [] => by simp only [map, zip_nil_right] | _ :: _, _ :: _ => by simp only [map, zip_cons_cons, zip_map, Prod.map] -theorem zip_map_left (f : α → γ) (l₁ : List α) (l₂ : List β) : +theorem zip_map_left {f : α → γ} {l₁ : List α} {l₂ : List β} : zip (l₁.map f) l₂ = (zip l₁ l₂).map (Prod.map f id) := by rw [← zip_map, map_id] -theorem zip_map_right (f : β → γ) (l₁ : List α) (l₂ : List β) : +theorem zip_map_right {f : β → γ} {l₁ : List α} {l₂ : List β} : zip l₁ (l₂.map f) = (zip l₁ l₂).map (Prod.map id f) := by rw [← zip_map, map_id] -@[simp] theorem tail_zip (l₁ : List α) (l₂ : List β) : +@[simp] theorem tail_zip {l₁ : List α} {l₂ : List β} : (zip l₁ l₂).tail = zip l₁.tail l₂.tail := by cases l₁ <;> cases l₂ <;> simp @@ -276,8 +276,8 @@ theorem zip_append : | _ :: _, _, _ :: _, _, h => by simp only [cons_append, zip_cons_cons, zip_append (Nat.succ.inj h)] -theorem zip_map' (f : α → β) (g : α → γ) : - ∀ l : List α, zip (l.map f) (l.map g) = l.map fun a => (f a, g a) +theorem zip_map' {f : α → β} {g : α → γ} : + ∀ {l : List α}, zip (l.map f) (l.map g) = l.map fun a => (f a, g a) | [] => rfl | a :: l => by simp only [map, zip_cons_cons, zip_map'] @@ -290,16 +290,16 @@ theorem of_mem_zip {a b} : ∀ {l₁ : List α} {l₂ : List β}, (a, b) ∈ zip exact ⟨Mem.tail _ this.1, Mem.tail _ this.2⟩ theorem map_fst_zip : - ∀ (l₁ : List α) (l₂ : List β), l₁.length ≤ l₂.length → map Prod.fst (zip l₁ l₂) = l₁ + ∀ {l₁ : List α} {l₂ : List β}, l₁.length ≤ l₂.length → map Prod.fst (zip l₁ l₂) = l₁ | [], _, _ => rfl | _ :: as, _ :: bs, h => by simp [Nat.succ_le_succ_iff] at h show _ :: map Prod.fst (zip as bs) = _ :: as - rw [map_fst_zip as bs h] + rw [map_fst_zip (l₁ := as) h] | _ :: _, [], h => by simp at h theorem map_snd_zip : - ∀ (l₁ : List α) (l₂ : List β), l₂.length ≤ l₁.length → map Prod.snd (zip l₁ l₂) = l₂ + ∀ {l₁ : List α} {l₂ : List β}, l₂.length ≤ l₁.length → map Prod.snd (zip l₁ l₂) = l₂ | _, [], _ => by rw [zip_nil_right] rfl @@ -307,15 +307,15 @@ theorem map_snd_zip : | a :: as, b :: bs, h => by simp [Nat.succ_le_succ_iff] at h show _ :: map Prod.snd (zip as bs) = _ :: bs - rw [map_snd_zip as bs h] + rw [map_snd_zip (l₂ := bs) h] -theorem map_prod_left_eq_zip {l : List α} (f : α → β) : +theorem map_prod_left_eq_zip {l : List α} {f : α → β} : (l.map fun x => (x, f x)) = l.zip (l.map f) := by rw [← zip_map'] congr simp -theorem map_prod_right_eq_zip {l : List α} (f : α → β) : +theorem map_prod_right_eq_zip {l : List α} {f : α → β} : (l.map fun x => (f x, x)) = (l.map f).zip l := by rw [← zip_map'] congr @@ -379,19 +379,19 @@ theorem head?_zipWithAll {f : Option α → Option β → γ} : (zipWithAll f as bs).tail = zipWithAll f as.tail bs.tail := by cases as <;> cases bs <;> simp -theorem zipWithAll_map {μ} (f : Option γ → Option δ → μ) (g : α → γ) (h : β → δ) (l₁ : List α) (l₂ : List β) : +theorem zipWithAll_map {μ} {f : Option γ → Option δ → μ} {g : α → γ} {h : β → δ} {l₁ : List α} {l₂ : List β} : zipWithAll f (l₁.map g) (l₂.map h) = zipWithAll (fun a b => f (g <$> a) (h <$> b)) l₁ l₂ := by induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all -theorem zipWithAll_map_left (l₁ : List α) (l₂ : List β) (f : α → α') (g : Option α' → Option β → γ) : +theorem zipWithAll_map_left {l₁ : List α} {l₂ : List β} {f : α → α'} {g : Option α' → Option β → γ} : zipWithAll g (l₁.map f) l₂ = zipWithAll (fun a b => g (f <$> a) b) l₁ l₂ := by induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all -theorem zipWithAll_map_right (l₁ : List α) (l₂ : List β) (f : β → β') (g : Option α → Option β' → γ) : +theorem zipWithAll_map_right {l₁ : List α} {l₂ : List β} {f : β → β'} {g : Option α → Option β' → γ} : zipWithAll g l₁ (l₂.map f) = zipWithAll (fun a b => g a (f <$> b)) l₁ l₂ := by induction l₁ generalizing l₂ <;> cases l₂ <;> simp_all -theorem map_zipWithAll {δ : Type _} (f : α → β) (g : Option γ → Option δ → α) (l : List γ) (l' : List δ) : +theorem map_zipWithAll {δ : Type _} {f : α → β} {g : Option γ → Option δ → α} {l : List γ} {l' : List δ} : map f (zipWithAll g l l') = zipWithAll (fun x y => f (g x y)) l l' := by induction l generalizing l' with | nil => simp @@ -412,10 +412,11 @@ theorem map_zipWithAll {δ : Type _} (f : α → β) (g : Option γ → Option @[simp] theorem unzip_snd : (unzip l).snd = l.map Prod.snd := by induction l <;> simp_all -theorem unzip_eq_map : ∀ l : List (α × β), unzip l = (l.map Prod.fst, l.map Prod.snd) +theorem unzip_eq_map : ∀ {l : List (α × β)}, unzip l = (l.map Prod.fst, l.map Prod.snd) | [] => rfl - | (a, b) :: l => by simp only [unzip_cons, map_cons, unzip_eq_map l] + | (a, b) :: l => by simp only [unzip_cons, map_cons, unzip_eq_map (l := l)] +-- The argument `l` is explicit so we can rewrite from right to left. theorem zip_unzip : ∀ l : List (α × β), zip (unzip l).1 (unzip l).2 = l | [] => rfl | (a, b) :: l => by simp only [unzip_cons, zip_cons_cons, zip_unzip l] diff --git a/src/Init/Data/Vector/Attach.lean b/src/Init/Data/Vector/Attach.lean index b3aaa25322..3a335f3c4d 100644 --- a/src/Init/Data/Vector/Attach.lean +++ b/src/Init/Data/Vector/Attach.lean @@ -89,9 +89,9 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep intro a m h₁ h₂ congr -@[simp] theorem pmap_empty {P : α → Prop} (f : ∀ a, P a → β) : pmap f #v[] (by simp) = #v[] := rfl +@[simp] theorem pmap_empty {P : α → Prop} {f : ∀ a, P a → β} : pmap f #v[] (by simp) = #v[] := rfl -@[simp] theorem pmap_push {P : α → Prop} (f : ∀ a, P a → β) (a : α) (xs : Vector α n) (h : ∀ b ∈ xs.push a, P b) : +@[simp] theorem pmap_push {P : α → Prop} {f : ∀ a, P a → β} {a : α} {xs : Vector α n} {h : ∀ b ∈ xs.push a, P b} : pmap f (xs.push a) h = (pmap f xs (fun a m => by simp at h; exact h a (.inl m))).push (f a (h a (by simp))) := by simp [pmap] @@ -101,7 +101,7 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep @[simp] theorem attachWith_empty {P : α → Prop} (H : ∀ x ∈ #v[], P x) : (#v[] : Vector α 0).attachWith P H = #v[] := rfl @[simp] -theorem pmap_eq_map (p : α → Prop) (f : α → β) (xs : Vector α n) (H) : +theorem pmap_eq_map {p : α → Prop} {f : α → β} {xs : Vector α n} (H) : @pmap _ _ _ p (fun a _ => f a) xs H = map f xs := by cases xs; simp @@ -112,13 +112,13 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a, apply Array.pmap_congr_left simpa using h -theorem map_pmap {p : α → Prop} (g : β → γ) (f : ∀ a, p a → β) (xs : Vector α n) (H) : +theorem map_pmap {p : α → Prop} {g : β → γ} {f : ∀ a, p a → β} {xs : Vector α n} (H) : map g (pmap f xs H) = pmap (fun a h => g (f a h)) xs H := by rcases xs with ⟨xs, rfl⟩ simp [Array.map_pmap] -theorem pmap_map {p : β → Prop} (g : ∀ b, p b → γ) (f : α → β) (xs : Vector α n) (H) : - pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem _ h) := by +theorem pmap_map {p : β → Prop} {g : ∀ b, p b → γ} {f : α → β} {xs : Vector α n} (H) : + pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem h) := by rcases xs with ⟨xs, rfl⟩ simp [Array.pmap_map] @@ -144,7 +144,7 @@ theorem attachWith_congr {xs ys : Vector α n} (w : xs = ys) {P : α → Prop} { rcases xs with ⟨xs, rfl⟩ simp -theorem pmap_eq_map_attach {p : α → Prop} (f : ∀ a, p a → β) (xs : Vector α n) (H) : +theorem pmap_eq_map_attach {p : α → Prop} {f : ∀ a, p a → β} {xs : Vector α n} (H) : pmap f xs H = xs.attach.map fun x => f x.1 (H _ x.2) := by rcases xs with ⟨xs, rfl⟩ simp only [pmap_mk, Array.pmap_eq_map_attach, attach_mk, map_mk, eq_mk] @@ -152,7 +152,7 @@ theorem pmap_eq_map_attach {p : α → Prop} (f : ∀ a, p a → β) (xs : Vecto ext i hi₁ hi₂ <;> simp @[simp] -theorem pmap_eq_attachWith {p q : α → Prop} (f : ∀ a, p a → q a) (xs : Vector α n) (H) : +theorem pmap_eq_attachWith {p q : α → Prop} {f : ∀ a, p a → q a} {xs : Vector α n} (H) : pmap (fun a h => ⟨a, f a h⟩) xs H = xs.attachWith q (fun x h => f x (H x h)) := by rcases xs with ⟨xs, rfl⟩ simp @@ -165,11 +165,12 @@ theorem attach_map_val (xs : Vector α n) (f : α → β) : @[deprecated attach_map_val (since := "2025-02-17")] abbrev attach_map_coe := @attach_map_val +-- The argument `xs : Vector α n` is explicit to allow rewriting from right to left. theorem attach_map_subtype_val (xs : Vector α n) : xs.attach.map Subtype.val = xs := by rcases xs with ⟨xs, rfl⟩ simp -theorem attachWith_map_val {p : α → Prop} (f : α → β) (xs : Vector α n) (H : ∀ a ∈ xs, p a) : +theorem attachWith_map_val {p : α → Prop} {f : α → β} {xs : Vector α n} (H : ∀ a ∈ xs, p a) : ((xs.attachWith p H).map fun (i : { i // p i}) => f i) = xs.map f := by rcases xs with ⟨xs, rfl⟩ simp @@ -177,7 +178,7 @@ theorem attachWith_map_val {p : α → Prop} (f : α → β) (xs : Vector α n) @[deprecated attachWith_map_val (since := "2025-02-17")] abbrev attachWith_map_coe := @attachWith_map_val -theorem attachWith_map_subtype_val {p : α → Prop} (xs : Vector α n) (H : ∀ a ∈ xs, p a) : +theorem attachWith_map_subtype_val {p : α → Prop} {xs : Vector α n} (H : ∀ a ∈ xs, p a) : (xs.attachWith p H).map Subtype.val = xs := by rcases xs with ⟨xs, rfl⟩ simp @@ -190,7 +191,7 @@ theorem mem_attach (xs : Vector α n) : ∀ x, x ∈ xs.attach exact m @[simp] -theorem mem_attachWith (xs : Vector α n) {q : α → Prop} (H) (x : {x // q x}) : +theorem mem_attachWith {xs : Vector α n} {q : α → Prop} (H) (x : {x // q x}) : x ∈ xs.attachWith q H ↔ x.1 ∈ xs := by rcases xs with ⟨xs, rfl⟩ simp @@ -211,11 +212,12 @@ theorem pmap_eq_self {xs : Vector α n} {p : α → Prop} {hp : ∀ (a : α), a simp [Array.pmap_eq_self] @[simp] -theorem getElem?_pmap {p : α → Prop} (f : ∀ a, p a → β) {xs : Vector α n} (h : ∀ a ∈ xs, p a) (i : Nat) : +theorem getElem?_pmap {p : α → Prop} {f : ∀ a, p a → β} {xs : Vector α n} (h : ∀ a ∈ xs, p a) (i : Nat) : (pmap f xs h)[i]? = Option.pmap f xs[i]? fun x H => h x (mem_of_getElem? H) := by rcases xs with ⟨xs, rfl⟩ simp +-- The argument `f` is explicit to allow rewriting from right to left. @[simp] theorem getElem_pmap {p : α → Prop} (f : ∀ a, p a → β) {xs : Vector α n} (h : ∀ a ∈ xs, p a) {i : Nat} (hn : i < n) : @@ -244,26 +246,26 @@ theorem getElem_attach {xs : Vector α n} {i : Nat} (h : i < n) : xs.attach[i] = ⟨xs[i]'(by simpa using h), getElem_mem (by simpa using h)⟩ := getElem_attachWith h -@[simp] theorem pmap_attach (xs : Vector α n) {p : {x // x ∈ xs} → Prop} (f : ∀ a, p a → β) (H) : +@[simp] theorem pmap_attach {xs : Vector α n} {p : {x // x ∈ xs} → Prop} {f : ∀ a, p a → β} (H) : pmap f xs.attach H = xs.pmap (P := fun a => ∃ h : a ∈ xs, p ⟨a, h⟩) (fun a h => f ⟨a, h.1⟩ h.2) (fun a h => ⟨h, H ⟨a, h⟩ (by simp)⟩) := by rcases xs with ⟨xs, rfl⟩ ext <;> simp -@[simp] theorem pmap_attachWith (xs : Vector α n) {p : {x // q x} → Prop} (f : ∀ a, p a → β) (H₁ H₂) : +@[simp] theorem pmap_attachWith {xs : Vector α n} {p : {x // q x} → Prop} {f : ∀ a, p a → β} (H₁ H₂) : pmap f (xs.attachWith q H₁) H₂ = xs.pmap (P := fun a => ∃ h : q a, p ⟨a, h⟩) (fun a h => f ⟨a, h.1⟩ h.2) (fun a h => ⟨H₁ _ h, H₂ ⟨a, H₁ _ h⟩ (by simpa)⟩) := by ext <;> simp -theorem foldl_pmap (xs : Vector α n) {P : α → Prop} (f : (a : α) → P a → β) - (H : ∀ (a : α), a ∈ xs → P a) (g : γ → β → γ) (x : γ) : +theorem foldl_pmap {xs : Vector α n} {P : α → Prop} {f : (a : α) → P a → β} + (H : ∀ (a : α), a ∈ xs → P a) (g : γ → β → γ) (x : γ) : (xs.pmap f H).foldl g x = xs.attach.foldl (fun acc a => g acc (f a.1 (H _ a.2))) x := by rw [pmap_eq_map_attach, foldl_map] -theorem foldr_pmap (xs : Vector α n) {P : α → Prop} (f : (a : α) → P a → β) - (H : ∀ (a : α), a ∈ xs → P a) (g : β → γ → γ) (x : γ) : +theorem foldr_pmap {xs : Vector α n} {P : α → Prop} {f : (a : α) → P a → β} + (H : ∀ (a : α), a ∈ xs → P a) (g : β → γ → γ) (x : γ) : (xs.pmap f H).foldr g x = xs.attach.foldr (fun a acc => g (f a.1 (H _ a.2)) acc) x := by rw [pmap_eq_map_attach, foldr_map] @@ -277,7 +279,7 @@ Unfortunately this can't be applied by `simp` because of the higher order unific and even when rewriting we need to specify the function explicitly. See however `foldl_subtype` below. -/ -theorem foldl_attach (xs : Vector α n) (f : β → α → β) (b : β) : +theorem foldl_attach {xs : Vector α n} {f : β → α → β} {b : β} : xs.attach.foldl (fun acc t => f acc t.1) b = xs.foldl f b := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldl_attach] @@ -292,37 +294,37 @@ Unfortunately this can't be applied by `simp` because of the higher order unific and even when rewriting we need to specify the function explicitly. See however `foldr_subtype` below. -/ -theorem foldr_attach (xs : Vector α n) (f : α → β → β) (b : β) : +theorem foldr_attach {xs : Vector α n} {f : α → β → β} {b : β} : xs.attach.foldr (fun t acc => f t.1 acc) b = xs.foldr f b := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldr_attach] -theorem attach_map {xs : Vector α n} (f : α → β) : - (xs.map f).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨f x, mem_map_of_mem f h⟩) := by +theorem attach_map {xs : Vector α n} {f : α → β} : + (xs.map f).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨f x, mem_map_of_mem h⟩) := by cases xs ext <;> simp -theorem attachWith_map {xs : Vector α n} (f : α → β) {P : β → Prop} {H : ∀ (b : β), b ∈ xs.map f → P b} : - (xs.map f).attachWith P H = (xs.attachWith (P ∘ f) (fun _ h => H _ (mem_map_of_mem f h))).map +theorem attachWith_map {xs : Vector α n} {f : α → β} {P : β → Prop} (H : ∀ (b : β), b ∈ xs.map f → P b) : + (xs.map f).attachWith P H = (xs.attachWith (P ∘ f) (fun _ h => H _ (mem_map_of_mem h))).map fun ⟨x, h⟩ => ⟨f x, h⟩ := by rcases xs with ⟨xs, rfl⟩ simp [Array.attachWith_map] @[simp] theorem map_attachWith {xs : Vector α n} {P : α → Prop} {H : ∀ (a : α), a ∈ xs → P a} - (f : { x // P x } → β) : + {f : { x // P x } → β} : (xs.attachWith P H).map f = xs.attach.map fun ⟨x, h⟩ => f ⟨x, H _ h⟩ := by rcases xs with ⟨xs, rfl⟩ simp [Array.map_attachWith] theorem map_attachWith_eq_pmap {xs : Vector α n} {P : α → Prop} {H : ∀ (a : α), a ∈ xs → P a} - (f : { x // P x } → β) : + {f : { x // P x } → β} : (xs.attachWith P H).map f = xs.pmap (fun a (h : a ∈ xs ∧ P a) => f ⟨a, H _ h.1⟩) (fun a h => ⟨h, H a h⟩) := by rcases xs with ⟨xs, rfl⟩ ext <;> simp /-- See also `pmap_eq_map_attach` for writing `pmap` in terms of `map` and `attach`. -/ -theorem map_attach_eq_pmap {xs : Vector α n} (f : { x // x ∈ xs } → β) : +theorem map_attach_eq_pmap {xs : Vector α n} {f : { x // x ∈ xs } → β} : xs.attach.map f = xs.pmap (fun a h => f ⟨a, h⟩) (fun _ => id) := by rcases xs with ⟨xs, rfl⟩ ext <;> simp @@ -330,14 +332,14 @@ theorem map_attach_eq_pmap {xs : Vector α n} (f : { x // x ∈ xs } → β) : @[deprecated map_attach_eq_pmap (since := "2025-02-09")] abbrev map_attach := @map_attach_eq_pmap -theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f : ∀ b, q b → γ) (xs : Vector α n) (H₁ H₂) : +theorem pmap_pmap {p : α → Prop} {q : β → Prop} {g : ∀ a, p a → β} {f : ∀ b, q b → γ} {xs : Vector α n} (H₁ H₂) : pmap f (pmap g xs H₁) H₂ = pmap (α := { x // x ∈ xs }) (fun a h => f (g a h) (H₂ (g a h) (mem_pmap_of_mem a.2))) xs.attach (fun a _ => H₁ a a.2) := by rcases xs with ⟨xs, rfl⟩ ext <;> simp -@[simp] theorem pmap_append {p : ι → Prop} (f : ∀ a : ι, p a → α) (xs : Vector ι n) (ys : Vector ι m) +@[simp] theorem pmap_append {p : ι → Prop} {f : ∀ a : ι, p a → α} {xs : Vector ι n} {ys : Vector ι m} (h : ∀ a ∈ xs ++ ys, p a) : (xs ++ ys).pmap f h = (xs.pmap f fun a ha => h a (mem_append_left ys ha)) ++ @@ -346,13 +348,13 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f cases ys simp -theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (xs : Vector α n) (ys : Vector α m) +theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs : Vector α n} {ys : Vector α m} (h₁ : ∀ a ∈ xs, p a) (h₂ : ∀ a ∈ ys, p a) : ((xs ++ ys).pmap f fun a ha => (mem_append.1 ha).elim (h₁ a) (h₂ a)) = xs.pmap f h₁ ++ ys.pmap f h₂ := - pmap_append f xs ys _ + pmap_append _ -@[simp] theorem attach_append (xs : Vector α n) (ys : Vector α m) : +@[simp] theorem attach_append {xs : Vector α n} {ys : Vector α m} : (xs ++ ys).attach = xs.attach.map (fun ⟨x, h⟩ => (⟨x, mem_append_left ys h⟩ : { x // x ∈ xs ++ ys })) ++ ys.attach.map (fun ⟨y, h⟩ => (⟨y, mem_append_right xs h⟩ : { y // y ∈ xs ++ ys })) := by rcases xs with ⟨xs, rfl⟩ @@ -365,12 +367,12 @@ theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (xs : Vector ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by simp [attachWith, attach_append, map_pmap, pmap_append] -@[simp] theorem pmap_reverse {P : α → Prop} (f : (a : α) → P a → β) (xs : Vector α n) +@[simp] theorem pmap_reverse {P : α → Prop} {f : (a : α) → P a → β} {xs : Vector α n} (H : ∀ (a : α), a ∈ xs.reverse → P a) : xs.reverse.pmap f H = (xs.pmap f (fun a h => H a (by simpa using h))).reverse := by induction xs <;> simp_all -theorem reverse_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : Vector α n) +theorem reverse_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Vector α n} (H : ∀ (a : α), a ∈ xs → P a) : (xs.pmap f H).reverse = xs.reverse.pmap f (fun a h => H a (by simpa using h)) := by rw [pmap_reverse] @@ -388,18 +390,18 @@ theorem reverse_attachWith {P : α → Prop} {xs : Vector α n} cases xs simp -@[simp] theorem attach_reverse (xs : Vector α n) : +@[simp] theorem attach_reverse {xs : Vector α n} : xs.reverse.attach = xs.attach.reverse.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by cases xs rw [attach_congr (reverse_mk ..)] simp [Array.map_attachWith] -theorem reverse_attach (xs : Vector α n) : +theorem reverse_attach {xs : Vector α n} : xs.attach.reverse = xs.reverse.attach.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by cases xs simp [Array.map_attach_eq_pmap] -@[simp] theorem back?_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : Vector α n) +@[simp] theorem back?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Vector α n} (H : ∀ (a : α), a ∈ xs → P a) : (xs.pmap f H).back? = xs.attach.back?.map fun ⟨a, m⟩ => f a (H a m) := by cases xs @@ -418,30 +420,30 @@ theorem back?_attach {xs : Vector α n} : simp @[simp] -theorem countP_attach (xs : Vector α n) (p : α → Bool) : +theorem countP_attach {xs : Vector α n} {p : α → Bool} : xs.attach.countP (fun a : {x // x ∈ xs} => p a) = xs.countP p := by cases xs simp [Function.comp_def] @[simp] -theorem countP_attachWith {p : α → Prop} (xs : Vector α n) (H : ∀ a ∈ xs, p a) (q : α → Bool) : +theorem countP_attachWith {p : α → Prop} {q : α → Bool} {xs : Vector α n} {H : ∀ a ∈ xs, p a} : (xs.attachWith p H).countP (fun a : {x // p x} => q a) = xs.countP q := by cases xs simp @[simp] -theorem count_attach [DecidableEq α] (xs : Vector α n) (a : {x // x ∈ xs}) : +theorem count_attach [DecidableEq α] {xs : Vector α n} {a : {x // x ∈ xs}} : xs.attach.count a = xs.count ↑a := by rcases xs with ⟨xs, rfl⟩ simp @[simp] -theorem count_attachWith [DecidableEq α] {p : α → Prop} (xs : Vector α n) (H : ∀ a ∈ xs, p a) (a : {x // p x}) : +theorem count_attachWith [DecidableEq α] {p : α → Prop} {xs : Vector α n} (H : ∀ a ∈ xs, p a) {a : {x // p x}} : (xs.attachWith p H).count a = xs.count ↑a := by cases xs simp -@[simp] theorem countP_pmap {p : α → Prop} (g : ∀ a, p a → β) (f : β → Bool) (xs : Vector α n) (H₁) : +@[simp] theorem countP_pmap {p : α → Prop} {g : ∀ a, p a → β} {f : β → Bool} {xs : Vector α n} (H₁) : (xs.pmap g H₁).countP f = xs.attach.countP (fun ⟨a, m⟩ => f (g a (H₁ a m))) := by rcases xs with ⟨xs, rfl⟩ diff --git a/src/Init/Data/Vector/Count.lean b/src/Init/Data/Vector/Count.lean index 583f14c97a..f6ff44ead0 100644 --- a/src/Init/Data/Vector/Count.lean +++ b/src/Init/Data/Vector/Count.lean @@ -21,26 +21,26 @@ open Nat /-! ### countP -/ section countP -variable (p q : α → Bool) +variable {p q : α → Bool} @[simp] theorem countP_empty : countP p #v[] = 0 := rfl -@[simp] theorem countP_push_of_pos (xs : Vector α n) (pa : p a) : countP p (xs.push a) = countP p xs + 1 := by +@[simp] theorem countP_push_of_pos {xs : Vector α n} (pa : p a) : countP p (xs.push a) = countP p xs + 1 := by rcases xs with ⟨xs, rfl⟩ simp_all -@[simp] theorem countP_push_of_neg (xs : Vector α n) (pa : ¬p a) : countP p (xs.push a) = countP p xs := by +@[simp] theorem countP_push_of_neg {xs : Vector α n} (pa : ¬p a) : countP p (xs.push a) = countP p xs := by rcases xs with ⟨xs, rfl⟩ simp_all -theorem countP_push (a : α) (xs : Vector α n) : countP p (xs.push a) = countP p xs + if p a then 1 else 0 := by +theorem countP_push {a : α} {xs : Vector α n} : countP p (xs.push a) = countP p xs + if p a then 1 else 0 := by rcases xs with ⟨xs, rfl⟩ simp [Array.countP_push] -@[simp] theorem countP_singleton (a : α) : countP p #v[a] = if p a then 1 else 0 := by +@[simp] theorem countP_singleton {a : α} : countP p #v[a] = if p a then 1 else 0 := by simp [countP_push] -theorem size_eq_countP_add_countP (xs : Vector α n) : n = countP p xs + countP (fun a => ¬p a) xs := by +theorem size_eq_countP_add_countP {xs : Vector α n} : n = countP p xs + countP (fun a => ¬p a) xs := by rcases xs with ⟨xs, rfl⟩ simp [List.length_eq_countP_add_countP (p := p)] @@ -48,7 +48,7 @@ theorem countP_le_size {xs : Vector α n} : countP p xs ≤ n := by rcases xs with ⟨xs, rfl⟩ simp [Array.countP_le_size (p := p)] -@[simp] theorem countP_append (xs : Vector α n) (ys : Vector α m) : countP p (xs ++ ys) = countP p xs + countP p ys := by +@[simp] theorem countP_append {xs : Vector α n} {ys : Vector α m} : countP p (xs ++ ys) = countP p xs + countP p ys := by cases xs cases ys simp @@ -72,20 +72,19 @@ theorem countP_le_size {xs : Vector α n} : countP p xs ≤ n := by rcases xs with ⟨xs, rfl⟩ simp -theorem countP_replicate (p : α → Bool) (a : α) (n : Nat) : - countP p (replicate n a) = if p a then n else 0 := by +theorem countP_replicate {a : α} {n : Nat} : countP p (replicate n a) = if p a then n else 0 := by simp only [replicate_eq_mk_replicate, countP_cast, countP_mk] simp [Array.countP_replicate] @[deprecated countP_replicate (since := "2025-03-18")] abbrev countP_mkVector := @countP_replicate -theorem boole_getElem_le_countP (p : α → Bool) (xs : Vector α n) (i : Nat) (h : i < n) : +theorem boole_getElem_le_countP {p : α → Bool} {xs : Vector α n} (h : i < n) : (if p xs[i] then 1 else 0) ≤ xs.countP p := by rcases xs with ⟨xs, rfl⟩ simp [Array.boole_getElem_le_countP] -theorem countP_set (p : α → Bool) (xs : Vector α n) (i : Nat) (a : α) (h : i < n) : +theorem countP_set {p : α → Bool} {xs : Vector α n} {a : α} (h : i < n) : (xs.set i a).countP p = xs.countP p - (if p xs[i] then 1 else 0) + (if p a then 1 else 0) := by rcases xs with ⟨xs, rfl⟩ simp [Array.countP_set, h] @@ -99,28 +98,25 @@ theorem countP_set (p : α → Bool) (xs : Vector α n) (i : Nat) (a : α) (h : funext xs simp -@[simp] theorem countP_map (p : β → Bool) (f : α → β) (xs : Vector α n) : +@[simp] theorem countP_map {p : β → Bool} {f : α → β} {xs : Vector α n} : countP p (map f xs) = countP (p ∘ f) xs := by rcases xs with ⟨xs, rfl⟩ simp -set_option linter.listVariables false in -- This can probably be removed later. -@[simp] theorem countP_flatten (xss : Vector (Vector α m) n) : +@[simp] theorem countP_flatten {xss : Vector (Vector α m) n} : countP p xss.flatten = (xss.map (countP p)).sum := by rcases xss with ⟨xss, rfl⟩ simp [Function.comp_def] -theorem countP_flatMap (p : β → Bool) (xs : Vector α n) (f : α → Vector β m) : +theorem countP_flatMap {p : β → Bool} {xs : Vector α n} {f : α → Vector β m} : countP p (xs.flatMap f) = (map (countP p ∘ f) xs).sum := by rcases xs with ⟨xs, rfl⟩ simp [Array.countP_flatMap, Function.comp_def] -@[simp] theorem countP_reverse (xs : Vector α n) : countP p xs.reverse = countP p xs := by +@[simp] theorem countP_reverse {xs : Vector α n} : countP p xs.reverse = countP p xs := by rcases xs with ⟨xs, rfl⟩ simp -variable {p q} - theorem countP_mono_left (h : ∀ x ∈ xs, p x → q x) : countP p xs ≤ countP q xs := by rcases xs with ⟨xs, rfl⟩ simpa using Array.countP_mono_left (by simpa using h) @@ -137,67 +133,66 @@ section count variable [BEq α] -@[simp] theorem count_empty (a : α) : count a #v[] = 0 := rfl +@[simp] theorem count_empty {a : α} : count a #v[] = 0 := rfl -theorem count_push (a b : α) (xs : Vector α n) : +theorem count_push {a b : α} {xs : Vector α n} : count a (xs.push b) = count a xs + if b == a then 1 else 0 := by rcases xs with ⟨xs, rfl⟩ simp [Array.count_push] -theorem count_eq_countP (a : α) (xs : Vector α n) : count a xs = countP (· == a) xs := rfl +theorem count_eq_countP {a : α} {xs : Vector α n} : count a xs = countP (· == a) xs := rfl theorem count_eq_countP' {a : α} : count (n := n) a = countP (· == a) := by funext xs apply count_eq_countP -theorem count_le_size (a : α) (xs : Vector α n) : count a xs ≤ n := countP_le_size _ +theorem count_le_size {a : α} {xs : Vector α n} : count a xs ≤ n := countP_le_size -theorem count_le_count_push (a b : α) (xs : Vector α n) : count a xs ≤ count a (xs.push b) := by +theorem count_le_count_push {a b : α} {xs : Vector α n} : count a xs ≤ count a (xs.push b) := by rcases xs with ⟨xs, rfl⟩ simp [Array.count_push] -@[simp] theorem count_singleton (a b : α) : count a #v[b] = if b == a then 1 else 0 := by +@[simp] theorem count_singleton {a b : α} : count a #v[b] = if b == a then 1 else 0 := by simp [count_eq_countP] -@[simp] theorem count_append (a : α) (xs : Vector α n) (ys : Vector α m) : +@[simp] theorem count_append {a : α} {xs : Vector α n} {ys : Vector α m} : count a (xs ++ ys) = count a xs + count a ys := countP_append .. -set_option linter.listVariables false in -- This can probably be removed later. -@[simp] theorem count_flatten (a : α) (xss : Vector (Vector α m) n) : +@[simp] theorem count_flatten {a : α} {xss : Vector (Vector α m) n} : count a xss.flatten = (xss.map (count a)).sum := by rcases xss with ⟨xss, rfl⟩ simp [Array.count_flatten, Function.comp_def] -@[simp] theorem count_reverse (a : α) (xs : Vector α n) : count a xs.reverse = count a xs := by +@[simp] theorem count_reverse {a : α} {xs : Vector α n} : count a xs.reverse = count a xs := by rcases xs with ⟨xs, rfl⟩ simp -theorem boole_getElem_le_count (a : α) (xs : Vector α n) (i : Nat) (h : i < n) : +theorem boole_getElem_le_count {a : α} {xs : Vector α n} (h : i < n) : (if xs[i] == a then 1 else 0) ≤ xs.count a := by rcases xs with ⟨xs, rfl⟩ simp [Array.boole_getElem_le_count, h] -theorem count_set (a b : α) (xs : Vector α n) (i : Nat) (h : i < n) : +theorem count_set {a b : α} {xs : Vector α n} (h : i < n) : (xs.set i a).count b = xs.count b - (if xs[i] == b then 1 else 0) + (if a == b then 1 else 0) := by rcases xs with ⟨xs, rfl⟩ simp [Array.count_set, h] -@[simp] theorem count_cast (xs : Vector α n) : (xs.cast h).count a = xs.count a := by +@[simp] theorem count_cast {xs : Vector α n} : (xs.cast h).count a = xs.count a := by rcases xs with ⟨xs, rfl⟩ simp variable [LawfulBEq α] -@[simp] theorem count_push_self (a : α) (xs : Vector α n) : count a (xs.push a) = count a xs + 1 := by +@[simp] theorem count_push_self {a : α} {xs : Vector α n} : count a (xs.push a) = count a xs + 1 := by rcases xs with ⟨xs, rfl⟩ simp [Array.count_push_self] -@[simp] theorem count_push_of_ne (h : b ≠ a) (xs : Vector α n) : count a (xs.push b) = count a xs := by +@[simp] theorem count_push_of_ne {xs : Vector α n} (h : b ≠ a) : count a (xs.push b) = count a xs := by rcases xs with ⟨xs, rfl⟩ simp [Array.count_push_of_ne, h] -theorem count_singleton_self (a : α) : count a #v[a] = 1 := by simp +theorem count_singleton_self {a : α} : count a #v[a] = 1 := by simp @[simp] theorem count_pos_iff {a : α} {xs : Vector α n} : 0 < count a xs ↔ a ∈ xs := by @@ -220,26 +215,26 @@ theorem count_eq_size {xs : Vector α n} : count a xs = xs.size ↔ ∀ b ∈ xs rcases xs with ⟨xs, rfl⟩ simp [Array.count_eq_size] -@[simp] theorem count_replicate_self (a : α) (n : Nat) : count a (replicate n a) = n := by +@[simp] theorem count_replicate_self {a : α} {n : Nat} : count a (replicate n a) = n := by simp only [replicate_eq_mk_replicate, count_cast, count_mk] simp @[deprecated count_replicate_self (since := "2025-03-18")] abbrev count_mkVector_self := @count_replicate_self -theorem count_replicate (a b : α) (n : Nat) : count a (replicate n b) = if b == a then n else 0 := by +theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by simp only [replicate_eq_mk_replicate, count_cast, count_mk] simp [Array.count_replicate] @[deprecated count_replicate (since := "2025-03-18")] abbrev count_mkVector := @count_replicate -theorem count_le_count_map [DecidableEq β] (xs : Vector α n) (f : α → β) (x : α) : +theorem count_le_count_map [DecidableEq β] {xs : Vector α n} {f : α → β} {x : α} : count x xs ≤ count (f x) (map f xs) := by rcases xs with ⟨xs, rfl⟩ simp [Array.count_le_count_map] -theorem count_flatMap {α} [BEq β] (xs : Vector α n) (f : α → Vector β m) (x : β) : +theorem count_flatMap {α} [BEq β] {xs : Vector α n} {f : α → Vector β m} {x : β} : count x (xs.flatMap f) = (map (count x ∘ f) xs).sum := by rcases xs with ⟨xs, rfl⟩ simp [Array.count_flatMap, Function.comp_def] diff --git a/src/Init/Data/Vector/Erase.lean b/src/Init/Data/Vector/Erase.lean index 834b7e6fca..7a6cf3ed61 100644 --- a/src/Init/Data/Vector/Erase.lean +++ b/src/Init/Data/Vector/Erase.lean @@ -20,29 +20,29 @@ open Nat /-! ### eraseIdx -/ -theorem eraseIdx_eq_take_drop_succ (xs : Vector α n) (i : Nat) (h) : +theorem eraseIdx_eq_take_drop_succ {xs : Vector α n} {i : Nat} (h) : xs.eraseIdx i = (xs.take i ++ xs.drop (i + 1)).cast (by omega) := by rcases xs with ⟨xs, rfl⟩ simp [Array.eraseIdx_eq_take_drop_succ, *] -theorem getElem?_eraseIdx (xs : Vector α n) (i : Nat) (h : i < n) (j : Nat) : +theorem getElem?_eraseIdx {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} : (xs.eraseIdx i)[j]? = if j < i then xs[j]? else xs[j + 1]? := by rcases xs with ⟨xs, rfl⟩ simp [Array.getElem?_eraseIdx] -theorem getElem?_eraseIdx_of_lt (xs : Vector α n) (i : Nat) (h : i < n) (j : Nat) (h' : j < i) : +theorem getElem?_eraseIdx_of_lt {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} (h' : j < i) : (xs.eraseIdx i)[j]? = xs[j]? := by rw [getElem?_eraseIdx] simp [h'] -theorem getElem?_eraseIdx_of_ge (xs : Vector α n) (i : Nat) (h : i < n) (j : Nat) (h' : i ≤ j) : +theorem getElem?_eraseIdx_of_ge {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} (h' : i ≤ j) : (xs.eraseIdx i)[j]? = xs[j + 1]? := by rw [getElem?_eraseIdx] simp only [dite_eq_ite, ite_eq_right_iff] intro h' omega -theorem getElem_eraseIdx (xs : Vector α n) (i : Nat) (h : i < n) (j : Nat) (h' : j < n - 1) : +theorem getElem_eraseIdx {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} (h' : j < n - 1) : (xs.eraseIdx i)[j] = if h'' : j < i then xs[j] else xs[j + 1] := by apply Option.some.inj rw [← getElem?_eq_getElem, getElem?_eraseIdx] @@ -85,12 +85,12 @@ theorem mem_eraseIdx_iff_getElem? {x : α} {xs : Vector α n} {k} {h} : x ∈ xs rcases xs with ⟨xs⟩ simp [Array.mem_eraseIdx_iff_getElem?, *] -theorem getElem_eraseIdx_of_lt (xs : Vector α n) (i : Nat) (w : i < n) (j : Nat) (h : j < n - 1) (h' : j < i) : +theorem getElem_eraseIdx_of_lt {xs : Vector α n} {i : Nat} (w : i < n) {j : Nat} (h : j < n - 1) (h' : j < i) : (xs.eraseIdx i)[j] = xs[j] := by rcases xs with ⟨xs⟩ simp [Array.getElem_eraseIdx_of_lt, *] -theorem getElem_eraseIdx_of_ge (xs : Vector α n) (i : Nat) (w : i < n) (j : Nat) (h : j < n - 1) (h' : i ≤ j) : +theorem getElem_eraseIdx_of_ge {xs : Vector α n} {i : Nat} (w : i < n) {j : Nat} (h : j < n - 1) (h' : i ≤ j) : (xs.eraseIdx i)[j] = xs[j + 1] := by rcases xs with ⟨xs⟩ simp [Array.getElem_eraseIdx_of_ge, *] diff --git a/src/Init/Data/Vector/FinRange.lean b/src/Init/Data/Vector/FinRange.lean index bad5a55652..af6fc0c740 100644 --- a/src/Init/Data/Vector/FinRange.lean +++ b/src/Init/Data/Vector/FinRange.lean @@ -15,20 +15,20 @@ namespace Vector /-- `finRange n` is the vector of all elements of `Fin n` in order. -/ protected def finRange (n : Nat) : Vector (Fin n) n := ofFn fun i => i -@[simp] theorem getElem_finRange (i : Nat) (h : i < n) : +@[simp] theorem getElem_finRange {i : Nat} (h : i < n) : (Vector.finRange n)[i] = ⟨i, h⟩ := by simp [Vector.finRange] @[simp] theorem finRange_zero : Vector.finRange 0 = #v[] := by simp [Vector.finRange] -theorem finRange_succ (n) : Vector.finRange (n+1) = +theorem finRange_succ {n} : Vector.finRange (n+1) = (#v[(0 : Fin (n+1))] ++ (Vector.finRange n).map Fin.succ).cast (by omega) := by ext i h · simp [getElem_append] split <;> · simp; omega -theorem finRange_succ_last (n) : +theorem finRange_succ_last {n} : Vector.finRange (n+1) = (Vector.finRange n).map Fin.castSucc ++ #v[Fin.last n] := by ext i h · simp [getElem_push] @@ -37,7 +37,7 @@ theorem finRange_succ_last (n) : · simp_all omega -theorem finRange_reverse (n) : (Vector.finRange n).reverse = (Vector.finRange n).map Fin.rev := by +theorem finRange_reverse {n} : (Vector.finRange n).reverse = (Vector.finRange n).map Fin.rev := by ext i h simp omega diff --git a/src/Init/Data/Vector/Find.lean b/src/Init/Data/Vector/Find.lean index 8594b0124a..f1d89c4196 100644 --- a/src/Init/Data/Vector/Find.lean +++ b/src/Init/Data/Vector/Find.lean @@ -24,11 +24,11 @@ open Nat /-! ### findSome? -/ -@[simp] theorem findSomeRev?_push_of_isSome (xs : Vector α n) (h : (f a).isSome) : (xs.push a).findSomeRev? f = f a := by +@[simp] theorem findSomeRev?_push_of_isSome {xs : Vector α n} {h : (f a).isSome} : (xs.push a).findSomeRev? f = f a := by rcases xs with ⟨xs, rfl⟩ simp only [push_mk, findSomeRev?_mk, Array.findSomeRev?_push_of_isSome, h] -@[simp] theorem findSomeRev?_push_of_isNone (xs : Vector α n) (h : (f a).isNone) : (xs.push a).findSomeRev? f = xs.findSomeRev? f := by +@[simp] theorem findSomeRev?_push_of_isNone {xs : Vector α n} {h : (f a).isNone} : (xs.push a).findSomeRev? f = xs.findSomeRev? f := by rcases xs with ⟨xs, rfl⟩ simp only [push_mk, findSomeRev?_mk, Array.findSomeRev?_push_of_isNone, h] @@ -60,25 +60,25 @@ theorem findSome?_eq_some_iff {f : α → Option β} {xs : Vector α n} {b : β} · rintro ⟨k₁, k₂, h, ys, a, zs, w, h₁, h₂⟩ exact ⟨ys.toArray, a, zs.toArray, by simp [w], h₁, by simpa using h₂⟩ -@[simp] theorem findSome?_guard (xs : Vector α n) : findSome? (Option.guard fun x => p x) xs = find? p xs := by +@[simp] theorem findSome?_guard {xs : Vector α n} : findSome? (Option.guard fun x => p x) xs = find? p xs := by rcases xs with ⟨xs, rfl⟩ simp -theorem find?_eq_findSome?_guard (xs : Vector α n) : find? p xs = findSome? (Option.guard fun x => p x) xs := - (findSome?_guard xs).symm +theorem find?_eq_findSome?_guard {xs : Vector α n} : find? p xs = findSome? (Option.guard fun x => p x) xs := + findSome?_guard.symm -@[simp] theorem map_findSome? (f : α → Option β) (g : β → γ) (xs : Vector α n) : +@[simp] theorem map_findSome? {f : α → Option β} {g : β → γ} {xs : Vector α n} : (xs.findSome? f).map g = xs.findSome? (Option.map g ∘ f) := by cases xs; simp -theorem findSome?_map (f : β → γ) (xs : Vector β n) : findSome? p (xs.map f) = xs.findSome? (p ∘ f) := by +theorem findSome?_map {f : β → γ} {xs : Vector β n} : findSome? p (xs.map f) = xs.findSome? (p ∘ f) := by rcases xs with ⟨xs, rfl⟩ simp [Array.findSome?_map] theorem findSome?_append {xs : Vector α n₁} {ys : Vector α n₂} : (xs ++ ys).findSome? f = (xs.findSome? f).or (ys.findSome? f) := by cases xs; cases ys; simp [Array.findSome?_append] -theorem getElem?_zero_flatten (xss : Vector (Vector α m) n) : +theorem getElem?_zero_flatten {xss : Vector (Vector α m) n} : (flatten xss)[0]? = xss.findSome? fun xs => xs[0]? := by cases xss using vector₂_induction simp [Array.getElem?_zero_flatten, Array.findSome?_map, Function.comp_def] @@ -96,7 +96,7 @@ theorem getElem_zero_flatten.proof {xss : Vector (Vector α m) n} (h : 0 < n * m theorem getElem_zero_flatten {xss : Vector (Vector α m) n} (h : 0 < n * m) : (flatten xss)[0] = (xss.findSome? fun xs => xs[0]?).get (getElem_zero_flatten.proof h) := by - have t := getElem?_zero_flatten xss + have t := getElem?_zero_flatten (xss := xss) simp [getElem?_eq_getElem, h] at t simp [← t] @@ -130,15 +130,15 @@ abbrev findSome?_mkVector_of_isNone := @findSome?_replicate_of_isNone /-! ### find? -/ -@[simp] theorem find?_singleton (a : α) (p : α → Bool) : +@[simp] theorem find?_singleton {a : α} {p : α → Bool} : #v[a].find? p = if p a then some a else none := by simp -@[simp] theorem findRev?_push_of_pos (xs : Vector α n) (h : p a) : +@[simp] theorem findRev?_push_of_pos {xs : Vector α n} (h : p a) : findRev? p (xs.push a) = some a := by cases xs; simp [h] -@[simp] theorem findRev?_cons_of_neg (xs : Vector α n) (h : ¬p a) : +@[simp] theorem findRev?_cons_of_neg {xs : Vector α n} (h : ¬p a) : findRev? p (xs.push a) = findRev? p xs := by cases xs; simp [h] @@ -184,17 +184,17 @@ theorem get_find?_mem {xs : Vector α n} (h) : (xs.find? p).get h ∈ xs := by (xs.filter p).find? q = xs.find? (fun a => p a ∧ q a) := by cases xs; simp -@[simp] theorem getElem?_zero_filter (p : α → Bool) (xs : Vector α n) : +@[simp] theorem getElem?_zero_filter {p : α → Bool} {xs : Vector α n} : (xs.filter p)[0]? = xs.find? p := by cases xs; simp [← List.head?_eq_getElem?] -@[simp] theorem getElem_zero_filter (p : α → Bool) (xs : Vector α n) (h) : +@[simp] theorem getElem_zero_filter {p : α → Bool} {xs : Vector α n} (h) : (xs.filter p)[0] = (xs.find? p).get (by cases xs; simpa [← Array.countP_eq_size_filter] using h) := by cases xs simp [List.getElem_zero_eq_head] -@[simp] theorem find?_map (f : β → α) (xs : Vector β n) : +@[simp] theorem find?_map {f : β → α} {xs : Vector β n} : find? p (xs.map f) = (xs.find? (p ∘ f)).map f := by cases xs; simp @@ -204,7 +204,7 @@ theorem get_find?_mem {xs : Vector α n} (h) : (xs.find? p).get h ∈ xs := by cases ys simp -@[simp] theorem find?_flatten (xs : Vector (Vector α m) n) (p : α → Bool) : +@[simp] theorem find?_flatten {xs : Vector (Vector α m) n} {p : α → Bool} : xs.flatten.find? p = xs.findSome? (·.find? p) := by cases xs using vector₂_induction simp [Array.findSome?_map, Function.comp_def] @@ -213,7 +213,7 @@ theorem find?_flatten_eq_none_iff {xs : Vector (Vector α m) n} {p : α → Bool xs.flatten.find? p = none ↔ ∀ ys ∈ xs, ∀ x ∈ ys, !p x := by simp -@[simp] theorem find?_flatMap (xs : Vector α n) (f : α → Vector β m) (p : β → Bool) : +@[simp] theorem find?_flatMap {xs : Vector α n} {f : α → Vector β m} {p : β → Bool} : (xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by cases xs simp [Array.find?_flatMap, Array.flatMap_toArray] @@ -266,7 +266,7 @@ abbrev find?_mkVector_eq_none_iff := @find?_replicate_eq_none_iff @[deprecated find?_replicate_eq_some_iff (since := "2025-03-18")] abbrev find?_mkVector_eq_some_iff := @find?_replicate_eq_some_iff -@[simp] theorem get_find?_replicate (n : Nat) (a : α) (p : α → Bool) (h) : +@[simp] theorem get_find?_replicate {n : Nat} {a : α} {p : α → Bool} (h) : ((replicate n a).find? p).get h = a := by simp only [replicate_eq_mk_replicate, find?_mk] simp @@ -274,8 +274,8 @@ abbrev find?_mkVector_eq_some_iff := @find?_replicate_eq_some_iff @[deprecated get_find?_replicate (since := "2025-03-18")] abbrev get_find?_mkVector := @get_find?_replicate -theorem find?_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : Vector α n) - (H : ∀ (a : α), a ∈ xs → P a) (p : β → Bool) : +theorem find?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Vector α n} + (H : ∀ (a : α), a ∈ xs → P a) {p : β → Bool} : (xs.pmap f H).find? p = (xs.attach.find? (fun ⟨a, m⟩ => p (f a (H a m)))).map fun ⟨a, m⟩ => f a (H a m) := by simp only [pmap_eq_map_attach, find?_map] rfl diff --git a/src/Init/Data/Vector/InsertIdx.lean b/src/Init/Data/Vector/InsertIdx.lean index d2008e5091..6c59ed960a 100644 --- a/src/Init/Data/Vector/InsertIdx.lean +++ b/src/Init/Data/Vector/InsertIdx.lean @@ -29,11 +29,11 @@ section InsertIdx variable {a : α} @[simp] -theorem insertIdx_zero (xs : Vector α n) (x : α) : xs.insertIdx 0 x = (#v[x] ++ xs).cast (by omega) := by +theorem insertIdx_zero {xs : Vector α n} {x : α} : xs.insertIdx 0 x = (#v[x] ++ xs).cast (by omega) := by cases xs simp -theorem eraseIdx_insertIdx (i : Nat) (xs : Vector α n) (h : i ≤ n) : +theorem eraseIdx_insertIdx {i : Nat} {xs : Vector α n} {h : i ≤ n} : (xs.insertIdx i a).eraseIdx i = xs := by rcases xs with ⟨xs, rfl⟩ simp_all [Array.eraseIdx_insertIdx] @@ -52,11 +52,11 @@ theorem insertIdx_eraseIdx_of_le {xs : Vector α n} rcases xs with ⟨as, rfl⟩ simpa using Array.insertIdx_eraseIdx_of_le (by simpa) (by simpa) (by simpa) -theorem insertIdx_comm (a b : α) (i j : Nat) (xs : Vector α n) (_ : i ≤ j) (_ : j ≤ n) : +theorem insertIdx_comm (a b : α) {i j : Nat} {xs : Vector α n} (_ : i ≤ j) (_ : j ≤ n) : (xs.insertIdx i a).insertIdx (j + 1) b = (xs.insertIdx j b).insertIdx i a := by rcases xs with ⟨as, rfl⟩ - simpa using Array.insertIdx_comm a b i j _ (by simpa) (by simpa) + simpa using Array.insertIdx_comm a b (by simpa) (by simpa) theorem mem_insertIdx {xs : Vector α n} {h : i ≤ n} : a ∈ xs.insertIdx i b h ↔ a = b ∨ a ∈ xs := by rcases xs with ⟨as, rfl⟩ @@ -64,7 +64,7 @@ theorem mem_insertIdx {xs : Vector α n} {h : i ≤ n} : a ∈ xs.insertIdx i b set_option linter.indexVariables false in @[simp] -theorem insertIdx_size_self (xs : Vector α n) (x : α) : xs.insertIdx n x = xs.push x := by +theorem insertIdx_size_self {xs : Vector α n} {x : α} : xs.insertIdx n x = xs.push x := by rcases xs with ⟨as, rfl⟩ simp diff --git a/src/Init/Data/Vector/Lemmas.lean b/src/Init/Data/Vector/Lemmas.lean index f47a87b4c3..3ef11c2036 100644 --- a/src/Init/Data/Vector/Lemmas.lean +++ b/src/Init/Data/Vector/Lemmas.lean @@ -29,9 +29,9 @@ namespace Vector /-! ### mk lemmas -/ -theorem toArray_mk (xs : Array α) (h : xs.size = n) : (Vector.mk xs h).toArray = xs := rfl +theorem toArray_mk {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).toArray = xs := rfl -@[simp] theorem mk_toArray (xs : Vector α n) : mk xs.toArray xs.2 = xs := by +@[simp] theorem mk_toArray {xs : Vector α n} : mk xs.toArray xs.2 = xs := by rfl @[simp] theorem getElem_mk {xs : Array α} {size : xs.size = n} {i : Nat} (h : i < n) : @@ -61,192 +61,194 @@ theorem toArray_mk (xs : Array α) (h : xs.size = n) : (Vector.mk xs h).toArray (Vector.mk xs h == Vector.mk ys h') = (xs == ys) := by simp [instBEq, isEqv, Array.instBEq, Array.isEqv, h, h'] -@[simp] theorem allDiff_mk [BEq α] (xs : Array α) (h : xs.size = n) : +@[simp] theorem allDiff_mk [BEq α] {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).allDiff = xs.allDiff := rfl -@[simp] theorem mk_append_mk (xs ys : Array α) (h : xs.size = n) (h' : ys.size = m) : +@[simp] theorem mk_append_mk {xs ys : Array α} (h : xs.size = n) (h' : ys.size = m) : Vector.mk xs h ++ Vector.mk ys h' = Vector.mk (xs ++ ys) (by simp [h, h']) := rfl -@[simp] theorem back!_mk [Inhabited α] (xs : Array α) (h : xs.size = n) : +@[simp] theorem back!_mk [Inhabited α] {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).back! = xs.back! := rfl -@[simp] theorem back?_mk (xs : Array α) (h : xs.size = n) : +@[simp] theorem back?_mk {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).back? = xs.back? := rfl -@[simp] theorem back_mk [NeZero n] (xs : Array α) (h : xs.size = n) : +@[simp] theorem back_mk [NeZero n] {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).back = xs.back (by have : 0 ≠ n := NeZero.ne' n; omega) := by simp [back, Array.back, h] -@[simp] theorem foldlM_mk [Monad m] (f : β → α → m β) (b : β) (xs : Array α) (h : xs.size = n) : +@[simp] theorem foldlM_mk [Monad m] {f : β → α → m β} {b : β} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).foldlM f b = xs.foldlM f b := rfl -@[simp] theorem foldrM_mk [Monad m] (f : α → β → m β) (b : β) (xs : Array α) (h : xs.size = n) : +@[simp] theorem foldrM_mk [Monad m] {f : α → β → m β} {b : β} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).foldrM f b = xs.foldrM f b := rfl -@[simp] theorem foldl_mk (f : β → α → β) (b : β) (xs : Array α) (h : xs.size = n) : +@[simp] theorem foldl_mk {f : β → α → β} {b : β} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).foldl f b = xs.foldl f b := rfl -@[simp] theorem foldr_mk (f : α → β → β) (b : β) (xs : Array α) (h : xs.size = n) : +@[simp] theorem foldr_mk {f : α → β → β} {b : β} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).foldr f b = xs.foldr f b := rfl -@[simp] theorem drop_mk (xs : Array α) (h : xs.size = n) (i) : +@[simp] theorem drop_mk {xs : Array α} {h : xs.size = n} {i} : (Vector.mk xs h).drop i = Vector.mk (xs.extract i xs.size) (by simp [h]) := rfl -@[simp] theorem eraseIdx_mk (xs : Array α) (h : xs.size = n) (i) (h') : +@[simp] theorem eraseIdx_mk {xs : Array α} {h : xs.size = n} {i} (h') : (Vector.mk xs h).eraseIdx i h' = Vector.mk (xs.eraseIdx i) (by simp [h]) := rfl -@[simp] theorem eraseIdx!_mk (xs : Array α) (h : xs.size = n) (i) (hi : i < n) : +@[simp] theorem eraseIdx!_mk {xs : Array α} {h : xs.size = n} {i} (hi : i < n) : (Vector.mk xs h).eraseIdx! i = Vector.mk (xs.eraseIdx i) (by simp [h, hi]) := by simp [Vector.eraseIdx!, hi] -@[simp] theorem insertIdx_mk (xs : Array α) (h : xs.size = n) (i x) (h') : +@[simp] theorem insertIdx_mk {xs : Array α} {h : xs.size = n} {i x} (h') : (Vector.mk xs h).insertIdx i x h' = Vector.mk (xs.insertIdx i x) (by simp [h, h']) := rfl -@[simp] theorem insertIdx!_mk (xs : Array α) (h : xs.size = n) (i x) (hi : i ≤ n) : +@[simp] theorem insertIdx!_mk {xs : Array α} {h : xs.size = n} {i x} (hi : i ≤ n) : (Vector.mk xs h).insertIdx! i x = Vector.mk (xs.insertIdx i x) (by simp [h, hi]) := by simp [Vector.insertIdx!, hi] -@[simp] theorem cast_mk (xs : Array α) (h : xs.size = n) (h' : n = m) : +@[simp] theorem cast_mk {xs : Array α} {h : xs.size = n} {h' : n = m} : (Vector.mk xs h).cast h' = Vector.mk xs (by simp [h, h']) := rfl -@[simp] theorem extract_mk (xs : Array α) (h : xs.size = n) (start stop) : +@[simp] theorem extract_mk {xs : Array α} {h : xs.size = n} {start stop} : (Vector.mk xs h).extract start stop = Vector.mk (xs.extract start stop) (by simp [h]) := rfl -@[simp] theorem finIdxOf?_mk [BEq α] (xs : Array α) (h : xs.size = n) (x : α) : +@[simp] theorem finIdxOf?_mk [BEq α] {xs : Array α} (h : xs.size = n) (x : α) : (Vector.mk xs h).finIdxOf? x = (xs.finIdxOf? x).map (Fin.cast h) := rfl -@[simp] theorem findFinIdx?_mk (xs : Array α) (h : xs.size = n) (f : α → Bool) : +@[simp] theorem findFinIdx?_mk {xs : Array α} (h : xs.size = n) (f : α → Bool) : (Vector.mk xs h).findFinIdx? f = (xs.findFinIdx? f).map (Fin.cast h) := rfl @[deprecated finIdxOf?_mk (since := "2025-01-29")] abbrev indexOf?_mk := @finIdxOf?_mk -@[simp] theorem findM?_mk [Monad m] (xs : Array α) (h : xs.size = n) (f : α → m Bool) : +@[simp] theorem findM?_mk [Monad m] {xs : Array α} (h : xs.size = n) (f : α → m Bool) : (Vector.mk xs h).findM? f = xs.findM? f := rfl -@[simp] theorem findSomeM?_mk [Monad m] (xs : Array α) (h : xs.size = n) (f : α → m (Option β)) : +@[simp] theorem findSomeM?_mk [Monad m] {xs : Array α} (h : xs.size = n) (f : α → m (Option β)) : (Vector.mk xs h).findSomeM? f = xs.findSomeM? f := rfl -@[simp] theorem findRevM?_mk [Monad m] (xs : Array α) (h : xs.size = n) (f : α → m Bool) : +@[simp] theorem findRevM?_mk [Monad m] {xs : Array α} (h : xs.size = n) (f : α → m Bool) : (Vector.mk xs h).findRevM? f = xs.findRevM? f := rfl -@[simp] theorem findSomeRevM?_mk [Monad m] (xs : Array α) (h : xs.size = n) (f : α → m (Option β)) : +@[simp] theorem findSomeRevM?_mk [Monad m] {xs : Array α} (h : xs.size = n) (f : α → m (Option β)) : (Vector.mk xs h).findSomeRevM? f = xs.findSomeRevM? f := rfl -@[simp] theorem find?_mk (xs : Array α) (h : xs.size = n) (f : α → Bool) : +@[simp] theorem find?_mk {xs : Array α} (h : xs.size = n) (f : α → Bool) : (Vector.mk xs h).find? f = xs.find? f := rfl -@[simp] theorem findSome?_mk (xs : Array α) (h : xs.size = n) (f : α → Option β) : +@[simp] theorem findSome?_mk {xs : Array α} (h : xs.size = n) (f : α → Option β) : (Vector.mk xs h).findSome? f = xs.findSome? f := rfl -@[simp] theorem findRev?_mk (xs : Array α) (h : xs.size = n) (f : α → Bool) : +@[simp] theorem findRev?_mk {xs : Array α} (h : xs.size = n) (f : α → Bool) : (Vector.mk xs h).findRev? f = xs.findRev? f := rfl -@[simp] theorem findSomeRev?_mk (xs : Array α) (h : xs.size = n) (f : α → Option β) : +@[simp] theorem findSomeRev?_mk {xs : Array α} (h : xs.size = n) (f : α → Option β) : (Vector.mk xs h).findSomeRev? f = xs.findSomeRev? f := rfl -@[simp] theorem mk_isEqv_mk (r : α → α → Bool) (xs ys : Array α) (h : xs.size = n) (h' : ys.size = n) : +@[simp] theorem mk_isEqv_mk {r : α → α → Bool} {xs ys : Array α} (h : xs.size = n) (h' : ys.size = n) : Vector.isEqv (Vector.mk xs h) (Vector.mk ys h') r = Array.isEqv xs ys r := by simp [Vector.isEqv, Array.isEqv, h, h'] -@[simp] theorem mk_isPrefixOf_mk [BEq α] (xs ys : Array α) (h : xs.size = n) (h' : ys.size = n) : +@[simp] theorem mk_isPrefixOf_mk [BEq α] {xs ys : Array α} (h : xs.size = n) (h' : ys.size = n) : (Vector.mk xs h).isPrefixOf (Vector.mk ys h') = xs.isPrefixOf ys := by simp [Vector.isPrefixOf, Array.isPrefixOf, h, h'] -@[simp] theorem map_mk (xs : Array α) (h : xs.size = n) (f : α → β) : +@[simp] theorem map_mk {f : α → β} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).map f = Vector.mk (xs.map f) (by simp [h]) := rfl -@[simp] theorem mapIdx_mk (xs : Array α) (h : xs.size = n) (f : Nat → α → β) : +@[simp] theorem mapIdx_mk {f : Nat → α → β} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).mapIdx f = Vector.mk (xs.mapIdx f) (by simp [h]) := rfl -@[simp] theorem mapFinIdx_mk (xs : Array α) (h : xs.size = n) (f : (i : Nat) → α → (h : i < n) → β) : +@[simp] theorem mapFinIdx_mk {f : (i : Nat) → α → (h : i < n) → β} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).mapFinIdx f = Vector.mk (xs.mapFinIdx fun i a h' => f i a (by simpa [h] using h')) (by simp [h]) := rfl -@[simp] theorem forM_mk [Monad m] (f : α → m PUnit) (xs : Array α) (h : xs.size = n) : +@[simp] theorem forM_mk [Monad m] {f : α → m PUnit} {xs : Array α} (h : xs.size = n) : forM (Vector.mk xs h) f = forM xs f := rfl -@[simp] theorem forIn'_mk [Monad m] - (xs : Array α) (h : xs.size = n) (b : β) - (f : (a : α) → a ∈ Vector.mk xs h → β → m (ForInStep β)) : +@[simp] theorem forIn'_mk [Monad m] {xs : Array α} (h : xs.size = n) {b : β} + {f : (a : α) → a ∈ Vector.mk xs h → β → m (ForInStep β)} : forIn' (Vector.mk xs h) b f = forIn' xs b (fun a m b => f a (by simpa using m) b) := rfl -@[simp] theorem forIn_mk [Monad m] - (xs : Array α) (h : xs.size = n) (b : β) (f : (a : α) → β → m (ForInStep β)) : +@[simp] theorem forIn_mk [Monad m] {f : (a : α) → β → m (ForInStep β)} + {xs : Array α} (h : xs.size = n) {b : β} : forIn (Vector.mk xs h) b f = forIn xs b f := rfl -@[simp] theorem flatMap_mk (f : α → Vector β m) (xs : Array α) (h : xs.size = n) : +@[simp] theorem flatMap_mk {f : α → Vector β m} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).flatMap f = Vector.mk (xs.flatMap (fun a => (f a).toArray)) (by simp [h, Array.map_const']) := rfl -@[simp] theorem firstM_mk [Alternative m] (f : α → m β) (xs : Array α) (h : xs.size = n) : +@[simp] theorem firstM_mk [Alternative m] {f : α → m β} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).firstM f = xs.firstM f := rfl -@[simp] theorem reverse_mk (xs : Array α) (h : xs.size = n) : +@[simp] theorem reverse_mk {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).reverse = Vector.mk xs.reverse (by simp [h]) := rfl -@[simp] theorem set_mk (xs : Array α) (h : xs.size = n) (i x w) : +@[simp] theorem set_mk {xs : Array α} (h : xs.size = n) {i x} (w) : (Vector.mk xs h).set i x = Vector.mk (xs.set i x) (by simp [h]) := rfl -@[simp] theorem set!_mk (xs : Array α) (h : xs.size = n) (i x) : +@[simp] theorem set!_mk {xs : Array α} (h : xs.size = n) {i x} : (Vector.mk xs h).set! i x = Vector.mk (xs.set! i x) (by simp [h]) := rfl -@[simp] theorem setIfInBounds_mk (xs : Array α) (h : xs.size = n) (i x) : +@[simp] theorem setIfInBounds_mk {xs : Array α} (h : xs.size = n) {i x} : (Vector.mk xs h).setIfInBounds i x = Vector.mk (xs.setIfInBounds i x) (by simp [h]) := rfl -@[simp] theorem swap_mk (xs : Array α) (h : xs.size = n) (i j) (hi hj) : +@[simp] theorem swap_mk {xs : Array α} (h : xs.size = n) {i j} (hi hj) : (Vector.mk xs h).swap i j = Vector.mk (xs.swap i j) (by simp [h]) := rfl -@[simp] theorem swapIfInBounds_mk (xs : Array α) (h : xs.size = n) (i j) : +@[simp] theorem swapIfInBounds_mk {xs : Array α} (h : xs.size = n) {i j} : (Vector.mk xs h).swapIfInBounds i j = Vector.mk (xs.swapIfInBounds i j) (by simp [h]) := rfl -@[simp] theorem swapAt_mk (xs : Array α) (h : xs.size = n) (i x) (hi) : +@[simp] theorem swapAt_mk {xs : Array α} (h : xs.size = n) {i x} (hi) : (Vector.mk xs h).swapAt i x = ((xs.swapAt i x).fst, Vector.mk (xs.swapAt i x).snd (by simp [h])) := rfl -@[simp] theorem swapAt!_mk (xs : Array α) (h : xs.size = n) (i x) : (Vector.mk xs h).swapAt! i x = - ((xs.swapAt! i x).fst, Vector.mk (xs.swapAt! i x).snd (by simp [h])) := rfl +@[simp] theorem swapAt!_mk {xs : Array α} (h : xs.size = n) {i x} : + (Vector.mk xs h).swapAt! i x = + ((xs.swapAt! i x).fst, Vector.mk (xs.swapAt! i x).snd (by simp [h])) := rfl -@[simp] theorem take_mk (xs : Array α) (h : xs.size = n) (i) : +@[simp] theorem take_mk {xs : Array α} (h : xs.size = n) {i} : (Vector.mk xs h).take i = Vector.mk (xs.take i) (by simp [h]) := rfl -@[simp] theorem zipIdx_mk (xs : Array α) (h : xs.size = n) (k : Nat := 0) : +@[simp] theorem zipIdx_mk {xs : Array α} (h : xs.size = n) (k : Nat := 0) : (Vector.mk xs h).zipIdx k = Vector.mk (xs.zipIdx k) (by simp [h]) := rfl @[deprecated zipIdx_mk (since := "2025-01-21")] abbrev zipWithIndex_mk := @zipIdx_mk -@[simp] theorem mk_zipWith_mk (f : α → β → γ) (as : Array α) (bs : Array β) - (h : as.size = n) (h' : bs.size = n) : zipWith f (Vector.mk as h) (Vector.mk bs h') = - Vector.mk (Array.zipWith f as bs) (by simp [h, h']) := rfl +@[simp] theorem mk_zipWith_mk {f : α → β → γ} {as : Array α} {bs : Array β} + (h : as.size = n) (h' : bs.size = n) : + zipWith f (Vector.mk as h) (Vector.mk bs h') = + Vector.mk (Array.zipWith f as bs) (by simp [h, h']) := rfl -@[simp] theorem mk_zip_mk (as : Array α) (bs : Array β) (h : as.size = n) (h' : bs.size = n) : +@[simp] theorem mk_zip_mk {as : Array α} {bs : Array β} (h : as.size = n) (h' : bs.size = n) : zip (Vector.mk as h) (Vector.mk bs h') = Vector.mk (Array.zip as bs) (by simp [h, h']) := rfl -@[simp] theorem unzip_mk (xs : Array (α × β)) (h : xs.size = n) : - (Vector.mk xs h).unzip = (Vector.mk xs.unzip.1 (by simp_all), Vector.mk xs.unzip.2 (by simp_all)) := rfl +@[simp] theorem unzip_mk {xs : Array (α × β)} (h : xs.size = n) : + (Vector.mk xs h).unzip = + (Vector.mk xs.unzip.1 (by simp_all), Vector.mk xs.unzip.2 (by simp_all)) := rfl -@[simp] theorem anyM_mk [Monad m] (p : α → m Bool) (xs : Array α) (h : xs.size = n) : +@[simp] theorem anyM_mk [Monad m] {p : α → m Bool} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).anyM p = xs.anyM p := rfl -@[simp] theorem allM_mk [Monad m] (p : α → m Bool) (xs : Array α) (h : xs.size = n) : +@[simp] theorem allM_mk [Monad m] {p : α → m Bool} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).allM p = xs.allM p := rfl -@[simp] theorem any_mk (p : α → Bool) (xs : Array α) (h : xs.size = n) : +@[simp] theorem any_mk {p : α → Bool} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).any p = xs.any p := rfl -@[simp] theorem all_mk (p : α → Bool) (xs : Array α) (h : xs.size = n) : +@[simp] theorem all_mk {p : α → Bool} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).all p = xs.all p := rfl -@[simp] theorem countP_mk (p : α → Bool) (xs : Array α) (h : xs.size = n) : +@[simp] theorem countP_mk {p : α → Bool} {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).countP p = xs.countP p := rfl -@[simp] theorem count_mk [BEq α] (xs : Array α) (h : xs.size = n) (a : α) : +@[simp] theorem count_mk [BEq α] {xs : Array α} (h : xs.size = n) {a : α} : (Vector.mk xs h).count a = xs.count a := rfl -@[simp] theorem replace_mk [BEq α] (xs : Array α) (h : xs.size = n) (a b) : +@[simp] theorem replace_mk [BEq α] {xs : Array α} (h : xs.size = n) {a b} : (Vector.mk xs h).replace a b = Vector.mk (xs.replace a b) (by simp [h]) := rfl @[simp] theorem eq_mk : xs = Vector.mk as h ↔ xs.toArray = as := by @@ -259,62 +261,62 @@ abbrev zipWithIndex_mk := @zipIdx_mk /-! ### toArray lemmas -/ -@[simp] theorem getElem_toArray {α n} (xs : Vector α n) (i : Nat) (h : i < xs.toArray.size) : +@[simp] theorem getElem_toArray {α n} {xs : Vector α n} {i : Nat} (h : i < xs.toArray.size) : xs.toArray[i] = xs[i]'(by simpa using h) := by cases xs simp -@[simp] theorem getElem?_toArray {α n} (xs : Vector α n) (i : Nat) : +@[simp] theorem getElem?_toArray {α n} {xs : Vector α n} {i : Nat} : xs.toArray[i]? = xs[i]? := by cases xs simp -@[simp] theorem toArray_append (xs : Vector α m) (ys : Vector α n) : +@[simp] theorem toArray_append {xs : Vector α m} {ys : Vector α n} : (xs ++ ys).toArray = xs.toArray ++ ys.toArray := rfl -@[simp] theorem toArray_drop (xs : Vector α n) (i) : +@[simp] theorem toArray_drop {xs : Vector α n} {i} : (xs.drop i).toArray = xs.toArray.extract i xs.size := rfl @[simp] theorem toArray_empty : (#v[] : Vector α 0).toArray = #[] := rfl -@[simp] theorem toArray_emptyWithCapacity (cap) : +@[simp] theorem toArray_emptyWithCapacity {cap} : (Vector.emptyWithCapacity (α := α) cap).toArray = Array.emptyWithCapacity cap := rfl @[deprecated toArray_emptyWithCapacity (since := "2025-03-12")] abbrev toArray_mkEmpty := @toArray_emptyWithCapacity -@[simp] theorem toArray_eraseIdx (xs : Vector α n) (i) (h) : +@[simp] theorem toArray_eraseIdx {xs : Vector α n} {i} (h) : (xs.eraseIdx i h).toArray = xs.toArray.eraseIdx i (by simp [h]) := rfl -@[simp] theorem toArray_eraseIdx! (xs : Vector α n) (i) (hi : i < n) : +@[simp] theorem toArray_eraseIdx! {xs : Vector α n} {i} (hi : i < n) : (xs.eraseIdx! i).toArray = xs.toArray.eraseIdx! i := by cases xs; simp_all [Array.eraseIdx!] -@[simp] theorem toArray_insertIdx (xs : Vector α n) (i x) (h) : +@[simp] theorem toArray_insertIdx {xs : Vector α n} {i x} (h) : (xs.insertIdx i x h).toArray = xs.toArray.insertIdx i x (by simp [h]) := rfl -@[simp] theorem toArray_insertIdx! (xs : Vector α n) (i x) (hi : i ≤ n) : +@[simp] theorem toArray_insertIdx! {xs : Vector α n} {i x} (hi : i ≤ n) : (xs.insertIdx! i x).toArray = xs.toArray.insertIdx! i x := by cases xs; simp_all [Array.insertIdx!] -@[simp] theorem toArray_cast (xs : Vector α n) (h : n = m) : +@[simp] theorem toArray_cast {xs : Vector α n} (h : n = m) : (xs.cast h).toArray = xs.toArray := rfl -@[simp] theorem toArray_extract (xs : Vector α n) (start stop) : +@[simp] theorem toArray_extract {xs : Vector α n} {start stop} : (xs.extract start stop).toArray = xs.toArray.extract start stop := rfl -@[simp] theorem toArray_map (f : α → β) (xs : Vector α n) : +@[simp] theorem toArray_map {f : α → β} {xs : Vector α n} : (xs.map f).toArray = xs.toArray.map f := rfl -@[simp] theorem toArray_mapIdx (f : Nat → α → β) (xs : Vector α n) : +@[simp] theorem toArray_mapIdx {f : Nat → α → β} {xs : Vector α n} : (xs.mapIdx f).toArray = xs.toArray.mapIdx f := rfl -@[simp] theorem toArray_mapFinIdx (f : (i : Nat) → α → (h : i < n) → β) (xs : Vector α n) : +@[simp] theorem toArray_mapFinIdx {f : (i : Nat) → α → (h : i < n) → β} {xs : Vector α n} : (xs.mapFinIdx f).toArray = xs.toArray.mapFinIdx (fun i a h => f i a (by simpa [xs.size_toArray] using h)) := rfl -theorem toArray_mapM_go [Monad m] [LawfulMonad m] (f : α → m β) (xs : Vector α n) (i h acc) : +theorem toArray_mapM_go [Monad m] [LawfulMonad m] {f : α → m β} {xs : Vector α n} {i} (h) {acc} : toArray <$> mapM.go f xs i h acc = Array.mapM.map f xs.toArray i acc.toArray := by unfold mapM.go unfold Array.mapM.map @@ -327,20 +329,20 @@ theorem toArray_mapM_go [Monad m] [LawfulMonad m] (f : α → m β) (xs : Vector rfl · simp -@[simp] theorem toArray_mapM [Monad m] [LawfulMonad m] (f : α → m β) (xs : Vector α n) : +@[simp] theorem toArray_mapM [Monad m] [LawfulMonad m] {f : α → m β} {xs : Vector α n} : toArray <$> xs.mapM f = xs.toArray.mapM f := by rcases xs with ⟨xs, rfl⟩ unfold mapM rw [toArray_mapM_go] rfl -@[simp] theorem toArray_ofFn (f : Fin n → α) : (Vector.ofFn f).toArray = Array.ofFn f := rfl +@[simp] theorem toArray_ofFn {f : Fin n → α} : (Vector.ofFn f).toArray = Array.ofFn f := rfl -@[simp] theorem toArray_pop (xs : Vector α n) : xs.pop.toArray = xs.toArray.pop := rfl +@[simp] theorem toArray_pop {xs : Vector α n} : xs.pop.toArray = xs.toArray.pop := rfl -@[simp] theorem toArray_push (xs : Vector α n) (x) : (xs.push x).toArray = xs.toArray.push x := rfl +@[simp] theorem toArray_push {xs : Vector α n} {x} : (xs.push x).toArray = xs.toArray.push x := rfl -@[simp] theorem toArray_beq_toArray [BEq α] (xs : Vector α n) (ys : Vector α n) : +@[simp] theorem toArray_beq_toArray [BEq α] {xs : Vector α n} {ys : Vector α n} : (xs.toArray == ys.toArray) = (xs == ys) := by simp [instBEq, isEqv, Array.instBEq, Array.isEqv, xs.2, ys.2] @@ -348,119 +350,119 @@ theorem toArray_mapM_go [Monad m] [LawfulMonad m] (f : α → m β) (xs : Vector @[simp] theorem toArray_reverse (xs : Vector α n) : xs.reverse.toArray = xs.toArray.reverse := rfl -@[simp] theorem toArray_set (xs : Vector α n) (i x h) : +@[simp] theorem toArray_set {xs : Vector α n} {i x} (h) : (xs.set i x).toArray = xs.toArray.set i x (by simpa using h):= rfl -@[simp] theorem toArray_set! (xs : Vector α n) (i x) : +@[simp] theorem toArray_set! {xs : Vector α n} {i x} : (xs.set! i x).toArray = xs.toArray.set! i x := rfl -@[simp] theorem toArray_setIfInBounds (xs : Vector α n) (i x) : +@[simp] theorem toArray_setIfInBounds {xs : Vector α n} {i x} : (xs.setIfInBounds i x).toArray = xs.toArray.setIfInBounds i x := rfl -@[simp] theorem toArray_singleton (x : α) : (Vector.singleton x).toArray = #[x] := rfl +@[simp] theorem toArray_singleton {x : α} : (Vector.singleton x).toArray = #[x] := rfl -@[simp] theorem toArray_swap (xs : Vector α n) (i j) (hi hj) : (xs.swap i j).toArray = +@[simp] theorem toArray_swap {xs : Vector α n} {i j} (hi hj) : (xs.swap i j).toArray = xs.toArray.swap i j (by simp [hi, hj]) (by simp [hi, hj]) := rfl -@[simp] theorem toArray_swapIfInBounds (xs : Vector α n) (i j) : +@[simp] theorem toArray_swapIfInBounds {xs : Vector α n} {i j} : (xs.swapIfInBounds i j).toArray = xs.toArray.swapIfInBounds i j := rfl -@[simp] theorem toArray_swapAt (xs : Vector α n) (i x h) : +@[simp] theorem toArray_swapAt {xs : Vector α n} {i x} (h) : ((xs.swapAt i x).fst, (xs.swapAt i x).snd.toArray) = ((xs.toArray.swapAt i x (by simpa using h)).fst, (xs.toArray.swapAt i x (by simpa using h)).snd) := rfl -@[simp] theorem toArray_swapAt! (xs : Vector α n) (i x) : +@[simp] theorem toArray_swapAt! {xs : Vector α n} {i x} : ((xs.swapAt! i x).fst, (xs.swapAt! i x).snd.toArray) = ((xs.toArray.swapAt! i x).fst, (xs.toArray.swapAt! i x).snd) := rfl -@[simp] theorem toArray_take (xs : Vector α n) (i) : (xs.take i).toArray = xs.toArray.take i := rfl +@[simp] theorem toArray_take {xs : Vector α n} {i} : (xs.take i).toArray = xs.toArray.take i := rfl -@[simp] theorem toArray_zipIdx (xs : Vector α n) (k : Nat := 0) : +@[simp] theorem toArray_zipIdx {xs : Vector α n} (k : Nat := 0) : (xs.zipIdx k).toArray = xs.toArray.zipIdx k := rfl -@[simp] theorem toArray_zipWith (f : α → β → γ) (as : Vector α n) (bs : Vector β n) : +@[simp] theorem toArray_zipWith {f : α → β → γ} {as : Vector α n} {bs : Vector β n} : (Vector.zipWith f as bs).toArray = Array.zipWith f as.toArray bs.toArray := rfl -@[simp] theorem anyM_toArray [Monad m] (p : α → m Bool) (xs : Vector α n) : +@[simp] theorem anyM_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} : xs.toArray.anyM p = xs.anyM p := by cases xs simp -@[simp] theorem allM_toArray [Monad m] (p : α → m Bool) (xs : Vector α n) : +@[simp] theorem allM_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} : xs.toArray.allM p = xs.allM p := by cases xs simp -@[simp] theorem any_toArray (p : α → Bool) (xs : Vector α n) : +@[simp] theorem any_toArray {p : α → Bool} {xs : Vector α n} : xs.toArray.any p = xs.any p := by cases xs simp -@[simp] theorem all_toArray (p : α → Bool) (xs : Vector α n) : +@[simp] theorem all_toArray {p : α → Bool} {xs : Vector α n} : xs.toArray.all p = xs.all p := by cases xs simp -@[simp] theorem countP_toArray (p : α → Bool) (xs : Vector α n) : +@[simp] theorem countP_toArray {p : α → Bool} {xs : Vector α n} : xs.toArray.countP p = xs.countP p := by cases xs simp -@[simp] theorem count_toArray [BEq α] (a : α) (xs : Vector α n) : +@[simp] theorem count_toArray [BEq α] {a : α} {xs : Vector α n} : xs.toArray.count a = xs.count a := by cases xs simp -@[simp] theorem replace_toArray [BEq α] (xs : Vector α n) (a b) : +@[simp] theorem replace_toArray [BEq α] {xs : Vector α n} {a b} : xs.toArray.replace a b = (xs.replace a b).toArray := rfl -@[simp] theorem find?_toArray (p : α → Bool) (xs : Vector α n) : +@[simp] theorem find?_toArray {p : α → Bool} {xs : Vector α n} : xs.toArray.find? p = xs.find? p := by cases xs simp -@[simp] theorem findSome?_toArray (f : α → Option β) (xs : Vector α n) : +@[simp] theorem findSome?_toArray {f : α → Option β} {xs : Vector α n} : xs.toArray.findSome? f = xs.findSome? f := by cases xs simp -@[simp] theorem findRev?_toArray (p : α → Bool) (xs : Vector α n) : +@[simp] theorem findRev?_toArray {p : α → Bool} {xs : Vector α n} : xs.toArray.findRev? p = xs.findRev? p := by cases xs simp -@[simp] theorem findSomeRev?_toArray (f : α → Option β) (xs : Vector α n) : +@[simp] theorem findSomeRev?_toArray {f : α → Option β} {xs : Vector α n} : xs.toArray.findSomeRev? f = xs.findSomeRev? f := by cases xs simp -@[simp] theorem findM?_toArray [Monad m] (p : α → m Bool) (xs : Vector α n) : +@[simp] theorem findM?_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} : xs.toArray.findM? p = xs.findM? p := by cases xs simp -@[simp] theorem findSomeM?_toArray [Monad m] (f : α → m (Option β)) (xs : Vector α n) : +@[simp] theorem findSomeM?_toArray [Monad m] {f : α → m (Option β)} {xs : Vector α n} : xs.toArray.findSomeM? f = xs.findSomeM? f := by cases xs simp -@[simp] theorem findRevM?_toArray [Monad m] (p : α → m Bool) (xs : Vector α n) : +@[simp] theorem findRevM?_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} : xs.toArray.findRevM? p = xs.findRevM? p := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem findSomeRevM?_toArray [Monad m] (f : α → m (Option β)) (xs : Vector α n) : +@[simp] theorem findSomeRevM?_toArray [Monad m] {f : α → m (Option β)} {xs : Vector α n} : xs.toArray.findSomeRevM? f = xs.findSomeRevM? f := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem finIdxOf?_toArray [BEq α] (a : α) (xs : Vector α n) : +@[simp] theorem finIdxOf?_toArray [BEq α] {a : α} {xs : Vector α n} : xs.toArray.finIdxOf? a = (xs.finIdxOf? a).map (Fin.cast xs.size_toArray.symm) := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem findFinIdx?_toArray (p : α → Bool) (xs : Vector α n) : +@[simp] theorem findFinIdx?_toArray {p : α → Bool} {xs : Vector α n} : xs.toArray.findFinIdx? p = (xs.findFinIdx? p).map (Fin.cast xs.size_toArray.symm) := by rcases xs with ⟨xs, rfl⟩ simp @@ -488,159 +490,162 @@ protected theorem ext {xs ys : Vector α n} (h : (i : Nat) → (_ : i < n) → x rw [xs.size_toArray] at hi exact h i hi -@[simp] theorem toArray_eq_empty_iff (xs : Vector α n) : xs.toArray = #[] ↔ n = 0 := by +@[simp] theorem toArray_eq_empty_iff {xs : Vector α n} : xs.toArray = #[] ↔ n = 0 := by rcases xs with ⟨xs, h⟩ exact ⟨by rintro rfl; simp_all, by rintro rfl; simpa using h⟩ /-! ### toList -/ -theorem toArray_toList (xs : Vector α n) : xs.toArray.toList = xs.toList := rfl +theorem toArray_toList {xs : Vector α n} : xs.toArray.toList = xs.toList := rfl -@[simp] theorem getElem_toList {α n} (xs : Vector α n) (i : Nat) (h : i < xs.toList.length) : +@[simp] theorem getElem_toList {xs : Vector α n} {i : Nat} (h : i < xs.toList.length) : xs.toList[i] = xs[i]'(by simpa using h) := by cases xs simp -@[simp] theorem getElem?_toList {α n} (xs : Vector α n) (i : Nat) : +@[simp] theorem getElem?_toList {xs : Vector α n} {i : Nat} : xs.toList[i]? = xs[i]? := by cases xs simp -theorem toList_append (xs : Vector α m) (ys : Vector α n) : +theorem toList_append {xs : Vector α m} {ys : Vector α n} : (xs ++ ys).toList = xs.toList ++ ys.toList := by simp -@[simp] theorem toList_drop (xs : Vector α n) (i) : +@[simp] theorem toList_drop {xs : Vector α n} {i} : (xs.drop i).toList = xs.toList.drop i := by simp [List.take_of_length_le] theorem toList_empty : (#v[] : Vector α 0).toArray = #[] := by simp -theorem toList_emptyWithCapacity (cap) : +theorem toList_emptyWithCapacity {cap} : (Vector.emptyWithCapacity (α := α) cap).toList = [] := rfl @[deprecated toList_emptyWithCapacity (since := "2025-03-12")] abbrev toList_mkEmpty := @toList_emptyWithCapacity -theorem toList_eraseIdx (xs : Vector α n) (i) (h) : +theorem toList_eraseIdx {xs : Vector α n} {i} (h) : (xs.eraseIdx i h).toList = xs.toList.eraseIdx i := by simp -@[simp] theorem toList_eraseIdx! (xs : Vector α n) (i) (hi : i < n) : +@[simp] theorem toList_eraseIdx! {xs : Vector α n} {i} (hi : i < n) : (xs.eraseIdx! i).toList = xs.toList.eraseIdx i := by cases xs; simp_all [Array.eraseIdx!] -theorem toList_insertIdx (xs : Vector α n) (i x) (h) : +theorem toList_insertIdx {xs : Vector α n} {i x} (h) : (xs.insertIdx i x h).toList = xs.toList.insertIdx i x := by simp -theorem toList_insertIdx! (xs : Vector α n) (i x) (hi : i ≤ n) : +theorem toList_insertIdx! {xs : Vector α n} {i x} (hi : i ≤ n) : (xs.insertIdx! i x).toList = xs.toList.insertIdx i x := by cases xs; simp_all [Array.insertIdx!] -theorem toList_cast (xs : Vector α n) (h : n = m) : +theorem toList_cast {xs : Vector α n} (h : n = m) : (xs.cast h).toList = xs.toList := rfl -theorem toList_extract (xs : Vector α n) (start stop) : +theorem toList_extract {xs : Vector α n} {start stop} : (xs.extract start stop).toList = (xs.toList.drop start).take (stop - start) := by simp -theorem toList_map (f : α → β) (xs : Vector α n) : +theorem toList_map {f : α → β} {xs : Vector α n} : (xs.map f).toList = xs.toList.map f := by simp -theorem toList_mapIdx (f : Nat → α → β) (xs : Vector α n) : +theorem toList_mapIdx {f : Nat → α → β} {xs : Vector α n} : (xs.mapIdx f).toList = xs.toList.mapIdx f := by simp -theorem toList_mapFinIdx (f : (i : Nat) → α → (h : i < n) → β) (xs : Vector α n) : +theorem toList_mapFinIdx {f : (i : Nat) → α → (h : i < n) → β} {xs : Vector α n} : (xs.mapFinIdx f).toList = xs.toList.mapFinIdx (fun i a h => f i a (by simpa [xs.size_toArray] using h)) := by simp -theorem toList_ofFn (f : Fin n → α) : (Vector.ofFn f).toList = List.ofFn f := by simp +theorem toList_ofFn {f : Fin n → α} : (Vector.ofFn f).toList = List.ofFn f := by simp -theorem toList_pop (xs : Vector α n) : xs.pop.toList = xs.toList.dropLast := rfl +theorem toList_pop {xs : Vector α n} : xs.pop.toList = xs.toList.dropLast := rfl -theorem toList_push (xs : Vector α n) (x) : (xs.push x).toList = xs.toList ++ [x] := by simp +theorem toList_push {xs : Vector α n} {x} : (xs.push x).toList = xs.toList ++ [x] := by simp -@[simp] theorem toList_beq_toList [BEq α] (xs : Vector α n) (ys : Vector α n) : +@[simp] theorem toList_beq_toList [BEq α] {xs : Vector α n} {ys : Vector α n} : (xs.toList == ys.toList) = (xs == ys) := by simp [instBEq, isEqv, Array.instBEq, Array.isEqv, xs.2, ys.2] theorem toList_range : (Vector.range n).toList = List.range n := by simp -theorem toList_reverse (xs : Vector α n) : xs.reverse.toList = xs.toList.reverse := by simp +theorem toList_reverse {xs : Vector α n} : xs.reverse.toList = xs.toList.reverse := by simp -theorem toList_set (xs : Vector α n) (i x h) : +theorem toList_set {xs : Vector α n} {i x} (h) : (xs.set i x).toList = xs.toList.set i x := rfl -@[simp] theorem toList_setIfInBounds (xs : Vector α n) (i x) : +@[simp] theorem toList_setIfInBounds {xs : Vector α n} {i x} : (xs.setIfInBounds i x).toList = xs.toList.set i x := by simp [Vector.setIfInBounds] -theorem toList_singleton (x : α) : (Vector.singleton x).toList = [x] := rfl +theorem toList_singleton {x : α} : (Vector.singleton x).toList = [x] := rfl -theorem toList_swap (xs : Vector α n) (i j) (hi hj) : +theorem toList_swap {xs : Vector α n} {i j} (hi hj) : (xs.swap i j).toList = (xs.toList.set i xs[j]).set j xs[i] := rfl -@[simp] theorem toList_take (xs : Vector α n) (i) : (xs.take i).toList = xs.toList.take i := by +@[simp] theorem toList_take {xs : Vector α n} {i} : (xs.take i).toList = xs.toList.take i := by simp [List.take_of_length_le] -@[simp] theorem toList_zipWith (f : α → β → γ) (as : Vector α n) (bs : Vector β n) : - (Vector.zipWith f as bs).toArray = Array.zipWith f as.toArray bs.toArray := rfl +@[simp] theorem toList_zipWith {f : α → β → γ} {as : Vector α n} {bs : Vector β n} : + (Vector.zipWith f as bs).toList = List.zipWith f as.toList bs.toList := by + rcases as with ⟨as, rfl⟩ + rcases bs with ⟨bs, h⟩ + simp -@[simp] theorem anyM_toList [Monad m] (p : α → m Bool) (xs : Vector α n) : +@[simp] theorem anyM_toList [Monad m] {p : α → m Bool} {xs : Vector α n} : xs.toList.anyM p = xs.anyM p := by cases xs simp -@[simp] theorem allM_toList [Monad m] [LawfulMonad m] (p : α → m Bool) (xs : Vector α n) : +@[simp] theorem allM_toList [Monad m] [LawfulMonad m] {p : α → m Bool} {xs : Vector α n} : xs.toList.allM p = xs.allM p := by cases xs simp -@[simp] theorem any_toList (p : α → Bool) (xs : Vector α n) : +@[simp] theorem any_toList {p : α → Bool} {xs : Vector α n} : xs.toList.any p = xs.any p := by cases xs simp -@[simp] theorem all_toList (p : α → Bool) (xs : Vector α n) : +@[simp] theorem all_toList {p : α → Bool} {xs : Vector α n} : xs.toList.all p = xs.all p := by cases xs simp -@[simp] theorem countP_toList (p : α → Bool) (xs : Vector α n) : +@[simp] theorem countP_toList {p : α → Bool} {xs : Vector α n} : xs.toList.countP p = xs.countP p := by cases xs simp -@[simp] theorem count_toList [BEq α] (a : α) (xs : Vector α n) : +@[simp] theorem count_toList [BEq α] {a : α} {xs : Vector α n} : xs.toList.count a = xs.count a := by cases xs simp -@[simp] theorem find?_toList (p : α → Bool) (xs : Vector α n) : +@[simp] theorem find?_toList {p : α → Bool} {xs : Vector α n} : xs.toList.find? p = xs.find? p := by cases xs simp -@[simp] theorem findSome?_toList (f : α → Option β) (xs : Vector α n) : +@[simp] theorem findSome?_toList {f : α → Option β} {xs : Vector α n} : xs.toList.findSome? f = xs.findSome? f := by cases xs simp -@[simp] theorem findM?_toList [Monad m] [LawfulMonad m] (p : α → m Bool) (xs : Vector α n) : +@[simp] theorem findM?_toList [Monad m] [LawfulMonad m] {p : α → m Bool} {xs : Vector α n} : xs.toList.findM? p = xs.findM? p := by cases xs simp -@[simp] theorem findSomeM?_toList [Monad m] [LawfulMonad m] (f : α → m (Option β)) (xs : Vector α n) : +@[simp] theorem findSomeM?_toList [Monad m] [LawfulMonad m] {f : α → m (Option β)} {xs : Vector α n} : xs.toList.findSomeM? f = xs.findSomeM? f := by cases xs simp -@[simp] theorem finIdxOf?_toList [BEq α] (a : α) (xs : Vector α n) : +@[simp] theorem finIdxOf?_toList [BEq α] {a : α} {xs : Vector α n} : xs.toList.finIdxOf? a = (xs.finIdxOf? a).map (Fin.cast xs.size_toArray.symm) := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem findFinIdx?_toList (p : α → Bool) (xs : Vector α n) : +@[simp] theorem findFinIdx?_toList {p : α → Bool} {xs : Vector α n} : xs.toList.findFinIdx? p = (xs.findFinIdx? p).map (Fin.cast xs.size_toArray.symm) := by rcases xs with ⟨xs, rfl⟩ simp @@ -655,12 +660,12 @@ theorem toList_inj {xs ys : Vector α n} : xs.toList = ys.toList ↔ xs = ys := cases ys simp [Array.toList_inj] -@[simp] theorem toList_eq_empty_iff (xs : Vector α n) : xs.toList = [] ↔ n = 0 := by +@[simp] theorem toList_eq_empty_iff {xs : Vector α n} : xs.toList = [] ↔ n = 0 := by rcases xs with ⟨xs, h⟩ simp only [Array.toList_eq_nil_iff] exact ⟨by rintro rfl; simp_all, by rintro rfl; simpa using h⟩ -@[simp] theorem mem_toList_iff (a : α) (xs : Vector α n) : a ∈ xs.toList ↔ a ∈ xs := by +@[simp] theorem mem_toList_iff {a : α} {xs : Vector α n} : a ∈ xs.toList ↔ a ∈ xs := by simp theorem length_toList {α n} (xs : Vector α n) : xs.toList.length = n := by simp @@ -672,14 +677,14 @@ theorem length_toList {α n} (xs : Vector α n) : xs.toList.length = n := by sim simp /-- A vector of length `0` is the empty vector. -/ -protected theorem eq_empty (xs : Vector α 0) : xs = #v[] := by +protected theorem eq_empty {xs : Vector α 0} : xs = #v[] := by apply Vector.toArray_inj.1 apply Array.eq_empty_of_size_eq_zero xs.2 /-! ### size -/ -theorem eq_empty_of_size_eq_zero (xs : Vector α n) (h : n = 0) : xs = #v[].cast h.symm := by +theorem eq_empty_of_size_eq_zero {xs : Vector α n} (h : n = 0) : xs = #v[].cast h.symm := by rcases xs with ⟨xs, rfl⟩ apply toArray_inj.1 simp only [List.length_eq_zero_iff, Array.toList_eq_nil_iff] at h @@ -729,17 +734,17 @@ theorem singleton_inj : #v[a] = #v[b] ↔ a = b := by /-! ### cast -/ -@[simp] theorem getElem_cast (xs : Vector α n) (h : n = m) (i : Nat) (hi : i < m) : +@[simp] theorem getElem_cast {xs : Vector α n} {h : n = m} {i : Nat} (hi : i < m) : (xs.cast h)[i] = xs[i] := by cases xs simp -@[simp] theorem getElem?_cast {xs : Vector α n} {m : Nat} {w : n = m} {i : Nat} : +@[simp] theorem getElem?_cast {xs : Vector α n} {w : n = m} {i : Nat} : (xs.cast w)[i]? = xs[i]? := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem mem_cast {a : α} {xs : Vector α n} {m : Nat} {w : n = m} : +@[simp] theorem mem_cast {a : α} {xs : Vector α n} {w : n = m} : a ∈ xs.cast w ↔ a ∈ xs := by rcases xs with ⟨xs, rfl⟩ simp @@ -783,13 +788,13 @@ abbrev replicate_mkVector_succ := @replicate_succ @[deprecated replicate_inj (since := "2025-03-18")] abbrev mkVector_inj := @replicate_inj -@[simp] theorem _root_.Array.vector_mk_replicate (a : α) (n : Nat) : +@[simp] theorem _root_.Array.vector_mk_replicate {a : α} {n : Nat} : mk (n := n) (Array.replicate n a) (by simp) = replicate n a := rfl @[deprecated _root_.Array.vector_mk_replicate (since := "2025-03-18")] abbrev _root_.Array.mk_mkArray := @_root_.Array.vector_mk_replicate -theorem replicate_eq_mk_replicate (a : α) (n : Nat) : +theorem replicate_eq_mk_replicate {a : α} {n : Nat} : replicate n a = mk (n := n) (Array.replicate n a) (by simp) := by simp @@ -819,11 +824,11 @@ theorem getElem?_eq_some_iff {xs : Vector α n} : xs[i]? = some b ↔ ∃ h : i theorem some_eq_getElem?_iff {xs : Vector α n} : some b = xs[i]? ↔ ∃ h : i < n, xs[i] = b := by rw [eq_comm, getElem?_eq_some_iff] -@[simp] theorem some_getElem_eq_getElem?_iff (xs : Vector α n) (i : Nat) (h : i < n) : +@[simp] theorem some_getElem_eq_getElem?_iff {xs : Vector α n} {i : Nat} (h : i < n) : (some xs[i] = xs[i]?) ↔ True := by simp [h] -@[simp] theorem getElem?_eq_some_getElem_iff (xs : Vector α n) (i : Nat) (h : i < n) : +@[simp] theorem getElem?_eq_some_getElem_iff {xs : Vector α n} {i : Nat} (h : i < n) : (xs[i]? = some xs[i]) ↔ True := by simp [h] @@ -831,11 +836,11 @@ theorem getElem_eq_iff {xs : Vector α n} {i : Nat} {h : i < n} : xs[i] = x ↔ simp only [getElem?_eq_some_iff] exact ⟨fun w => ⟨h, w⟩, fun h => h.2⟩ -theorem getElem_eq_getElem?_get (xs : Vector α n) (i : Nat) (h : i < n) : +theorem getElem_eq_getElem?_get {xs : Vector α n} {i : Nat} (h : i < n) : xs[i] = xs[i]?.get (by simp [getElem?_eq_getElem, h]) := by simp [getElem_eq_iff] -theorem getD_getElem? (xs : Vector α n) (i : Nat) (d : α) : +theorem getD_getElem? {xs : Vector α n} {i : Nat} {d : α} : xs[i]?.getD d = if p : i < n then xs[i]'p else d := by if h : i < n then simp [h, getElem?_def] @@ -868,11 +873,11 @@ set_option linter.indexVariables false in @[simp] theorem getElem?_push_size {xs : Vector α n} {x : α} : (xs.push x)[n]? = some x := by simp [getElem?_push] -@[simp] theorem getElem_singleton (a : α) (h : i < 1) : #v[a][i] = a := +@[simp] theorem getElem_singleton {a : α} (h : i < 1) : #v[a][i] = a := match i, h with | 0, _ => rfl -theorem getElem?_singleton (a : α) (i : Nat) : #v[a][i]? = if i = 0 then some a else none := by +theorem getElem?_singleton {a : α} {i : Nat} : #v[a][i]? = if i = 0 then some a else none := by simp [List.getElem?_singleton] /-! ### mem -/ @@ -902,7 +907,7 @@ theorem eq_push_append_of_mem {xs : Vector α n} {x : α} (h : x ∈ xs) : theorem mem_push_of_mem {xs : Vector α n} {x : α} (y : α) (h : x ∈ xs) : x ∈ xs.push y := mem_push.2 (Or.inl h) -theorem exists_mem_of_size_pos (xs : Vector α n) (h : 0 < n) : ∃ x, x ∈ xs := by +theorem exists_mem_of_size_pos {xs : Vector α n} (h : 0 < n) : ∃ x, x ∈ xs := by simpa using List.exists_mem_of_ne_nil xs.toList (by simpa using (Nat.ne_of_gt h)) theorem size_zero_iff_forall_not_mem {xs : Vector α n} : n = 0 ↔ ∀ a, a ∉ xs := by @@ -1206,49 +1211,48 @@ theorem contains_iff [BEq α] [LawfulBEq α] {a : α} {as : Vector α n} : /-! ### set -/ -theorem getElem_set (xs : Vector α n) (i : Nat) (x : α) (hi : i < n) (j : Nat) (hj : j < n) : +theorem getElem_set {xs : Vector α n} {i : Nat} {x : α} (hi : i < n) {j : Nat} (hj : j < n) : (xs.set i x hi)[j] = if i = j then x else xs[j] := by cases xs split <;> simp_all [Array.getElem_set] -@[simp] theorem getElem_set_self (xs : Vector α n) (i : Nat) (x : α) (hi : i < n) : +@[simp] theorem getElem_set_self {xs : Vector α n} {i : Nat} {x : α} (hi : i < n) : (xs.set i x hi)[i] = x := by simp [getElem_set] @[deprecated getElem_set_self (since := "2024-12-12")] abbrev getElem_set_eq := @getElem_set_self -@[simp] theorem getElem_set_ne (xs : Vector α n) (i : Nat) (x : α) (hi : i < n) (j : Nat) - (hj : j < n) (h : i ≠ j) : (xs.set i x hi)[j] = xs[j] := by simp [getElem_set, h] +@[simp] theorem getElem_set_ne {xs : Vector α n} {x : α} (hi : i < n) (hj : j < n) (h : i ≠ j) : + (xs.set i x hi)[j] = xs[j] := by simp [getElem_set, h] -theorem getElem?_set (xs : Vector α n) (i : Nat) (hi : i < n) (x : α) (j : Nat) : +theorem getElem?_set {xs : Vector α n} {x : α} (hi : i < n) : (xs.set i x hi)[j]? = if i = j then some x else xs[j]? := by cases xs split <;> simp_all [getElem?_eq_getElem, getElem_set] -@[simp] theorem getElem?_set_self (xs : Vector α n) (i : Nat) (hi : i < n) (x : α) : +@[simp] theorem getElem?_set_self {xs : Vector α n} {x : α} (hi : i < n) : (xs.set i x hi)[i]? = some x := by simp [getElem?_eq_getElem, hi] -@[simp] theorem getElem?_set_ne (xs : Vector α n) (i : Nat) (hi : i < n) (x : α) (j : Nat) - (h : i ≠ j) : (xs.set i x hi)[j]? = xs[j]? := by +@[simp] theorem getElem?_set_ne {xs : Vector α n} {x : α} (hi : i < n) (h : i ≠ j) : + (xs.set i x hi)[j]? = xs[j]? := by simp [getElem?_set, h] -@[simp] theorem set_getElem_self {xs : Vector α n} {i : Nat} (hi : i < n) : +@[simp] theorem set_getElem_self {xs : Vector α n} (hi : i < n) : xs.set i xs[i] hi = xs := by cases xs simp -theorem set_comm (a b : α) {i j : Nat} (xs : Vector α n) {hi : i < n} {hj : j < n} (h : i ≠ j) : +theorem set_comm (a b : α) {xs : Vector α n} {hi : i < n} {hj : j < n} (h : i ≠ j) : (xs.set i a hi).set j b hj = (xs.set j b hj).set i a hi := by cases xs simp [Array.set_comm, h] -@[simp] theorem set_set (a b : α) (xs : Vector α n) (i : Nat) (hi : i < n) : +@[simp] theorem set_set (a : α) {b : α} {xs : Vector α n} (hi : i < n) : (xs.set i a hi).set i b hi = xs.set i b hi := by cases xs simp -theorem mem_set (xs : Vector α n) (i : Nat) (hi : i < n) (a : α) : - a ∈ xs.set i a hi := by +theorem mem_set {xs : Vector α n} {i : Nat} {a : α} (hi : i < n) : a ∈ xs.set i a hi := by simp [mem_iff_getElem] exact ⟨i, (by simpa using hi), by simp⟩ @@ -1258,51 +1262,51 @@ theorem mem_or_eq_of_mem_set {xs : Vector α n} {i : Nat} {a b : α} {hi : i < n /-! ### setIfInBounds -/ -theorem getElem_setIfInBounds (xs : Vector α n) (i : Nat) (x : α) (j : Nat) - (hj : j < n) : (xs.setIfInBounds i x)[j] = if i = j then x else xs[j] := by +theorem getElem_setIfInBounds {xs : Vector α n} {x : α} (hj : j < n) : + (xs.setIfInBounds i x)[j] = if i = j then x else xs[j] := by cases xs split <;> simp_all [Array.getElem_setIfInBounds] -@[simp] theorem getElem_setIfInBounds_self (xs : Vector α n) (i : Nat) (x : α) (hi : i < n) : +@[simp] theorem getElem_setIfInBounds_self {xs : Vector α n} {x : α} (hi : i < n) : (xs.setIfInBounds i x)[i] = x := by simp [getElem_setIfInBounds, hi] @[deprecated getElem_setIfInBounds_self (since := "2024-12-12")] abbrev getElem_setIfInBounds_eq := @getElem_setIfInBounds_self -@[simp] theorem getElem_setIfInBounds_ne (xs : Vector α n) (i : Nat) (x : α) (j : Nat) - (hj : j < n) (h : i ≠ j) : (xs.setIfInBounds i x)[j] = xs[j] := by simp [getElem_setIfInBounds, h] +@[simp] theorem getElem_setIfInBounds_ne {xs : Vector α n} {x : α} (hj : j < n) (h : i ≠ j) : + (xs.setIfInBounds i x)[j] = xs[j] := by simp [getElem_setIfInBounds, h] -theorem getElem?_setIfInBounds (xs : Vector α n) (i : Nat) (x : α) (j : Nat) : +theorem getElem?_setIfInBounds {xs : Vector α n} {x : α} : (xs.setIfInBounds i x)[j]? = if i = j then if i < n then some x else none else xs[j]? := by rcases xs with ⟨xs, rfl⟩ simp [Array.getElem?_setIfInBounds] -theorem getElem?_setIfInBounds_self (xs : Vector α n) (i : Nat) (x : α) : +theorem getElem?_setIfInBounds_self {xs : Vector α n} {x : α} : (xs.setIfInBounds i x)[i]? = if i < n then some x else none := by simp [getElem?_setIfInBounds] -@[simp] theorem getElem?_setIfInBounds_self_of_lt (xs : Vector α n) (i : Nat) (x : α) (h : i < n) : +@[simp] theorem getElem?_setIfInBounds_self_of_lt {xs : Vector α n} {x : α} (h : i < n) : (xs.setIfInBounds i x)[i]? = some x := by simp [getElem?_setIfInBounds, h] -@[simp] theorem getElem?_setIfInBounds_ne (xs : Vector α n) (i : Nat) (x : α) (j : Nat) - (h : i ≠ j) : (xs.setIfInBounds i x)[j]? = xs[j]? := by simp [getElem?_setIfInBounds, h] +@[simp] theorem getElem?_setIfInBounds_ne {xs : Vector α n} {x : α} (h : i ≠ j) : + (xs.setIfInBounds i x)[j]? = xs[j]? := by simp [getElem?_setIfInBounds, h] theorem setIfInBounds_eq_of_size_le {xs : Vector α n} {i : Nat} (h : xs.size ≤ i) {a : α} : xs.setIfInBounds i a = xs := by rcases xs with ⟨xs, rfl⟩ simp [Array.setIfInBounds_eq_of_size_le (by simpa using h)] -theorem setIfInBound_comm (a b : α) {i j : Nat} (xs : Vector α n) (h : i ≠ j) : +theorem setIfInBound_comm (a b : α) {i j : Nat} {xs : Vector α n} (h : i ≠ j) : (xs.setIfInBounds i a).setIfInBounds j b = (xs.setIfInBounds j b).setIfInBounds i a := by rcases xs with ⟨xs, rfl⟩ simp only [setIfInBounds_mk, mk.injEq] - rw [Array.setIfInBounds_comm _ _ _ h] + rw [Array.setIfInBounds_comm _ _ h] -@[simp] theorem setIfInBounds_setIfInBounds (a b : α) (xs : Vector α n) (i : Nat) : +@[simp] theorem setIfInBounds_setIfInBounds (a : α) {b : α} {xs : Vector α n} : (xs.setIfInBounds i a).setIfInBounds i b = xs.setIfInBounds i b := by rcases xs with ⟨xs, rfl⟩ simp -theorem mem_setIfInBounds (xs : Vector α n) (i : Nat) (hi : i < n) (a : α) : +theorem mem_setIfInBounds {xs : Vector α n} {a : α} (hi : i < n) : a ∈ xs.setIfInBounds i a := by simp [mem_iff_getElem] exact ⟨i, (by simpa using hi), by simp⟩ @@ -1377,11 +1381,11 @@ abbrev mkVector_beq_mkVector := @replicate_beq_replicate /-! ### back -/ -theorem back_eq_getElem [NeZero n] (xs : Vector α n) : xs.back = xs[n - 1]'(by have := NeZero.ne n; omega) := by +theorem back_eq_getElem [NeZero n] {xs : Vector α n} : xs.back = xs[n - 1]'(by have := NeZero.ne n; omega) := by rcases xs with ⟨xs, rfl⟩ simp [Array.back_eq_getElem] -theorem back?_eq_getElem? (xs : Vector α n) : xs.back? = xs[n - 1]? := by +theorem back?_eq_getElem? {xs : Vector α n} : xs.back? = xs[n - 1]? := by rcases xs with ⟨xs, rfl⟩ simp [Array.back?_eq_getElem?] @@ -1391,21 +1395,22 @@ theorem back?_eq_getElem? (xs : Vector α n) : xs.back? = xs[n - 1]? := by /-! ### map -/ -@[simp] theorem getElem_map (f : α → β) (xs : Vector α n) (i : Nat) (hi : i < n) : +-- The argument `f : α → β` is explicit, to facilitate rewriting from right to left. +@[simp] theorem getElem_map (f : α → β) {xs : Vector α n} (hi : i < n) : (xs.map f)[i] = f xs[i] := by cases xs simp -@[simp] theorem getElem?_map (f : α → β) (xs : Vector α n) (i : Nat) : +@[simp] theorem getElem?_map {f : α → β} {xs : Vector α n} {i : Nat}: (xs.map f)[i]? = xs[i]?.map f := by cases xs simp /-- The empty vector maps to the empty vector. -/ @[simp] -theorem map_empty (f : α → β) : map f #v[] = #v[] := by +theorem map_empty {f : α → β} : map f #v[] = #v[] := by rw [map, mk.injEq] - exact Array.map_empty f + exact Array.map_empty @[simp] theorem map_push {f : α → β} {as : Vector α n} {x : α} : (as.push x).map f = (as.map f).push (f x) := by @@ -1420,18 +1425,21 @@ theorem map_empty (f : α → β) : map f #v[] = #v[] := by @[simp] theorem map_id_fun' : map (n := n) (fun (a : α) => a) = id := map_id_fun -- This is not a `@[simp]` lemma because `map_id_fun` will apply. +-- The argument `xs : Vector α n` is explicit to allow rewriting from right to left. theorem map_id (xs : Vector α n) : map (id : α → α) xs = xs := by cases xs <;> simp_all /-- `map_id'` differs from `map_id` by representing the identity function as a lambda, rather than `id`. -/ -- This is not a `@[simp]` lemma because `map_id_fun'` will apply. +-- The argument `xs : Vector α n` is explicit to allow rewriting from right to left. theorem map_id' (xs : Vector α n) : map (fun (a : α) => a) xs = xs := map_id xs /-- Variant of `map_id`, with a side condition that the function is pointwise the identity. -/ +-- The argument `xs : Vector α n` is explicit to allow rewriting from right to left. theorem map_id'' {f : α → α} (h : ∀ x, f x = x) (xs : Vector α n) : map f xs = xs := by simp [show f = id from funext h] -theorem map_singleton (f : α → β) (a : α) : map f #v[a] = #v[f a] := by simp +theorem map_singleton {f : α → β} {a : α} : map f #v[a] = #v[f a] := by simp -- We use a lower priority here as there are more specific lemmas in downstream libraries -- which should be able to fire first. @@ -1441,7 +1449,7 @@ theorem map_singleton (f : α → β) (a : α) : map f #v[a] = #v[f a] := by sim theorem exists_of_mem_map (h : b ∈ map f xs) : ∃ a, a ∈ xs ∧ f a = b := mem_map.1 h -theorem mem_map_of_mem (f : α → β) (h : a ∈ xs) : f a ∈ map f xs := mem_map.2 ⟨_, h, rfl⟩ +theorem mem_map_of_mem {f : α → β} (h : a ∈ xs) : f a ∈ map f xs := mem_map.2 ⟨_, h, rfl⟩ theorem forall_mem_map {f : α → β} {xs : Vector α n} {P : β → Prop} : (∀ (i) (_ : i ∈ xs.map f), P i) ↔ ∀ (j) (_ : j ∈ xs), P (f j) := by @@ -1561,7 +1569,7 @@ theorem vector₃_induction (P : Vector (Vector (Vector α n) m) k → Prop) /-! ### singleton -/ -@[simp] theorem singleton_def (v : α) : Vector.singleton v = #v[v] := rfl +@[simp] theorem singleton_def {v : α} : Vector.singleton v = #v[v] := rfl /-! ### append -/ @@ -1571,7 +1579,7 @@ theorem vector₃_induction (P : Vector (Vector (Vector α n) m) k → Prop) cases bs simp -theorem singleton_eq_toVector_singleton (a : α) : #v[a] = #[a].toVector := rfl +theorem singleton_eq_toVector_singleton {a : α} : #v[a] = #[a].toVector := rfl @[simp] theorem mem_append {a : α} {xs : Vector α n} {ys : Vector α m} : a ∈ xs ++ ys ↔ a ∈ xs ∨ a ∈ ys := by @@ -1609,34 +1617,34 @@ theorem forall_mem_append {p : α → Prop} {xs : Vector α n} {ys : Vector α m (∀ (x) (_ : x ∈ xs ++ ys), p x) ↔ (∀ (x) (_ : x ∈ xs), p x) ∧ (∀ (x) (_ : x ∈ ys), p x) := by simp only [mem_append, or_imp, forall_and] -theorem empty_append (xs : Vector α n) : (#v[] : Vector α 0) ++ xs = xs.cast (by omega) := by +theorem empty_append {xs : Vector α n} : (#v[] : Vector α 0) ++ xs = xs.cast (by omega) := by rcases xs with ⟨as, rfl⟩ simp -theorem append_empty (xs : Vector α n) : xs ++ (#v[] : Vector α 0) = xs := by +theorem append_empty {xs : Vector α n} : xs ++ (#v[] : Vector α 0) = xs := by rw [← toArray_inj, toArray_append, Array.append_empty] -theorem getElem_append (xs : Vector α n) (ys : Vector α m) (i : Nat) (hi : i < n + m) : +theorem getElem_append {xs : Vector α n} {ys : Vector α m} (hi : i < n + m) : (xs ++ ys)[i] = if h : i < n then xs[i] else ys[i - n] := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, rfl⟩ simp [Array.getElem_append, hi] @[simp] -theorem getElem_append_left {xs : Vector α n} {ys : Vector α m} {i : Nat} (hi : i < n) : +theorem getElem_append_left {xs : Vector α n} {ys : Vector α m} (hi : i < n) : (xs ++ ys)[i] = xs[i] := by simp [getElem_append, hi] @[simp] -theorem getElem_append_right {xs : Vector α n} {ys : Vector α m} {i : Nat} (h : i < n + m) (hi : n ≤ i) : +theorem getElem_append_right {xs : Vector α n} {ys : Vector α m} (h : i < n + m) (hi : n ≤ i) : (xs ++ ys)[i] = ys[i - n] := by rw [getElem_append, dif_neg (by omega)] -theorem getElem?_append_left {xs : Vector α n} {ys : Vector α m} {i : Nat} (hn : i < n) : +theorem getElem?_append_left {xs : Vector α n} {ys : Vector α m} (hn : i < n) : (xs ++ ys)[i]? = xs[i]? := by have hn' : i < n + m := by omega simp_all [getElem?_eq_getElem, getElem_append] -theorem getElem?_append_right {xs : Vector α n} {ys : Vector α m} {i : Nat} (h : n ≤ i) : +theorem getElem?_append_right {xs : Vector α n} {ys : Vector α m} (h : n ≤ i) : (xs ++ ys)[i]? = ys[i - n]? := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, rfl⟩ @@ -1649,12 +1657,12 @@ theorem getElem?_append {xs : Vector α n} {ys : Vector α m} {i : Nat} : · exact getElem?_append_right (by simpa using h) /-- Variant of `getElem_append_left` useful for rewriting from the small array to the big array. -/ -theorem getElem_append_left' (xs : Vector α m) {ys : Vector α n} {i : Nat} (hi : i < m) : +theorem getElem_append_left' {xs : Vector α m} (hi : i < m) (ys : Vector α n) : xs[i] = (xs ++ ys)[i] := by rw [getElem_append_left] <;> simp /-- Variant of `getElem_append_right` useful for rewriting from the small array to the big array. -/ -theorem getElem_append_right' (xs : Vector α m) {ys : Vector α n} {i : Nat} (hi : i < n) : +theorem getElem_append_right' (xs : Vector α m) {ys : Vector α n} (hi : i < n) : ys[i] = (xs ++ ys)[i + m] := by rw [getElem_append_right] <;> simp [*, Nat.le_add_left] @@ -1760,7 +1768,7 @@ theorem setIfInBounds_append {xs : Vector α n} {ys : Vector α m} {i : Nat} {x (xs ++ ys).setIfInBounds i x = xs ++ ys.setIfInBounds (i - n) x := by rw [setIfInBounds_append, if_neg (by omega)] -@[simp] theorem map_append (f : α → β) (xs : Vector α n) (ys : Vector α m) : +@[simp] theorem map_append {f : α → β} {xs : Vector α n} {ys : Vector α m} : map f (xs ++ ys) = map f xs ++ map f ys := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, rfl⟩ @@ -1786,12 +1794,12 @@ theorem append_eq_map_iff {f : α → β} : /-! ### flatten -/ set_option linter.listVariables false in -@[simp] theorem flatten_mk (xss : Array (Vector α n)) (h : xss.size = m) : +@[simp] theorem flatten_mk {xss : Array (Vector α n)} (h : xss.size = m) : (mk xss h).flatten = mk (xss.map toArray).flatten (by simp [Function.comp_def, Array.map_const', h]) := by simp [flatten] -@[simp] theorem getElem_flatten (xss : Vector (Vector β m) n) (i : Nat) (hi : i < n * m) : +@[simp] theorem getElem_flatten {xss : Vector (Vector β m) n} {i : Nat} (hi : i < n * m) : xss.flatten[i] = haveI : i / m < n := by rwa [Nat.div_lt_iff_lt_mul (Nat.pos_of_lt_mul_left hi)] haveI : i % m < m := Nat.mod_lt _ (Nat.pos_of_lt_mul_left hi) @@ -1810,7 +1818,7 @@ set_option linter.listVariables false in · have h₁ : xs.toList.length ≤ i := by simp; omega rw [List.getElem_append_right h₁] simp only [Array.length_toList, size_toArray] - specialize ih (i - m) (by simp_all [Nat.add_one_mul]; omega) + specialize ih (i := i - m) (by simp_all [Nat.add_one_mul]; omega) have h₂ : i / m = (i - m) / m + 1 := by conv => lhs; rw [show i = i - m + m by omega] rw [Nat.add_div_right] @@ -1819,7 +1827,7 @@ set_option linter.listVariables false in have h₃ : (i - m) % m = i % m := (Nat.mod_eq_sub_mod h₁).symm simp_all -theorem getElem?_flatten (xss : Vector (Vector β m) n) (i : Nat) : +theorem getElem?_flatten {xss : Vector (Vector β m) n} {i : Nat} : xss.flatten[i]? = if hi : i < n * m then haveI : i / m < n := by rwa [Nat.div_lt_iff_lt_mul (Nat.pos_of_lt_mul_left hi)] @@ -1829,7 +1837,7 @@ theorem getElem?_flatten (xss : Vector (Vector β m) n) (i : Nat) : none := by simp [getElem?_def] -@[simp] theorem flatten_singleton (xs : Vector α n) : #v[xs].flatten = xs.cast (by simp) := by +@[simp] theorem flatten_singleton {xs : Vector α n} : #v[xs].flatten = xs.cast (by simp) := by simp [flatten] set_option linter.listVariables false in @@ -1851,18 +1859,18 @@ theorem forall_mem_flatten {p : α → Prop} {xss : Vector (Vector α n) m} : simp only [mem_flatten, forall_exists_index, and_imp] constructor <;> (intros; solve_by_elim) -@[simp] theorem map_flatten (f : α → β) (xss : Vector (Vector α n) m) : +@[simp] theorem map_flatten {f : α → β} {xss : Vector (Vector α n) m} : (flatten xss).map f = (map (map f) xss).flatten := by induction xss using vector₂_induction with | of xss h₁ h₂ => simp -@[simp] theorem flatten_append (xss₁ : Vector (Vector α n) m₁) (xss₂ : Vector (Vector α n) m₂) : +@[simp] theorem flatten_append {xss₁ : Vector (Vector α n) m₁} {xss₂ : Vector (Vector α n) m₂} : flatten (xss₁ ++ xss₂) = (flatten xss₁ ++ flatten xss₂).cast (by simp [Nat.add_mul]) := by induction xss₁ using vector₂_induction induction xss₂ using vector₂_induction simp -theorem flatten_push (xss : Vector (Vector α n) m) (xs : Vector α n) : +theorem flatten_push {xss : Vector (Vector α n) m} {xs : Vector α n} : flatten (xss.push xs) = (flatten xss ++ xs).cast (by simp [Nat.add_mul]) := by induction xss using vector₂_induction rcases xs with ⟨xs⟩ @@ -1903,23 +1911,23 @@ theorem eq_iff_flatten_eq {xss xss' : Vector (Vector α n) m} : /-! ### flatMap -/ -@[simp] theorem flatMap_toArray (xs : Vector α n) (f : α → Vector β m) : +@[simp] theorem flatMap_toArray {xs : Vector α n} {f : α → Vector β m} : xs.toArray.flatMap (fun a => (f a).toArray) = (xs.flatMap f).toArray := by rcases xs with ⟨xs, rfl⟩ simp -theorem flatMap_def (xs : Vector α n) (f : α → Vector β m) : xs.flatMap f = flatten (map f xs) := by +theorem flatMap_def {xs : Vector α n} {f : α → Vector β m} : xs.flatMap f = flatten (map f xs) := by rcases xs with ⟨xs, rfl⟩ simp [Array.flatMap_def, Function.comp_def] -@[simp] theorem getElem_flatMap (xs : Vector α n) (f : α → Vector β m) (i : Nat) (hi : i < n * m) : +@[simp] theorem getElem_flatMap {xs : Vector α n} {f : α → Vector β m} {i : Nat} (hi : i < n * m) : (xs.flatMap f)[i] = haveI : i / m < n := by rwa [Nat.div_lt_iff_lt_mul (Nat.pos_of_lt_mul_left hi)] haveI : i % m < m := Nat.mod_lt _ (Nat.pos_of_lt_mul_left hi) (f (xs[i / m]))[i % m] := by rw [flatMap_def, getElem_flatten, getElem_map] -theorem getElem?_flatMap (xs : Vector α n) (f : α → Vector β m) (i : Nat) : +theorem getElem?_flatMap {xs : Vector α n} {f : α → Vector β m} {i : Nat} : (xs.flatMap f)[i]? = if hi : i < n * m then haveI : i / m < n := by rwa [Nat.div_lt_iff_lt_mul (Nat.pos_of_lt_mul_left hi)] @@ -1929,9 +1937,9 @@ theorem getElem?_flatMap (xs : Vector α n) (f : α → Vector β m) (i : Nat) : none := by simp [getElem?_def] -@[simp] theorem flatMap_id (xss : Vector (Vector α m) n) : xss.flatMap id = xss.flatten := by simp [flatMap_def] +@[simp] theorem flatMap_id {xss : Vector (Vector α m) n} : xss.flatMap id = xss.flatten := by simp [flatMap_def] -@[simp] theorem flatMap_id' (xss : Vector (Vector α m) n) : xss.flatMap (fun xs => xs) = xss.flatten := by simp [flatMap_def] +@[simp] theorem flatMap_id' {xss : Vector (Vector α m) n} : xss.flatMap (fun xs => xs) = xss.flatten := by simp [flatMap_def] @[simp] theorem mem_flatMap {f : α → Vector β m} {b} {xs : Vector α n} : b ∈ xs.flatMap f ↔ ∃ a, a ∈ xs ∧ b ∈ f a := by simp [flatMap_def, mem_flatten] @@ -1948,35 +1956,35 @@ theorem forall_mem_flatMap {p : β → Prop} {xs : Vector α n} {f : α → Vect simp only [mem_flatMap, forall_exists_index, and_imp] constructor <;> (intros; solve_by_elim) -theorem flatMap_singleton (f : α → Vector β m) (x : α) : #v[x].flatMap f = (f x).cast (by simp) := by +theorem flatMap_singleton {f : α → Vector β m} {x : α} : #v[x].flatMap f = (f x).cast (by simp) := by simp [flatMap_def] -@[simp] theorem flatMap_singleton' (xs : Vector α n) : (xs.flatMap fun x => #v[x]) = xs.cast (by simp) := by +@[simp] theorem flatMap_singleton' {xs : Vector α n} : (xs.flatMap fun x => #v[x]) = xs.cast (by simp) := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem flatMap_append (xs ys : Vector α n) (f : α → Vector β m) : +@[simp] theorem flatMap_append {xs ys : Vector α n} {f : α → Vector β m} : (xs ++ ys).flatMap f = (xs.flatMap f ++ ys.flatMap f).cast (by simp [Nat.add_mul]) := by rcases xs with ⟨xs⟩ rcases ys with ⟨ys⟩ simp [flatMap_def, flatten_append] -theorem flatMap_assoc {xs : Vector α n} (f : α → Vector β m) (g : β → Vector γ k) : +theorem flatMap_assoc {xs : Vector α n} {f : α → Vector β m} {g : β → Vector γ k} : (xs.flatMap f).flatMap g = (xs.flatMap fun x => (f x).flatMap g).cast (by simp [Nat.mul_assoc]) := by rcases xs with ⟨xs, rfl⟩ simp [Array.flatMap_assoc] -theorem map_flatMap (f : β → γ) (g : α → Vector β m) (xs : Vector α n) : +theorem map_flatMap {f : β → γ} {g : α → Vector β m} {xs : Vector α n} : (xs.flatMap g).map f = xs.flatMap fun a => (g a).map f := by rcases xs with ⟨xs, rfl⟩ simp [Array.map_flatMap] -theorem flatMap_map (f : α → β) (g : β → Vector γ k) (xs : Vector α n) : +theorem flatMap_map {f : α → β} {g : β → Vector γ k} {xs : Vector α n} : (map f xs).flatMap g = xs.flatMap (fun a => g (f a)) := by rcases xs with ⟨xs, rfl⟩ simp [Array.flatMap_map] -theorem map_eq_flatMap {α β} (f : α → β) (xs : Vector α n) : +theorem map_eq_flatMap {f : α → β} {xs : Vector α n} : map f xs = (xs.flatMap fun x => #v[f x]).cast (by simp) := by rcases xs with ⟨xs, rfl⟩ simp [Array.map_eq_flatMap] @@ -2016,14 +2024,14 @@ theorem forall_mem_replicate {p : α → Prop} {a : α} {n} : @[deprecated forall_mem_replicate (since := "2025-03-18")] abbrev forall_mem_mkVector := @forall_mem_replicate -@[simp] theorem getElem_replicate (a : α) (n i : Nat) (h : i < n) : (replicate n a)[i] = a := by +@[simp] theorem getElem_replicate {a : α} (h : i < n) : (replicate n a)[i] = a := by rw [replicate_eq_mk_replicate, getElem_mk] simp @[deprecated getElem_replicate (since := "2025-03-18")] abbrev getElem_mkVector := @getElem_replicate -theorem getElem?_replicate (a : α) (n i : Nat) : (replicate n a)[i]? = if i < n then some a else none := by +theorem getElem?_replicate {a : α} {n i : Nat} : (replicate n a)[i]? = if i < n then some a else none := by simp [getElem?_def] @[deprecated getElem?_replicate (since := "2025-03-18")] @@ -2057,17 +2065,17 @@ theorem map_eq_replicate_iff {xs : Vector α n} {f : α → β} {b : β} : @[deprecated map_eq_replicate_iff (since := "2025-03-18")] abbrev map_eq_mkVector_iff := @map_eq_replicate_iff -@[simp] theorem map_const (xs : Vector α n) (b : β) : map (Function.const α b) xs = replicate n b := +@[simp] theorem map_const {xs : Vector α n} {b : β} : map (Function.const α b) xs = replicate n b := map_eq_replicate_iff.mpr fun _ _ => rfl -@[simp] theorem map_const_fun (x : β) : map (n := n) (Function.const α x) = fun _ => replicate n x := by +@[simp] theorem map_const_fun {x : β} : map (n := n) (Function.const α x) = fun _ => replicate n x := by funext xs simp /-- Variant of `map_const` using a lambda rather than `Function.const`. -/ -- This can not be a `@[simp]` lemma because it would fire on every `List.map`. -theorem map_const' (xs : Vector α n) (b : β) : map (fun _ => b) xs = replicate n b := - map_const xs b +theorem map_const' {xs : Vector α n} {b : β} : map (fun _ => b) xs = replicate n b := + map_const @[simp] theorem set_replicate_self : (replicate n a).set i a h = replicate n a := by rw [← toArray_inj] @@ -2132,14 +2140,14 @@ abbrev flatten_mkVector_singleton := @flatten_replicate_singleton @[deprecated flatten_replicate_replicate (since := "2025-03-18")] abbrev flatten_mkVector_mkVector := @flatten_replicate_replicate -theorem flatMap_replicate {β} (f : α → Vector β m) : (replicate n a).flatMap f = (replicate n (f a)).flatten := by +theorem flatMap_replicate {f : α → Vector β m} : (replicate n a).flatMap f = (replicate n (f a)).flatten := by ext i h simp [h] @[deprecated flatMap_replicate (since := "2025-03-18")] abbrev flatMap_mkVector := @flatMap_replicate -@[simp] theorem sum_replicate_nat (n : Nat) (a : Nat) : (replicate n a).sum = n * a := by +@[simp] theorem sum_replicate_nat {n : Nat} {a : Nat} : (replicate n a).sum = n * a := by simp [toArray_replicate] @[deprecated sum_replicate_nat (since := "2025-03-18")] @@ -2147,7 +2155,7 @@ abbrev sum_mkVector := @sum_replicate_nat /-! ### reverse -/ -@[simp] theorem reverse_push (as : Vector α n) (a : α) : +@[simp] theorem reverse_push {as : Vector α n} {a : α} : (as.push a).reverse = (#v[a] ++ as.reverse).cast (by omega) := by rcases as with ⟨as, rfl⟩ simp [Array.reverse_push] @@ -2160,21 +2168,21 @@ abbrev sum_mkVector := @sum_replicate_nat rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem getElem_reverse (xs : Vector α n) (i : Nat) (hi : i < n) : +@[simp] theorem getElem_reverse {xs : Vector α n} {i : Nat} (hi : i < n) : (xs.reverse)[i] = xs[n - 1 - i] := by rcases xs with ⟨xs, rfl⟩ simp -theorem getElem_eq_getElem_reverse {xs : Vector α n} {i} (h : i < n) : +theorem getElem_eq_getElem_reverse {xs : Vector α n} {i : Nat} (h : i < n) : xs[i] = xs.reverse[n - 1 - i] := by rw [getElem_reverse] congr omega /-- Variant of `getElem?_reverse` with a hypothesis giving the linear relation between the indices. -/ -theorem getElem?_reverse' {xs : Vector α n} (i j) (h : i + j + 1 = n) : xs.reverse[i]? = xs[j]? := by +theorem getElem?_reverse' {xs : Vector α n} {i j : Nat} (h : i + j + 1 = n) : xs.reverse[i]? = xs[j]? := by rcases xs with ⟨xs, rfl⟩ - simpa using Array.getElem?_reverse' i j h + simpa using Array.getElem?_reverse' h @[simp] theorem getElem?_reverse {xs : Vector α n} {i} (h : i < n) : @@ -2182,6 +2190,7 @@ theorem getElem?_reverse {xs : Vector α n} {i} (h : i < n) : cases xs simp_all +-- The argument `xs : Vector α n` is explicit so we can rewrite from right to left. @[simp] theorem reverse_reverse (xs : Vector α n) : xs.reverse.reverse = xs := by rcases xs with ⟨xs, rfl⟩ simp [Array.reverse_reverse] @@ -2198,11 +2207,11 @@ theorem reverse_eq_iff {xs ys : Vector α n} : xs.reverse = ys ↔ xs = ys.rever rcases ys with ⟨ys, rfl⟩ simp [Array.reverse_eq_push_iff] -@[simp] theorem map_reverse (f : α → β) (xs : Vector α n) : xs.reverse.map f = (xs.map f).reverse := by +@[simp] theorem map_reverse {f : α → β} {xs : Vector α n} : xs.reverse.map f = (xs.map f).reverse := by rcases xs with ⟨xs, rfl⟩ simp [Array.map_reverse] -@[simp] theorem reverse_append (xs : Vector α n) (ys : Vector α m) : +@[simp] theorem reverse_append {xs : Vector α n} {ys : Vector α m} : (xs ++ ys).reverse = (ys.reverse ++ xs.reverse).cast (by omega) := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, rfl⟩ @@ -2216,28 +2225,28 @@ theorem reverse_eq_iff {xs ys : Vector α n} : xs.reverse = ys ↔ xs = ys.rever simp /-- Reversing a flatten is the same as reversing the order of parts and reversing all parts. -/ -theorem reverse_flatten (xss : Vector (Vector α m) n) : +theorem reverse_flatten {xss : Vector (Vector α m) n} : xss.flatten.reverse = (xss.map reverse).reverse.flatten := by cases xss using vector₂_induction simp [Array.reverse_flatten] /-- Flattening a reverse is the same as reversing all parts and reversing the flattened result. -/ -theorem flatten_reverse (xss : Vector (Vector α m) n) : +theorem flatten_reverse {xss : Vector (Vector α m) n} : xss.reverse.flatten = (xss.map reverse).flatten.reverse := by cases xss using vector₂_induction simp [Array.flatten_reverse] -theorem reverse_flatMap {β} (xs : Vector α n) (f : α → Vector β m) : +theorem reverse_flatMap {xs : Vector α n} {f : α → Vector β m} : (xs.flatMap f).reverse = xs.reverse.flatMap (reverse ∘ f) := by rcases xs with ⟨xs, rfl⟩ simp [Array.reverse_flatMap, Function.comp_def] -theorem flatMap_reverse {β} (xs : Vector α n) (f : α → Vector β m) : +theorem flatMap_reverse {xs : Vector α n} {f : α → Vector β m} : (xs.reverse.flatMap f) = (xs.flatMap (reverse ∘ f)).reverse := by rcases xs with ⟨xs, rfl⟩ simp [Array.flatMap_reverse, Function.comp_def] -@[simp] theorem reverse_replicate (n) (a : α) : reverse (replicate n a) = replicate n a := by +@[simp] theorem reverse_replicate {n : Nat} {a : α} : reverse (replicate n a) = replicate n a := by rw [← toArray_inj] simp @@ -2258,72 +2267,72 @@ theorem getElem?_extract {as : Vector α n} {start stop : Nat} : simp [Array.getElem?_extract] set_option linter.indexVariables false in -@[simp] theorem extract_size (as : Vector α n) : as.extract 0 n = as.cast (by simp) := by +@[simp] theorem extract_size {as : Vector α n} : as.extract 0 n = as.cast (by simp) := by rcases as with ⟨as, rfl⟩ simp -theorem extract_empty (start stop : Nat) : +theorem extract_empty {start stop : Nat} : (#v[] : Vector α 0).extract start stop = #v[].cast (by simp) := by simp /-! ### foldlM and foldrM -/ -@[simp] theorem foldlM_append [Monad m] [LawfulMonad m] (f : β → α → m β) (b) (xs : Vector α n) (ys : Vector α k) : +@[simp] theorem foldlM_append [Monad m] [LawfulMonad m] {f : β → α → m β} {b} {xs : Vector α n} {ys : Vector α k} : (xs ++ ys).foldlM f b = xs.foldlM f b >>= ys.foldlM f := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, rfl⟩ simp -@[simp] theorem foldlM_empty [Monad m] (f : β → α → m β) (init : β) : +@[simp] theorem foldlM_empty [Monad m] {f : β → α → m β} {init : β} : foldlM f init #v[] = return init := by simp [foldlM] -@[simp] theorem foldrM_empty [Monad m] (f : α → β → m β) (init : β) : +@[simp] theorem foldrM_empty [Monad m] {f : α → β → m β} {init : β} : foldrM f init #v[] = return init := by simp [foldrM] -@[simp] theorem foldlM_push [Monad m] [LawfulMonad m] (xs : Vector α n) (a : α) (f : β → α → m β) (b) : +@[simp] theorem foldlM_push [Monad m] [LawfulMonad m] {xs : Vector α n} {a : α} {f : β → α → m β} {b} : (xs.push a).foldlM f b = xs.foldlM f b >>= fun b => f b a := by rcases xs with ⟨xs, rfl⟩ simp @[simp] -theorem foldlM_pure [Monad m] [LawfulMonad m] (f : β → α → β) (b) (xs : Vector α n) : +theorem foldlM_pure [Monad m] [LawfulMonad m] {f : β → α → β} {b} {xs : Vector α n} : xs.foldlM (m := m) (pure <| f · ·) b = pure (xs.foldl f b) := - Array.foldlM_pure _ _ _ + Array.foldlM_pure @[simp] -theorem foldrM_pure [Monad m] [LawfulMonad m] (f : α → β → β) (b) (xs : Vector α n) : +theorem foldrM_pure [Monad m] [LawfulMonad m] {f : α → β → β} {b} {xs : Vector α n} : xs.foldrM (m := m) (pure <| f · ·) b = pure (xs.foldr f b) := - Array.foldrM_pure _ _ _ + Array.foldrM_pure -theorem foldl_eq_foldlM (f : β → α → β) (b) (xs : Vector α n) : +theorem foldl_eq_foldlM {f : β → α → β} {b} {xs : Vector α n} : xs.foldl f b = xs.foldlM (m := Id) f b := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldl_eq_foldlM] -theorem foldr_eq_foldrM (f : α → β → β) (b) (xs : Vector α n) : +theorem foldr_eq_foldrM {f : α → β → β} {b} {xs : Vector α n} : xs.foldr f b = xs.foldrM (m := Id) f b := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldr_eq_foldrM] -@[simp] theorem id_run_foldlM (f : β → α → Id β) (b) (xs : Vector α n) : - Id.run (xs.foldlM f b) = xs.foldl f b := (foldl_eq_foldlM f b xs).symm +@[simp] theorem id_run_foldlM {f : β → α → Id β} {b} {xs : Vector α n} : + Id.run (xs.foldlM f b) = xs.foldl f b := foldl_eq_foldlM.symm -@[simp] theorem id_run_foldrM (f : α → β → Id β) (b) (xs : Vector α n) : - Id.run (xs.foldrM f b) = xs.foldr f b := (foldr_eq_foldrM f b xs).symm +@[simp] theorem id_run_foldrM {f : α → β → Id β} {b} {xs : Vector α n} : + Id.run (xs.foldrM f b) = xs.foldr f b := foldr_eq_foldrM.symm -@[simp] theorem foldlM_reverse [Monad m] (xs : Vector α n) (f : β → α → m β) (b) : +@[simp] theorem foldlM_reverse [Monad m] {xs : Vector α n} {f : β → α → m β} {b} : xs.reverse.foldlM f b = xs.foldrM (fun x y => f y x) b := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldlM_reverse] -@[simp] theorem foldrM_reverse [Monad m] (xs : Vector α n) (f : α → β → m β) (b) : +@[simp] theorem foldrM_reverse [Monad m] {xs : Vector α n} {f : α → β → m β} {b} : xs.reverse.foldrM f b = xs.foldlM (fun x y => f y x) b := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem foldrM_push [Monad m] (f : α → β → m β) (init : β) (xs : Vector α n) (a : α) : +@[simp] theorem foldrM_push [Monad m] {f : α → β → m β} {init : β} {xs : Vector α n} {a : α} : (xs.push a).foldrM f init = f a init >>= xs.foldrM f := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldrM_push] @@ -2342,131 +2351,133 @@ theorem foldr_congr {xs ys : Vector α n} (h₀ : xs = ys) {f g : α → β → xs.foldr f a = ys.foldr g b := by congr -@[simp] theorem foldr_push (f : α → β → β) (init : β) (xs : Vector α n) (a : α) : +@[simp] theorem foldr_push {f : α → β → β} {init : β} {xs : Vector α n} {a : α} : (xs.push a).foldr f init = xs.foldr f (f a init) := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldr_push] -theorem foldl_map (f : β₁ → β₂) (g : α → β₂ → α) (xs : Vector β₁ n) (init : α) : +theorem foldl_map {f : β₁ → β₂} {g : α → β₂ → α} {xs : Vector β₁ n} {init : α} : (xs.map f).foldl g init = xs.foldl (fun x y => g x (f y)) init := by cases xs; simp [Array.foldl_map'] -theorem foldr_map (f : α₁ → α₂) (g : α₂ → β → β) (xs : Vector α₁ n) (init : β) : +theorem foldr_map {f : α₁ → α₂} {g : α₂ → β → β} {xs : Vector α₁ n} {init : β} : (xs.map f).foldr g init = xs.foldr (fun x y => g (f x) y) init := by cases xs; simp [Array.foldr_map'] -theorem foldl_filterMap (f : α → Option β) (g : γ → β → γ) (xs : Vector α n) (init : γ) : +theorem foldl_filterMap {f : α → Option β} {g : γ → β → γ} {xs : Vector α n} {init : γ} : (xs.filterMap f).foldl g init = xs.foldl (fun x y => match f y with | some b => g x b | none => x) init := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldl_filterMap'] rfl -theorem foldr_filterMap (f : α → Option β) (g : β → γ → γ) (xs : Vector α n) (init : γ) : +theorem foldr_filterMap {f : α → Option β} {g : β → γ → γ} {xs : Vector α n} {init : γ} : (xs.filterMap f).foldr g init = xs.foldr (fun x y => match f x with | some b => g b y | none => y) init := by cases xs; simp [Array.foldr_filterMap'] rfl -theorem foldl_map_hom (g : α → β) (f : α → α → α) (f' : β → β → β) (a : α) (xs : Vector α n) +theorem foldl_map_hom {g : α → β} {f : α → α → α} {f' : β → β → β} {a : α} {xs : Vector α n} (h : ∀ x y, f' (g x) (g y) = g (f x y)) : (xs.map g).foldl f' (g a) = g (xs.foldl f a) := by rcases xs with ⟨xs, rfl⟩ simp - rw [Array.foldl_map_hom' _ _ _ _ _ h rfl] + rw [Array.foldl_map_hom' h rfl] -theorem foldr_map_hom (g : α → β) (f : α → α → α) (f' : β → β → β) (a : α) (xs : Vector α n) +theorem foldr_map_hom {g : α → β} {f : α → α → α} {f' : β → β → β} {a : α} {xs : Vector α n} (h : ∀ x y, f' (g x) (g y) = g (f x y)) : (xs.map g).foldr f' (g a) = g (xs.foldr f a) := by rcases xs with ⟨xs, rfl⟩ simp - rw [Array.foldr_map_hom' _ _ _ _ _ h rfl] + rw [Array.foldr_map_hom' h rfl] -@[simp] theorem foldrM_append [Monad m] [LawfulMonad m] (f : α → β → m β) (b) (xs : Vector α n) (ys : Vector α k) : +@[simp] theorem foldrM_append [Monad m] [LawfulMonad m] {f : α → β → m β} {b} {xs : Vector α n} {ys : Vector α k} : (xs ++ ys).foldrM f b = ys.foldrM f b >>= xs.foldrM f := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, rfl⟩ simp -@[simp] theorem foldl_append {β : Type _} (f : β → α → β) (b) (xs : Vector α n) (ys : Vector α k) : +@[simp] theorem foldl_append {β : Type _} {f : β → α → β} {b} {xs : Vector α n} {ys : Vector α k} : (xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) := by simp [foldl_eq_foldlM] -@[simp] theorem foldr_append (f : α → β → β) (b) (xs : Vector α n) (ys : Vector α k) : +@[simp] theorem foldr_append {f : α → β → β} {b} {xs : Vector α n} {ys : Vector α k} : (xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) := by simp [foldr_eq_foldrM] -@[simp] theorem foldl_flatten (f : β → α → β) (b : β) (xss : Vector (Vector α m) n) : +@[simp] theorem foldl_flatten {f : β → α → β} {b} {xss : Vector (Vector α m) n} : (flatten xss).foldl f b = xss.foldl (fun b xs => xs.foldl f b) b := by cases xss using vector₂_induction simp [Array.foldl_flatten', Array.foldl_map'] -@[simp] theorem foldr_flatten (f : α → β → β) (b : β) (xss : Vector (Vector α m) n) : +@[simp] theorem foldr_flatten {f : α → β → β} {b} {xss : Vector (Vector α m) n} : (flatten xss).foldr f b = xss.foldr (fun xs b => xs.foldr f b) b := by cases xss using vector₂_induction simp [Array.foldr_flatten', Array.foldr_map'] -@[simp] theorem foldl_reverse (xs : Vector α n) (f : β → α → β) (b) : +@[simp] theorem foldl_reverse {xs : Vector α n} {f : β → α → β} {b} : xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b := by simp [foldl_eq_foldlM, foldr_eq_foldrM] -@[simp] theorem foldr_reverse (xs : Vector α n) (f : α → β → β) (b) : +@[simp] theorem foldr_reverse {xs : Vector α n} {f : α → β → β} {b} : xs.reverse.foldr f b = xs.foldl (fun x y => f y x) b := (foldl_reverse ..).symm.trans <| by simp -theorem foldl_eq_foldr_reverse (xs : Vector α n) (f : β → α → β) (b) : +theorem foldl_eq_foldr_reverse {xs : Vector α n} {f : β → α → β} {b} : xs.foldl f b = xs.reverse.foldr (fun x y => f y x) b := by simp -theorem foldr_eq_foldl_reverse (xs : Vector α n) (f : α → β → β) (b) : +theorem foldr_eq_foldl_reverse {xs : Vector α n} {f : α → β → β} {b} : xs.foldr f b = xs.reverse.foldl (fun x y => f y x) b := by simp -theorem foldl_assoc {op : α → α → α} [ha : Std.Associative op] (xs : Vector α n) (a₁ a₂) : +theorem foldl_assoc {op : α → α → α} [ha : Std.Associative op] {xs : Vector α n} {a₁ a₂} : xs.foldl op (op a₁ a₂) = op a₁ (xs.foldl op a₂) := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldl_assoc] -@[simp] theorem foldr_assoc {op : α → α → α} [ha : Std.Associative op] (xs : Vector α n) (a₁ a₂) : +@[simp] theorem foldr_assoc {op : α → α → α} [ha : Std.Associative op] {xs : Vector α n} {a₁ a₂} : xs.foldr op (op a₁ a₂) = op (xs.foldr op a₁) a₂ := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldr_assoc] -theorem foldl_hom (f : α₁ → α₂) (g₁ : α₁ → β → α₁) (g₂ : α₂ → β → α₂) (xs : Vector β n) (init : α₁) +-- The argument `f : α₁ → α₂` is intentionally explicit, as it is sometimes not found by unification. +theorem foldl_hom (f : α₁ → α₂) {g₁ : α₁ → β → α₁} {g₂ : α₂ → β → α₂} {xs : Vector β n} {init : α₁} (H : ∀ x y, g₂ (f x) y = f (g₁ x y)) : xs.foldl g₂ (f init) = f (xs.foldl g₁ init) := by rcases xs with ⟨xs, rfl⟩ simp - rw [Array.foldl_hom _ _ _ _ _ H] + rw [Array.foldl_hom _ H] -theorem foldr_hom (f : β₁ → β₂) (g₁ : α → β₁ → β₁) (g₂ : α → β₂ → β₂) (xs : Vector α n) (init : β₁) +-- The argument `f : β₁ → β₂` is intentionally explicit, as it is sometimes not found by unification. +theorem foldr_hom (f : β₁ → β₂) {g₁ : α → β₁ → β₁} {g₂ : α → β₂ → β₂} {xs : Vector α n} {init : β₁} (H : ∀ x y, g₂ x (f y) = f (g₁ x y)) : xs.foldr g₂ (f init) = f (xs.foldr g₁ init) := by rcases xs with ⟨xs, rfl⟩ simp - rw [Array.foldr_hom _ _ _ _ _ H] + rw [Array.foldr_hom _ H] /-- We can prove that two folds over the same array are related (by some arbitrary relation) if we know that the initial elements are related and the folding function, for each element of the array, preserves the relation. -/ -theorem foldl_rel {xs : Array α} {f g : β → α → β} {a b : β} (r : β → β → Prop) +theorem foldl_rel {xs : Vector α n} {f g : β → α → β} {a b : β} {r : β → β → Prop} (h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c c' : β), r c c' → r (f c a) (g c' a)) : r (xs.foldl (fun acc a => f acc a) a) (xs.foldl (fun acc a => g acc a) b) := by - rcases xs with ⟨xs⟩ - simpa using List.foldl_rel r h (by simpa using h') + rcases xs with ⟨xs, rfl⟩ + simpa using Array.foldl_rel h (by simpa using h') /-- We can prove that two folds over the same array are related (by some arbitrary relation) if we know that the initial elements are related and the folding function, for each element of the array, preserves the relation. -/ -theorem foldr_rel {xs : Array α} {f g : α → β → β} {a b : β} (r : β → β → Prop) +theorem foldr_rel {xs : Vector α n} {f g : α → β → β} {a b : β} {r : β → β → Prop} (h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c c' : β), r c c' → r (f a c) (g a c')) : r (xs.foldr (fun a acc => f a acc) a) (xs.foldr (fun a acc => g a acc) b) := by - rcases xs with ⟨xs⟩ - simpa using List.foldr_rel r h (by simpa using h') + rcases xs with ⟨xs, rfl⟩ + simpa using Array.foldr_rel h (by simpa using h') -@[simp] theorem foldl_add_const (xs : Array α) (a b : Nat) : +@[simp] theorem foldl_add_const {xs : Vector α n} {a b : Nat} : xs.foldl (fun x _ => x + a) b = b + a * xs.size := by - rcases xs with ⟨xs⟩ + rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem foldr_add_const (xs : Array α) (a b : Nat) : +@[simp] theorem foldr_add_const {xs : Vector α n} {a b : Nat} : xs.foldr (fun _ x => x + a) b = b + a * xs.size := by - rcases xs with ⟨xs⟩ + rcases xs with ⟨xs, rfl⟩ simp /-! #### Further results about `back` and `back?` -/ @@ -2476,7 +2487,7 @@ theorem foldr_rel {xs : Array α} {f g : α → β → β} {a b : β} (r : β simp theorem back?_eq_some_iff {xs : Vector α n} {a : α} : - xs.back? = some a ↔ ∃ (w : 0 < n)(ys : Vector α (n - 1)), xs = (ys.push a).cast (by omega) := by + xs.back? = some a ↔ ∃ (w : 0 < n) (ys : Vector α (n - 1)), xs = (ys.push a).cast (by omega) := by rcases xs with ⟨xs, rfl⟩ simp only [back?_mk, Array.back?_eq_some_iff, mk_eq, toArray_cast, toArray_push] constructor @@ -2539,14 +2550,13 @@ theorem back?_flatMap {xs : Vector α n} {f : α → Vector β m} : simp [Array.back?_flatMap] rfl -set_option linter.listVariables false in -- This can probably be removed later. theorem back?_flatten {xss : Vector (Vector α m) n} : (flatten xss).back? = xss.reverse.findSome? fun xs => xs.back? := by rcases xss with ⟨xss, rfl⟩ simp [Array.back?_flatten, ← Array.map_reverse, Array.findSome?_map, Function.comp_def] rfl -theorem back?_replicate (a : α) (n : Nat) : +theorem back?_replicate {a : α} {n : Nat} : (replicate n a).back? = if n = 0 then none else some a := by rw [replicate_eq_mk_replicate] simp only [back?_mk, Array.back?_replicate] @@ -2562,17 +2572,17 @@ abbrev back_mkVector := @back_replicate /-! ### leftpad and rightpad -/ -@[simp] theorem leftpad_mk (n : Nat) (a : α) (xs : Array α) (h : xs.size = m) : +@[simp] theorem leftpad_mk {n : Nat} {a : α} {xs : Array α} (h : xs.size = m) : (Vector.mk xs h).leftpad n a = Vector.mk (Array.leftpad n a xs) (by simp [h]; omega) := by simp [h] -@[simp] theorem rightpad_mk (n : Nat) (a : α) (xs : Array α) (h : xs.size = m) : +@[simp] theorem rightpad_mk {n : Nat} {a : α} {xs : Array α} (h : xs.size = m) : (Vector.mk xs h).rightpad n a = Vector.mk (Array.rightpad n a xs) (by simp [h]; omega) := by simp [h] /-! ### contains -/ -theorem contains_eq_any_beq [BEq α] (xs : Vector α n) (a : α) : xs.contains a = xs.any (a == ·) := by +theorem contains_eq_any_beq [BEq α] {xs : Vector α n} {a : α} : xs.contains a = xs.any (a == ·) := by rcases xs with ⟨xs, rfl⟩ simp [Array.contains_eq_any_beq] @@ -2589,7 +2599,7 @@ theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Vector α n} {a : α} : @[simp] theorem pop_empty : (#v[] : Vector α 0).pop = #v[] := rfl -@[simp] theorem pop_push (xs : Vector α n) : (xs.push x).pop = xs := by simp [pop] +@[simp] theorem pop_push {xs : Vector α n} {x : α} : (xs.push x).pop = xs := by simp [pop] @[simp] theorem getElem_pop {xs : Vector α n} {i : Nat} (h : i < n - 1) : xs.pop[i] = xs[i] := by @@ -2600,11 +2610,11 @@ theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Vector α n} {a : α} : Variant of `getElem_pop` that will sometimes fire when `getElem_pop` gets stuck because of defeq issues in the implicit size argument. -/ -@[simp] theorem getElem_pop' (xs : Vector α (n + 1)) (i : Nat) (h : i < n + 1 - 1) : +@[simp] theorem getElem_pop' {xs : Vector α (n + 1)} {i : Nat} (h : i < n + 1 - 1) : @getElem (Vector α n) Nat α (fun _ i => i < n) instGetElemNatLt xs.pop i h = xs[i] := getElem_pop h -theorem getElem?_pop (xs : Vector α n) (i : Nat) : +theorem getElem?_pop {xs : Vector α n} {i : Nat} : xs.pop[i]? = if i < n - 1 then xs[i]? else none := by rcases xs with ⟨xs, rfl⟩ simp [Array.getElem?_pop] @@ -2637,7 +2647,7 @@ theorem pop_append {xs : Vector α n} {ys : Vector α m} : rw [Array.pop_append] split <;> simp_all -@[simp] theorem pop_replicate (n) (a : α) : (replicate n a).pop = replicate (n - 1) a := by +@[simp] theorem pop_replicate {n : Nat} {a : α} : (replicate n a).pop = replicate (n - 1) a := by ext <;> simp @[deprecated pop_replicate (since := "2025-03-18")] @@ -2728,35 +2738,35 @@ end replace /-! ### any / all -/ -theorem not_any_eq_all_not (xs : Vector α n) (p : α → Bool) : (!xs.any p) = xs.all fun a => !p a := by +theorem not_any_eq_all_not {xs : Vector α n} {p : α → Bool} : (!xs.any p) = xs.all fun a => !p a := by rcases xs with ⟨xs, rfl⟩ simp [Array.not_any_eq_all_not] -theorem not_all_eq_any_not (xs : Vector α n) (p : α → Bool) : (!xs.all p) = xs.any fun a => !p a := by +theorem not_all_eq_any_not {xs : Vector α n} {p : α → Bool} : (!xs.all p) = xs.any fun a => !p a := by rcases xs with ⟨xs, rfl⟩ simp [Array.not_all_eq_any_not] -theorem and_any_distrib_left (xs : Vector α n) (p : α → Bool) (q : Bool) : +theorem and_any_distrib_left {xs : Vector α n} {p : α → Bool} {q : Bool} : (q && xs.any p) = xs.any fun a => q && p a := by rcases xs with ⟨xs, rfl⟩ simp [Array.and_any_distrib_left] -theorem and_any_distrib_right (xs : Vector α n) (p : α → Bool) (q : Bool) : +theorem and_any_distrib_right {xs : Vector α n} {p : α → Bool} {q : Bool} : (xs.any p && q) = xs.any fun a => p a && q := by rcases xs with ⟨xs, rfl⟩ simp [Array.and_any_distrib_right] -theorem or_all_distrib_left (xs : Vector α n) (p : α → Bool) (q : Bool) : +theorem or_all_distrib_left {xs : Vector α n} {p : α → Bool} {q : Bool} : (q || xs.all p) = xs.all fun a => q || p a := by rcases xs with ⟨xs, rfl⟩ simp [Array.or_all_distrib_left] -theorem or_all_distrib_right (xs : Vector α n) (p : α → Bool) (q : Bool) : +theorem or_all_distrib_right {xs : Vector α n} {p : α → Bool} {q : Bool} : (xs.all p || q) = xs.all fun a => p a || q := by rcases xs with ⟨xs, rfl⟩ simp [Array.or_all_distrib_right] -theorem any_eq_not_all_not (xs : Vector α n) (p : α → Bool) : xs.any p = !xs.all (!p .) := by +theorem any_eq_not_all_not {xs : Vector α n} {p : α → Bool} : xs.any p = !xs.all (!p .) := by simp only [not_all_eq_any_not, Bool.not_not] @[simp] theorem any_map {xs : Vector α n} {p : β → Bool} : (xs.map f).any p = xs.any (p ∘ f) := by @@ -2902,17 +2912,17 @@ set_option linter.indexVariables false in /-! ### findRev? and findSomeRev? -/ -@[simp] theorem findRev?_eq_find?_reverse (f : α → Bool) (xs : Vector α n) : +@[simp] theorem findRev?_eq_find?_reverse {f : α → Bool} {xs : Vector α n} : findRev? f xs = find? f xs.reverse := by simp [findRev?, find?] -@[simp] theorem findSomeRev?_eq_findSome?_reverse (f : α → Option β) (xs : Vector α n) : +@[simp] theorem findSomeRev?_eq_findSome?_reverse {f : α → Option β} {xs : Vector α n} : findSomeRev? f xs = findSome? f xs.reverse := by simp [findSomeRev?, findSome?] /-! ### zipWith -/ -@[simp] theorem getElem_zipWith (f : α → β → γ) (as : Vector α n) (bs : Vector β n) (i : Nat) +@[simp] theorem getElem_zipWith {f : α → β → γ} {as : Vector α n} {bs : Vector β n} {i : Nat} (hi : i < n) : (zipWith f as bs)[i] = f as[i] bs[i] := by cases as cases bs @@ -2921,35 +2931,35 @@ set_option linter.indexVariables false in /-! ### take -/ set_option linter.indexVariables false in -@[simp] theorem take_size (as : Vector α n) : as.take n = as.cast (by simp) := by +@[simp] theorem take_size {as : Vector α n} : as.take n = as.cast (by simp) := by rcases as with ⟨as, rfl⟩ simp /-! ### swap -/ -theorem getElem_swap (xs : Vector α n) (i j : Nat) {hi hj} (k : Nat) (hk : k < n) : +theorem getElem_swap {xs : Vector α n} {i j : Nat} (hi hj) {k : Nat} (hk : k < n) : (xs.swap i j hi hj)[k] = if k = i then xs[j] else if k = j then xs[i] else xs[k] := by cases xs simp_all [Array.getElem_swap] -@[simp] theorem getElem_swap_right (xs : Vector α n) {i j : Nat} {hi hj} : +@[simp] theorem getElem_swap_right {xs : Vector α n} {i j : Nat} (hi hj) : (xs.swap i j hi hj)[j]'(by simpa using hj) = xs[i] := by simp +contextual [getElem_swap] -@[simp] theorem getElem_swap_left (xs : Vector α n) {i j : Nat} {hi hj} : +@[simp] theorem getElem_swap_left {xs : Vector α n} {i j : Nat} (hi hj) : (xs.swap i j hi hj)[i]'(by simpa using hi) = xs[j] := by simp [getElem_swap] -@[simp] theorem getElem_swap_of_ne (xs : Vector α n) {i j : Nat} {hi hj} (hk : k < n) +@[simp] theorem getElem_swap_of_ne {xs : Vector α n} {i j : Nat} (hi hj) (hk : k < n) (hi' : k ≠ i) (hj' : k ≠ j) : (xs.swap i j hi hj)[k] = xs[k] := by simp_all [getElem_swap] -@[simp] theorem swap_swap (xs : Vector α n) {i j : Nat} {hi hj} : +@[simp] theorem swap_swap {xs : Vector α n} {i j : Nat} (hi hj) : (xs.swap i j hi hj).swap i j hi hj = xs := by cases xs simp_all [Array.swap_swap] -theorem swap_comm (xs : Vector α n) {i j : Nat} {hi hj} : +theorem swap_comm {xs : Vector α n} {i j : Nat} (hi hj) : xs.swap i j hi hj = xs.swap j i hj hi := by cases xs simp only [swap_mk, mk.injEq] @@ -2957,14 +2967,14 @@ theorem swap_comm (xs : Vector α n) {i j : Nat} {hi hj} : /-! ### take -/ -@[simp] theorem getElem_take (xs : Vector α n) (j : Nat) (hi : i < min j n) : +@[simp] theorem getElem_take {xs : Vector α n} {j : Nat} (hi : i < min j n) : (xs.take j)[i] = xs[i] := by cases xs simp /-! ### drop -/ -@[simp] theorem getElem_drop (xs : Vector α n) (j : Nat) (hi : i < n - j) : +@[simp] theorem getElem_drop {xs : Vector α n} {j : Nat} (hi : i < n - j) : (xs.drop j)[i] = xs[j + i] := by cases xs simp diff --git a/src/Init/Data/Vector/Lex.lean b/src/Init/Data/Vector/Lex.lean index 655eb47d4e..ae9ca8d268 100644 --- a/src/Init/Data/Vector/Lex.lean +++ b/src/Init/Data/Vector/Lex.lean @@ -16,14 +16,14 @@ namespace Vector /-! ### Lexicographic ordering -/ -@[simp] theorem lt_toArray [LT α] (xs ys : Vector α n) : xs.toArray < ys.toArray ↔ xs < ys := Iff.rfl -@[simp] theorem le_toArray [LT α] (xs ys : Vector α n) : xs.toArray ≤ ys.toArray ↔ xs ≤ ys := Iff.rfl +@[simp] theorem lt_toArray [LT α] {xs ys : Vector α n} : xs.toArray < ys.toArray ↔ xs < ys := Iff.rfl +@[simp] theorem le_toArray [LT α] {xs ys : Vector α n} : xs.toArray ≤ ys.toArray ↔ xs ≤ ys := Iff.rfl -@[simp] theorem lt_toList [LT α] (xs ys : Vector α n) : xs.toList < ys.toList ↔ xs < ys := Iff.rfl -@[simp] theorem le_toList [LT α] (xs ys : Vector α n) : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl +@[simp] theorem lt_toList [LT α] {xs ys : Vector α n} : xs.toList < ys.toList ↔ xs < ys := Iff.rfl +@[simp] theorem le_toList [LT α] {xs ys : Vector α n} : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl -protected theorem not_lt_iff_ge [LT α] (xs ys : Vector α n) : ¬ xs < ys ↔ ys ≤ xs := Iff.rfl -protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] (xs ys : Vector α n) : +protected theorem not_lt_iff_ge [LT α] {xs ys : Vector α n} : ¬ xs < ys ↔ ys ≤ xs := Iff.rfl +protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Vector α n} : ¬ xs ≤ ys ↔ ys < xs := Decidable.not_not @@ -33,18 +33,18 @@ protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] (xs ys @[simp] theorem mk_le_mk [LT α] : Vector.mk (α := α) (n := n) data₁ size₁ ≤ Vector.mk data₂ size₂ ↔ data₁ ≤ data₂ := Iff.rfl -@[simp] theorem mk_lex_mk [BEq α] (lt : α → α → Bool) {xs ys : Array α} {n₁ : xs.size = n} {n₂ : ys.size = n} : +@[simp] theorem mk_lex_mk [BEq α] {lt : α → α → Bool} {xs ys : Array α} {n₁ : xs.size = n} {n₂ : ys.size = n} : (Vector.mk xs n₁).lex (Vector.mk ys n₂) lt = xs.lex ys lt := by simp [Vector.lex, Array.lex, n₁, n₂] rfl -@[simp] theorem lex_toArray [BEq α] (lt : α → α → Bool) (xs ys : Vector α n) : +@[simp] theorem lex_toArray [BEq α] {lt : α → α → Bool} {xs ys : Vector α n} : xs.toArray.lex ys.toArray lt = xs.lex ys lt := by cases xs cases ys simp -@[simp] theorem lex_toList [BEq α] (lt : α → α → Bool) (xs ys : Vector α n) : +@[simp] theorem lex_toList [BEq α] {lt : α → α → Bool} {xs ys : Vector α n} : xs.toList.lex ys.toList lt = xs.lex ys lt := by rcases xs with ⟨xs, n₁⟩ rcases ys with ⟨ys, n₂⟩ @@ -68,7 +68,7 @@ instance ltIrrefl [LT α] [Std.Irrefl (· < · : α → α → Prop)] : Std.Irre @[simp] theorem not_lt_empty [LT α] (xs : Vector α 0) : ¬ xs < #v[] := Array.not_lt_empty xs.toArray @[simp] theorem empty_le [LT α] (xs : Vector α 0) : #v[] ≤ xs := Array.empty_le xs.toArray -@[simp] theorem le_empty [LT α] (xs : Vector α 0) : xs ≤ #v[] ↔ xs = #v[] := by +@[simp] theorem le_empty [LT α] {xs : Vector α 0} : xs ≤ #v[] ↔ xs = #v[] := by cases xs simp diff --git a/src/Init/Data/Vector/MapIdx.lean b/src/Init/Data/Vector/MapIdx.lean index cfd1d8de9e..e600ebb692 100644 --- a/src/Init/Data/Vector/MapIdx.lean +++ b/src/Init/Data/Vector/MapIdx.lean @@ -15,13 +15,13 @@ namespace Vector /-! ### mapFinIdx -/ -@[simp] theorem getElem_mapFinIdx (xs : Vector α n) (f : (i : Nat) → α → (h : i < n) → β) (i : Nat) +@[simp] theorem getElem_mapFinIdx {xs : Vector α n} {f : (i : Nat) → α → (h : i < n) → β} {i : Nat} (h : i < n) : (xs.mapFinIdx f)[i] = f i xs[i] h := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem getElem?_mapFinIdx (xs : Vector α n) (f : (i : Nat) → α → (h : i < n) → β) (i : Nat) : +@[simp] theorem getElem?_mapFinIdx {xs : Vector α n} {f : (i : Nat) → α → (h : i < n) → β} {i : Nat} : (xs.mapFinIdx f)[i]? = xs[i]?.pbind fun b h => f i b (getElem?_eq_some_iff.1 h).1 := by simp only [getElem?_def, getElem_mapFinIdx] @@ -29,12 +29,12 @@ namespace Vector /-! ### mapIdx -/ -@[simp] theorem getElem_mapIdx (f : Nat → α → β) (xs : Vector α n) (i : Nat) (h : i < n) : +@[simp] theorem getElem_mapIdx {f : Nat → α → β} {xs : Vector α n} {i : Nat} (h : i < n) : (xs.mapIdx f)[i] = f i (xs[i]'(by simp_all)) := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem getElem?_mapIdx (f : Nat → α → β) (xs : Vector α n) (i : Nat) : +@[simp] theorem getElem?_mapIdx {f : Nat → α → β} {xs : Vector α n} {i : Nat} : (xs.mapIdx f)[i]? = xs[i]?.map (f i) := by rcases xs with ⟨xs, rfl⟩ simp @@ -43,11 +43,11 @@ end Vector namespace Array -@[simp] theorem mapFinIdx_toVector (xs : Array α) (f : (i : Nat) → α → (h : i < xs.size) → β) : +@[simp] theorem mapFinIdx_toVector {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} : xs.toVector.mapFinIdx f = (xs.mapFinIdx f).toVector.cast (by simp) := by ext <;> simp -@[simp] theorem mapIdx_toVector (f : Nat → α → β) (xs : Array α) : +@[simp] theorem mapIdx_toVector {f : Nat → α → β} {xs : Array α} : xs.toVector.mapIdx f = (xs.mapIdx f).toVector.cast (by simp) := by ext <;> simp @@ -57,12 +57,12 @@ namespace Vector /-! ### zipIdx -/ -@[simp] theorem toList_zipIdx (xs : Vector α n) (k : Nat := 0) : +@[simp] theorem toList_zipIdx {xs : Vector α n} (k : Nat := 0) : (xs.zipIdx k).toList = xs.toList.zipIdx k := by rcases xs with ⟨xs, rfl⟩ simp -@[simp] theorem getElem_zipIdx (xs : Vector α n) (i : Nat) (h : i < n) : +@[simp] theorem getElem_zipIdx {xs : Vector α n} {i : Nat} {h : i < n} : (xs.zipIdx k)[i] = (xs[i]'(by simp_all), k + i) := by rcases xs with ⟨xs, rfl⟩ simp @@ -366,8 +366,8 @@ abbrev mapIdx_eq_mkVector_iff := @mapIdx_eq_replicate_iff rcases xs with ⟨xs, rfl⟩ simp [Array.mapIdx_reverse] -theorem toArray_mapFinIdxM [Monad m] [LawfulMonad m] - (xs : Vector α n) (f : (i : Nat) → α → (h : i < n) → m β) : +theorem toArray_mapFinIdxM [Monad m] [LawfulMonad m] {xs : Vector α n} + {f : (i : Nat) → α → (h : i < n) → m β} : toArray <$> xs.mapFinIdxM f = xs.toArray.mapFinIdxM (fun i x h => f i x (size_toArray xs ▸ h)) := by let rec go (i j : Nat) (inv : i + j = n) (bs : Vector β (n - i)) : @@ -383,8 +383,9 @@ theorem toArray_mapFinIdxM [Monad m] [LawfulMonad m] simp only [mapFinIdxM, Array.mapFinIdxM, size_toArray] exact go _ _ _ _ -theorem toArray_mapIdxM [Monad m] [LawfulMonad m] (xs : Vector α n) (f : Nat → α → m β) : +theorem toArray_mapIdxM [Monad m] [LawfulMonad m] {xs : Vector α n} + {f : Nat → α → m β} : toArray <$> xs.mapIdxM f = xs.toArray.mapIdxM f := by - exact toArray_mapFinIdxM _ _ + exact toArray_mapFinIdxM end Vector diff --git a/src/Init/Data/Vector/Monadic.lean b/src/Init/Data/Vector/Monadic.lean index e4c8b104d3..bcff54ee79 100644 --- a/src/Init/Data/Vector/Monadic.lean +++ b/src/Init/Data/Vector/Monadic.lean @@ -41,14 +41,14 @@ theorem mapM_pure [Monad m] [LawfulMonad m] {xs : Vector α n} (f : α → β) : subst w simp -@[simp] theorem mapM_mk_empty [Monad m] (f : α → m β) : +@[simp] theorem mapM_mk_empty [Monad m] {f : α → m β} : (mk #[] rfl).mapM f = pure #v[] := by unfold mapM unfold mapM.go simp @[simp] theorem mapM_append [Monad m] [LawfulMonad m] - (f : α → m β) {xs : Vector α n} {ys : Vector α n'} : + {f : α → m β} {xs : Vector α n} {ys : Vector α n'} : (xs ++ ys).mapM f = (return (← xs.mapM f) ++ (← ys.mapM f)) := by apply map_toArray_inj.mp suffices toArray <$> (xs ++ ys).mapM f = (return (← toArray <$> xs.mapM f) ++ (← toArray <$> ys.mapM f)) by @@ -58,50 +58,50 @@ theorem mapM_pure [Monad m] [LawfulMonad m] {xs : Vector α n} (f : α → β) : /-! ### foldlM and foldrM -/ -theorem foldlM_map [Monad m] (f : β₁ → β₂) (g : α → β₂ → m α) (xs : Vector β₁ n) (init : α) : +theorem foldlM_map [Monad m] {f : β₁ → β₂} {g : α → β₂ → m α} {xs : Vector β₁ n} {init : α} : (xs.map f).foldlM g init = xs.foldlM (fun x y => g x (f y)) init := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldlM_map] -theorem foldrM_map [Monad m] [LawfulMonad m] (f : β₁ → β₂) (g : β₂ → α → m α) (xs : Vector β₁ n) - (init : α) : (xs.map f).foldrM g init = xs.foldrM (fun x y => g (f x) y) init := by +theorem foldrM_map [Monad m] [LawfulMonad m] {f : β₁ → β₂} {g : β₂ → α → m α} {xs : Vector β₁ n} {init : α} : + (xs.map f).foldrM g init = xs.foldrM (fun x y => g (f x) y) init := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldrM_map] -theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : γ → β → m γ) (xs : Vector α n) (init : γ) : +theorem foldlM_filterMap [Monad m] [LawfulMonad m] {f : α → Option β} {g : γ → β → m γ} {xs : Vector α n} {init : γ} : (xs.filterMap f).foldlM g init = xs.foldlM (fun x y => match f y with | some b => g x b | none => pure x) init := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldlM_filterMap] rfl -theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : β → γ → m γ) (xs : Vector α n) (init : γ) : +theorem foldrM_filterMap [Monad m] [LawfulMonad m] {f : α → Option β} {g : β → γ → m γ} {xs : Vector α n} {init : γ} : (xs.filterMap f).foldrM g init = xs.foldrM (fun x y => match f x with | some b => g b y | none => pure y) init := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldrM_filterMap] rfl -theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : β → α → m β) (xs : Vector α n) (init : β) : +theorem foldlM_filter [Monad m] [LawfulMonad m] {p : α → Bool} {g : β → α → m β} {xs : Vector α n} {init : β} : (xs.filter p).foldlM g init = xs.foldlM (fun x y => if p y then g x y else pure x) init := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldlM_filter] -theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β → m β) (xs : Vector α n) (init : β) : +theorem foldrM_filter [Monad m] [LawfulMonad m] {p : α → Bool} {g : α → β → m β} {xs : Vector α n} {init : β} : (xs.filter p).foldrM g init = xs.foldrM (fun x y => if p x then g x y else pure y) init := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldrM_filter] @[simp] theorem foldlM_attachWith [Monad m] - (xs : Vector α n) {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : β → { x // q x} → m β} {b} : + {xs : Vector α n} {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : β → { x // q x} → m β} {b} : (xs.attachWith q H).foldlM f b = xs.attach.foldlM (fun b ⟨a, h⟩ => f b ⟨a, H _ h⟩) b := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldlM_map] @[simp] theorem foldrM_attachWith [Monad m] [LawfulMonad m] - (xs : Vector α n) {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : { x // q x} → β → m β} {b} : + {xs : Vector α n} {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : { x // q x} → β → m β} {b} : (xs.attachWith q H).foldrM f b = xs.attach.foldrM (fun a acc => f ⟨a.1, H _ a.2⟩ acc) b := by rcases xs with ⟨xs, rfl⟩ simp [Array.foldrM_map] @@ -114,13 +114,13 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β cases as <;> cases bs simp_all -@[simp] theorem forM_append [Monad m] [LawfulMonad m] (xs : Vector α n) (ys : Vector α n') (f : α → m PUnit) : +@[simp] theorem forM_append [Monad m] [LawfulMonad m] {xs : Vector α n} {ys : Vector α n'} {f : α → m PUnit} : forM (xs ++ ys) f = (do forM xs f; forM ys f) := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, rfl⟩ simp -@[simp] theorem forM_map [Monad m] [LawfulMonad m] (xs : Vector α n) (g : α → β) (f : β → m PUnit) : +@[simp] theorem forM_map [Monad m] [LawfulMonad m] {xs : Vector α n} {g : α → β} {f : β → m PUnit} : forM (xs.map g) f = forM xs (fun a => f (g a)) := by rcases xs with ⟨xs, rfl⟩ simp @@ -142,7 +142,7 @@ We can express a for loop over a vector as a fold, in which whenever we reach `.done b` we keep that value through the rest of the fold. -/ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m] - (xs : Vector α n) (f : (a : α) → a ∈ xs → β → m (ForInStep β)) (init : β) : + {xs : Vector α n} (f : (a : α) → a ∈ xs → β → m (ForInStep β)) (init : β) : forIn' xs init f = ForInStep.value <$> xs.attach.foldlM (fun b ⟨a, m⟩ => match b with | .yield b => f a m b @@ -153,29 +153,29 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m] /-- We can express a for loop over a vector which always yields as a fold. -/ @[simp] theorem forIn'_yield_eq_foldlM [Monad m] [LawfulMonad m] - (xs : Vector α n) (f : (a : α) → a ∈ xs → β → m γ) (g : (a : α) → a ∈ xs → β → γ → β) (init : β) : + {xs : Vector α n} (f : (a : α) → a ∈ xs → β → m γ) (g : (a : α) → a ∈ xs → β → γ → β) (init : β) : forIn' xs init (fun a m b => (fun c => .yield (g a m b c)) <$> f a m b) = xs.attach.foldlM (fun b ⟨a, m⟩ => g a m b <$> f a m b) init := by rcases xs with ⟨xs, rfl⟩ simp @[simp] theorem forIn'_pure_yield_eq_foldl [Monad m] [LawfulMonad m] - (xs : Vector α n) (f : (a : α) → a ∈ xs → β → β) (init : β) : + {xs : Vector α n} (f : (a : α) → a ∈ xs → β → β) (init : β) : forIn' xs init (fun a m b => pure (.yield (f a m b))) = pure (f := m) (xs.attach.foldl (fun b ⟨a, h⟩ => f a h b) init) := by rcases xs with ⟨xs, rfl⟩ simp [Array.forIn'_pure_yield_eq_foldl, Array.foldl_map] @[simp] theorem forIn'_yield_eq_foldl - (xs : Vector α n) (f : (a : α) → a ∈ xs → β → β) (init : β) : + {xs : Vector α n} (f : (a : α) → a ∈ xs → β → β) (init : β) : forIn' (m := Id) xs init (fun a m b => .yield (f a m b)) = xs.attach.foldl (fun b ⟨a, h⟩ => f a h b) init := by rcases xs with ⟨xs, rfl⟩ simp [List.foldl_map] @[simp] theorem forIn'_map [Monad m] [LawfulMonad m] - (xs : Vector α n) (g : α → β) (f : (b : β) → b ∈ xs.map g → γ → m (ForInStep γ)) : - forIn' (xs.map g) init f = forIn' xs init fun a h y => f (g a) (mem_map_of_mem g h) y := by + {xs : Vector α n} (g : α → β) (f : (b : β) → b ∈ xs.map g → γ → m (ForInStep γ)) : + forIn' (xs.map g) init f = forIn' xs init fun a h y => f (g a) (mem_map_of_mem h) y := by rcases xs with ⟨xs, rfl⟩ simp @@ -184,7 +184,7 @@ We can express a for loop over a vector as a fold, in which whenever we reach `.done b` we keep that value through the rest of the fold. -/ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m] - (f : α → β → m (ForInStep β)) (init : β) (xs : Vector α n) : + {xs : Vector α n} (f : α → β → m (ForInStep β)) (init : β) : forIn xs init f = ForInStep.value <$> xs.foldlM (fun b a => match b with | .yield b => f a b @@ -195,28 +195,28 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m] /-- We can express a for loop over a vector which always yields as a fold. -/ @[simp] theorem forIn_yield_eq_foldlM [Monad m] [LawfulMonad m] - (xs : Vector α n) (f : α → β → m γ) (g : α → β → γ → β) (init : β) : + {xs : Vector α n} (f : α → β → m γ) (g : α → β → γ → β) (init : β) : forIn xs init (fun a b => (fun c => .yield (g a b c)) <$> f a b) = xs.foldlM (fun b a => g a b <$> f a b) init := by rcases xs with ⟨xs, rfl⟩ simp @[simp] theorem forIn_pure_yield_eq_foldl [Monad m] [LawfulMonad m] - (xs : Vector α n) (f : α → β → β) (init : β) : + {xs : Vector α n} (f : α → β → β) (init : β) : forIn xs init (fun a b => pure (.yield (f a b))) = pure (f := m) (xs.foldl (fun b a => f a b) init) := by rcases xs with ⟨xs, rfl⟩ simp [Array.forIn_pure_yield_eq_foldl, Array.foldl_map] @[simp] theorem forIn_yield_eq_foldl - (xs : Vector α n) (f : α → β → β) (init : β) : + {xs : Vector α n} (f : α → β → β) (init : β) : forIn (m := Id) xs init (fun a b => .yield (f a b)) = xs.foldl (fun b a => f a b) init := by rcases xs with ⟨xs, rfl⟩ simp @[simp] theorem forIn_map [Monad m] [LawfulMonad m] - (xs : Vector α n) (g : α → β) (f : β → γ → m (ForInStep γ)) : + {xs : Vector α n} (g : α → β) (f : β → γ → m (ForInStep γ)) : forIn (xs.map g) init f = forIn xs init fun a y => f (g a) y := by rcases xs with ⟨xs, rfl⟩ simp @@ -224,25 +224,25 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m] /-! ### allM and anyM -/ -@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] (p : α → Bool) (xs : Vector α n) : +@[simp] theorem anyM_pure [Monad m] [LawfulMonad m] {p : α → Bool} {xs : Vector α n} : xs.anyM (m := m) (pure <| p ·) = pure (xs.any p) := by cases xs simp -@[simp] theorem allM_pure [Monad m] [LawfulMonad m] (p : α → Bool) (xs : Vector α n) : +@[simp] theorem allM_pure [Monad m] [LawfulMonad m] {p : α → Bool} {xs : Vector α n} : xs.allM (m := m) (pure <| p ·) = pure (xs.all p) := by cases xs simp /-! ### findM? and findSomeM? -/ -theorem findM?_pure {m} [Monad m] [LawfulMonad m] (p : α → Bool) (xs : Vector α n) : +theorem findM?_pure {m} [Monad m] [LawfulMonad m] {p : α → Bool} {xs : Vector α n} : findM? (m := m) (pure <| p ·) xs = pure (xs.find? p) := by cases xs simp @[simp] -theorem findSomeM?_pure [Monad m] [LawfulMonad m] (f : α → Option β) (xs : Vector α n) : +theorem findSomeM?_pure [Monad m] [LawfulMonad m] {f : α → Option β} {xs : Vector α n} : findSomeM? (m := m) (pure <| f ·) xs = pure (xs.findSome? f) := by cases xs simp diff --git a/src/Init/Data/Vector/OfFn.lean b/src/Init/Data/Vector/OfFn.lean index 27f2fd3806..2f2fa867cb 100644 --- a/src/Init/Data/Vector/OfFn.lean +++ b/src/Init/Data/Vector/OfFn.lean @@ -16,16 +16,16 @@ set_option linter.indexVariables true -- Enforce naming conventions for index va namespace Vector -@[simp] theorem getElem_ofFn {α n} (f : Fin n → α) (i : Nat) (h : i < n) : +@[simp] theorem getElem_ofFn {α n} {f : Fin n → α} (h : i < n) : (Vector.ofFn f)[i] = f ⟨i, by simpa using h⟩ := by simp [ofFn] -theorem getElem?_ofFn (f : Fin n → α) (i : Nat) : +theorem getElem?_ofFn {α n} {f : Fin n → α} : (ofFn f)[i]? = if h : i < n then some (f ⟨i, h⟩) else none := by simp [getElem?_def] @[simp 500] -theorem mem_ofFn {n} (f : Fin n → α) (a : α) : a ∈ ofFn f ↔ ∃ i, f i = a := by +theorem mem_ofFn {n} {f : Fin n → α} {a : α} : a ∈ ofFn f ↔ ∃ i, f i = a := by constructor · intro w obtain ⟨i, h, rfl⟩ := getElem_of_mem w @@ -33,7 +33,7 @@ theorem mem_ofFn {n} (f : Fin n → α) (a : α) : a ∈ ofFn f ↔ ∃ i, f i = · rintro ⟨i, rfl⟩ apply mem_of_getElem (i := i) <;> simp -theorem back_ofFn {n} [NeZero n](f : Fin n → α) : +theorem back_ofFn {n} [NeZero n] {f : Fin n → α} : (ofFn f).back = f ⟨n - 1, by have := NeZero.ne n; omega⟩ := by simp [back] diff --git a/src/Init/Data/Vector/Range.lean b/src/Init/Data/Vector/Range.lean index aa295ce97b..df4ac46398 100644 --- a/src/Init/Data/Vector/Range.lean +++ b/src/Init/Data/Vector/Range.lean @@ -25,23 +25,23 @@ open Nat /-! ### range' -/ -@[simp] theorem toArray_range' (start size step) : +@[simp] theorem toArray_range' {start size step} : (range' start size step).toArray = Array.range' start size step := by rfl -theorem range'_eq_mk_range' (start size step) : +theorem range'_eq_mk_range' {start size step} : range' start size step = Vector.mk (Array.range' start size step) (by simp) := by rfl -@[simp] theorem getElem_range' (start size step i) (h : i < size) : +@[simp] theorem getElem_range' {start size step i} (h : i < size) : (range' start size step)[i] = start + step * i := by simp [range', h] -@[simp] theorem getElem?_range' (start size step i) : +@[simp] theorem getElem?_range' {start size step i} : (range' start size step)[i]? = if i < size then some (start + step * i) else none := by simp [getElem?_def, range'] -theorem range'_succ (s n step) : +theorem range'_succ {s n step} : range' s (n + 1) step = (#v[s] ++ range' (s + step) n step).cast (by omega) := by rw [← toArray_inj] simp [Array.range'_succ] @@ -61,24 +61,24 @@ theorem mem_range' {n} : m ∈ range' s n step ↔ ∃ i < n, m = s + step * i : theorem pop_range' : (range' s n step).pop = range' s (n - 1) step := by ext <;> simp -theorem map_add_range' (a) (s n step) : map (a + ·) (range' s n step) = range' (a + s) n step := by +theorem map_add_range' {a} (s n step) : map (a + ·) (range' s n step) = range' (a + s) n step := by ext <;> simp <;> omega theorem range'_succ_left : range' (s + 1) n step = (range' s n step).map (· + 1) := by ext <;> simp <;> omega -theorem range'_append (s m n step : Nat) : +theorem range'_append {s m n step : Nat} : range' s m step ++ range' (s + step * m) n step = range' s (m + n) step := by rw [← toArray_inj] simp [Array.range'_append] -@[simp] theorem range'_append_1 (s m n : Nat) : - range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append s m n 1 +@[simp] theorem range'_append_1 {s m n : Nat} : + range' s m ++ range' (s + m) n = range' s (m + n) := by simpa using range'_append (step := 1) -theorem range'_concat (s n : Nat) : range' s (n + 1) step = range' s n step ++ #v[s + step * n] := by - simpa using (range'_append s n 1 step).symm +theorem range'_concat {s n : Nat} : range' s (n + 1) step = range' s n step ++ #v[s + step * n] := by + simpa using range'_append.symm -theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ #v[s + n] := by +theorem range'_1_concat {s n : Nat} : range' s (n + 1) = range' s n ++ #v[s + n] := by simp [range'_concat] @[simp] theorem mem_range'_1 : m ∈ range' s n ↔ s ≤ m ∧ m < s + n := by @@ -86,7 +86,7 @@ theorem range'_1_concat (s n : Nat) : range' s (n + 1) = range' s n ++ #v[s + n] fun ⟨i, h, e⟩ => e ▸ ⟨Nat.le_add_right .., Nat.add_lt_add_left h _⟩, fun ⟨h₁, h₂⟩ => ⟨m - s, Nat.sub_lt_left_of_lt_add h₁ h₂, (Nat.add_sub_cancel' h₁).symm⟩⟩ -theorem map_sub_range' (a s n : Nat) (h : a ≤ s) : +theorem map_sub_range' {a s n : Nat} (h : a ≤ s) : map (· - a) (range' s n step) = range' (s - a) n step := by conv => lhs; rw [← Nat.add_sub_cancel' h] rw [← map_add_range', map_map, (?_ : _∘_ = _), map_id] @@ -115,29 +115,30 @@ theorem range'_eq_append_iff : range' s (n + m) = xs ++ ys ↔ xs = range' s n /-! ### range -/ -@[simp] theorem getElem_range (i : Nat) (hi : i < n) : (Vector.range n)[i] = i := by +@[simp] theorem getElem_range {i : Nat} (hi : i < n) : (Vector.range n)[i] = i := by simp [Vector.range] -theorem range_eq_range' (n : Nat) : range n = range' 0 n := by +theorem range_eq_range' {n : Nat} : range n = range' 0 n := by simp [range, range', Array.range_eq_range'] -theorem range_succ_eq_map (n : Nat) : range (n + 1) = - (#v[0] ++ map succ (range n)).cast (by omega) := by +theorem range_succ_eq_map {n : Nat} : + range (n + 1) = + (#v[0] ++ map succ (range n)).cast (by omega) := by rw [← toArray_inj] simp [Array.range_succ_eq_map] -theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) := by +theorem range'_eq_map_range {s n : Nat} : range' s n = map (s + ·) (range n) := by rw [range_eq_range', map_add_range']; rfl -theorem range_succ (n : Nat) : range (succ n) = range n ++ #v[n] := by +theorem range_succ {n : Nat} : range (succ n) = range n ++ #v[n] := by rw [← toArray_inj] simp [Array.range_succ] -theorem range_add (n m : Nat) : range (n + m) = range n ++ (range m).map (n + ·) := by +theorem range_add {n m : Nat} : range (n + m) = range n ++ (range m).map (n + ·) := by rw [← range'_eq_map_range] - simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 n m).symm + simpa [range_eq_range', Nat.add_comm] using (range'_append_1 (s := 0)).symm -theorem reverse_range' (s n : Nat) : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by +theorem reverse_range' {s n : Nat} : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by simp [← toList_inj, List.reverse_range'] @[simp] @@ -146,9 +147,9 @@ theorem mem_range {m n : Nat} : m ∈ range n ↔ m < n := by theorem not_mem_range_self {n : Nat} : n ∉ range n := by simp -theorem self_mem_range_succ (n : Nat) : n ∈ range (n + 1) := by simp +theorem self_mem_range_succ {n : Nat} : n ∈ range (n + 1) := by simp -@[simp] theorem take_range (n i : Nat) : take (range n) i = range (min i n) := by +@[simp] theorem take_range {n i : Nat} : take (range n) i = range (min i n) := by ext <;> simp erw [getElem_extract] -- Why is an `erw` needed here? This should be by simp! simp @@ -164,48 +165,50 @@ theorem self_mem_range_succ (n : Nat) : n ∈ range (n + 1) := by simp /-! ### zipIdx -/ @[simp] -theorem getElem?_zipIdx (xs : Vector α n) (i j) : (zipIdx xs i)[j]? = xs[j]?.map fun a => (a, i + j) := by +theorem getElem?_zipIdx {xs : Vector α n} {i j} : (zipIdx xs i)[j]? = xs[j]?.map fun a => (a, i + j) := by simp [getElem?_def] -theorem map_snd_add_zipIdx_eq_zipIdx (xs : Vector α n) (m k : Nat) : +theorem map_snd_add_zipIdx_eq_zipIdx {xs : Vector α n} {m k : Nat} : map (Prod.map id (· + m)) (zipIdx xs k) = zipIdx xs (m + k) := by ext <;> simp <;> omega +-- Arguments are explicit for parity with `zipIdx_map_fst`. @[simp] theorem zipIdx_map_snd (i) (xs : Vector α n) : map Prod.snd (zipIdx xs i) = range' i n := by rcases xs with ⟨xs, rfl⟩ simp [Array.zipIdx_map_snd] +-- Arguments are explicit so we can rewrite from right to left. @[simp] theorem zipIdx_map_fst (i) (xs : Vector α n) : map Prod.fst (zipIdx xs i) = xs := by rcases xs with ⟨xs, rfl⟩ simp [Array.zipIdx_map_fst] -theorem zipIdx_eq_zip_range' (xs : Vector α n) : xs.zipIdx i = xs.zip (range' i n) := by +theorem zipIdx_eq_zip_range' {xs : Vector α n} : xs.zipIdx i = xs.zip (range' i n) := by simp [zip_of_prod (zipIdx_map_fst _ _) (zipIdx_map_snd _ _)] @[simp] -theorem unzip_zipIdx_eq_prod (xs : Vector α n) {i : Nat} : +theorem unzip_zipIdx_eq_prod {xs : Vector α n} {i : Nat} : (xs.zipIdx i).unzip = (xs, range' i n) := by simp only [zipIdx_eq_zip_range', unzip_zip] /-- Replace `zipIdx` with a starting index `i+1` with `zipIdx` starting from `i`, followed by a `map` increasing the indices by one. -/ -theorem zipIdx_succ (xs : Vector α n) (i : Nat) : +theorem zipIdx_succ {xs : Vector α n} {i : Nat} : xs.zipIdx (i + 1) = (xs.zipIdx i).map (fun ⟨a, i⟩ => (a, i + 1)) := by rcases xs with ⟨xs, rfl⟩ simp [Array.zipIdx_succ] /-- Replace `zipIdx` with a starting index with `zipIdx` starting from 0, followed by a `map` increasing the indices. -/ -theorem zipIdx_eq_map_add (xs : Vector α n) (i : Nat) : +theorem zipIdx_eq_map_add {xs : Vector α n} {i : Nat} : xs.zipIdx i = xs.zipIdx.map (fun ⟨a, j⟩ => (a, i + j)) := by rcases xs with ⟨xs, rfl⟩ simp only [zipIdx_mk, map_mk, eq_mk] rw [Array.zipIdx_eq_map_add] @[simp] -theorem zipIdx_singleton (x : α) (k : Nat) : zipIdx #v[x] k = #v[(x, k)] := +theorem zipIdx_singleton {x : α} {k : Nat} : zipIdx (#v[x]) k = #v[(x, k)] := rfl theorem mk_add_mem_zipIdx_iff_getElem? {k i : Nat} {x : α} {xs : Vector α n} : @@ -225,13 +228,13 @@ theorem snd_lt_of_mem_zipIdx {x : α × Nat} {k : Nat} {xs : Vector α n} (h : x x.2 < n + k := by simpa [Nat.add_comm] using snd_lt_add_of_mem_zipIdx h -theorem map_zipIdx (f : α → β) (xs : Vector α n) (k : Nat) : +theorem map_zipIdx {f : α → β} {xs : Vector α n} {k : Nat} : map (Prod.map f id) (zipIdx xs k) = zipIdx (xs.map f) k := by rcases xs with ⟨xs, rfl⟩ simp [Array.map_zipIdx] theorem fst_mem_of_mem_zipIdx {x : α × Nat} {xs : Vector α n} {k : Nat} (h : x ∈ zipIdx xs k) : x.1 ∈ xs := - zipIdx_map_fst k xs ▸ mem_map_of_mem _ h + zipIdx_map_fst k xs ▸ mem_map_of_mem h theorem fst_eq_of_mem_zipIdx {x : α × Nat} {xs : Vector α n} {k : Nat} (h : x ∈ zipIdx xs k) : x.1 = xs[x.2 - k]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) := by @@ -248,12 +251,12 @@ theorem mem_zipIdx' {x : α} {i : Nat} {xs : Vector α n} (h : (x, i) ∈ xs.zip i < n ∧ x = xs[i]'(by have := le_snd_of_mem_zipIdx h; have := snd_lt_add_of_mem_zipIdx h; omega) := ⟨by simpa using snd_lt_add_of_mem_zipIdx h, fst_eq_of_mem_zipIdx h⟩ -theorem zipIdx_map (xs : Vector α n) (k : Nat) (f : α → β) : +theorem zipIdx_map {f : α → β} {xs : Vector α n} {k : Nat} : zipIdx (xs.map f) k = (zipIdx xs k).map (Prod.map f id) := by rcases xs with ⟨xs, rfl⟩ simp [Array.zipIdx_map] -theorem zipIdx_append (xs : Vector α n) (ys : Vector α m) (k : Nat) : +theorem zipIdx_append {xs : Vector α n} {ys : Vector α m} {k : Nat} : zipIdx (xs ++ ys) k = zipIdx xs k ++ zipIdx ys (k + n) := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, rfl⟩ diff --git a/src/Init/Data/Vector/Zip.lean b/src/Init/Data/Vector/Zip.lean index 2731849610..5d0224abd6 100644 --- a/src/Init/Data/Vector/Zip.lean +++ b/src/Init/Data/Vector/Zip.lean @@ -22,19 +22,19 @@ open Nat /-! ### zipWith -/ -theorem zipWith_comm (f : α → β → γ) (as : Vector α n) (bs : Vector β n) : +theorem zipWith_comm {f : α → β → γ} {as : Vector α n} {bs : Vector β n} : zipWith f as bs = zipWith (fun b a => f a b) bs as := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ - simpa using Array.zipWith_comm _ _ _ + simpa using Array.zipWith_comm -theorem zipWith_comm_of_comm (f : α → α → β) (comm : ∀ x y : α, f x y = f y x) (xs ys : Vector α n) : +theorem zipWith_comm_of_comm {f : α → α → β} (comm : ∀ x y : α, f x y = f y x) {xs ys : Vector α n} : zipWith f xs ys = zipWith f ys xs := by rw [zipWith_comm] simp only [comm] @[simp] -theorem zipWith_self (f : α → α → δ) (xs : Vector α n) : zipWith f xs xs = xs.map fun a => f a a := by +theorem zipWith_self {f : α → α → δ} {xs : Vector α n} : zipWith f xs xs = xs.map fun a => f a a := by cases xs simp @@ -71,38 +71,37 @@ theorem getElem?_zip_eq_some {as : Vector α n} {bs : Vector β n} {z : α × β simp [Array.getElem?_zip_eq_some] @[simp] -theorem zipWith_map {μ} (f : γ → δ → μ) (g : α → γ) (h : β → δ) (as : Vector α n) (bs : Vector β n) : +theorem zipWith_map {μ} {f : γ → δ → μ} {g : α → γ} {h : β → δ} {as : Vector α n} {bs : Vector β n} : zipWith f (as.map g) (bs.map h) = zipWith (fun a b => f (g a) (h b)) as bs := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ simp [Array.zipWith_map] -theorem zipWith_map_left (as : Vector α n) (bs : Vector β n) (f : α → α') (g : α' → β → γ) : +theorem zipWith_map_left {as : Vector α n} {bs : Vector β n} {f : α → α'} {g : α' → β → γ} : zipWith g (as.map f) bs = zipWith (fun a b => g (f a) b) as bs := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ simp [Array.zipWith_map_left] -theorem zipWith_map_right (as : Vector α n) (bs : Vector β n) (f : β → β') (g : α → β' → γ) : +theorem zipWith_map_right {as : Vector α n} {bs : Vector β n} {f : β → β'} {g : α → β' → γ} : zipWith g as (bs.map f) = zipWith (fun a b => g a (f b)) as bs := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ simp [Array.zipWith_map_right] -theorem zipWith_foldr_eq_zip_foldr {f : α → β → γ} (i : δ): +theorem zipWith_foldr_eq_zip_foldr {f : α → β → γ} {i : δ} : (zipWith f as bs).foldr g i = (zip as bs).foldr (fun p r => g (f p.1 p.2) r) i := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ - simpa using Array.zipWith_foldr_eq_zip_foldr _ + simpa using Array.zipWith_foldr_eq_zip_foldr -theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} (i : δ): +theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} {i : δ} : (zipWith f as bs).foldl g i = (zip as bs).foldl (fun r p => g r (f p.1 p.2)) i := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ - simpa using Array.zipWith_foldl_eq_zip_foldl _ + simpa using Array.zipWith_foldl_eq_zip_foldl - -theorem map_zipWith {δ : Type _} (f : α → β) (g : γ → δ → α) (as : Vector γ n) (bs : Vector δ n) : +theorem map_zipWith {δ : Type _} {f : α → β} {g : γ → δ → α} {as : Vector γ n} {bs : Vector δ n} : map f (zipWith g as bs) = zipWith (fun x y => f (g x y)) as bs := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ @@ -118,8 +117,8 @@ theorem extract_zipWith : (zipWith f as bs).extract i j = zipWith f (as.extract rcases bs with ⟨bs, h⟩ simp [Array.extract_zipWith] -theorem zipWith_append (f : α → β → γ) - (as : Vector α n) (as' : Vector α m) (bs : Vector β n) (bs' : Vector β m) : +theorem zipWith_append {f : α → β → γ} + {as : Vector α n} {as' : Vector α m} {bs : Vector β n} {bs' : Vector β m} : zipWith f (as ++ as') (bs ++ bs') = zipWith f as bs ++ zipWith f as' bs' := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ @@ -152,19 +151,19 @@ theorem zipWith_eq_append_iff {f : α → β → γ} {as : Vector α (n + m)} {b @[deprecated zipWith_replicate (since := "2025-03-18")] abbrev zipWith_mkVector := @zipWith_replicate -theorem map_uncurry_zip_eq_zipWith (f : α → β → γ) (as : Vector α n) (bs : Vector β n) : +theorem map_uncurry_zip_eq_zipWith {f : α → β → γ} {as : Vector α n} {bs : Vector β n} : map (Function.uncurry f) (as.zip bs) = zipWith f as bs := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ simp [Array.map_uncurry_zip_eq_zipWith] -theorem map_zip_eq_zipWith (f : α × β → γ) (as : Vector α n) (bs : Vector β n) : +theorem map_zip_eq_zipWith {f : α × β → γ} {as : Vector α n} {bs : Vector β n} : map f (as.zip bs) = zipWith (Function.curry f) as bs := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ simp [Array.map_zip_eq_zipWith] -theorem reverse_zipWith (f : α → β → γ) (as : Vector α n) (bs : Vector β n) : +theorem reverse_zipWith {f : α → β → γ} {as : Vector α n} {bs : Vector β n} : (zipWith f as bs).reverse = zipWith f as.reverse bs.reverse := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ @@ -177,21 +176,21 @@ theorem getElem_zip {as : Vector α n} {bs : Vector β n} {i : Nat} {h : i < n} (zip as bs)[i] = (as[i], bs[i]) := getElem_zipWith .. -theorem zip_eq_zipWith (as : Vector α n) (bs : Vector β n) : zip as bs = zipWith Prod.mk as bs := by +theorem zip_eq_zipWith {as : Vector α n} {bs : Vector β n} : zip as bs = zipWith Prod.mk as bs := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ simp [Array.zip_eq_zipWith, h] -theorem zip_map (f : α → γ) (g : β → δ) (as : Vector α n) (bs : Vector β n) : +theorem zip_map {f : α → γ} {g : β → δ} {as : Vector α n} {bs : Vector β n} : zip (as.map f) (bs.map g) = (zip as bs).map (Prod.map f g) := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ simp [Array.zip_map, h] -theorem zip_map_left (f : α → γ) (as : Vector α n) (bs : Vector β n) : +theorem zip_map_left {f : α → γ} {as : Vector α n} {bs : Vector β n} : zip (as.map f) bs = (zip as bs).map (Prod.map f id) := by rw [← zip_map, map_id] -theorem zip_map_right (f : β → γ) (as : Vector α n) (bs : Vector β n) : +theorem zip_map_right {f : β → γ} {as : Vector α n} {bs : Vector β n} : zip as (bs.map f) = (zip as bs).map (Prod.map id f) := by rw [← zip_map, map_id] theorem zip_append {as : Vector α n} {bs : Vector β n} {as' : Vector α m} {bs' : Vector β m} : @@ -202,7 +201,7 @@ theorem zip_append {as : Vector α n} {bs : Vector β n} {as' : Vector α m} {bs rcases bs' with ⟨bs', h'⟩ simp [Array.zip_append, h, h'] -theorem zip_map' (f : α → β) (g : α → γ) (xs : Vector α n) : +theorem zip_map' {f : α → β} {g : α → γ} {xs : Vector α n} : zip (xs.map f) (xs.map g) = xs.map fun a => (f a, g a) := by rcases xs with ⟨xs, rfl⟩ simp [Array.zip_map'] @@ -212,26 +211,28 @@ theorem of_mem_zip {a b} {as : Vector α n} {bs : Vector β n} : (a, b) ∈ zip rcases bs with ⟨bs, h⟩ simpa using Array.of_mem_zip -theorem map_fst_zip (as : Vector α n) (bs : Vector β n) : +-- The argument `as` is explicit so we can rewrite from right to left. +theorem map_fst_zip (as : Vector α n) {bs : Vector β n} : map Prod.fst (zip as bs) = as := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ simp [Array.map_fst_zip, h] -theorem map_snd_zip (as : Vector α n) (bs : Vector β n) : +-- The argument `bs` is explicit so we can rewrite from right to left. +theorem map_snd_zip {as : Vector α n} (bs : Vector β n) : map Prod.snd (zip as bs) = bs := by rcases as with ⟨as, rfl⟩ rcases bs with ⟨bs, h⟩ simp [Array.map_snd_zip, h] -theorem map_prod_left_eq_zip {xs : Vector α n} (f : α → β) : +theorem map_prod_left_eq_zip {xs : Vector α n} {f : α → β} : (xs.map fun x => (x, f x)) = xs.zip (xs.map f) := by rcases xs with ⟨xs, rfl⟩ rw [← zip_map'] congr simp -theorem map_prod_right_eq_zip {xs : Vector α n} (f : α → β) : +theorem map_prod_right_eq_zip {xs : Vector α n} {f : α → β} : (xs.map fun x => (f x, x)) = (xs.map f).zip xs := by rcases xs with ⟨xs, rfl⟩ rw [← zip_map'] @@ -260,10 +261,11 @@ abbrev zip_mkVector := @zip_replicate cases xs simp_all -theorem unzip_eq_map (xs : Vector (α × β) n) : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by +theorem unzip_eq_map {xs : Vector (α × β) n} : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by cases xs simp [List.unzip_eq_map] +-- The argument `xs` is explicit so we can rewrite from right to left. theorem zip_unzip (xs : Vector (α × β) n) : zip (unzip xs).1 (unzip xs).2 = xs := by cases xs simp only [unzip_mk, mk_zip_mk, Array.zip_unzip] diff --git a/src/Init/Omega/Coeffs.lean b/src/Init/Omega/Coeffs.lean index 43ba74d582..b8f82bfc00 100644 --- a/src/Init/Omega/Coeffs.lean +++ b/src/Init/Omega/Coeffs.lean @@ -98,7 +98,7 @@ theorem combo_eq_smul_add_smul (a : Int) (xs : Coeffs) (b : Int) (ys : Coeffs) : theorem gcd_dvd_dot_left (xs ys : Coeffs) : (gcd xs : Int) ∣ dot xs ys := IntList.gcd_dvd_dot_left xs ys theorem map_length {xs : Coeffs} : (xs.map f).length ≤ xs.length := - Nat.le_of_eq (List.length_map xs f) + Nat.le_of_eq (List.length_map f) theorem dot_nil_right {xs : Coeffs} : dot xs .nil = 0 := IntList.dot_nil_right theorem get_nil : get .nil i = 0 := IntList.get_nil diff --git a/src/Init/Omega/IntList.lean b/src/Init/Omega/IntList.lean index cd7595b94d..7f4c203b09 100644 --- a/src/Init/Omega/IntList.lean +++ b/src/Init/Omega/IntList.lean @@ -355,7 +355,7 @@ theorem dot_eq_zero_of_left_eq_zero {xs ys : IntList} (h : ∀ x, x ∈ xs → x cases ys with | nil => rfl | cons y ys => - rw [dot_cons₂, h x (List.mem_cons_self _ _), ih (fun x m => h x (List.mem_cons_of_mem _ m)), + rw [dot_cons₂, h x List.mem_cons_self, ih (fun x m => h x (List.mem_cons_of_mem _ m)), Int.zero_mul, Int.add_zero] @[simp] theorem nil_dot (xs : IntList) : dot [] xs = 0 := rfl @@ -377,7 +377,7 @@ theorem dot_sdiv_left (xs ys : IntList) {d : Int} (h : d ∣ xs.gcd) : abbrev bmod (x : IntList) (m : Nat) : IntList := x.map (Int.bmod · m) theorem bmod_length (x : IntList) (m) : (bmod x m).length ≤ x.length := - Nat.le_of_eq (List.length_map _ _) + Nat.le_of_eq (List.length_map _) /-- The difference between the balanced mod of a dot product, diff --git a/src/Lean/Elab/Tactic/Omega/MinNatAbs.lean b/src/Lean/Elab/Tactic/Omega/MinNatAbs.lean index f55330fe03..a958348044 100644 --- a/src/Lean/Elab/Tactic/Omega/MinNatAbs.lean +++ b/src/Lean/Elab/Tactic/Omega/MinNatAbs.lean @@ -121,7 +121,7 @@ theorem nonzeroMininum_map_le_nonzeroMinimum (f : α → β) (p : α → Nat) (q have := nonzeroMinimum_eq_of_nonzero z simp only [mem_map] at this obtain ⟨x, ⟨a, m, rfl⟩, eq⟩ := this - refine .inr ⟨q (f a), List.mem_map_of_mem _ (List.mem_map_of_mem _ m), ?_, ?_⟩ + refine .inr ⟨q (f a), List.mem_map_of_mem (List.mem_map_of_mem m), ?_, ?_⟩ · rw [eq] at z ⊢ apply w _ m z · rwa [Ne, ← h _ m, ← eq] diff --git a/src/Std/Data/DHashMap/Internal/Model.lean b/src/Std/Data/DHashMap/Internal/Model.lean index 6514e39961..16039b3f25 100644 --- a/src/Std/Data/DHashMap/Internal/Model.lean +++ b/src/Std/Data/DHashMap/Internal/Model.lean @@ -101,7 +101,7 @@ theorem exists_bucket_of_uset [BEq α] [Hashable α] ∀ k : α, (mkIdx self.size (by omega) (hash k)).1.toNat = i.toNat → containsKey k l = false) := by have h₀ : 0 < self.size := by omega - obtain ⟨l₁, l₂, h₁, h₂, h₃⟩ := Array.exists_of_uset self i d hi + obtain ⟨l₁, l₂, h₁, h₂, h₃⟩ := Array.exists_of_uset hi refine ⟨l₁.flatMap AssocList.toList ++ l₂.flatMap AssocList.toList, ?_, ?_, ?_⟩ · rw [toListModel, h₁] simpa using perm_append_comm_assoc _ _ _ diff --git a/src/Std/Data/DHashMap/Internal/WF.lean b/src/Std/Data/DHashMap/Internal/WF.lean index 29f5d3afd3..3911346cdd 100644 --- a/src/Std/Data/DHashMap/Internal/WF.lean +++ b/src/Std/Data/DHashMap/Internal/WF.lean @@ -303,7 +303,7 @@ theorem expand.go_eq [BEq α] [Hashable α] [PartialEquivBEq α] (source : Array refine ih.trans ?_ simp only [AssocList.foldl_eq, Array.toList_set] rw [List.drop_eq_getElem_cons hi, List.flatMap_cons, List.foldl_append, - List.drop_set_of_lt _ _ (by omega), Array.getElem_toList] + List.drop_set_of_lt (by omega), Array.getElem_toList] · next i source target hi => rw [expand.go_neg hi, List.drop_eq_nil_of_le, flatMap_nil, foldl_nil] rwa [Array.size_eq_length_toList, Nat.not_lt] at hi @@ -515,7 +515,7 @@ theorem wfImp_replaceₘ [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α theorem toListModel_consₘ [BEq α] [Hashable α] [PartialEquivBEq α] [LawfulHashable α] (m : Raw₀ α β) (h : Raw.WFImp m.1) (a : α) (b : β a) : Perm (toListModel (m.consₘ a b).1.buckets) (⟨a, b⟩ :: (toListModel m.1.2)) := - toListModel_updateBucket h .rfl (fun _ => Perm.cons _) (fun _ => cons_append _ _ _) + toListModel_updateBucket h .rfl (fun _ => Perm.cons _) (fun _ => cons_append) theorem isHashSelf_consₘ [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] (m : Raw₀ α β) (h : Raw.WFImp m.1) (a : α) (b : β a) : IsHashSelf (m.consₘ a b).1.buckets := by diff --git a/src/Std/Data/DTreeMap/Internal/Ordered.lean b/src/Std/Data/DTreeMap/Internal/Ordered.lean index 6ff463e782..894928d095 100644 --- a/src/Std/Data/DTreeMap/Internal/Ordered.lean +++ b/src/Std/Data/DTreeMap/Internal/Ordered.lean @@ -43,7 +43,7 @@ theorem Ordered.right [Ord α] {sz k v l r} (h : (.inner sz k v l r : Impl α β theorem Ordered.compare_left [Ord α] {sz k v l r} (h : (.inner sz k v l r : Impl α β).Ordered) {k'} (hk' : k' ∈ l.toListModel) : compare k'.1 k = .lt := - h.rel_of_mem_append hk' (List.mem_cons_self _ _) + h.rel_of_mem_append hk' List.mem_cons_self theorem Ordered.compare_left_beq_gt [Ord α] [TransOrd α] {k : α → Ordering} [IsStrictCut compare k] {sz k' v' l r} (ho : (.inner sz k' v' l r : Impl α β).Ordered) (hcmp : (k k').isGE) diff --git a/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean b/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean index 049d0ac06c..294cd162ed 100644 --- a/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean +++ b/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean @@ -225,7 +225,7 @@ theorem toListModel_find?_of_lt [Ord α] [TransOrd α] {k : α → Ordering} [Is (inner sz k' v' l r : Impl α β).toListModel.find? (k ·.1 == .eq) = l.toListModel.find? (k ·.1 == .eq) := by rw [toListModel_inner, List.find?_append, Option.or_eq_left_of_none] - rw [List.find?_cons_of_neg _ (by simp [hcmp])] + rw [List.find?_cons_of_neg (by simp [hcmp])] refine List.find?_eq_none.2 (fun p hp => by simp [IsCut.lt hcmp (ho.compare_right hp)]) theorem toListModel_filter_lt_of_gt [Ord α] [TransOrd α] {k : α → Ordering} [IsCut compare k] diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index f85f37ffea..df01d778b0 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -115,7 +115,7 @@ theorem getEntry?_eq_some_iff [BEq α] [EquivBEq α] {l : List ((a : α) × β a · rfl · exfalso rename_i h - have := hd.1 _ <| keys_eq_map ▸ List.mem_map_of_mem _ h + have := hd.1 _ <| keys_eq_map ▸ List.mem_map_of_mem h simp_all [BEq.trans hlkk hbeq] · rename_i h replace h := h.imp BEq.symm @@ -617,7 +617,7 @@ theorem getKey?_eq_getEntry? [BEq α] {l : List ((a : α) × β a)} {a : α} : theorem fst_mem_keys_of_mem [BEq α] [EquivBEq α] {a : (a : α) × β a} {l : List ((a : α) × β a)} (hm : a ∈ l) : a.1 ∈ keys l := - keys_eq_map ▸ List.mem_map_of_mem _ hm + keys_eq_map ▸ List.mem_map_of_mem hm theorem getKey?_eq_some_iff [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k k'} (hd : DistinctKeys l) : @@ -1632,7 +1632,7 @@ theorem keys_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a) theorem DistinctKeys.eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α} : DistinctKeys l → DistinctKeys (eraseKey k l) := by - apply distinctKeys_of_sublist_keys (by simpa using erase_sublist _ _) + apply distinctKeys_of_sublist_keys (by simpa using erase_sublist) theorem getEntry?_eraseKey_self [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α} (h : DistinctKeys l) : getEntry? k (eraseKey k l) = none := by @@ -1691,7 +1691,7 @@ theorem DistinctKeys.filterMap [BEq α] [PartialEquivBEq α] {l : List ((a : α) apply distinctKeys_of_sublist_keys rw [keys_filterMap, keys_eq_map, keys_eq_map] apply Sublist.map - exact filter_sublist l + exact filter_sublist theorem DistinctKeys.map [BEq α] {l : List ((a : α) × β a)} {f : (a : α) → β a → γ a} (h : DistinctKeys l) : DistinctKeys (l.map fun p => ⟨p.1, f p.1 p.2⟩) := @@ -1699,7 +1699,7 @@ theorem DistinctKeys.map [BEq α] {l : List ((a : α) × β a)} {f : (a : α) theorem DistinctKeys.filter [BEq α] {l : List ((a : α) × β a)} {f : (a : α) → β a → Bool} (h : DistinctKeys l) : DistinctKeys (l.filter fun p => f p.1 p.2) := - distinctKeys_of_sublist (filter_sublist _) h + distinctKeys_of_sublist filter_sublist h section @@ -2471,7 +2471,7 @@ theorem insertList_cons_perm [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) simp only [getEntry?_insertEntry] split <;> rename_i hp <;> split <;> rename_i hh <;> try rfl rw [DistinctKeys.def] at hl₂ - have := List.rel_of_pairwise_cons hl₂ (List.mem_cons_self _ _) + have := List.rel_of_pairwise_cons hl₂ List.mem_cons_self simp [BEq.trans hh (BEq.symm hp)] at this theorem getEntry?_insertList [BEq α] [EquivBEq α] @@ -2874,7 +2874,7 @@ theorem length_insertListConst_le [BEq α] {l : List ((_ : α) × β)} {toInsert : List (α × β)} : (insertListConst l toInsert).length ≤ l.length + toInsert.length := by unfold insertListConst - rw [← List.length_map toInsert Prod.toSigma] + rw [← List.length_map Prod.toSigma] apply length_insertList_le theorem isEmpty_insertListConst [BEq α] diff --git a/src/Std/Sat/CNF/Relabel.lean b/src/Std/Sat/CNF/Relabel.lean index 0f967eba78..56bbde476e 100644 --- a/src/Std/Sat/CNF/Relabel.lean +++ b/src/Std/Sat/CNF/Relabel.lean @@ -60,7 +60,7 @@ def relabel (r : α → β) (f : CNF α) : CNF β := f.map (Clause.relabel r) induction f <;> simp_all @[simp] theorem relabel_append : relabel r (f1 ++ f2) = relabel r f1 ++ relabel r f2 := - List.map_append _ _ _ + List.map_append @[simp] theorem relabel_relabel : relabel r1 (relabel r2 f) = relabel (r1 ∘ r2) f := by simp only [relabel, List.map_map, Clause.relabel_relabel'] diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/Lemmas.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/Lemmas.lean index 710c7f455a..c28cd15036 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/Lemmas.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/Lemmas.lean @@ -110,7 +110,7 @@ theorem readyForRupAdd_ofArray {n : Nat} (arr : Array (Option (DefaultClause n)) have hb : (Array.replicate n unassigned).size = n := by simp only [Array.size_replicate] have hl (acc : Array Assignment) (ih : acc.size = n) (cOpt : Option (DefaultClause n)) (_cOpt_in_arr : cOpt ∈ arr.toList) : (ofArray_fold_fn acc cOpt).size = n := by rw [size_ofArray_fold_fn acc cOpt, ih] - exact List.foldlRecOn arr.toList ofArray_fold_fn (.replicate n unassigned) hb hl + exact List.foldlRecOn arr.toList ofArray_fold_fn hb hl apply Exists.intro hsize let ModifiedAssignmentsInvariant (assignments : Array Assignment) : Prop := ∃ hsize : assignments.size = n, @@ -185,7 +185,7 @@ theorem readyForRupAdd_ofArray {n : Nat} (arr : Array (Option (DefaultClause n)) · next i_ne_l => simp only [Array.getElem_modify_of_ne (Ne.symm i_ne_l)] at h exact ih i b h - rcases List.foldlRecOn arr.toList ofArray_fold_fn (.replicate n unassigned) hb hl with ⟨_h_size, h'⟩ + rcases List.foldlRecOn arr.toList ofArray_fold_fn hb hl with ⟨_h_size, h'⟩ intro i b h simp only [ofArray, ← Array.foldl_toList] at h exact h' i b h @@ -379,7 +379,7 @@ theorem mem_of_insertRupUnits {n : Nat} (f : DefaultFormula n) (units : CNF.Clau · exact ih l l_in_acc · rw [l_eq_unit] exact Or.inr unit_in_units - have h_insertUnit_fold := List.foldlRecOn units insertUnit (f.rupUnits, f.assignments, false) hb hl + have h_insertUnit_fold := List.foldlRecOn units insertUnit hb hl rcases h with h | ⟨i, ⟨h1, h2⟩ | ⟨h1, h2⟩⟩ | h · exact Or.inr <| Or.inl h · rcases h_insertUnit_fold (i, false) h1 with h_insertUnit_fold | h_insertUnit_fold @@ -416,7 +416,7 @@ theorem mem_of_insertRatUnits {n : Nat} (f : DefaultFormula n) (units : CNF.Clau · exact ih l l_in_acc · rw [l_eq_unit] exact Or.inr unit_in_units - have h_insertUnit_fold := List.foldlRecOn units insertUnit (f.ratUnits, f.assignments, false) hb hl + have h_insertUnit_fold := List.foldlRecOn units insertUnit hb hl rcases h with h | h | ⟨i, ⟨h1, h2⟩ | ⟨h1, h2⟩⟩ · exact Or.inr <| Or.inl h · exact (Or.inr ∘ Or.inr ∘ Or.inl) h @@ -610,11 +610,11 @@ theorem readyForRupAdd_delete {n : Nat} (f : DefaultFormula n) (arr : Array Nat) · have hb : f.rupUnits = #[] := h.1 have hl (acc : DefaultFormula n) (ih : acc.rupUnits = #[]) (id : Nat) (_id_in_arr : id ∈ arr.toList) : (deleteOne acc id).rupUnits = #[] := by rw [deleteOne_preserves_rupUnits, ih] - exact List.foldlRecOn arr.toList deleteOne f hb hl + exact List.foldlRecOn arr.toList deleteOne hb hl · have hb : StrongAssignmentsInvariant f := h.2 have hl (acc : DefaultFormula n) (ih : StrongAssignmentsInvariant acc) (id : Nat) (_id_in_arr : id ∈ arr.toList) : StrongAssignmentsInvariant (deleteOne acc id) := deleteOne_preserves_strongAssignmentsInvariant acc id ih - exact List.foldlRecOn arr.toList deleteOne f hb hl + exact List.foldlRecOn arr.toList deleteOne hb hl theorem deleteOne_preserves_ratUnits {n : Nat} (f : DefaultFormula n) (id : Nat) : (deleteOne f id).ratUnits = f.ratUnits := by @@ -629,7 +629,7 @@ theorem readyForRatAdd_delete {n : Nat} (f : DefaultFormula n) (arr : Array Nat) have hb : f.ratUnits = #[] := h.1 have hl (acc : DefaultFormula n) (ih : acc.ratUnits = #[]) (id : Nat) (_id_in_arr : id ∈ arr.toList) : (deleteOne acc id).ratUnits = #[] := by rw [deleteOne_preserves_ratUnits, ih] - exact List.foldlRecOn arr.toList deleteOne f hb hl + exact List.foldlRecOn arr.toList deleteOne hb hl · exact readyForRupAdd_delete f arr h.2 theorem deleteOne_subset (f : DefaultFormula n) (id : Nat) (c : DefaultClause n) : @@ -663,7 +663,7 @@ theorem delete_subset (f : DefaultFormula n) (arr : Array Nat) (c : DefaultClaus have hb : c ∈ toList f → c ∈ toList f := id have hl (f' : DefaultFormula n) (ih : c ∈ toList f' → c ∈ toList f) (id : Nat) (_ : id ∈ arr.toList) : c ∈ toList (deleteOne f' id) → c ∈ toList f := by intro h; exact ih <| deleteOne_subset f' id c h - exact List.foldlRecOn arr.toList deleteOne f hb hl + exact List.foldlRecOn arr.toList deleteOne hb hl end DefaultFormula diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean index 023eeaf5f4..1e28d9ce2a 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean @@ -131,7 +131,7 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen exact k_property · intro h simp only [← h, not_true, mostRecentUnitIdx] at hk - rw [Array.getElem_push_lt _ _ _ k_in_bounds] + rw [Array.getElem_push_lt k_in_bounds] rw [i_eq_l] at h2 exact h2 ⟨k.1, k_in_bounds⟩ · next i_ne_l => @@ -190,7 +190,7 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen refine ⟨⟨j.1, j_lt_updatedUnits_size⟩, mostRecentUnitIdx, i_gt_zero, ?_⟩ simp only [insertUnit, h5, ite_false, Array.getElem_push_eq, ne_eq, reduceCtorEq] constructor - · rw [Array.getElem_push_lt units l j.1 j.2, h1] + · rw [Array.getElem_push_lt, h1] · constructor · simp +zetaDelta [i_eq_l, ← hl] rfl @@ -230,7 +230,7 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen · simp +zetaDelta [i_eq_l, ← hl] rfl · constructor - · rw [Array.getElem_push_lt units l j.1 j.2, h1] + · rw [Array.getElem_push_lt, h1] · constructor · simp only [i_eq_l] rw [Array.getElem_modify_self] @@ -273,7 +273,7 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen refine ⟨⟨j.1, j_lt_updatedUnits_size⟩, b,i_gt_zero, ?_⟩ simp only [insertUnit, h5, ite_false, reduceCtorEq] constructor - · rw [Array.getElem_push_lt units l j.1 j.2, h1] + · rw [Array.getElem_push_lt, h1] · constructor · rw [Array.getElem_modify_of_ne (Ne.symm i_ne_l), h2] · constructor @@ -305,11 +305,11 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen constructor · split · exact h1 - · simp only [Array.getElem_push_lt units l j1.1 j1.2, h1] + · simp only [Array.getElem_push_lt j1.2, h1] · constructor · split · exact h2 - · simp only [Array.getElem_push_lt units l j2.1 j2.2, h2] + · simp only [Array.getElem_push_lt j2.2, h2] · constructor · split · exact h3 @@ -477,7 +477,7 @@ theorem size_clearUnit_foldl {α : Type u} (assignments : Array Assignment) have hb : assignments.size = assignments.size := rfl have hl (assignments' : Array Assignment) (hsize : assignments'.size = assignments.size) (a : α) (_ : a ∈ l) : (f assignments' a).size = assignments.size := by rw [f_preserves_size assignments' a, hsize] - exact List.foldlRecOn l f assignments hb hl + exact List.foldlRecOn l f hb hl def ClearInsertInductionMotive {n : Nat} (f : DefaultFormula n) (assignments_size : f.assignments.size = n) (units : Array (Literal (PosFin n))) : @@ -743,7 +743,7 @@ theorem size_assignments_performRupCheck {n : Nat} (f : DefaultFormula n) (rupHi (id : Nat) (_ : id ∈ rupHints.toList) : (confirmRupHint f.clauses acc id).1.size = f.assignments.size := by have h := size_assignemnts_confirmRupHint f.clauses acc.1 acc.2.1 acc.2.2.1 acc.2.2.2 id rw [h, hsize] - exact List.foldlRecOn rupHints.toList (confirmRupHint f.clauses) (f.assignments, [], false, false) hb hl + exact List.foldlRecOn rupHints.toList (confirmRupHint f.clauses) hb hl def DerivedLitsInvariant {n : Nat} (f : DefaultFormula n) (fassignments_size : f.assignments.size = n) (assignments : Array Assignment) diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean index 7efcaf1d44..7c7d85ad07 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean @@ -88,7 +88,7 @@ theorem contradiction_of_insertUnit_fold_success {n : Nat} (assignments : Array intro insertUnit_res_success rcases h with ⟨acc_size, h⟩ exact contradiction_of_insertUnit_success acc.2.1 acc_size acc.1 acc.2.2 l' h insertUnit_res_success - rcases List.foldlRecOn l insertUnit acc0 hb hl with ⟨_, h⟩ + rcases List.foldlRecOn l insertUnit hb hl with ⟨_, h⟩ exact h insertUnit_fold_success theorem mem_insertUnit_units {n : Nat} (units : Array (Literal (PosFin n))) (assignments : Array Assignment) @@ -118,7 +118,7 @@ theorem mem_insertUnit_fold_units {n : Nat} (units : Array (Literal (PosFin n))) · rw [l'_eq_l''] exact Or.inl l''_in_l · exact h l' l'_in_acc - exact List.foldlRecOn l insertUnit (units, assignments, foundContradiction) hb hl + exact List.foldlRecOn l insertUnit hb hl theorem sat_of_insertRup {n : Nat} (f : DefaultFormula n) (f_readyForRupAdd : ReadyForRupAdd f) (c : DefaultClause n) (p : PosFin n → Bool) (pf : p ⊨ f) : @@ -394,7 +394,7 @@ theorem unsat_of_encounteredBoth {n : Nat} (c : DefaultClause n) simp [heq, has_both] at hp · simp at h · simp at h - exact List.foldlRecOn c.clause (reduce_fold_fn assignment) reducedToEmpty hb hl + exact List.foldlRecOn c.clause (reduce_fold_fn assignment) hb hl def ReducePostconditionInductionMotive (c_arr : Array (Literal (PosFin n))) (assignment : Array Assignment) (idx : Nat) (res : ReduceResult (PosFin n)) : diff --git a/tests/lean/run/2899.lean b/tests/lean/run/2899.lean index dad34bb8e9..83eae43049 100644 --- a/tests/lean/run/2899.lean +++ b/tests/lean/run/2899.lean @@ -6,7 +6,7 @@ def myfun (x : Array α) (i : Fin x.size) : Array α := let next := 2*i.1 + 1 if h : next < x.size then have : x.size - next < x.size - i.1 := sorry - myfun (x.swap i next) ⟨next, (x.size_swap _ _).symm ▸ h⟩ + myfun (x.swap i next) ⟨next, (x.size_swap).symm ▸ h⟩ else x termination_by x.size - i.1 diff --git a/tests/lean/run/4051.lean b/tests/lean/run/4051.lean index a7d2bc99bb..116c220fcc 100644 --- a/tests/lean/run/4051.lean +++ b/tests/lean/run/4051.lean @@ -1,7 +1,7 @@ def Array.swaps (a : Array α) : List (Fin a.size × Fin a.size) → Array α | [] => a | (i, j) :: ijs => - have : (a.swap i j).size = a.size := a.size_swap _ _ + have : (a.swap i j).size = a.size := a.size_swap swaps (a.swap i j) (ijs.map (fun p => ⟨⟨p.1.1, by simp⟩, ⟨p.2.1, by simp⟩⟩)) termination_by l => l.length diff --git a/tests/lean/run/binderNameHint.lean b/tests/lean/run/binderNameHint.lean index dcc7abb3e0..084bb48469 100644 --- a/tests/lean/run/binderNameHint.lean +++ b/tests/lean/run/binderNameHint.lean @@ -1,6 +1,6 @@ theorem all_eq_not_any_not (l : List α) (p : α → Bool) : l.all p = !l.any fun x => binderNameHint x p (!p x) - := List.all_eq_not_any_not l p + := List.all_eq_not_any_not /-- error: tactic 'fail' failed diff --git a/tests/lean/run/grind_mark_nested_proofs_bug.lean b/tests/lean/run/grind_mark_nested_proofs_bug.lean index 69ccafbb56..adc145d25e 100644 --- a/tests/lean/run/grind_mark_nested_proofs_bug.lean +++ b/tests/lean/run/grind_mark_nested_proofs_bug.lean @@ -14,7 +14,7 @@ example (as bs cs : Array α) (v : α) theorem Array.getElem_set_ne_abstracted (xs : Array α) (i : Nat) (h' : i < xs.size) (v : α) {j : Nat} (pj : j < xs.size) (h : i ≠ j) : - (xs.set i v)[j]'(by as_aux_lemma => simp [*]) = xs[j] := Array.getElem_set_ne xs i h' v pj h + (xs.set i v)[j]'(by as_aux_lemma => simp [*]) = xs[j] := Array.getElem_set_ne h' pj h example (as bs cs : Array α) (v : α) (i : Nat) diff --git a/tests/lean/run/heapSort.lean b/tests/lean/run/heapSort.lean index fc76b691a1..b053ac9780 100644 --- a/tests/lean/run/heapSort.lean +++ b/tests/lean/run/heapSort.lean @@ -27,11 +27,11 @@ def heapifyDown (lt : α → α → Bool) (a : Array α) (i : Fin a.size) : if lt a[j.1] a[right] then ⟨⟨right, h⟩, right_le⟩ else j else j if h : i.1 = j then ⟨a, rfl⟩ else let a' := a.swap i j - let j' := ⟨j, by rw [a.size_swap i j]; exact j.1.2⟩ + let j' := ⟨j, by rw [a.size_swap]; exact j.1.2⟩ have : a'.size - j < a.size - i := by - rw [a.size_swap i j]; sorry + rw [a.size_swap]; sorry let ⟨a₂, h₂⟩ := heapifyDown lt a' j' - ⟨a₂, h₂.trans (a.size_swap i j)⟩ + ⟨a₂, h₂.trans a.size_swap⟩ termination_by a.size - i decreasing_by assumption @@ -62,8 +62,8 @@ if i0 : i.1 = 0 then ⟨a, rfl⟩ else let j : Fin a.size := ⟨(i.1 - 1) / 2, Nat.lt_trans this i.2⟩ if lt a[j] a[i] then let a' := a.swap i j - let ⟨a₂, h₂⟩ := heapifyUp lt a' ⟨j.1, by rw [a.size_swap i j]; exact j.2⟩ - ⟨a₂, h₂.trans (a.size_swap i j)⟩ + let ⟨a₂, h₂⟩ := heapifyUp lt a' ⟨j.1, by rw [a.size_swap]; exact j.2⟩ + ⟨a₂, h₂.trans (a.size_swap)⟩ else ⟨a, rfl⟩ termination_by i.1 decreasing_by assumption diff --git a/tests/lean/run/subst.lean b/tests/lean/run/subst.lean index 9e541db1b0..c13629fcd0 100644 --- a/tests/lean/run/subst.lean +++ b/tests/lean/run/subst.lean @@ -49,7 +49,7 @@ theorem ex12 {α : Type u} {n : Nat} (a b : Array α) (hsz₁ : a.size = n) (hsz₂ : b.size = n) (h : ∀ (i : Nat) (hi : i < n), a.getLit i hsz₁ hi = b.getLit i hsz₂ hi) : a = b := -Array.ext a b (hsz₁.trans hsz₂.symm) fun i hi₁ hi₂ => h i (hsz₁ ▸ hi₁) +Array.ext (hsz₁.trans hsz₂.symm) fun i hi₁ hi₂ => h i (hsz₁ ▸ hi₁) def toArrayLit {α : Type u} (a : Array α) (n : Nat) (hsz : a.size = n) : Array α := List.toArray $ Array.toListLitAux a n hsz n (hsz ▸ Nat.le_refl _) []