-
Notifications
You must be signed in to change notification settings - Fork 465
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
219 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
/- | ||
Copyright (c) 2024 Lean FRO. All rights reserved. | ||
Released under Apache 2.0 license as described in the file LICENSE. | ||
Authors: Kim Morrison | ||
-/ | ||
prelude | ||
import Init.Data.Option.Basic | ||
import Init.Data.Option.List | ||
import Init.Data.List.Attach | ||
import Init.BinderPredicates | ||
|
||
namespace Option | ||
|
||
/-- | ||
Unsafe implementation of `attachWith`, taking advantage of the fact that the representation of | ||
`Option {x // P x}` is the same as the input `Option α`. | ||
-/ | ||
@[inline] private unsafe def attachWithImpl | ||
(o : Option α) (P : α → Prop) (_ : ∀ x ∈ o, P x) : Option {x // P x} := unsafeCast o | ||
|
||
/-- "Attach" a proof `P x` that holds for the element of `o`, if present, | ||
to produce a new option with the same element but in the type `{x // P x}`. -/ | ||
@[implemented_by attachWithImpl] def attachWith | ||
(xs : Option α) (P : α → Prop) (H : ∀ x ∈ xs, P x) : Option {x // P x} := | ||
match xs with | ||
| none => none | ||
| some x => some ⟨x, H x (mem_some_self x)⟩ | ||
|
||
/-- "Attach" the proof that the element of `xs`, if present, is in `xs` | ||
to produce a new option with the same elements but in the type `{x // x ∈ xs}`. -/ | ||
@[inline] def attach (xs : Option α) : Option {x // x ∈ xs} := xs.attachWith _ fun _ => id | ||
|
||
@[simp] theorem attach_none : (none : Option α).attach = none := rfl | ||
@[simp] theorem attachWith_none : (none : Option α).attachWith P H = none := rfl | ||
|
||
@[simp] theorem attach_some {x : α} : | ||
(some x).attach = some ⟨x, rfl⟩ := rfl | ||
@[simp] theorem attachWith_some {x : α} {P : α → Prop} (h : ∀ (b : α), b ∈ some x → P b) : | ||
(some x).attachWith P h = some ⟨x, by simpa using h⟩ := rfl | ||
|
||
theorem attach_congr {o₁ o₂ : Option α} (h : o₁ = o₂) : | ||
o₁.attach = o₂.attach.map (fun x => ⟨x.1, h ▸ x.2⟩) := by | ||
subst h | ||
simp | ||
|
||
theorem attachWith_congr {o₁ o₂ : Option α} (w : o₁ = o₂) {P : α → Prop} {H : ∀ x ∈ o₁, P x} : | ||
o₁.attachWith P H = o₂.attachWith P fun x h => H _ (w ▸ h) := by | ||
subst w | ||
simp | ||
|
||
theorem attach_map_coe (o : Option α) (f : α → β) : | ||
(o.attach.map fun (i : {i // i ∈ o}) => f i) = o.map f := by | ||
cases o <;> simp | ||
|
||
theorem attach_map_val (o : Option α) (f : α → β) : | ||
(o.attach.map fun i => f i.val) = o.map f := | ||
attach_map_coe _ _ | ||
|
||
@[simp] | ||
theorem attach_map_subtype_val (o : Option α) : | ||
o.attach.map Subtype.val = o := | ||
(attach_map_coe _ _).trans (congrFun Option.map_id _) | ||
|
||
theorem attachWith_map_coe {p : α → Prop} (f : α → β) (o : Option α) (H : ∀ a ∈ o, p a) : | ||
((o.attachWith p H).map fun (i : { i // p i}) => f i.val) = o.map f := by | ||
cases o <;> simp [H] | ||
|
||
theorem attachWith_map_val {p : α → Prop} (f : α → β) (o : Option α) (H : ∀ a ∈ o, p a) : | ||
((o.attachWith p H).map fun i => f i.val) = o.map f := | ||
attachWith_map_coe _ _ _ | ||
|
||
@[simp] | ||
theorem attachWith_map_subtype_val {p : α → Prop} (o : Option α) (H : ∀ a ∈ o, p a) : | ||
(o.attachWith p H).map Subtype.val = o := | ||
(attachWith_map_coe _ _ _).trans (congrFun Option.map_id _) | ||
|
||
@[simp] theorem mem_attach : ∀ (o : Option α) (x : {x // x ∈ o}), x ∈ o.attach | ||
| none, ⟨x, h⟩ => by simp at h | ||
| some a, ⟨x, h⟩ => by simpa using h | ||
|
||
@[simp] theorem isNone_attach (o : Option α) : o.attach.isNone = o.isNone := by | ||
cases o <;> simp | ||
|
||
@[simp] theorem isNone_attachWith {p : α → Prop} (o : Option α) (H : ∀ a ∈ o, p a) : | ||
(o.attachWith p H).isNone = o.isNone := by | ||
cases o <;> simp | ||
|
||
@[simp] theorem isSome_attach (o : Option α) : o.attach.isSome = o.isSome := by | ||
cases o <;> simp | ||
|
||
@[simp] theorem isSome_attachWith {p : α → Prop} (o : Option α) (H : ∀ a ∈ o, p a) : | ||
(o.attachWith p H).isSome = o.isSome := by | ||
cases o <;> simp | ||
|
||
@[simp] theorem attach_eq_none_iff (o : Option α) : o.attach = none ↔ o = none := by | ||
cases o <;> simp | ||
|
||
@[simp] theorem attach_eq_some_iff {o : Option α} {x : {x // x ∈ o}} : | ||
o.attach = some x ↔ o = some x.val := by | ||
cases o <;> cases x <;> simp | ||
|
||
@[simp] theorem attachWith_eq_none_iff {p : α → Prop} (o : Option α) (H : ∀ a ∈ o, p a) : | ||
o.attachWith p H = none ↔ o = none := by | ||
cases o <;> simp | ||
|
||
@[simp] theorem attachWith_eq_some_iff {p : α → Prop} {o : Option α} (H : ∀ a ∈ o, p a) {x : {x // p x}} : | ||
o.attachWith p H = some x ↔ o = some x.val := by | ||
cases o <;> cases x <;> simp | ||
|
||
@[simp] theorem get_attach {o : Option α} (h : o.attach.isSome = true) : | ||
o.attach.get h = ⟨o.get (by simpa using h), by simp⟩ := by | ||
cases o | ||
· simp at h | ||
· simp [get_some] | ||
|
||
@[simp] theorem get_attachWith {p : α → Prop} {o : Option α} (H : ∀ a ∈ o, p a) (h : (o.attachWith p H).isSome) : | ||
(o.attachWith p H).get h = ⟨o.get (by simpa using h), H _ (by simp)⟩ := by | ||
cases o | ||
· simp at h | ||
· simp [get_some] | ||
|
||
@[simp] theorem toList_attach (o : Option α) : | ||
o.attach.toList = o.toList.attach.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by | ||
cases o <;> simp | ||
|
||
theorem attach_map {o : Option α} (f : α → β) : | ||
(o.map f).attach = o.attach.map (fun ⟨x, h⟩ => ⟨f x, mem_map_of_mem f h⟩) := by | ||
cases o <;> simp | ||
|
||
theorem attachWith_map {o : Option α} (f : α → β) {P : β → Prop} {H : ∀ (b : β), b ∈ o.map f → P b} : | ||
(o.map f).attachWith P H = (o.attachWith (P ∘ f) (fun a h => H _ (mem_map_of_mem f h))).map | ||
fun ⟨x, h⟩ => ⟨f x, h⟩ := by | ||
cases o <;> simp | ||
|
||
theorem map_attach {o : Option α} (f : { x // x ∈ o } → β) : | ||
o.attach.map f = o.pmap (fun a (h : a ∈ o) => f ⟨a, h⟩) (fun a h => h) := by | ||
cases o <;> simp | ||
|
||
theorem map_attachWith {o : Option α} {P : α → Prop} {H : ∀ (a : α), a ∈ o → P a} | ||
(f : { x // P x } → β) : | ||
(o.attachWith P H).map f = | ||
o.pmap (fun a (h : a ∈ o ∧ P a) => f ⟨a, h.2⟩) (fun a h => ⟨h, H a h⟩) := by | ||
cases o <;> simp | ||
|
||
theorem attach_bind {o : Option α} {f : α → Option β} : | ||
(o.bind f).attach = | ||
o.attach.bind fun ⟨x, h⟩ => (f x).attach.map fun ⟨y, h'⟩ => ⟨y, mem_bind_iff.mpr ⟨x, h, h'⟩⟩ := by | ||
cases o <;> simp | ||
|
||
theorem bind_attach {o : Option α} {f : {x // x ∈ o} → Option β} : | ||
o.attach.bind f = o.pbind fun a h => f ⟨a, h⟩ := by | ||
cases o <;> simp | ||
|
||
theorem pbind_eq_bind_attach {o : Option α} {f : (a : α) → a ∈ o → Option β} : | ||
o.pbind f = o.attach.bind fun ⟨x, h⟩ => f x h := by | ||
cases o <;> simp | ||
|
||
theorem attach_filter {o : Option α} {p : α → Bool} : | ||
(o.filter p).attach = | ||
o.attach.bind fun ⟨x, h⟩ => if h' : p x then some ⟨x, by simp_all⟩ else none := by | ||
cases o with | ||
| none => simp | ||
| some a => | ||
simp only [filter_some, attach_some] | ||
ext | ||
simp only [mem_def, attach_eq_some_iff, ite_none_right_eq_some, some.injEq, some_bind, | ||
dite_none_right_eq_some] | ||
constructor | ||
· rintro ⟨h, w⟩ | ||
refine ⟨h, by ext; simpa using w⟩ | ||
· rintro ⟨h, rfl⟩ | ||
simp [h] | ||
|
||
theorem filter_attach {o : Option α} {p : {x // x ∈ o} → Bool} : | ||
o.attach.filter p = o.pbind fun a h => if p ⟨a, h⟩ then some ⟨a, h⟩ else none := by | ||
cases o <;> simp [filter_some] | ||
|
||
end Option |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/- | ||
Copyright (c) 2024 Lean FRO. All rights reserved. | ||
Released under Apache 2.0 license as described in the file LICENSE. | ||
Authors: Kim Morrison | ||
-/ | ||
prelude | ||
import Init.Data.List.Lemmas | ||
|
||
namespace Option | ||
|
||
@[simp] theorem mem_toList (a : α) (o : Option α) : a ∈ o.toList ↔ a ∈ o := by | ||
cases o <;> simp [eq_comm] | ||
|
||
end Option |