Skip to content

Commit

Permalink
feat: more List.attach lemmas (#5277)
Browse files Browse the repository at this point in the history
  • Loading branch information
kim-em authored Sep 7, 2024
1 parent fcfead8 commit 7432a6f
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 30 deletions.
85 changes: 57 additions & 28 deletions src/Init/Data/List/Attach.lean
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -255,31 +260,55 @@ theorem head_attach {xs : List α} (h) :
| nil => simp at h
| cons x xs => simp [head_attach, 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
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 [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'
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
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) :
Expand All @@ -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
Expand All @@ -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]
Expand Down
40 changes: 38 additions & 2 deletions src/Init/Data/Option/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -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} :
Expand All @@ -422,15 +458,15 @@ 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

@[simp] theorem pmap_isSome {p : α → Prop} {f : ∀ (a : α), p a → β} {o : Option α} {h} :
(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
Expand Down

0 comments on commit 7432a6f

Please sign in to comment.