Lean 语言参考

20.12. 任选值🔗

Option α 是值的类型,对于某些 v:αsome v,或 none。 在函数式编程中,此类型的使用方式与可空类型类似:none 表示不存在值。 此外,从 αβ 的部分函数可以由类型 α Option β 表示,其中当函数对于某些输入未定义时,结果为 none。 从计算角度来看,这些部分函数代表了失败或错误的可能性,它们对应于可以提前终止但不会抛出信息性异常的程序。

Option 也可以被认为类似于最多包含一个元素的列表。 从这个角度来看,迭代 Option 包括仅当值存在时才执行操作。 Option API 经常使用这个视角。

Options as Nullability

函数 Std.HashMap.get?HashMap α β 内查找指定的键 a : α

Std.HashMap.get?.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : HashMap α β) (a : α) : Option β

由于无法提前知道该键是否确实在映射中,因此返回类型为 Option β,其中 none 表示该键不在映射中,some b 表示找到该键,b 是检索到的值。

xs[i] 语法用于在有可用证据证明 ixs 中的有效索引时对集合进行索引,它有一个变体 xs[i]?,它根据给定索引是否有效返回一个可选值。 如果 m:HashMap α βa:α,则 m[a]? 相当于 HashMap.get? m a

Options as Safe Nullability

在许多编程语言中,记住检查空值非常重要。 使用 Option 时,类型系统要求在正确的位置进行这些检查:Option αα 不是同一类型,从一种类型转换为另一种类型需要处理 none 的情况。 这可以通过 Option.getD 等帮助程序或模式匹配来完成。

def postalCodes : Std.HashMap Nat String := Std.HashMap.emptyWithCapacity 1 |>.insert 12345 "Schenectady" "not found"#eval postalCodes[12346]?.getD "not found"
"not found"
"not found"#eval match postalCodes[12346]? with | none => "not found" | some city => city
"not found"
"Schenectady"#eval if let some city := postalCodes[12345]? then city else "not found"
"Schenectady"
🔗inductive type
Option.{u} (α : Type u) : Type u
Option.{u} (α : Type u) : Type u

Optional values, which are either some around a value from the underlying type or none.

Option can represent nullable types or computations that might fail. In the codomain of a function type, it can also represent partiality.

Constructors

Option.none.{u} {α : Type u} : Option α

No value.

Option.some.{u} {α : Type u} (val : α) : Option α

Some value of type α.

20.12.1. 强制🔗

有一个从 αOption α强制 将值包装在 some 中。 这允许 Option 的使用方式与其他语言中的可空类型类似,其中缺少的值由 none 指示,而存在的值没有特别标记。

Coercions and Option

getAlpha中,读取一行输入。 如果该行仅由字母组成(从其开头和结尾删除空格后),则返回该行;否则,函数返回 none

def getAlpha : IO (Option String) := do let line := ( ( IO.getStdin).getLine).`String.trim` has been deprecated: Use `String.trimAscii` instead Note: The updated constant has a different type: String String.Slice instead of String Stringtrim if line.length > 0 && line.all Char.isAlpha then return line else return none

在成功的情况下,line 周围没有显式的 somesome 通过强制自动插入。

20.12.2. API 参考🔗

20.12.2.1. 提取值🔗

🔗def
Option.get.{u} {α : Type u} (o : Option α) : o.isSome = true α
Option.get.{u} {α : Type u} (o : Option α) : o.isSome = true α

Extracts the value from an option that can be proven to be some.

🔗def
Option.get!.{u} {α : Type u} [Inhabited α] : Option α α
Option.get!.{u} {α : Type u} [Inhabited α] : Option α α

Extracts the value from an Option, panicking on none.

🔗def
Option.getD.{u_1} {α : Type u_1} (opt : Option α) (dflt : α) : α
Option.getD.{u_1} {α : Type u_1} (opt : Option α) (dflt : α) : α

Gets an optional value, returning a given default on none.

This function is @[macro_inline], so dflt will not be evaluated unless opt turns out to be none.

Examples:

🔗def
Option.getDM.{u_1, u_2} {m : Type u_1 Type u_2} {α : Type u_1} [Pure m] (x : Option α) (y : m α) : m α
Option.getDM.{u_1, u_2} {m : Type u_1 Type u_2} {α : Type u_1} [Pure m] (x : Option α) (y : m α) : m α

Gets the value in an option, monadically computing a default value on none.

This is the monadic analogue of Option.getD.

🔗def
Option.getM.{u_1, u_2} {m : Type u_1 Type u_2} {α : Type u_1} [Alternative m] : Option α m α
Option.getM.{u_1, u_2} {m : Type u_1 Type u_2} {α : Type u_1} [Alternative m] : Option α m α

Lifts an optional value to any Alternative, sending none to failure.

🔗def
Option.elim.{u_1, u_2} {α : Type u_1} {β : Sort u_2} : Option α β (α β) β
Option.elim.{u_1, u_2} {α : Type u_1} {β : Sort u_2} : Option α β (α β) β

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:

🔗def
Option.elimM.{u_1, u_2} {m : Type u_1 Type u_2} {α β : Type u_1} [Monad m] (x : m (Option α)) (y : m β) (z : α m β) : m β
Option.elimM.{u_1, u_2} {m : Type u_1 Type u_2} {α β : Type u_1} [Monad m] (x : m (Option α)) (y : m β) (z : α m β) : m β

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.

🔗def
Option.merge.{u_1} {α : Type u_1} (fn : α α α) : Option α Option α Option α
Option.merge.{u_1} {α : Type u_1} (fn : α α α) : Option α Option α Option α

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:

20.12.2.2. 特性和比较🔗

🔗def
Option.isNone.{u_1} {α : Type u_1} : Option α Bool
Option.isNone.{u_1} {α : Type u_1} : Option α Bool

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:

🔗def
Option.isSome.{u_1} {α : Type u_1} : Option α Bool
Option.isSome.{u_1} {α : Type u_1} : Option α Bool

Returns true on some x and false on none.

🔗def
Option.isEqSome.{u_1} {α : Type u_1} [BEq α] : Option α α Bool
Option.isEqSome.{u_1} {α : Type u_1} [BEq α] : Option α α Bool

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.

可选值的排序通常使用 DecidableEq (Option α)LT (Option α)Min (Option α)Max (Option α) 实例。

🔗def
Option.min.{u_1} {α : Type u_1} [Min α] : Option α Option α Option α
Option.min.{u_1} {α : Type u_1} [Min α] : Option α Option α Option α

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:

🔗def
Option.max.{u_1} {α : Type u_1} [Max α] : Option α Option α Option α
Option.max.{u_1} {α : Type u_1} [Max α] : Option α Option α Option α

The maximum of two optional values.

This function is usually accessed through the Max (Option α) instance, rather than directly.

Examples:

🔗def
Option.lt.{u_1, u_2} {α : Type u_1} {β : Type u_2} (r : α β Prop) : Option α Option β Prop
Option.lt.{u_1, u_2} {α : Type u_1} {β : Type u_2} (r : α β Prop) : Option α Option β Prop

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:

🔗def

Equality with none is decidable even if the wrapped type does not have decidable equality.

20.12.2.3. 转换🔗

🔗def
Option.toArray.{u_1} {α : Type u_1} : Option α Array α
Option.toArray.{u_1} {α : Type u_1} : Option α Array α

Converts an optional value to an array with zero or one element.

Examples:

🔗def
Option.toList.{u_1} {α : Type u_1} : Option α List α
Option.toList.{u_1} {α : Type u_1} : Option α List α

Converts an optional value to a list with zero or one element.

Examples:

🔗def
Option.repr.{u_1} {α : Type u_1} [Repr α] : Option α Nat Std.Format
Option.repr.{u_1} {α : Type u_1} [Repr α] : Option α Nat Std.Format

Returns a representation of an optional value that should be able to be parsed as an equivalent optional value.

This function is typically accessed through the Repr (Option α) instance.

🔗def
Option.format.{u} {α : Type u} [Std.ToFormat α] : Option α Std.Format
Option.format.{u} {α : Type u} [Std.ToFormat α] : Option α Std.Format

Formats an optional value, with no expectation that the Lean parser should be able to parse the result.

This function is usually accessed through the ToFormat (Option α) instance.

20.12.2.4. 控制🔗

Option 可以被认为是描述可能无法返回值的计算。 Monad Option 实例以及 Alternative Option 均基于这种理解。 返回 none 也可以被认为是抛出一个不包含任何有趣信息的异常,该异常在 MonadExcept Unit Option 实例中捕获。

🔗def
Option.guard.{u_1} {α : Type u_1} (p : α Bool) (a : α) : Option α
Option.guard.{u_1} {α : Type u_1} (p : α Bool) (a : α) : Option α

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:

🔗def
Option.bind.{u_1, u_2} {α : Type u_1} {β : Type u_2} : Option α (α Option β) Option β
Option.bind.{u_1, u_2} {α : Type u_1} {β : Type u_2} : Option α (α Option β) Option β

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.

Examples:

🔗def
Option.bindM.{u_1, u_2, u_3} {m : Type u_1 Type u_2} {α : Type u_3} {β : Type u_1} [Pure m] (f : α m (Option β)) : Option α m (Option β)
Option.bindM.{u_1, u_2, u_3} {m : Type u_1 Type u_2} {α : Type u_3} {β : Type u_1} [Pure m] (f : α m (Option β)) : Option α m (Option β)

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.

🔗def
Option.join.{u_1} {α : Type u_1} (x : Option (Option α)) : Option α
Option.join.{u_1} {α : Type u_1} (x : Option (Option α)) : Option α

Flattens nested optional values, preserving any value found.

This is analogous to List.flatten.

Examples:

🔗def
Option.sequence.{u, u_1} {m : Type u Type u_1} [Applicative m] {α : Type u} : Option (m α) m (Option α)
Option.sequence.{u, u_1} {m : Type u Type u_1} [Applicative m] {α : Type u} : Option (m α) m (Option α)

Converts an optional monadic computation into a monadic computation of an optional value.

This function only requires m to be an applicative functor.

Example:

some "world"hello #eval show IO (Option String) from Option.sequence <| some do IO.println "hello" return "world"
hello
some "world"
🔗def
Option.tryCatch.{u_1} {α : Type u_1} (x : Option α) (handle : Unit Option α) : Option α
Option.tryCatch.{u_1} {α : Type u_1} (x : Option α) (handle : Unit Option α) : Option α

Recover from failing Option computations with a handler function.

This function is usually accessed through the MonadExceptOf Unit Option instance.

Examples:

🔗def
Option.or.{u_1} {α : Type u_1} : Option α Option α Option α
Option.or.{u_1} {α : Type u_1} : Option α Option α Option α

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.

🔗def
Option.orElse.{u_1} {α : Type u_1} : Option α (Unit Option α) Option α
Option.orElse.{u_1} {α : Type u_1} : Option α (Unit Option α) Option α

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.

20.12.2.5. 迭代🔗

Option 可以被认为是最多包含一个值的集合。 从这个角度来看,迭代运算符可以理解为对包含的值(如果存在)执行某些操作,或者如果不存在则不执行任何操作。

🔗def
Option.all.{u_1} {α : Type u_1} (p : α Bool) : Option α Bool
Option.all.{u_1} {α : Type u_1} (p : α Bool) : Option α Bool

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

🔗def
Option.any.{u_1} {α : Type u_1} (p : α Bool) : Option α Bool
Option.any.{u_1} {α : Type u_1} (p : α Bool) : Option α Bool

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

🔗def
Option.filter.{u_1} {α : Type u_1} (p : α Bool) : Option α Option α
Option.filter.{u_1} {α : Type u_1} (p : α Bool) : Option α Option α

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:

🔗def
Option.filterM.{u_1} {m : Type Type u_1} {α : Type} [Applicative m] (p : α m Bool) : Option α m (Option α)
Option.filterM.{u_1} {m : Type Type u_1} {α : Type} [Applicative m] (p : α m Bool) : Option α m (Option α)

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.

🔗def
Option.forM.{u_1, u_2, u_3} {m : Type u_1 Type u_2} {α : Type u_3} [Pure m] : Option α (α m PUnit) m PUnit
Option.forM.{u_1, u_2, u_3} {m : Type u_1 Type u_2} {α : Type u_3} [Pure m] : Option α (α m PUnit) m PUnit

Executes a monadic action on an optional value if it is present, or does nothing if there is no value.

Examples:

((), 5)#eval ((some 5).forM set : StateM Nat Unit).run 0 ((), 5)((), 0)#eval (none.forM (fun x : Nat => set x) : StateM Nat Unit).run 0 ((), 0)
🔗def
Option.map.{u_1, u_2} {α : Type u_1} {β : Type u_2} (f : α β) : Option α Option β
Option.map.{u_1, u_2} {α : Type u_1} {β : Type u_2} (f : α β) : Option α Option β

Apply a function to an optional value, if present.

From the perspective of Option as a container with at most one value, this is analogous to List.map. It can also be accessed via the Functor Option instance.

Examples:

🔗def
Option.mapA.{u_1, u_2, u_3} {m : Type u_1 Type u_2} {α : Type u_3} {β : Type u_1} [Applicative m] (f : α m β) : Option α m (Option β)
Option.mapA.{u_1, u_2, u_3} {m : Type u_1 Type u_2} {α : Type u_3} {β : Type u_1} [Applicative m] (f : α m β) : Option α m (Option β)

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.

🔗def
Option.mapM.{u_1, u_2, u_3} {m : Type u_1 Type u_2} {α : Type u_3} {β : Type u_1} [Applicative m] (f : α m β) : Option α m (Option β)
Option.mapM.{u_1, u_2, u_3} {m : Type u_1 Type u_2} {α : Type u_3} {β : Type u_1} [Applicative m] (f : α m β) : Option α m (Option β)

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.

20.12.2.6. 递归助手🔗

🔗def
Option.attach.{u_1} {α : Type u_1} (xs : Option α) : Option { x // xs = some x }
Option.attach.{u_1} {α : Type u_1} (xs : Option α) : Option { x // xs = some x }

“Attaches” a proof that an optional value, if present, is indeed this value, returning a subtype that expresses this fact.

This function is primarily used to allow definitions by well-founded recursion that use iteration operators (such as Option.map) to prove that an optional value drawn from a parameter is smaller than the parameter. This allows the well-founded recursion mechanism to prove that the function terminates.

🔗def
Option.attachWith.{u_1} {α : Type u_1} (xs : Option α) (P : α Prop) (H : (x : α), xs = some x P x) : Option { x // P x }
Option.attachWith.{u_1} {α : Type u_1} (xs : Option α) (P : α Prop) (H : (x : α), xs = some x P x) : Option { x // P x }

“Attaches” a proof that some predicate holds for an optional value, if present, returning a subtype that expresses this fact.

This function is primarily used to implement Option.attach, which allows definitions by well-founded recursion that use iteration operators (such as Option.map) to prove that an optional value drawn from a parameter is smaller than the parameter. This allows the well-founded recursion mechanism to prove that the function terminates.

🔗def
Option.unattach.{u_1} {α : Type u_1} {p : α Prop} (o : Option { x // p x }) : Option α
Option.unattach.{u_1} {α : Type u_1} {p : α Prop} (o : Option { x // p x }) : Option α

Remove an attached proof that the value in an Option is indeed that value.

This function is usually inserted automatically by Lean, rather than explicitly in code. It is introduced as an intermediate step during the elaboration of definitions by well-founded recursion.

If this function is encountered in a proof state, the right approach is usually the tactic simp [Option.unattach, -Option.map_subtype].

It is a synonym for Option.map Subtype.val.

20.12.2.7. 推理🔗

🔗def
Option.choice.{u_1} (α : Type u_1) : Option α
Option.choice.{u_1} (α : Type u_1) : Option α

An optional arbitrary element of a given type.

If α is non-empty, then there exists some v : α and this arbitrary element is some v. Otherwise, it is none.

🔗def
Option.pbind.{u_1, u_2} {α : Type u_1} {β : Type u_2} (o : Option α) (f : (a : α) o = some a Option β) : Option β
Option.pbind.{u_1, u_2} {α : Type u_1} {β : Type u_2} (o : Option α) (f : (a : α) o = some a Option β) : Option β

Given an optional value and a function that can be applied when the value is some, returns the result of applying the function if this is possible.

The function f is partial because it is only defined for the values a : α such that o = some a. This restriction allows the function to use the fact that it can only be called when o is not none: it can relate its argument to the optional value o. Its runtime behavior is equivalent to that of Option.bind.

Examples:

def attach (v : Option α) : Option { y : α // v = some y } := v.pbind fun x h => some x, h
#reduce attach (some 3)
some 3,
#reduce attach none
none
🔗def
Option.pelim.{u_1, u_2} {α : Type u_1} {β : Sort u_2} (o : Option α) (b : β) (f : (a : α) o = some a β) : β
Option.pelim.{u_1, u_2} {α : Type u_1} {β : Sort u_2} (o : Option α) (b : β) (f : (a : α) o = some a β) : β

Given an optional value and a function that can be applied when the value is some, returns the result of applying the function if this is possible, or a fallback value otherwise.

The function f is partial because it is only defined for the values a : α such that o = some a. This restriction allows the function to use the fact that it can only be called when o is not none: it can relate its argument to the optional value o. Its runtime behavior is equivalent to that of Option.elim.

Examples:

def attach (v : Option α) : Option { y : α // v = some y } := v.pelim none fun x h => some x, h
#reduce attach (some 3)
some 3,
#reduce attach none
none
🔗def
Option.pmap.{u_1, u_2} {α : Type u_1} {β : Type u_2} {p : α Prop} (f : (a : α) p a β) (o : Option α) : (∀ (a : α), o = some a p a) Option β
Option.pmap.{u_1, u_2} {α : Type u_1} {β : Type u_2} {p : α Prop} (f : (a : α) p a β) (o : Option α) : (∀ (a : α), o = some a p a) Option β

Given a function from the elements of α that satisfy p to β and a proof that an optional value satisfies p if it's present, applies the function to the value.

Examples:

def attach (v : Option α) : Option { y : α // v = some y } := v.pmap (fun a (h : a v) => _, h) (fun _ h => h)
#reduce attach (some 3)
some 3,
#reduce attach none
none