feat: complete addition of @[grind] annotations for Option (#8216)
This PR completes adding `@[grind]` annotations for `Option` lemmas, and incidentally fills in some `Option` API gaps/defects.
This commit is contained in:
parent
6e2e1a4f89
commit
80349ac77b
9 changed files with 167 additions and 141 deletions
|
|
@ -195,7 +195,7 @@ theorem attach_filter {o : Option α} {p : α → Bool} :
|
|||
| some a =>
|
||||
simp only [filter_some, attach_some]
|
||||
ext
|
||||
simp only [attach_eq_some_iff, ite_none_right_eq_some, some.injEq, some_bind,
|
||||
simp only [attach_eq_some_iff, ite_none_right_eq_some, some.injEq, bind_some,
|
||||
dite_none_right_eq_some]
|
||||
constructor
|
||||
· rintro ⟨h, w⟩
|
||||
|
|
|
|||
|
|
@ -13,11 +13,20 @@ namespace Option
|
|||
deriving instance DecidableEq for Option
|
||||
deriving instance BEq for Option
|
||||
|
||||
@[simp, grind] theorem getD_none : getD none a = a := rfl
|
||||
@[simp, grind] theorem getD_some : getD (some a) b = a := rfl
|
||||
|
||||
@[simp, grind] theorem map_none (f : α → β) : none.map f = none := rfl
|
||||
@[simp, grind] theorem map_some (a) (f : α → β) : (some a).map f = some (f a) := rfl
|
||||
|
||||
/-- Lifts an optional value to any `Alternative`, sending `none` to `failure`. -/
|
||||
def getM [Alternative m] : Option α → m α
|
||||
| none => failure
|
||||
| some a => pure a
|
||||
|
||||
@[simp, grind] theorem getM_none [Alternative m] : getM none = (failure : m α) := rfl
|
||||
@[simp, grind] theorem getM_some [Alternative m] {a : α} : getM (some a) = (pure a : m α) := rfl
|
||||
|
||||
/-- Returns `true` on `some x` and `false` on `none`. -/
|
||||
@[inline] def isSome : Option α → Bool
|
||||
| some _ => true
|
||||
|
|
@ -75,6 +84,14 @@ Examples:
|
|||
| none, _ => none
|
||||
| some a, f => f a
|
||||
|
||||
@[simp, grind] theorem bind_none (f : α → Option β) : none.bind f = none := rfl
|
||||
@[simp, grind] theorem bind_some (a) (f : α → Option β) : (some a).bind f = f a := rfl
|
||||
|
||||
@[deprecated bind_none (since := "2025-05-03")]
|
||||
abbrev none_bind := @bind_none
|
||||
@[deprecated bind_some (since := "2025-05-03")]
|
||||
abbrev some_bind := @bind_some
|
||||
|
||||
/--
|
||||
Runs the monadic action `f` on `o`'s value, if any, and returns the result, or `none` if there is
|
||||
no value.
|
||||
|
|
@ -102,6 +119,9 @@ This function only requires `m` to be an applicative functor. An alias `Option.m
|
|||
| none => pure none
|
||||
| some x => some <$> f x
|
||||
|
||||
@[simp, grind] theorem mapM_none [Applicative m] (f : α → m β) : none.mapM f = pure none := rfl
|
||||
@[simp, grind] theorem mapM_some [Applicative m] (x) (f : α → m β) : (some x).mapM f = some <$> f x := rfl
|
||||
|
||||
/--
|
||||
Applies a function in some applicative functor to an optional value, returning `none` with no
|
||||
effects if the value is missing.
|
||||
|
|
@ -111,6 +131,10 @@ This is an alias for `Option.mapM`, which already works for applicative functors
|
|||
@[inline] protected def mapA [Applicative m] (f : α → m β) : Option α → m (Option β) :=
|
||||
Option.mapM f
|
||||
|
||||
/-- For verification purposes, we replace `mapA` with `mapM`. -/
|
||||
@[simp, grind] theorem mapA_eq_mapM [Applicative m] {f : α → m β} : Option.mapA f o = Option.mapM f o := rfl
|
||||
|
||||
@[simp, grind]
|
||||
theorem map_id : (Option.map id : Option α → Option α) = id :=
|
||||
funext (fun o => match o with | none => rfl | some _ => rfl)
|
||||
|
||||
|
|
@ -142,6 +166,9 @@ Examples:
|
|||
| some a => p a
|
||||
| none => true
|
||||
|
||||
@[simp, grind] theorem all_none : Option.all p none = true := rfl
|
||||
@[simp, grind] theorem all_some : Option.all p (some x) = p x := rfl
|
||||
|
||||
/--
|
||||
Checks whether an optional value is not `none` and satisfies a Boolean predicate.
|
||||
|
||||
|
|
@ -154,6 +181,9 @@ Examples:
|
|||
| some a => p a
|
||||
| none => false
|
||||
|
||||
@[simp, grind] theorem any_none : Option.any p none = false := rfl
|
||||
@[simp, grind] theorem any_some : Option.any p (some x) = p x := rfl
|
||||
|
||||
/--
|
||||
Implementation of `OrElse`'s `<|>` syntax for `Option`. If the first argument is `some a`, returns
|
||||
`some a`, otherwise evaluates and returns the second argument.
|
||||
|
|
@ -164,6 +194,9 @@ See also `or` for a version that is strict in the second argument.
|
|||
| some a, _ => some a
|
||||
| none, b => b ()
|
||||
|
||||
@[simp, grind] theorem orElse_some : (some a).orElse b = some a := rfl
|
||||
@[simp, grind] theorem orElse_none : none.orElse b = b () := rfl
|
||||
|
||||
instance : OrElse (Option α) where
|
||||
orElse := Option.orElse
|
||||
|
||||
|
|
@ -230,15 +263,6 @@ def merge (fn : α → α → α) : Option α → Option α → Option α
|
|||
| none , some y => some y
|
||||
| some x, some y => some <| fn x y
|
||||
|
||||
@[simp, grind] theorem getD_none : getD none a = a := rfl
|
||||
@[simp, grind] theorem getD_some : getD (some a) b = a := rfl
|
||||
|
||||
@[simp, grind] theorem map_none (f : α → β) : none.map f = none := rfl
|
||||
@[simp, grind] theorem map_some (a) (f : α → β) : (some a).map f = some (f a) := rfl
|
||||
|
||||
@[simp, grind] theorem none_bind (f : α → Option β) : none.bind f = none := rfl
|
||||
@[simp, grind] theorem some_bind (a) (f : α → Option β) : (some a).bind f = f a := rfl
|
||||
|
||||
/--
|
||||
A case analysis function for `Option`.
|
||||
|
||||
|
|
@ -262,9 +286,9 @@ Extracts the value from an option that can be proven to be `some`.
|
|||
@[inline] def get {α : Type u} : (o : Option α) → isSome o → α
|
||||
| some x, _ => x
|
||||
|
||||
@[simp] theorem some_get : ∀ {x : Option α} (h : isSome x), some (x.get h) = x
|
||||
@[simp, grind] theorem some_get : ∀ {x : Option α} (h : isSome x), some (x.get h) = x
|
||||
| some _, _ => rfl
|
||||
@[simp] theorem get_some (x : α) (h : isSome (some x)) : (some x).get h = x := rfl
|
||||
@[simp, grind] theorem get_some (x : α) (h : isSome (some x)) : (some x).get h = x := rfl
|
||||
|
||||
/--
|
||||
Returns `none` if a value doesn't satisfy a Boolean predicate, or the value itself otherwise.
|
||||
|
|
@ -342,6 +366,9 @@ Examples:
|
|||
-/
|
||||
@[simp, inline] def join (x : Option (Option α)) : Option α := x.bind id
|
||||
|
||||
@[simp, grind] theorem join_none : (none : Option (Option α)).join = none := rfl
|
||||
@[simp, grind] theorem join_some : (some o).join = o := rfl
|
||||
|
||||
/--
|
||||
Converts an optional monadic computation into a monadic computation of an optional value.
|
||||
|
||||
|
|
@ -363,7 +390,10 @@ some "world"
|
|||
-/
|
||||
@[inline] def sequence [Applicative m] {α : Type u} : Option (m α) → m (Option α)
|
||||
| none => pure none
|
||||
| some fn => some <$> fn
|
||||
| some f => some <$> f
|
||||
|
||||
@[simp, grind] theorem sequence_none [Applicative m] : (none : Option (m α)).sequence = pure none := rfl
|
||||
@[simp, grind] theorem sequence_some [Applicative m] (f : m (Option α)) : (some f).sequence = some <$> f := rfl
|
||||
|
||||
/--
|
||||
A monadic case analysis function for `Option`.
|
||||
|
|
@ -388,6 +418,9 @@ This is the monadic analogue of `Option.getD`.
|
|||
| some a => pure a
|
||||
| none => y
|
||||
|
||||
@[simp, grind] theorem getDM_none [Pure m] (y : m α) : (none : Option α).getDM y = y := rfl
|
||||
@[simp, grind] theorem getDM_some [Pure m] (a : α) (y : m α) : (some a).getDM y = pure a := rfl
|
||||
|
||||
instance (α) [BEq α] [ReflBEq α] : ReflBEq (Option α) where
|
||||
rfl {x} :=
|
||||
match x with
|
||||
|
|
@ -400,12 +433,6 @@ instance (α) [BEq α] [LawfulBEq α] : LawfulBEq (Option α) where
|
|||
| some x, some y => rw [LawfulBEq.eq_of_beq (α := α) h]
|
||||
| none, none => rfl
|
||||
|
||||
@[simp, grind] theorem all_none : Option.all p none = true := rfl
|
||||
@[simp, grind] theorem all_some : Option.all p (some x) = p x := rfl
|
||||
|
||||
@[simp, grind] theorem any_none : Option.any p none = false := rfl
|
||||
@[simp, grind] theorem any_some : Option.any p (some x) = p x := rfl
|
||||
|
||||
/--
|
||||
The minimum of two optional values, with `none` treated as the least element. This function is
|
||||
usually accessed through the `Min (Option α)` instance, rather than directly.
|
||||
|
|
@ -428,10 +455,10 @@ protected def min [Min α] : Option α → Option α → Option α
|
|||
|
||||
instance [Min α] : Min (Option α) where min := Option.min
|
||||
|
||||
@[simp] theorem min_some_some [Min α] {a b : α} : min (some a) (some b) = some (min a b) := rfl
|
||||
@[simp] theorem min_some_none [Min α] {a : α} : min (some a) none = none := rfl
|
||||
@[simp] theorem min_none_some [Min α] {b : α} : min none (some b) = none := rfl
|
||||
@[simp] theorem min_none_none [Min α] : min (none : Option α) none = none := rfl
|
||||
@[simp, grind] theorem min_some_some [Min α] {a b : α} : min (some a) (some b) = some (min a b) := rfl
|
||||
@[simp, grind] theorem min_some_none [Min α] {a : α} : min (some a) none = none := rfl
|
||||
@[simp, grind] theorem min_none_some [Min α] {b : α} : min none (some b) = none := rfl
|
||||
@[simp, grind] theorem min_none_none [Min α] : min (none : Option α) none = none := rfl
|
||||
|
||||
/--
|
||||
The maximum of two optional values.
|
||||
|
|
@ -453,10 +480,10 @@ protected def max [Max α] : Option α → Option α → Option α
|
|||
|
||||
instance [Max α] : Max (Option α) where max := Option.max
|
||||
|
||||
@[simp] theorem max_some_some [Max α] {a b : α} : max (some a) (some b) = some (max a b) := rfl
|
||||
@[simp] theorem max_some_none [Max α] {a : α} : max (some a) none = some a := rfl
|
||||
@[simp] theorem max_none_some [Max α] {b : α} : max none (some b) = some b := rfl
|
||||
@[simp] theorem max_none_none [Max α] : max (none : Option α) none = none := rfl
|
||||
@[simp, grind] theorem max_some_some [Max α] {a b : α} : max (some a) (some b) = some (max a b) := rfl
|
||||
@[simp, grind] theorem max_some_none [Max α] {a : α} : max (some a) none = some a := rfl
|
||||
@[simp, grind] theorem max_none_some [Max α] {b : α} : max none (some b) = some b := rfl
|
||||
@[simp, grind] theorem max_none_none [Max α] : max (none : Option α) none = none := rfl
|
||||
|
||||
|
||||
end Option
|
||||
|
|
@ -481,6 +508,7 @@ instance : Alternative Option where
|
|||
failure := Option.none
|
||||
orElse := Option.orElse
|
||||
|
||||
-- This is a duplicate of `Option.getM`; one may be deprecated in the future.
|
||||
def liftOption [Alternative m] : Option α → m α
|
||||
| some a => pure a
|
||||
| none => failure
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ universe u v
|
|||
|
||||
namespace Option
|
||||
|
||||
theorem eq_of_eq_some {α : Type u} : ∀ {x y : Option α}, (∀z, x = some z ↔ y = some z) → x = y
|
||||
theorem eq_of_eq_some {α : Type u} : ∀ {x y : Option α}, (∀ z, x = some z ↔ y = some z) → x = y
|
||||
| none, none, _ => rfl
|
||||
| none, some z, h => Option.noConfusion ((h z).2 rfl)
|
||||
| some z, none, h => Option.noConfusion ((h z).1 rfl)
|
||||
|
|
|
|||
|
|
@ -180,9 +180,9 @@ abbrev ball_ne_none := @forall_ne_none
|
|||
|
||||
@[simp] theorem orElse_eq_orElse : HOrElse.hOrElse = @Option.orElse α := rfl
|
||||
|
||||
@[simp] theorem bind_some (x : Option α) : x.bind some = x := by cases x <;> rfl
|
||||
@[simp] theorem bind_fun_some (x : Option α) : x.bind some = x := by cases x <;> rfl
|
||||
|
||||
@[simp] theorem bind_none (x : Option α) : x.bind (fun _ => none (α := β)) = none := by
|
||||
@[simp] theorem bind_fun_none (x : Option α) : x.bind (fun _ => none (α := β)) = none := by
|
||||
cases x <;> rfl
|
||||
|
||||
theorem bind_eq_some_iff : x.bind f = some b ↔ ∃ a, x = some a ∧ f a = some b := by
|
||||
|
|
@ -295,21 +295,21 @@ theorem map_congr {x : Option α} (h : ∀ a, x = some a → f a = g a) :
|
|||
x.map f = x.map g := by
|
||||
cases x <;> simp only [map_none, map_some, h]
|
||||
|
||||
@[simp] theorem map_id_fun {α : Type u} : Option.map (id : α → α) = id := by
|
||||
@[simp, grind] theorem map_id_fun {α : Type u} : Option.map (id : α → α) = id := by
|
||||
funext; simp [map_id]
|
||||
|
||||
theorem map_id' {x : Option α} : (x.map fun a => a) = x := congrFun map_id x
|
||||
|
||||
@[simp] theorem map_id_fun' {α : Type u} : Option.map (fun (a : α) => a) = id := by
|
||||
@[simp, grind] theorem map_id_fun' {α : Type u} : Option.map (fun (a : α) => a) = id := by
|
||||
funext; simp [map_id']
|
||||
|
||||
theorem get_map {f : α → β} {o : Option α} {h : (o.map f).isSome} :
|
||||
@[simp, grind] theorem get_map {f : α → β} {o : Option α} {h : (o.map f).isSome} :
|
||||
(o.map f).get h = f (o.get (by simpa using h)) := by
|
||||
cases o with
|
||||
| none => simp at h
|
||||
| some a => simp
|
||||
|
||||
@[simp] theorem map_map (h : β → γ) (g : α → β) (x : Option α) :
|
||||
@[simp, grind _=_] theorem map_map (h : β → γ) (g : α → β) (x : Option α) :
|
||||
(x.map g).map h = x.map (h ∘ g) := by
|
||||
cases x <;> simp only [map_none, map_some, ·∘·]
|
||||
|
||||
|
|
@ -381,12 +381,12 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
|
|||
x.filter p = x.bind (Option.guard p) := by
|
||||
cases x <;> rfl
|
||||
|
||||
@[simp] theorem all_guard (a : α) :
|
||||
@[simp, grind] theorem all_guard (a : α) :
|
||||
Option.all q (guard p a) = (!p a || q a) := by
|
||||
simp only [guard]
|
||||
split <;> simp_all
|
||||
|
||||
@[simp] theorem any_guard (a : α) : Option.any q (guard p a) = (p a && q a) := by
|
||||
@[simp, grind] theorem any_guard (a : α) : Option.any q (guard p a) = (p a && q a) := by
|
||||
simp only [guard]
|
||||
split <;> simp_all
|
||||
|
||||
|
|
@ -432,26 +432,28 @@ theorem any_map {α β : Type _} {x : Option α} {f : α → β} {p : β → Boo
|
|||
theorem bind_map_comm {α β} {x : Option (Option α)} {f : α → β} :
|
||||
x.bind (Option.map f) = (x.map (Option.map f)).bind id := by cases x <;> simp
|
||||
|
||||
theorem bind_map {f : α → β} {g : β → Option γ} {x : Option α} :
|
||||
@[grind] theorem bind_map {f : α → β} {g : β → Option γ} {x : Option α} :
|
||||
(x.map f).bind g = x.bind (g ∘ f) := by cases x <;> simp
|
||||
|
||||
@[simp] theorem map_bind {f : α → Option β} {g : β → γ} {x : Option α} :
|
||||
@[simp, grind] theorem map_bind {f : α → Option β} {g : β → γ} {x : Option α} :
|
||||
(x.bind f).map g = x.bind (Option.map g ∘ f) := by cases x <;> simp
|
||||
|
||||
theorem join_map_eq_map_join {f : α → β} {x : Option (Option α)} :
|
||||
@[grind] theorem join_map_eq_map_join {f : α → β} {x : Option (Option α)} :
|
||||
(x.map (Option.map f)).join = x.join.map f := by cases x <;> simp
|
||||
|
||||
theorem join_join {x : Option (Option (Option α))} : x.join.join = (x.map join).join := by
|
||||
@[grind _=_] theorem join_join {x : Option (Option (Option α))} : x.join.join = (x.map join).join := by
|
||||
cases x <;> simp
|
||||
|
||||
theorem mem_of_mem_join {a : α} {x : Option (Option α)} (h : a ∈ x.join) : some a ∈ x :=
|
||||
h.symm ▸ join_eq_some_iff.1 h
|
||||
|
||||
@[simp, grind] theorem some_orElse (a : α) (f) : (some a).orElse f = some a := rfl
|
||||
@[deprecated orElse_some (since := "2025-05-03")]
|
||||
theorem some_orElse (a : α) (f) : (some a).orElse f = some a := rfl
|
||||
|
||||
@[simp, grind] theorem none_orElse (f : Unit → Option α) : none.orElse f = f () := rfl
|
||||
@[deprecated orElse_none (since := "2025-05-03")]
|
||||
theorem none_orElse (f : Unit → Option α) : none.orElse f = f () := rfl
|
||||
|
||||
@[simp] theorem orElse_none (x : Option α) : x.orElse (fun _ => none) = x := by cases x <;> rfl
|
||||
@[simp] theorem orElse_fun_none (x : Option α) : x.orElse (fun _ => none) = x := by cases x <;> rfl
|
||||
|
||||
theorem orElse_eq_some_iff (o : Option α) (f) (x : α) :
|
||||
(o.orElse f) = some x ↔ o = some x ∨ o = none ∧ f () = some x := by
|
||||
|
|
@ -460,7 +462,7 @@ theorem orElse_eq_some_iff (o : Option α) (f) (x : α) :
|
|||
theorem orElse_eq_none_iff (o : Option α) (f) : (o.orElse f) = none ↔ o = none ∧ f () = none := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem map_orElse {x : Option α} {y} :
|
||||
@[grind]theorem map_orElse {x : Option α} {y} :
|
||||
(x.orElse y).map f = (x.map f).orElse (fun _ => (y ()).map f) := by
|
||||
cases x <;> simp
|
||||
|
||||
|
|
@ -504,7 +506,7 @@ theorem guard_comp {p : α → Bool} {f : β → α} :
|
|||
ext1 b
|
||||
simp [guard]
|
||||
|
||||
theorem bind_guard (x : Option α) (p : α → Bool) :
|
||||
@[grind] theorem bind_guard (x : Option α) (p : α → Bool) :
|
||||
x.bind (Option.guard p) = x.filter p := by
|
||||
simp only [Option.filter_eq_bind, decide_eq_true_eq]
|
||||
|
||||
|
|
@ -599,9 +601,11 @@ abbrev choice_isSome_iff_nonempty := @isSome_choice_iff_nonempty
|
|||
end choice
|
||||
|
||||
@[simp, grind] theorem toList_some (a : α) : (some a).toList = [a] := rfl
|
||||
|
||||
@[simp, grind] theorem toList_none (α : Type _) : (none : Option α).toList = [] := rfl
|
||||
|
||||
@[simp, grind] theorem toArray_some (a : α) : (some a).toArray = #[a] := rfl
|
||||
@[simp, grind] theorem toArray_none (α : Type _) : (none : Option α).toArray = #[] := rfl
|
||||
|
||||
-- See `Init.Data.Option.List` for lemmas about `toList`.
|
||||
|
||||
@[simp, grind] theorem some_or : (some a).or o = some a := rfl
|
||||
|
|
@ -637,7 +641,7 @@ abbrev or_eq_none := @or_eq_none_iff
|
|||
@[deprecated or_eq_some_iff (since := "2025-04-10")]
|
||||
abbrev or_eq_some := @or_eq_some_iff
|
||||
|
||||
theorem or_assoc : or (or o₁ o₂) o₃ = or o₁ (or o₂ o₃) := by
|
||||
@[grind] theorem or_assoc : or (or o₁ o₂) o₃ = or o₁ (or o₂ o₃) := by
|
||||
cases o₁ <;> cases o₂ <;> rfl
|
||||
instance : Std.Associative (or (α := α)) := ⟨@or_assoc _⟩
|
||||
|
||||
|
|
@ -685,10 +689,14 @@ section beq
|
|||
|
||||
variable [BEq α]
|
||||
|
||||
@[simp] theorem none_beq_none : ((none : Option α) == none) = true := rfl
|
||||
@[simp] theorem none_beq_some (a : α) : ((none : Option α) == some a) = false := rfl
|
||||
@[simp] theorem some_beq_none (a : α) : ((some a : Option α) == none) = false := rfl
|
||||
@[simp] theorem some_beq_some {a b : α} : (some a == some b) = (a == b) := rfl
|
||||
@[simp, grind] theorem none_beq_none : ((none : Option α) == none) = true := rfl
|
||||
@[simp, grind] theorem none_beq_some (a : α) : ((none : Option α) == some a) = false := rfl
|
||||
@[simp, grind] theorem some_beq_none (a : α) : ((some a : Option α) == none) = false := rfl
|
||||
@[simp, grind] theorem some_beq_some {a b : α} : (some a == some b) = (a == b) := rfl
|
||||
|
||||
/-- We simplify away `isEqSome` in terms of `==`. -/
|
||||
@[simp, grind] theorem isEqSome_eq_beq_some {o : Option α} : isEqSome o y = (o == some y) := by
|
||||
cases o <;> simp [isEqSome]
|
||||
|
||||
@[simp] theorem reflBEq_iff : ReflBEq (Option α) ↔ ReflBEq α := by
|
||||
constructor
|
||||
|
|
@ -802,14 +810,14 @@ theorem mem_ite_none_right {x : α} {_ : Decidable p} {l : Option α} :
|
|||
|
||||
end ite
|
||||
|
||||
theorem isSome_filter {α : Type _} {x : Option α} {f : α → Bool} :
|
||||
@[grind] theorem isSome_filter {α : Type _} {x : Option α} {f : α → Bool} :
|
||||
(x.filter f).isSome = x.any f := by
|
||||
cases x
|
||||
· rfl
|
||||
· rw [Bool.eq_iff_iff]
|
||||
simp only [Option.any_some, Option.filter, Option.isSome_ite]
|
||||
|
||||
@[simp] theorem get_filter {α : Type _} {x : Option α} {f : α → Bool} (h : (x.filter f).isSome) :
|
||||
@[simp, grind] theorem get_filter {α : Type _} {x : Option α} {f : α → Bool} (h : (x.filter f).isSome) :
|
||||
(x.filter f).get h = x.get (isSome_of_isSome_filter f x h) := by
|
||||
cases x
|
||||
· contradiction
|
||||
|
|
@ -821,11 +829,11 @@ theorem isSome_filter {α : Type _} {x : Option α} {f : α → Bool} :
|
|||
@[simp, grind] theorem pbind_none : pbind none f = none := rfl
|
||||
@[simp, grind] theorem pbind_some : pbind (some a) f = f a rfl := rfl
|
||||
|
||||
@[simp] theorem map_pbind {o : Option α} {f : (a : α) → o = some a → Option β}
|
||||
@[simp, grind] theorem map_pbind {o : Option α} {f : (a : α) → o = some a → Option β}
|
||||
{g : β → γ} : (o.pbind f).map g = o.pbind (fun a h => (f a h).map g) := by
|
||||
cases o <;> rfl
|
||||
|
||||
@[simp] theorem pbind_map {α β γ : Type _} (o : Option α)
|
||||
@[simp, grind] theorem pbind_map {α β γ : Type _} (o : Option α)
|
||||
(f : α → β) (g : (x : β) → o.map f = some x → Option γ) :
|
||||
(o.map f).pbind g = o.pbind (fun x h => g (f x) (h ▸ rfl)) := by
|
||||
cases o <;> rfl
|
||||
|
|
@ -895,11 +903,11 @@ theorem pmap_eq_map (p : α → Prop) (f : α → β) (o : Option α) (H) :
|
|||
@pmap _ _ p (fun a _ => f a) o H = Option.map f o := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem map_pmap {p : α → Prop} (g : β → γ) (f : ∀ a, p a → β) (o H) :
|
||||
@[grind] theorem map_pmap {p : α → Prop} (g : β → γ) (f : ∀ a, p a → β) (o H) :
|
||||
Option.map g (pmap f o H) = pmap (fun a h => g (f a h)) o H := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem pmap_map (o : Option α) (f : α → β) {p : β → Prop} (g : ∀ b, p b → γ) (H) :
|
||||
@[grind] theorem pmap_map (o : Option α) (f : α → β) {p : β → Prop} (g : ∀ b, p b → γ) (H) :
|
||||
pmap g (o.map f) H =
|
||||
pmap (fun a h => g (f a) h) o (fun a m => H (f a) (map_eq_some_iff.2 ⟨_, m, rfl⟩)) := by
|
||||
cases o <;> simp
|
||||
|
|
@ -941,7 +949,7 @@ theorem pmap_congr {α : Type u} {β : Type v}
|
|||
@[simp] theorem pelim_eq_elim : pelim o b (fun a _ => f a) = o.elim b f := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem elim_pmap {p : α → Prop} (f : (a : α) → p a → β) (o : Option α)
|
||||
@[simp, grind] theorem elim_pmap {p : α → Prop} (f : (a : α) → p a → β) (o : Option α)
|
||||
(H : ∀ (a : α), o = some a → p a) (g : γ) (g' : β → γ) :
|
||||
(o.pmap f H).elim g g' =
|
||||
o.pelim g (fun a h => g' (f a (H a h))) := by
|
||||
|
|
@ -978,7 +986,7 @@ theorem isSome_of_isSome_pfilter {α : Type _} {o : Option α} {p : (a : α) →
|
|||
(h : (o.pfilter p).isSome) : o.isSome :=
|
||||
(isSome_pfilter_iff_get.mp h).1
|
||||
|
||||
@[simp] theorem get_pfilter {α : Type _} {o : Option α} {p : (a : α) → o = some a → Bool}
|
||||
@[simp, grind] theorem get_pfilter {α : Type _} {o : Option α} {p : (a : α) → o = some a → Bool}
|
||||
(h : (o.pfilter p).isSome) :
|
||||
(o.pfilter p).get h = o.get (isSome_of_isSome_pfilter h) := by
|
||||
cases o <;> simp
|
||||
|
|
|
|||
|
|
@ -10,62 +10,38 @@ import Init.Data.List.Lemmas
|
|||
|
||||
namespace Option
|
||||
|
||||
@[simp] theorem mem_toList {a : α} {o : Option α} : a ∈ o.toList ↔ o = some a := by
|
||||
@[simp, grind] theorem mem_toList {a : α} {o : Option α} : a ∈ o.toList ↔ o = some a := by
|
||||
cases o <;> simp [eq_comm]
|
||||
|
||||
@[simp] theorem forIn'_none [Monad m] (b : β) (f : (a : α) → a ∈ none → β → m (ForInStep β)) :
|
||||
forIn' none b f = pure b := by
|
||||
rfl
|
||||
|
||||
@[simp] theorem forIn'_some [Monad m] [LawfulMonad m] (a : α) (b : β) (f : (a' : α) → a' ∈ some a → β → m (ForInStep β)) :
|
||||
forIn' (some a) b f = bind (f a rfl b) (fun r => pure (ForInStep.value r)) := by
|
||||
simp only [forIn', bind_pure_comp]
|
||||
rw [map_eq_pure_bind]
|
||||
congr
|
||||
funext x
|
||||
split <;> rfl
|
||||
|
||||
@[simp] theorem forIn_none [Monad m] (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn none b f = pure b := by
|
||||
rfl
|
||||
|
||||
@[simp] theorem forIn_some [Monad m] [LawfulMonad m] (a : α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn (some a) b f = bind (f a b) (fun r => pure (ForInStep.value r)) := by
|
||||
simp only [forIn, forIn', bind_pure_comp]
|
||||
rw [map_eq_pure_bind]
|
||||
congr
|
||||
funext x
|
||||
split <;> rfl
|
||||
|
||||
@[simp] theorem forIn'_toList [Monad m] (o : Option α) (b : β) (f : (a : α) → a ∈ o.toList → β → m (ForInStep β)) :
|
||||
@[simp, grind] theorem forIn'_toList [Monad m] (o : Option α) (b : β) (f : (a : α) → a ∈ o.toList → β → m (ForInStep β)) :
|
||||
forIn' o.toList b f = forIn' o b fun a m b => f a (by simpa using m) b := by
|
||||
cases o <;> rfl
|
||||
|
||||
@[simp] theorem forIn_toList [Monad m] (o : Option α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
@[simp, grind] theorem forIn_toList [Monad m] (o : Option α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn o.toList b f = forIn o b f := by
|
||||
cases o <;> rfl
|
||||
|
||||
@[simp] theorem foldlM_toList [Monad m] [LawfulMonad m] (o : Option β) (a : α) (f : α → β → m α) :
|
||||
@[simp, grind] theorem foldlM_toList [Monad m] [LawfulMonad m] (o : Option β) (a : α) (f : α → β → m α) :
|
||||
o.toList.foldlM f a = o.elim (pure a) (fun b => f a b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem foldrM_toList [Monad m] [LawfulMonad m] (o : Option β) (a : α) (f : β → α → m α) :
|
||||
@[simp, grind] theorem foldrM_toList [Monad m] [LawfulMonad m] (o : Option β) (a : α) (f : β → α → m α) :
|
||||
o.toList.foldrM f a = o.elim (pure a) (fun b => f b a) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem foldl_toList (o : Option β) (a : α) (f : α → β → α) :
|
||||
@[simp, grind] theorem foldl_toList (o : Option β) (a : α) (f : α → β → α) :
|
||||
o.toList.foldl f a = o.elim a (fun b => f a b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem foldr_toList (o : Option β) (a : α) (f : β → α → α) :
|
||||
@[simp, grind] theorem foldr_toList (o : Option β) (a : α) (f : β → α → α) :
|
||||
o.toList.foldr f a = o.elim a (fun b => f b a) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
@[simp, grind]
|
||||
theorem pairwise_toList {P : α → α → Prop} {o : Option α} : o.toList.Pairwise P := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
@[simp, grind]
|
||||
theorem head?_toList {o : Option α} : o.toList.head? = o := by
|
||||
cases o <;> simp
|
||||
|
||||
|
|
|
|||
|
|
@ -12,16 +12,47 @@ import Init.Control.Lawful.Basic
|
|||
|
||||
namespace Option
|
||||
|
||||
@[simp] theorem forM_none [Monad m] (f : α → m PUnit) :
|
||||
none.forM f = pure .unit := rfl
|
||||
@[simp, grind] theorem bindM_none [Monad m] (f : α → m (Option β)) : none.bindM f = pure none := rfl
|
||||
@[simp, grind] theorem bindM_some [Monad m] [LawfulMonad m] (a) (f : α → m (Option β)) : (some a).bindM f = f a := by
|
||||
simp [Option.bindM]
|
||||
|
||||
@[simp] theorem forM_some [Monad m] (f : α → m PUnit) (a : α) :
|
||||
(some a).forM f = f a := rfl
|
||||
-- We simplify `Option.forM` to `forM`.
|
||||
@[simp] theorem forM_eq_forM [Monad m] : @Option.forM m α _ = forM := rfl
|
||||
|
||||
@[simp] theorem forM_map [Monad m] [LawfulMonad m] (o : Option α) (g : α → β) (f : β → m PUnit) :
|
||||
(o.map g).forM f = o.forM (fun a => f (g a)) := by
|
||||
@[simp, grind] theorem forM_none [Monad m] (f : α → m PUnit) :
|
||||
forM none f = pure .unit := rfl
|
||||
|
||||
@[simp, grind] theorem forM_some [Monad m] (f : α → m PUnit) (a : α) :
|
||||
forM (some a) f = f a := rfl
|
||||
|
||||
@[simp, grind] theorem forM_map [Monad m] [LawfulMonad m] (o : Option α) (g : α → β) (f : β → m PUnit) :
|
||||
forM (o.map g) f = forM o (fun a => f (g a)) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind] theorem forIn'_none [Monad m] (b : β) (f : (a : α) → a ∈ none → β → m (ForInStep β)) :
|
||||
forIn' none b f = pure b := by
|
||||
rfl
|
||||
|
||||
@[simp, grind] theorem forIn'_some [Monad m] [LawfulMonad m] (a : α) (b : β) (f : (a' : α) → a' ∈ some a → β → m (ForInStep β)) :
|
||||
forIn' (some a) b f = bind (f a rfl b) (fun r => pure (ForInStep.value r)) := by
|
||||
simp only [forIn', bind_pure_comp]
|
||||
rw [map_eq_pure_bind]
|
||||
congr
|
||||
funext x
|
||||
split <;> rfl
|
||||
|
||||
@[simp, grind] theorem forIn_none [Monad m] (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn none b f = pure b := by
|
||||
rfl
|
||||
|
||||
@[simp, grind] theorem forIn_some [Monad m] [LawfulMonad m] (a : α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn (some a) b f = bind (f a b) (fun r => pure (ForInStep.value r)) := by
|
||||
simp only [forIn, forIn', bind_pure_comp]
|
||||
rw [map_eq_pure_bind]
|
||||
congr
|
||||
funext x
|
||||
split <;> rfl
|
||||
|
||||
@[congr] theorem forIn'_congr [Monad m] [LawfulMonad m] {as bs : Option α} (w : as = bs)
|
||||
{b b' : β} (hb : b = b')
|
||||
{f : (a' : α) → a' ∈ as → β → m (ForInStep β)}
|
||||
|
|
@ -60,7 +91,7 @@ theorem forIn'_eq_pelim [Monad m] [LawfulMonad m]
|
|||
o.pelim b (fun a h => f a h b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
|
||||
@[simp, grind] theorem forIn'_map [Monad m] [LawfulMonad m]
|
||||
(o : Option α) (g : α → β) (f : (b : β) → b ∈ o.map g → γ → m (ForInStep γ)) :
|
||||
forIn' (o.map g) init f = forIn' o init fun a h y => f (g a) (mem_map_of_mem g h) y := by
|
||||
cases o <;> simp
|
||||
|
|
@ -89,11 +120,9 @@ theorem forIn_eq_elim [Monad m] [LawfulMonad m]
|
|||
o.elim b (fun a => f a b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
|
||||
@[simp, grind] theorem forIn_map [Monad m] [LawfulMonad m]
|
||||
(o : Option α) (g : α → β) (f : β → γ → m (ForInStep γ)) :
|
||||
forIn (o.map g) init f = forIn o init fun a y => f (g a) y := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem mapA_eq_mapM : @Option.mapA = @Option.mapM := rfl
|
||||
|
||||
end Option
|
||||
|
|
|
|||
|
|
@ -4495,10 +4495,10 @@ theorem getEntry?_filterMap' [BEq α] [EquivBEq α]
|
|||
specialize hf ⟨k', v⟩
|
||||
split
|
||||
· rename_i h
|
||||
simp only [List.filterMap_cons, Option.some_bind]
|
||||
simp only [List.filterMap_cons, Option.bind_some]
|
||||
simp only [containsKey_congr h] at hl
|
||||
split
|
||||
· simp only [ih, ‹f _ = _›, Option.none_bind, getEntry?_eq_none.mpr hl.2]
|
||||
· simp only [ih, ‹f _ = _›, Option.bind_none, getEntry?_eq_none.mpr hl.2]
|
||||
· rw [‹f _ = _›, Option.all_some, BEq.congr_right h] at hf
|
||||
rw [getEntry?_cons, hf, ‹f _ = _›, cond_true]
|
||||
· simp only [List.filterMap_cons]
|
||||
|
|
@ -5169,7 +5169,7 @@ theorem getValue?_filterMap_of_getKey?_eq_some {β : Type v} {γ : Type w} [BEq
|
|||
simp only [getKey?_eq_getEntry?, Option.map_eq_some_iff, getValue?_eq_getEntry?,
|
||||
getEntry?_filterMap distinct, Option.map_bind, forall_exists_index, and_imp]
|
||||
intro x hx hk
|
||||
simp only [hx, Option.some_bind, Function.comp_apply, hk, Option.map_map, Option.map_some]
|
||||
simp only [hx, Option.bind_some, Function.comp_apply, hk, Option.map_map, Option.map_some]
|
||||
cases f k' x.2 <;> simp
|
||||
|
||||
theorem getValue!_filterMap {β : Type v} {γ : Type w} [BEq α] [EquivBEq α] [Inhabited γ]
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
/-!
|
||||
This file contains WIP notes about potential further `grind` attributes for `Option`.
|
||||
|
||||
-/
|
||||
|
||||
attribute [grind] Option.some_get Option.get_some
|
||||
attribute [grind] Option.map_map -- `[grind _=_]`?
|
||||
attribute [grind] Option.get_map -- ??
|
||||
attribute [grind] Option.map_id_fun Option.map_id_fun'
|
||||
attribute [grind] Option.all_guard Option.any_guard
|
||||
attribute [grind] Option.bind_map Option.map_bind
|
||||
attribute [grind] Option.join_map_eq_map_join
|
||||
attribute [grind] Option.join_join -- `[grind _=_]`?
|
||||
attribute [grind] Option.map_orElse
|
||||
|
||||
-- Look again at `Option.guard` lemmas, consider `bind_gaurd`.
|
||||
-- Fix statement of `isSome_guard`, add `isNone_guard`
|
||||
|
||||
attribute [grind] Option.or_assoc -- unless `grind` gains native associativity support in the meantime!
|
||||
|
||||
-- attribute [grind] Option.none_beq_none -- warning: this generates just `none` as the pattern!
|
||||
-- attribute [grind] Option.none_beq_some
|
||||
-- attribute [grind] Option.some_beq_none -- warning: this generates just `some _` as the pattern!
|
||||
-- attribute [grind] Option.some_beq_some
|
||||
|
||||
attribute [grind] Option.isSome_filter
|
||||
attribute [grind] Option.get_filter Option.get_pfilter
|
||||
|
||||
attribute [grind] Option.map_pbind Option.pbind_map
|
||||
attribute [grind] Option.map_pmap Option.pmap_map Option.elim_pmap
|
||||
|
||||
-- Lemmas about inequalities?
|
||||
|
||||
-- The `min_none_none` family of lemmas result in grind issues:
|
||||
-- failed to synthesize instance when instantiating Option.min_none_none
|
||||
-- Min α
|
||||
21
tests/lean/run/grind_option.lean
Normal file
21
tests/lean/run/grind_option.lean
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
-- This file uses `#guard_msgs` to check which lemmas `grind` is using.
|
||||
-- This may prove fragile, so remember it is okay to update the expected output if appropriate!
|
||||
-- Hopefully these will act as regression tests against `grind` activating irrelevant lemmas.
|
||||
|
||||
set_option grind.warning false
|
||||
|
||||
variable [BEq α] {o₁ o₂ o₃ o₄ o₅ : Option α}
|
||||
|
||||
/--
|
||||
info: Try this: grind only [Option.some_or, Option.or_some', Option.or_assoc, Option.some_beq_none]
|
||||
-/
|
||||
#guard_msgs in
|
||||
example : ((o₁.or (o₂.or (some x))).or (o₄.or o₅) == none) = false := by grind?
|
||||
|
||||
/-- info: Try this: grind only [= Nat.min_def, Option.max_some_none, Option.min_some_some] -/
|
||||
#guard_msgs in
|
||||
example : max (some 7) none = min (some 13) (some 7) := by grind?
|
||||
|
||||
/-- info: Try this: grind only [Option.guard_pos] -/
|
||||
#guard_msgs in
|
||||
example : Option.guard (· ≤ 7) 3 = some 3 := by grind? [Option.guard_pos]
|
||||
Loading…
Add table
Reference in a new issue