feat: more List.attach lemmas (#5277)

This commit is contained in:
Kim Morrison 2024-09-07 15:29:40 +10:00 committed by GitHub
parent fcfead8cde
commit 7432a6f01f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 95 additions and 30 deletions

View file

@ -76,6 +76,11 @@ theorem pmap_map {p : β → Prop} (g : ∀ b, p b → γ) (f : α → β) (l H)
· rfl
· simp only [*, pmap, map]
theorem attach_congr {l₁ l₂ : List α} (h : l₁ = l₂) :
l₁.attach = l₂.attach.map (fun x => ⟨x.1, h ▸ x.2⟩) := by
subst h
simp
@[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
@ -255,31 +260,55 @@ theorem head_attach {xs : List α} (h) :
| nil => simp at h
| cons x xs => simp [head_attach, h]
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
induction l <;> simp [*]
theorem attach_filterMap {l : List α} {f : α → Option β} :
(l.filterMap f).attach = l.attach.filterMap
fun ⟨x, h⟩ => (f x).pbind (fun b m => some ⟨b, mem_filterMap.mpr ⟨x, h, m⟩⟩) := by
induction l with
| nil => rfl
| cons x xs ih =>
simp only [filterMap_cons, attach_cons, ih, filterMap_map]
split <;> rename_i h
· simp only [Option.pbind_eq_none_iff, reduceCtorEq, Option.mem_def, exists_false,
or_false] at h
rw [attach_congr]
rotate_left
· simp only [h]
rfl
rw [ih]
simp only [map_filterMap, Option.map_pbind, Option.map_some']
rfl
· simp only [Option.pbind_eq_some_iff] at h
obtain ⟨a, h, w⟩ := h
simp only [Option.some.injEq] at w
subst w
simp only [Option.mem_def] at h
rw [attach_congr]
rotate_left
· simp only [h]
rfl
rw [attach_cons, map_cons, map_map, ih, map_filterMap]
congr
ext
simp
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]
simp only [Option.guard]
congr
ext1
split <;> simp
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
induction l with
| nil => rfl
| cons x xs ih =>
simp only [pmap, ih, cons.injEq, true_and]
ext1 i
simp only [getElem?_pmap, Option.pmap]
split <;> rename_i h _ <;> split <;> rename_i h' _
· rfl
· simp only [getElem?_attach, Option.pmap_eq_none, getElem?_eq_none_iff] at h
simp [getElem?_eq_none h] at h'
· simp only [getElem?_pmap, Option.pmap_eq_none, getElem?_eq_none_iff] at h'
rw [getElem?_eq_none] at h
simp only [reduceCtorEq] at h
simpa using h'
· simp only [getElem?_attach, Option.pmap_eq_some, exists_and_left] at h
simp only [getElem?_pmap, Option.pmap_eq_some, mem_cons, exists_and_left] at h'
obtain ⟨a, h, x, rfl⟩ := h
obtain ⟨a, h', x', rfl⟩ := h'
simp only [h, Option.some.injEq] at h'
subst h'
rfl
simp [pmap_eq_map_attach, attach_map]
@[simp] theorem pmap_append {p : ι → Prop} (f : ∀ a : ι, p a → α) (l₁ l₂ : List ι)
(h : ∀ a ∈ l₁ ++ l₂, p a) :
@ -298,6 +327,13 @@ theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (l₁ l₂ :
l₁.pmap f h₁ ++ l₂.pmap f h₂ :=
pmap_append f l₁ l₂ _
@[simp] theorem attach_append (xs ys : List α) :
(xs ++ ys).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨x, mem_append_of_mem_left ys h⟩) ++
ys.attach.map fun ⟨x, h⟩ => ⟨x, mem_append_of_mem_right xs h⟩ := by
simp only [attach, attachWith, pmap, map_pmap, pmap_append]
congr 1 <;>
exact pmap_congr_left _ fun _ _ _ _ => rfl
@[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
@ -308,13 +344,6 @@ theorem reverse_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : List
(xs.pmap f H).reverse = xs.reverse.pmap f (fun a h => H a (by simpa using h)) := by
rw [pmap_reverse]
@[simp] theorem attach_append (xs ys : List α) :
(xs ++ ys).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨x, mem_append_of_mem_left ys h⟩) ++
ys.attach.map fun ⟨x, h⟩ => ⟨x, mem_append_of_mem_right xs h⟩ := by
simp only [attach, attachWith, pmap, map_pmap, pmap_append]
congr 1 <;>
exact pmap_congr_left _ fun _ _ _ _ => rfl
@[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]

View file

@ -414,6 +414,42 @@ end ite
subst ho
exact (funext fun a => funext fun h => hf a h) ▸ Eq.refl (o.pbind f)
theorem pbind_eq_none_iff {o : Option α} {f : (a : α) → a ∈ o → Option β} :
o.pbind f = none ↔ o = none ∃ a h, f a h = none := by
cases o with
| none => simp
| some a =>
simp only [pbind_some, reduceCtorEq, mem_def, some.injEq, false_or]
constructor
· intro h
exact ⟨a, rfl, h⟩
· rintro ⟨a, rfl, h⟩
exact h
theorem pbind_isSome {o : Option α} {f : (a : α) → a ∈ o → Option β} :
(o.pbind f).isSome = ∃ a h, (f a h).isSome := by
cases o with
| none => simp
| some a =>
simp only [pbind_some, mem_def, some.injEq, eq_iff_iff]
constructor
· intro h
exact ⟨a, rfl, h⟩
· rintro ⟨a, rfl, h⟩
exact h
theorem pbind_eq_some_iff {o : Option α} {f : (a : α) → a ∈ o → Option β} {b : β} :
o.pbind f = some b ↔ ∃ a h, f a h = some b := by
cases o with
| none => simp
| some a =>
simp only [pbind_some, mem_def, some.injEq]
constructor
· intro h
exact ⟨a, rfl, h⟩
· rintro ⟨a, rfl, h⟩
exact h
/-! ### pmap -/
@[simp] theorem pmap_none {p : α → Prop} {f : ∀ (a : α), p a → β} {h} :
@ -422,7 +458,7 @@ end ite
@[simp] theorem pmap_some {p : α → Prop} {f : ∀ (a : α), p a → β} {h}:
pmap f (some a) h = f a (h a (mem_some_self a)) := rfl
@[simp] theorem pmap_eq_none {p : α → Prop} {f : ∀ (a : α), p a → β} {h} :
@[simp] theorem pmap_eq_none_iff {p : α → Prop} {f : ∀ (a : α), p a → β} {h} :
pmap f o h = none ↔ o = none := by
cases o <;> simp
@ -430,7 +466,7 @@ end ite
(pmap f o h).isSome = o.isSome := by
cases o <;> simp
@[simp] theorem pmap_eq_some {p : α → Prop} {f : ∀ (a : α), p a → β} {o : Option α} {h} :
@[simp] theorem pmap_eq_some_iff {p : α → Prop} {f : ∀ (a : α), p a → β} {o : Option α} {h} :
pmap f o h = some b ↔ ∃ (a : α) (h : p a), o = some a ∧ b = f a h := by
cases o with
| none => simp