625 lines
22 KiB
Text
625 lines
22 KiB
Text
/-
|
||
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Leonardo de Moura, Mario Carneiro
|
||
-/
|
||
module
|
||
|
||
prelude
|
||
public import Init.Control.Basic
|
||
public import Init.Grind.Tactics
|
||
|
||
public section
|
||
|
||
@[expose] section
|
||
|
||
namespace Option
|
||
|
||
instance instDecidableEq {α} [inst : DecidableEq α] : DecidableEq (Option α) := fun a b =>
|
||
/-
|
||
Structured for compatibility with the decidable-equality-with-none instances.
|
||
-/
|
||
match a with
|
||
| none => match b with
|
||
| none => .isTrue rfl
|
||
| some _ => .isFalse (fun h => Option.noConfusion rfl (heq_of_eq h))
|
||
| some a => match b with
|
||
| none => .isFalse (fun h => Option.noConfusion rfl (heq_of_eq h))
|
||
| some b => match inst a b with
|
||
| .isTrue h => .isTrue (h ▸ rfl)
|
||
| .isFalse n => .isFalse (fun h => Option.noConfusion rfl (heq_of_eq h) (fun h' => absurd (eq_of_heq h') n))
|
||
|
||
/--
|
||
Equality with `none` is decidable even if the wrapped type does not have decidable equality.
|
||
-/
|
||
instance decidableEqNone (o : Option α) : Decidable (o = none) :=
|
||
/- We use a `match` instead of transferring from `isNone_iff_eq_none` for
|
||
compatibility with the `DecidableEq` instance. -/
|
||
match o with
|
||
| none => .isTrue rfl
|
||
| some _ => .isFalse (fun h => Option.noConfusion rfl (heq_of_eq h))
|
||
|
||
/--
|
||
Equality with `none` is decidable even if the wrapped type does not have decidable equality.
|
||
-/
|
||
instance decidableNoneEq (o : Option α) : Decidable (none = o) :=
|
||
/- We use a `match` instead of transferring from `isNone_iff_eq_none` for
|
||
compatibility with the `DecidableEq` instance. -/
|
||
match o with
|
||
| none => .isTrue rfl
|
||
| some _ => .isFalse (fun h => Option.noConfusion rfl (heq_of_eq h))
|
||
|
||
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
|
||
| none => false
|
||
|
||
@[simp, grind =] theorem isSome_none : @isSome α none = false := rfl
|
||
@[simp, grind =] theorem isSome_some : isSome (some a) = true := rfl
|
||
|
||
/--
|
||
Returns `true` on `none` and `false` on `some x`.
|
||
|
||
This function is more flexible than `(· == none)` because it does not require a `BEq α` instance.
|
||
|
||
Examples:
|
||
* `(none : Option Nat).isNone = true`
|
||
* `(some Nat.add).isNone = false`
|
||
-/
|
||
@[inline] def isNone : Option α → Bool
|
||
| some _ => false
|
||
| none => true
|
||
|
||
@[simp, grind =] theorem isNone_none : @isNone α none = true := rfl
|
||
@[simp, grind =] theorem isNone_some : isNone (some a) = false := rfl
|
||
|
||
/--
|
||
Checks whether an optional value is both present and equal to some other value.
|
||
|
||
Given `x? : Option α` and `y : α`, `x?.isEqSome y` is equivalent to `x? == some y`. It is more
|
||
efficient because it avoids an allocation.
|
||
-/
|
||
@[inline] def isEqSome [BEq α] : Option α → α → Bool
|
||
| some a, b => a == b
|
||
| none, _ => false
|
||
|
||
/--
|
||
Sequencing of `Option` computations.
|
||
|
||
From the perspective of `Option` as computations that might fail, this function sequences
|
||
potentially-failing computations, failing if either fails. From the perspective of `Option` as a
|
||
collection with at most one element, the function is applied to the element if present, and the
|
||
final result is empty if either the initial or the resulting collections are empty.
|
||
|
||
This function is often accessed via the `>>=` operator from the `Bind (Option α)` instance, or
|
||
implicitly via `do`-notation, but it is also idiomatic to call it using [generalized field
|
||
notation](lean-manual://section/generalized-field-notation).
|
||
|
||
Examples:
|
||
* `none.bind (fun x => some x) = none`
|
||
* `(some 4).bind (fun x => some x) = some 4`
|
||
* `none.bind (Option.guard (· > 2)) = none`
|
||
* `(some 2).bind (Option.guard (· > 2)) = none`
|
||
* `(some 4).bind (Option.guard (· > 2)) = some 4`
|
||
-/
|
||
@[inline] protected def bind : Option α → (α → Option β) → Option β
|
||
| 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.
|
||
|
||
From the perspective of `Option` as a collection with at most one element, the monadic the function
|
||
is applied to the element if present, and the final result is empty if either the initial or the
|
||
resulting collections are empty.
|
||
-/
|
||
@[inline] protected def bindM [Pure m] (f : α → m (Option β)) : Option α → m (Option β)
|
||
| none => pure none
|
||
| some a => f a
|
||
|
||
/--
|
||
Applies a function in some applicative functor to an optional value, returning `none` with no
|
||
effects if the value is missing.
|
||
|
||
Runs a monadic function `f` on an optional value, returning the result. If the optional value is
|
||
`none`, the function is not called and the result is also `none`.
|
||
|
||
From the perspective of `Option` as a container with at most one element, this is analogous to
|
||
`List.mapM`, returning the result of running the monadic function on all elements of the container.
|
||
|
||
This function only requires `m` to be an applicative functor. An alias `Option.mapA` is provided.
|
||
-/
|
||
@[inline] protected def mapM [Applicative m] (f : α → m β) : Option α → m (Option β)
|
||
| 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.
|
||
|
||
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)
|
||
|
||
/--
|
||
Keeps an optional value only if it satisfies a monadic Boolean predicate.
|
||
|
||
If `Option` is thought of as a collection that contains at most one element, then `Option.filterM`
|
||
is analogous to `List.filterM`.
|
||
-/
|
||
@[inline] protected def filterM [Applicative m] (p : α → m Bool) : Option α → m (Option α)
|
||
| none => pure none
|
||
| some a => (fun b => if b then some a else none) <$> p a
|
||
|
||
/--
|
||
Keeps an optional value only if it satisfies a Boolean predicate.
|
||
|
||
If `Option` is thought of as a collection that contains at most one element, then `Option.filter` is
|
||
analogous to `List.filter` or `Array.filter`.
|
||
|
||
Examples:
|
||
* `(some 5).filter (· % 2 == 0) = none`
|
||
* `(some 4).filter (· % 2 == 0) = some 4`
|
||
* `none.filter (fun x : Nat => x % 2 == 0) = none`
|
||
* `none.filter (fun x : Nat => true) = none`
|
||
-/
|
||
@[always_inline, inline] protected def filter (p : α → Bool) : Option α → Option α
|
||
| some a => if p a then some a else none
|
||
| none => none
|
||
|
||
/--
|
||
Checks whether an optional value either satisfies a Boolean predicate or is `none`.
|
||
|
||
Examples:
|
||
* `(some 33).all (· % 2 == 0) = false
|
||
* `(some 22).all (· % 2 == 0) = true
|
||
* `none.all (fun x : Nat => x % 2 == 0) = true
|
||
-/
|
||
@[always_inline, inline] protected def all (p : α → Bool) : Option α → Bool
|
||
| 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.
|
||
|
||
Examples:
|
||
* `(some 33).any (· % 2 == 0) = false
|
||
* `(some 22).any (· % 2 == 0) = true
|
||
* `none.any (fun x : Nat => true) = false
|
||
-/
|
||
@[always_inline, inline] protected def any (p : α → Bool) : Option α → Bool
|
||
| 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.
|
||
|
||
See also `or` for a version that is strict in the second argument.
|
||
-/
|
||
@[always_inline, macro_inline] protected def orElse : Option α → (Unit → Option α) → Option α
|
||
| 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
|
||
|
||
/--
|
||
Returns the first of its arguments that is `some`, or `none` if neither is `some`.
|
||
|
||
This is similar to the `<|>` operator, also known as `OrElse.orElse`, but both arguments are always
|
||
evaluated without short-circuiting.
|
||
-/
|
||
@[always_inline, macro_inline] def or : Option α → Option α → Option α
|
||
| some a, _ => some a
|
||
| none, b => b
|
||
|
||
/--
|
||
Lifts an ordering relation to `Option`, such that `none` is the least element.
|
||
|
||
It can be understood as adding a distinguished least element, represented by `none`, to both `α` and
|
||
`β`.
|
||
|
||
This definition is part of the implementation of the `LT (Option α)` instance. However, because it
|
||
can be used with heterogeneous relations, it is sometimes useful on its own.
|
||
|
||
Examples:
|
||
* `Option.lt (fun n k : Nat => n < k) none none = False`
|
||
* `Option.lt (fun n k : Nat => n < k) none (some 3) = True`
|
||
* `Option.lt (fun n k : Nat => n < k) (some 3) none = False`
|
||
* `Option.lt (fun n k : Nat => n < k) (some 4) (some 5) = True`
|
||
* `Option.lt (fun n k : Nat => n < k) (some 4) (some 4) = False`
|
||
-/
|
||
@[inline] protected def lt (r : α → β → Prop) : Option α → Option β → Prop
|
||
| none, some _ => True
|
||
| some x, some y => r x y
|
||
| _, _ => False
|
||
|
||
@[inline] protected def le (r : α → β → Prop) : Option α → Option β → Prop
|
||
| none, some _ => True
|
||
| none, none => True
|
||
| some _, none => False
|
||
| some x, some y => r x y
|
||
|
||
instance (r : α → β → Prop) [s : DecidableRel r] : DecidableRel (Option.lt r)
|
||
| none, some _ => isTrue trivial
|
||
| some x, some y => s x y
|
||
| some _, none => isFalse not_false
|
||
| none, none => isFalse not_false
|
||
|
||
namespace SomeLtNone
|
||
|
||
/--
|
||
Lifts an ordering relation to `Option` such that `none` is the *greatest* element.
|
||
|
||
It can be understood as adding a distinguished greatest element, represented by `none`, to both `α`
|
||
and `β`.
|
||
|
||
Caution: Given `LT α`, `Option.SomeLtNone.lt LT.lt` differs from the `LT (Option α)` instance,
|
||
which is implemented by `Option.lt Lt.lt`.
|
||
|
||
Examples:
|
||
* `Option.lt (fun n k : Nat => n < k) none none = False`
|
||
* `Option.lt (fun n k : Nat => n < k) none (some 3) = False`
|
||
* `Option.lt (fun n k : Nat => n < k) (some 3) none = True`
|
||
* `Option.lt (fun n k : Nat => n < k) (some 4) (some 5) = True`
|
||
* `Option.le (fun n k : Nat => n < k) (some 5) (some 4) = False`
|
||
* `Option.lt (fun n k : Nat => n < k) (some 4) (some 4) = False`
|
||
-/
|
||
def lt {α} (r : α → β → Prop) : Option α → Option β → Prop
|
||
| none, _ => False
|
||
| some _, none => True
|
||
| some x, some y => r x y
|
||
|
||
/--
|
||
Lifts an ordering relation to `Option` such that `none` is the *greatest* element.
|
||
|
||
It can be understood as adding a distinguished greatest element, represented by `none`, to both `α`
|
||
and `β`.
|
||
|
||
Caution: Given `LE α`, `Option.SomeLtNone.le LE.le` differs from the `LE (Option α)` instance,
|
||
which is implemented by `Option.le LE.le`.
|
||
|
||
Examples:
|
||
* `Option.le (fun n k : Nat => n < k) none none = True`
|
||
* `Option.le (fun n k : Nat => n < k) none (some 3) = False`
|
||
* `Option.le (fun n k : Nat => n < k) (some 3) none = True`
|
||
* `Option.le (fun n k : Nat => n < k) (some 4) (some 5) = True`
|
||
* `Option.le (fun n k : Nat => n < k) (some 5) (some 4) = False`
|
||
* `Option.le (fun n k : Nat => n < k) (some 4) (some 4) = True`
|
||
-/
|
||
def le {α} (r : α → β → Prop) : Option α → Option β → Prop
|
||
| none, none => True
|
||
| none, some _ => False
|
||
| some _, none => True
|
||
| some x, some y => r x y
|
||
|
||
end SomeLtNone
|
||
|
||
/--
|
||
Applies a function to a two optional values if both are present. Otherwise, if one value is present,
|
||
it is returned and the function is not used.
|
||
|
||
The value is `some (fn a b)` if the inputs are `some a` and `some b`. Otherwise, the behavior is
|
||
equivalent to `Option.orElse`: if only one input is `some x`, then the value is `some x`, and if
|
||
both are `none`, then the value is `none`.
|
||
|
||
Examples:
|
||
* `Option.merge (· + ·) none (some 3) = some 3`
|
||
* `Option.merge (· + ·) (some 2) (some 3) = some 5`
|
||
* `Option.merge (· + ·) (some 2) none = some 2`
|
||
* `Option.merge (· + ·) none none = none`
|
||
-/
|
||
def merge (fn : α → α → α) : Option α → Option α → Option α
|
||
| none , none => none
|
||
| some x, none => some x
|
||
| none , some y => some y
|
||
| some x, some y => some <| fn x y
|
||
|
||
/--
|
||
A case analysis function for `Option`.
|
||
|
||
Given a value for `none` and a function to apply to the contents of `some`, `Option.elim` checks
|
||
which constructor a given `Option` consists of, and uses the appropriate argument.
|
||
|
||
`Option.elim` is an elimination principle for `Option`. In particular, it is a non-dependent version
|
||
of `Option.recOn`. It can also be seen as a combination of `Option.map` and `Option.getD`.
|
||
|
||
Examples:
|
||
* `(some "hello").elim 0 String.length = 5`
|
||
* `none.elim 0 String.length = 0`
|
||
-/
|
||
@[inline] protected def elim : Option α → β → (α → β) → β
|
||
| some x, _, f => f x
|
||
| none, y, _ => y
|
||
|
||
/--
|
||
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, grind =] theorem some_get : ∀ {x : Option α} (h : isSome x), some (x.get h) = x
|
||
| some _, _ => 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.
|
||
|
||
From the perspective of `Option` as computations that might fail, this function is a run-time
|
||
assertion operator in the `Option` monad.
|
||
|
||
Examples:
|
||
* `Option.guard (· > 2) 1 = none`
|
||
* `Option.guard (· > 2) 5 = some 5`
|
||
-/
|
||
@[inline] def guard (p : α → Bool) (a : α) : Option α :=
|
||
if p a then some a else none
|
||
|
||
/--
|
||
Converts an optional value to a list with zero or one element.
|
||
|
||
Examples:
|
||
* `(some "value").toList = ["value"]`
|
||
* `none.toList = []`
|
||
-/
|
||
@[inline] def toList : Option α → List α
|
||
| none => .nil
|
||
| some a => .cons a .nil
|
||
|
||
/--
|
||
Converts an optional value to an array with zero or one element.
|
||
|
||
Examples:
|
||
* `(some "value").toArray = #["value"]`
|
||
* `none.toArray = #[]`
|
||
-/
|
||
@[inline] def toArray : Option α → Array α
|
||
| none => List.toArray .nil
|
||
| some a => List.toArray (.cons a .nil)
|
||
|
||
/-- Lifts a relation `α → β → Prop` to a relation `Option α → Option β → Prop` by just adding
|
||
`none ~ none`. -/
|
||
inductive Rel (r : α → β → Prop) : Option α → Option β → Prop
|
||
/-- If `a ~ b`, then `some a ~ some b` -/
|
||
| some {a b} : r a b → Rel r (some a) (some b)
|
||
/-- `none ~ none` -/
|
||
| none : Rel r none none
|
||
|
||
/--
|
||
Flattens nested optional values, preserving any value found.
|
||
|
||
This is analogous to `List.flatten`.
|
||
|
||
Examples:
|
||
* `none.join = none`
|
||
* `(some none).join = none`
|
||
* `(some (some v)).join = some v`
|
||
-/
|
||
@[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.
|
||
|
||
This function only requires `m` to be an applicative functor.
|
||
|
||
Example:
|
||
```lean example
|
||
#eval show IO (Option String) from
|
||
Option.sequence <| some do
|
||
IO.println "hello"
|
||
return "world"
|
||
```
|
||
```output
|
||
hello
|
||
```
|
||
```output
|
||
some "world"
|
||
```
|
||
-/
|
||
@[inline] def sequence [Applicative m] {α : Type u} : Option (m α) → m (Option α)
|
||
| none => pure none
|
||
| 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 α) : (some f).sequence = some <$> f := rfl
|
||
|
||
/--
|
||
A monadic case analysis function for `Option`.
|
||
|
||
Given a fallback computation for `none` and a monadic operation to apply to the contents of `some`,
|
||
`Option.elimM` checks which constructor a given `Option` consists of, and uses the appropriate
|
||
argument.
|
||
|
||
`Option.elimM` can also be seen as a combination of `Option.mapM` and `Option.getDM`. It is a
|
||
monadic analogue of `Option.elim`.
|
||
-/
|
||
@[inline] def elimM [Monad m] (x : m (Option α)) (y : m β) (z : α → m β) : m β :=
|
||
do (← x).elim y z
|
||
|
||
/--
|
||
Gets the value in an option, monadically computing a default value on `none`.
|
||
|
||
This is the monadic analogue of `Option.getD`.
|
||
-/
|
||
@[inline] def getDM [Pure m] (x : Option α) (y : m α) : m α :=
|
||
match x with
|
||
| 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} := private
|
||
match x with
|
||
| some _ => BEq.rfl (α := α)
|
||
| none => rfl
|
||
|
||
instance (α) [BEq α] [LawfulBEq α] : LawfulBEq (Option α) where
|
||
eq_of_beq {x y h} := by
|
||
match x, y with
|
||
| some x, some y => rw [LawfulBEq.eq_of_beq (α := α) h]
|
||
| none, none => 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.
|
||
|
||
Prior to `nightly-2025-02-27`, `none` was treated as the greatest element, so
|
||
`min none (some x) = min (some x) none = some x`.
|
||
|
||
Examples:
|
||
* `Option.min (some 2) (some 5) = some 2`
|
||
* `Option.min (some 5) (some 2) = some 2`
|
||
* `Option.min (some 2) none = none`
|
||
* `Option.min none (some 5) = none`
|
||
* `Option.min none none = none`
|
||
-/
|
||
protected def min [Min α] : Option α → Option α → Option α
|
||
| some x, some y => some (Min.min x y)
|
||
| some _, none => none
|
||
| none, some _ => none
|
||
| none, none => none
|
||
|
||
instance [Min α] : Min (Option α) where min := Option.min
|
||
|
||
@[simp, grind =] theorem min_some_some [Min α] {a b : α} : min (some a) (some b) = some (min a b) := rfl
|
||
@[simp, grind =] theorem min_none_left [Min α] {o : Option α} : min none o = none := by
|
||
cases o <;> rfl
|
||
@[simp, grind =] theorem min_none_right [Min α] {o : Option α} : min o none = none := by
|
||
cases o <;> rfl
|
||
|
||
@[deprecated min_none_right (since := "2025-05-12")]
|
||
theorem min_some_none [Min α] {a : α} : min (some a) none = none := rfl
|
||
@[deprecated min_none_left (since := "2025-05-12")]
|
||
theorem min_none_some [Min α] {b : α} : min none (some b) = none := rfl
|
||
@[deprecated min_none_left (since := "2025-05-12")]
|
||
theorem min_none_none [Min α] : min (none : Option α) none = none := rfl
|
||
|
||
/--
|
||
The maximum of two optional values.
|
||
|
||
This function is usually accessed through the `Max (Option α)` instance, rather than directly.
|
||
|
||
Examples:
|
||
* `Option.max (some 2) (some 5) = some 5`
|
||
* `Option.max (some 5) (some 2) = some 5`
|
||
* `Option.max (some 2) none = some 2`
|
||
* `Option.max none (some 5) = some 5`
|
||
* `Option.max none none = none`
|
||
-/
|
||
protected def max [Max α] : Option α → Option α → Option α
|
||
| some x, some y => some (Max.max x y)
|
||
| some x, none => some x
|
||
| none, some y => some y
|
||
| none, none => none
|
||
|
||
instance [Max α] : Max (Option α) where max := Option.max
|
||
|
||
@[simp, grind =] theorem max_some_some [Max α] {a b : α} : max (some a) (some b) = some (max a b) := rfl
|
||
@[simp, grind =] theorem max_none_left [Max α] {o : Option α} : max none o = o := by
|
||
cases o <;> rfl
|
||
@[simp, grind =] theorem max_none_right [Max α] {o : Option α} : max o none = o := by
|
||
cases o <;> rfl
|
||
|
||
@[deprecated max_none_right (since := "2025-05-12")]
|
||
theorem max_some_none [Max α] {a : α} : max (some a) none = some a := rfl
|
||
@[deprecated max_none_left (since := "2025-05-12")]
|
||
theorem max_none_some [Max α] {b : α} : max none (some b) = some b := rfl
|
||
@[deprecated max_none_left (since := "2025-05-12")]
|
||
theorem max_none_none [Max α] : max (none : Option α) none = none := rfl
|
||
|
||
|
||
end Option
|
||
|
||
instance [LT α] : LT (Option α) where
|
||
lt := Option.lt (· < ·)
|
||
|
||
instance [LE α] : LE (Option α) where
|
||
le := Option.le (· ≤ ·)
|
||
|
||
@[always_inline]
|
||
instance : Functor Option where
|
||
map := Option.map
|
||
|
||
@[always_inline]
|
||
instance : Monad Option where
|
||
pure := Option.some
|
||
bind := Option.bind
|
||
|
||
@[always_inline]
|
||
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
|
||
|
||
/--
|
||
Recover from failing `Option` computations with a handler function.
|
||
|
||
This function is usually accessed through the `MonadExceptOf Unit Option` instance.
|
||
|
||
Examples:
|
||
* `Option.tryCatch none (fun () => some "handled") = some "handled"`
|
||
* `Option.tryCatch (some "succeeded") (fun () => some "handled") = some "succeeded"`
|
||
-/
|
||
@[always_inline, inline] protected def Option.tryCatch (x : Option α) (handle : Unit → Option α) : Option α :=
|
||
match x with
|
||
| some _ => x
|
||
| none => handle ()
|
||
|
||
instance : MonadExceptOf Unit Option where
|
||
throw := fun _ => Option.none
|
||
tryCatch := Option.tryCatch
|