199 lines
8.1 KiB
Text
199 lines
8.1 KiB
Text
/-
|
||
Copyright (c) 2024 Lean FRO. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Kim Morrison
|
||
-/
|
||
module
|
||
|
||
prelude
|
||
|
||
import all Init.Data.Option.Instances
|
||
public import Init.Data.Option.Attach
|
||
|
||
public section
|
||
|
||
namespace Option
|
||
|
||
@[simp, grind =] theorem bindM_none [Pure m] (f : α → m (Option β)) : none.bindM f = pure none := rfl
|
||
@[simp, grind =] theorem bindM_some [Pure m] (a) (f : α → m (Option β)) : (some a).bindM f = f a := by
|
||
simp [Option.bindM]
|
||
|
||
-- We simplify `Option.forM` to `forM`.
|
||
@[simp] theorem forM_eq_forM [Monad m] : @Option.forM m α _ = forM := rfl
|
||
|
||
@[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
|
||
|
||
theorem forM_join [Monad m] [LawfulMonad m] (o : Option (Option α)) (f : α → m PUnit) :
|
||
forM o.join f = forM o (forM · f) := 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 <;> simp
|
||
|
||
@[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 <;> simp
|
||
|
||
@[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 β)}
|
||
{g : (a' : α) → a' ∈ bs → β → m (ForInStep β)}
|
||
(h : ∀ a m b, f a (by simpa [w] using m) b = g a m b) :
|
||
forIn' as b f = forIn' bs b' g := by
|
||
cases as <;> cases bs
|
||
· simp [hb]
|
||
· simp at w
|
||
· simp at w
|
||
· simp only [some.injEq] at w
|
||
subst w
|
||
simp [hb, h]
|
||
|
||
theorem forIn'_eq_pelim [Monad m] [LawfulMonad m]
|
||
(o : Option α) (f : (a : α) → a ∈ o → β → m (ForInStep β)) (b : β) :
|
||
forIn' o b f =
|
||
o.pelim (pure b) (fun a h => ForInStep.value <$> f a h b) := by
|
||
cases o <;> simp
|
||
|
||
@[simp] theorem forIn'_yield_eq_pelim [Monad m] [LawfulMonad m] (o : Option α)
|
||
(f : (a : α) → a ∈ o → β → m γ) (g : (a : α) → a ∈ o → β → γ → β) (b : β) :
|
||
forIn' o b (fun a m b => (fun c => .yield (g a m b c)) <$> f a m b) =
|
||
o.pelim (pure b) (fun a h => g a h b <$> f a h b) := by
|
||
cases o <;> simp
|
||
|
||
@[simp] theorem forIn'_pure_yield_eq_pelim [Monad m] [LawfulMonad m]
|
||
(o : Option α) (f : (a : α) → a ∈ o → β → β) (b : β) :
|
||
forIn' o b (fun a m b => pure (.yield (f a m b))) =
|
||
pure (f := m) (o.pelim b (fun a h => f a h b)) := by
|
||
cases o <;> simp
|
||
|
||
@[simp] theorem idRun_forIn'_yield_eq_pelim
|
||
(o : Option α) (f : (a : α) → a ∈ o → β → Id β) (b : β) :
|
||
(forIn' o b (fun a m b => .yield <$> f a m b)).run =
|
||
o.pelim b (fun a h => f a h b |>.run) :=
|
||
forIn'_pure_yield_eq_pelim _ _ _
|
||
|
||
@[deprecated idRun_forIn'_yield_eq_pelim (since := "2025-05-21")]
|
||
theorem forIn'_id_yield_eq_pelim
|
||
(o : Option α) (f : (a : α) → a ∈ o → β → β) (b : β) :
|
||
forIn' (m := Id) o b (fun a m b => .yield (f a m b)) =
|
||
o.pelim b (fun a h => f a h b) :=
|
||
forIn'_pure_yield_eq_pelim _ _ _
|
||
|
||
@[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
|
||
|
||
theorem forIn'_join [Monad m] [LawfulMonad m] (b : β) (o : Option (Option α))
|
||
(f : (a : α) → a ∈ o.join → β → m (ForInStep β)) :
|
||
forIn' o.join b f = forIn' o b (fun o' ho' b => ForInStep.yield <$> forIn' o' b (fun a ha b' => f a (by simp_all) b')) := by
|
||
cases o with
|
||
| none => simp
|
||
| some a => simpa using forIn'_congr rfl rfl (by simp)
|
||
|
||
theorem forIn_eq_elim [Monad m] [LawfulMonad m]
|
||
(o : Option α) (f : (a : α) → β → m (ForInStep β)) (b : β) :
|
||
forIn o b f =
|
||
o.elim (pure b) (fun a => ForInStep.value <$> f a b) := by
|
||
cases o <;> simp
|
||
|
||
@[simp] theorem forIn_yield_eq_elim [Monad m] [LawfulMonad m] (o : Option α)
|
||
(f : (a : α) → β → m γ) (g : (a : α) → β → γ → β) (b : β) :
|
||
forIn o b (fun a b => (fun c => .yield (g a b c)) <$> f a b) =
|
||
o.elim (pure b) (fun a => g a b <$> f a b) := by
|
||
cases o <;> simp
|
||
|
||
@[simp] theorem forIn_pure_yield_eq_elim [Monad m] [LawfulMonad m]
|
||
(o : Option α) (f : (a : α) → β → β) (b : β) :
|
||
forIn o b (fun a b => pure (.yield (f a b))) =
|
||
pure (f := m) (o.elim b (fun a => f a b)) := by
|
||
cases o <;> simp
|
||
|
||
@[simp] theorem idRun_forIn_yield_eq_elim
|
||
(o : Option α) (f : (a : α) → β → Id β) (b : β) :
|
||
(forIn o b (fun a b => .yield <$> f a b)).run =
|
||
o.elim b (fun a => f a b |>.run) :=
|
||
forIn_pure_yield_eq_elim _ _ _
|
||
|
||
@[deprecated idRun_forIn_yield_eq_elim (since := "2025-05-21")]
|
||
theorem forIn_id_yield_eq_elim
|
||
(o : Option α) (f : (a : α) → β → β) (b : β) :
|
||
forIn (m := Id) o b (fun a b => .yield (f a b)) =
|
||
o.elim b (fun a => f a b) :=
|
||
forIn_pure_yield_eq_elim _ _ _
|
||
|
||
@[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
|
||
|
||
theorem forIn_join [Monad m] [LawfulMonad m]
|
||
(o : Option (Option α)) (f : α → β → m (ForInStep β)) :
|
||
forIn o.join init f = forIn o init (fun o' b => ForInStep.yield <$> forIn o' b f) := by
|
||
cases o <;> simp
|
||
|
||
@[simp, grind =] theorem elimM_pure [Monad m] [LawfulMonad m] (x : Option α) (y : m β) (z : α → m β) :
|
||
Option.elimM (pure x : m (Option α)) y z = x.elim y z := by
|
||
simp [Option.elimM]
|
||
|
||
@[simp, grind =] theorem elimM_bind [Monad m] [LawfulMonad m] (x : m α) (f : α → m (Option β))
|
||
(y : m γ) (z : β → m γ) : Option.elimM (x >>= f) y z = (do Option.elimM (f (← x)) y z) := by
|
||
simp [Option.elimM]
|
||
|
||
@[simp, grind =] theorem elimM_map [Monad m] [LawfulMonad m] (x : m α) (f : α → Option β)
|
||
(y : m γ) (z : β → m γ) : Option.elimM (f <$> x) y z = (do Option.elim (f (← x)) y z) := by
|
||
simp [Option.elimM]
|
||
|
||
@[simp, grind =] theorem tryCatch_eq_or (o : Option α) (alternative : Unit → Option α) :
|
||
tryCatch o alternative = o.or (alternative ()) := by cases o <;> rfl
|
||
|
||
@[simp, grind =] theorem throw_eq_none : throw () = (none : Option α) := rfl
|
||
|
||
@[simp, grind =] theorem filterM_none [Applicative m] (p : α → m Bool) :
|
||
none.filterM p = pure none := rfl
|
||
@[grind =] theorem filterM_some [Applicative m] (p : α → m Bool) (a : α) :
|
||
(some a).filterM p = (fun b => if b then some a else none) <$> p a := rfl
|
||
|
||
theorem sequence_join [Applicative m] [LawfulApplicative m] {o : Option (Option (m α))} :
|
||
o.join.sequence = join <$> sequence (o.map sequence) := by
|
||
cases o <;> simp
|
||
|
||
theorem bindM_join [Pure m] {f : α → m (Option β)} {o : Option (Option α)} :
|
||
o.join.bindM f = o.bindM (·.bindM f) := by
|
||
cases o <;> simp
|
||
|
||
theorem mapM_join [Applicative m] [LawfulApplicative m] {f : α → m β} {o : Option (Option α)} :
|
||
o.join.mapM f = join <$> o.mapM (Option.mapM f) := by
|
||
cases o <;> simp
|
||
|
||
theorem mapM_guard [Applicative m] {x : α} {p : α → Bool} {f : α → m β} :
|
||
(guard p x).mapM f = if p x then some <$> f x else pure none := by
|
||
simp only [guard_eq_ite]
|
||
split <;> simp
|
||
|
||
end Option
|