Store a value in a thunk. Note that the value has already been computed, so there is no laziness.

## Instances For

- intro :: (
- mp : a → b
Modus ponens for if and only if. If

`a ↔ b`

and`a`

, then`b`

. - mpr : b → a
Modus ponens for if and only if, reversed. If

`a ↔ b`

and`b`

, then`a`

. - )

If and only if, or logical bi-implication. `a ↔ b`

means that `a`

implies `b`

and vice versa.
By `propext`

, this implies that `a`

and `b`

are equal and hence any expression involving `a`

is equivalent to the corresponding expression with `b`

instead.

## Instances For

If and only if, or logical bi-implication. `a ↔ b`

means that `a`

implies `b`

and vice versa.
By `propext`

, this implies that `a`

and `b`

are equal and hence any expression involving `a`

is equivalent to the corresponding expression with `b`

instead.

## Instances For

If and only if, or logical bi-implication. `a ↔ b`

means that `a`

implies `b`

and vice versa.
By `propext`

, this implies that `a`

and `b`

are equal and hence any expression involving `a`

is equivalent to the corresponding expression with `b`

instead.

## Instances For

- inl: {α : Type u} → {β : Type v} → α → α ⊕ β
Left injection into the sum type

`α ⊕ β`

. If`a : α`

then`.inl a : α ⊕ β`

. - inr: {α : Type u} → {β : Type v} → β → α ⊕ β
Right injection into the sum type

`α ⊕ β`

. If`b : β`

then`.inr b : α ⊕ β`

.

`Sum α β`

, or `α ⊕ β`

, is the disjoint union of types `α`

and `β`

.
An element of `α ⊕ β`

is either of the form `.inl a`

where `a : α`

,
or `.inr b`

where `b : β`

.

## Instances For

- inl: {α : Sort u} → {β : Sort v} → α → α ⊕' β
Left injection into the sum type

`α ⊕' β`

. If`a : α`

then`.inl a : α ⊕' β`

. - inr: {α : Sort u} → {β : Sort v} → β → α ⊕' β
Right injection into the sum type

`α ⊕' β`

. If`b : β`

then`.inr b : α ⊕' β`

.

`PSum α β`

, or `α ⊕' β`

, is the disjoint union of types `α`

and `β`

.
It differs from `α ⊕ β`

in that it allows `α`

and `β`

to have arbitrary sorts
`Sort u`

and `Sort v`

, instead of restricting to `Type u`

and `Type v`

. This means
that it can be used in situations where one side is a proposition, like `True ⊕' Nat`

.

The reason this is not the default is that this type lives in the universe `Sort (max 1 u v)`

,
which can cause problems for universe level unification,
because the equation `max 1 u v = ?u + 1`

has no solution in level arithmetic.
`PSum`

is usually only used in automation that constructs sums of arbitrary types.

## Instances For

`PSum α β`

, or `α ⊕' β`

, is the disjoint union of types `α`

and `β`

.
It differs from `α ⊕ β`

in that it allows `α`

and `β`

to have arbitrary sorts
`Sort u`

and `Sort v`

, instead of restricting to `Type u`

and `Type v`

. This means
that it can be used in situations where one side is a proposition, like `True ⊕' Nat`

.

The reason this is not the default is that this type lives in the universe `Sort (max 1 u v)`

,
which can cause problems for universe level unification,
because the equation `max 1 u v = ?u + 1`

has no solution in level arithmetic.
`PSum`

is usually only used in automation that constructs sums of arbitrary types.

## Instances For

- fst : α
The first component of a dependent pair. If

`p : @Sigma α β`

then`p.1 : α`

. - snd : β s.fst
The second component of a dependent pair. If

`p : Sigma β`

then`p.2 : β p.1`

.

`Sigma β`

, also denoted `Σ a : α, β a`

or `(a : α) × β a`

, is the type of dependent pairs
whose first component is `a : α`

and whose second component is `b : β a`

(so the type of the second component can depend on the value of the first component).
It is sometimes known as the dependent sum type, since it is the type level version
of an indexed summation.

## Instances For

- fst : α
The first component of a dependent pair. If

`p : @Sigma α β`

then`p.1 : α`

. - snd : β s.fst
The second component of a dependent pair. If

`p : Sigma β`

then`p.2 : β p.1`

.

`PSigma β`

, also denoted `Σ' a : α, β a`

or `(a : α) ×' β a`

, is the type of dependent pairs
whose first component is `a : α`

and whose second component is `b : β a`

(so the type of the second component can depend on the value of the first component).
It differs from `Σ a : α, β a`

in that it allows `α`

and `β`

to have arbitrary sorts
`Sort u`

and `Sort v`

, instead of restricting to `Type u`

and `Type v`

. This means
that it can be used in situations where one side is a proposition, like `(p : Nat) ×' p = p`

.

The reason this is not the default is that this type lives in the universe `Sort (max 1 u v)`

,
which can cause problems for universe level unification,
because the equation `max 1 u v = ?u + 1`

has no solution in level arithmetic.
`PSigma`

is usually only used in automation that constructs pairs of arbitrary types.

## Instances For

- intro: ∀ {α : Sort u} {p : α → Prop} (w : α), p w → Exists p
Existential introduction. If

`a : α`

and`h : p a`

, then`⟨a, h⟩`

is a proof that`∃ x : α, p x`

.

Existential quantification. If `p : α → Prop`

is a predicate, then `∃ x : α, p x`

asserts that there is some `x`

of type `α`

such that `p x`

holds.
To create an existential proof, use the `exists`

tactic,
or the anonymous constructor notation `⟨x, h⟩`

.
To unpack an existential, use `cases h`

where `h`

is a proof of `∃ x : α, p x`

,
or `let ⟨x, hx⟩ := h`

where `.

Because Lean has proof irrelevance, any two proofs of an existential are definitionally equal. One consequence of this is that it is impossible to recover the witness of an existential from the mere fact of its existence. For example, the following does not compile:

```
example (h : ∃ x : Nat, x = x) : Nat :=
let ⟨x, _⟩ := h -- fail, because the goal is `Nat : Type`
x
```

The error message `recursor 'Exists.casesOn' can only eliminate into Prop`

means
that this only works when the current goal is another proposition:

```
example (h : ∃ x : Nat, x = x) : True :=
let ⟨x, _⟩ := h -- ok, because the goal is `True : Prop`
trivial
```

## Instances For

Auxiliary type used to compile `for x in xs`

notation.

This is the return value of the body of a `ForIn`

call,
representing the body of a for loop. It can be:

`.yield (a : α)`

, meaning that we should continue the loop and`a`

is the new state.`.yield`

is produced by`continue`

and reaching the bottom of the loop body.`.done (a : α)`

, meaning that we should early-exit the loop with state`a`

.`.done`

is produced by calls to`break`

or`return`

in the loop,

## Instances For

`forIn x b f : m β`

runs a for-loop in the monad`m`

with additional state`β`

. This traverses over the "contents" of`x`

, and passes the elements`a : α`

to`f : α → β → m (ForInStep β)`

.`b : β`

is the initial state, and the return value of`f`

is the new state as well as a directive`.done`

or`.yield`

which indicates whether to abort early or continue iteration.The expression

`let mut b := ... for x in xs do b ← foo x b`

in a

`do`

block is syntactic sugar for:`let b := ... let b ← forIn xs b (fun x b => do let b ← foo x b return .yield b)`

(Here

`b`

corresponds to the variables mutated in the loop.)

`ForIn m ρ α`

is the typeclass which supports `for x in xs`

notation.
Here `xs : ρ`

is the type of the collection to iterate over, `x : α`

is the element type which is made available inside the loop, and `m`

is the monad
for the encompassing `do`

block.

## Instances

- forIn' : {β : Type u₁} → [inst : Monad m] → (x : ρ) → β → ((a : α) → a ∈ x → β → m (ForInStep β)) → m β
`forIn' x b f : m β`

runs a for-loop in the monad`m`

with additional state`β`

. This traverses over the "contents" of`x`

, and passes the elements`a : α`

along with a proof that`a ∈ x`

to`f : (a : α) → a ∈ x → β → m (ForInStep β)`

.`b : β`

is the initial state, and the return value of`f`

is the new state as well as a directive`.done`

or`.yield`

which indicates whether to abort early or continue iteration.

`ForIn' m ρ α d`

is a variation on the `ForIn m ρ α`

typeclass which supports the
`for h : x in xs`

notation. It is the same as `for x in xs`

except that `h : x ∈ xs`

is provided as an additional argument to the body of the for-loop.

## Instances

- pure: {α β σ : Type u} → α → σ → DoResultPRBC α β σ
`pure (a : α) s`

means that the block exited normally with return value`a`

- return: {α β σ : Type u} → β → σ → DoResultPRBC α β σ
- break: {α β σ : Type u} → σ → DoResultPRBC α β σ
- continue: {α β σ : Type u} → σ → DoResultPRBC α β σ

Auxiliary type used to compile `do`

notation. It is used when compiling a do block
nested inside a combinator like `tryCatch`

. It encodes the possible ways the
block can exit:

`pure (a : α) s`

means that the block exited normally with return value`a`

.`return (b : β) s`

means that the block exited via a`return b`

early-exit command.`break s`

means that`break`

was called, meaning that we should exit from the containing loop.`continue s`

means that`continue`

was called, meaning that we should continue to the next iteration of the containing loop.

All cases return a value `s : σ`

which bundles all the mutable variables of the do-block.

## Instances For

- pure: {α β σ : Type u} → α → σ → DoResultPR α β σ
`pure (a : α) s`

means that the block exited normally with return value`a`

- return: {α β σ : Type u} → β → σ → DoResultPR α β σ

Auxiliary type used to compile `do`

notation. It is the same as
`DoResultPRBC α β σ`

except that `break`

and `continue`

are not available
because we are not in a loop context.

## Instances For

- break: {σ : Type u} → σ → DoResultBC σ
- continue: {σ : Type u} → σ → DoResultBC σ

Auxiliary type used to compile `do`

notation. It is an optimization of
`DoResultPRBC PEmpty PEmpty σ`

to remove the impossible cases,
used when neither `pure`

nor `return`

are possible exit paths.

## Instances For

- pureReturn: {α σ : Type u} → α → σ → DoResultSBC α σ
- break: {α σ : Type u} → σ → DoResultSBC α σ
- continue: {α σ : Type u} → σ → DoResultSBC α σ

Auxiliary type used to compile `do`

notation. It is an optimization of
either `DoResultPRBC α PEmpty σ`

or `DoResultPRBC PEmpty α σ`

to remove the
impossible case, used when either `pure`

or `return`

is never used.

## Instances For

`x ≈ y`

says that `x`

and `y`

are equivalent. Because this is a typeclass,
the notion of equivalence is type-dependent.

## Instances For

- emptyCollection : α
`∅`

or`{}`

is the empty set or empty collection. It is supported by the`EmptyCollection`

typeclass.

`EmptyCollection α`

is the typeclass which supports the notation `∅`

, also written as `{}`

.

## Instances

`∅`

or `{}`

is the empty set or empty collection.
It is supported by the `EmptyCollection`

typeclass.

## Instances For

`∅`

or `{}`

is the empty set or empty collection.
It is supported by the `EmptyCollection`

typeclass.

## Instances For

- pure :: (
- get : α
- )

`Task α`

is a primitive for asynchronous computation.
It represents a computation that will resolve to a value of type `α`

,
possibly being computed on another thread. This is similar to `Future`

in Scala,
`Promise`

in Javascript, and `JoinHandle`

in Rust.

The tasks have an overridden representation in the runtime.

## Instances For

Task priority. Tasks with higher priority will always be scheduled before ones with lower priority.

## Instances For

The default priority for spawned tasks, also the lowest priority: `0`

.

## Instances For

The highest regular priority for spawned tasks: `8`

.

Spawning a task with a priority higher than `Task.Priority.max`

is not an error but
will spawn a dedicated worker for the task, see `Task.Priority.dedicated`

.
Regular priority tasks are placed in a thread pool and worked on according to the priority order.

## Instances For

Any priority higher than `Task.Priority.max`

will result in the task being scheduled
immediately on a dedicated thread. This is particularly useful for long-running and/or
I/O-bound tasks since Lean will by default allocate no more non-dedicated workers
than the number of cores to reduce context switches.

## Instances For

`spawn fn : Task α`

constructs and immediately launches a new task for
evaluating the function `fn () : α`

asynchronously.

`prio`

, if provided, is the priority of the task.

## Instances For

`map f x`

maps function `f`

over the task `x`

: that is, it constructs
(and immediately launches) a new task which will wait for the value of `x`

to
be available and then calls `f`

on the result.

`prio`

, if provided, is the priority of the task.

## Instances For

`bind x f`

does a monad "bind" operation on the task `x`

with function `f`

:
that is, it constructs (and immediately launches) a new task which will wait
for the value of `x`

to be available and then calls `f`

on the result,
resulting in a new task which is then run for a result.

`prio`

, if provided, is the priority of the task.

## Instances For

- val : Nat
You should not use this function

`NonScalar`

is a type that is not a scalar value in our runtime.
It is used as a stand-in for an arbitrary boxed value to avoid excessive
monomorphization, and it is only created using `unsafeCast`

. It is somewhat
analogous to C `void*`

in usage, but the type itself is not special.

## Instances For

- mk: Nat → PNonScalar
You should not use this function

`PNonScalar`

is a type that is not a scalar value in our runtime.
It is used as a stand-in for an arbitrary boxed value to avoid excessive
monomorphization, and it is only created using `unsafeCast`

. It is somewhat
analogous to C `void*`

in usage, but the type itself is not special.

This is the universe-polymorphic version of `PNonScalar`

; it is preferred to use
`NonScalar`

instead where applicable.

## Instances For

# Boolean operators #

If

`a == b`

evaluates to`true`

, then`a`

and`b`

are equal in the logic.`==`

is reflexive, that is,`(a == a) = true`

.

`LawfulBEq α`

is a typeclass which asserts that the `BEq α`

implementation
(which supplies the `a == b`

notation) coincides with logical equality `a = b`

.
In other words, `a == b`

implies `a = b`

, and `a == a`

is true.

## Instances

# Logical connectives and equality #

If `h : α = β`

is a proof of type equality, then `h.mpr : β → α`

is the induced
"cast" operation in the reverse direction, mapping elements of `β`

to elements of `α`

.

You can prove theorems about the resulting element by induction on `h`

, since
`rfl.mpr`

is definitionally the identity function.

## Instances For

# Exists #

# Decidable #

Similar to `decide`

, but uses an explicit instance

## Instances For

Synonym for `dite`

(dependent if-then-else). We can construct an element `q`

(of any sort, not just a proposition) by cases on whether `p`

is true or false,
provided `p`

is decidable.

## Instances For

# if-then-else expression theorems #

Auxiliary definition for generating compact `noConfusion`

for enumeration types

## Instances For

Auxiliary definition for generating compact `noConfusion`

for enumeration types

## Instances For

# Inhabited #

# Subsingleton #

- intro :: (
- allEq : ∀ (a b : α), a = b
Any two elements of a subsingleton are equal.

- )

A "subsingleton" is a type with at most one element.
In other words, it is either empty, or has a unique element.
All propositions are subsingletons because of proof irrelevance, but some other types
are subsingletons as well and they inherit many of the same properties as propositions.
`Subsingleton α`

is a typeclass, so it is usually used as an implicit argument and
inferred by typeclass inference.

## Instances

- refl : ∀ (x : α), r x x
An equivalence relation is reflexive:

`x ~ x`

- symm : ∀ {x y : α}, r x y → r y x
An equivalence relation is symmetric:

`x ~ y`

implies`y ~ x`

- trans : ∀ {x y z : α}, r x y → r y z → r x z
An equivalence relation is transitive:

`x ~ y`

and`y ~ z`

implies`x ~ z`

An equivalence relation `~ : α → α → Prop`

is a relation that is:

- reflexive:
`x ~ x`

- symmetric:
`x ~ y`

implies`y ~ x`

- transitive:
`x ~ y`

and`y ~ z`

implies`x ~ z`

Equality is an equivalence relation, and equivalence relations share many of
the properties of equality. In particular, `Quot α r`

is most well behaved
when `r`

is an equivalence relation, and in this case we use `Quotient`

instead.

## Instances For

The empty relation is the relation on `α`

which is always `False`

.

## Instances For

`Subrelation q r`

means that `q ⊆ r`

or `∀ x y, q x y → r x y`

.
It is the analogue of the subset relation on relations.

## Instances For

- base: ∀ {α : Sort u} {r : α → α → Prop} (a b : α), r a b → TC r a b
If

`r a b`

then`r⁺ a b`

. This is the base case of the transitive closure. - trans: ∀ {α : Sort u} {r : α → α → Prop} (a b c : α), TC r a b → TC r b c → TC r a c
The transitive closure is transitive.

The transitive closure `r⁺`

of a relation `r`

is the smallest relation which is
transitive and contains `r`

. `r⁺ a z`

if and only if there exists a sequence
`a r b r ... r z`

of length at least 1 connecting `a`

to `z`

.

## Instances For

# Subtype #

# Sum #

# Product #

# Dependent products #

# Universe polymorphic unit #

# Setoid #

- r : α → α → Prop
`x ≈ y`

is the distinguished equivalence relation of a setoid. - iseqv : Equivalence Setoid.r
The relation

`x ≈ y`

is an equivalence relation.

A setoid is a type with a distinguished equivalence relation, denoted `≈`

.
This is mainly used as input to the `Quotient`

type constructor.

## Instances

# Propositional extensionality #

The axiom of **propositional extensionality**. It asserts that if propositions
`a`

and `b`

are logically equivalent (i.e. we can prove `a`

from `b`

and vice versa),
then `a`

and `b`

are *equal*, meaning that we can replace `a`

with `b`

in all
contexts.

For simple expressions like `a ∧ c ∨ d → e`

we can prove that because all the logical
connectives respect logical equivalence, we can replace `a`

with `b`

in this expression
without using `propext`

. However, for higher order expressions like `P a`

where
`P : Prop → Prop`

is unknown, or indeed for `a = b`

itself, we cannot replace `a`

with `b`

without an axiom which says exactly this.

This is a relatively uncontroversial axiom, which is intuitionistically valid.
It does however block computation when using `#reduce`

to reduce proofs directly
(which is not recommended), meaning that canonicity,
the property that all closed terms of type `Nat`

normalize to numerals,
fails to hold when this (or any) axiom is used:

```
set_option pp.proofs true
def foo : Nat := by
have : (True → True) ↔ True := ⟨λ _ => trivial, λ _ _ => trivial⟩
have := propext this ▸ (2 : Nat)
exact this
#reduce foo
-- propext { mp := fun x x => True.intro, mpr := fun x => True.intro } ▸ 2
#eval foo -- 2
```

`#eval`

can evaluate it to a numeral because the compiler erases casts and
does not evaluate proofs, so `propext`

, whose return type is a proposition,
can never block it.

# Quotients #

The **quotient axiom**, or at least the nontrivial part of the quotient
axiomatization. Quotient types are introduced by the `init_quot`

command
in `Init.Prelude`

which introduces the axioms:

```
opaque Quot {α : Sort u} (r : α → α → Prop) : Sort u
opaque Quot.mk {α : Sort u} (r : α → α → Prop) (a : α) : Quot r
opaque Quot.lift {α : Sort u} {r : α → α → Prop} {β : Sort v} (f : α → β) :
(∀ a b : α, r a b → f a = f b) → Quot r → β
opaque Quot.ind {α : Sort u} {r : α → α → Prop} {β : Quot r → Prop} :
(∀ a : α, β (Quot.mk r a)) → ∀ q : Quot r, β q
```

All of these axioms are true if we assume `Quot α r = α`

and `Quot.mk`

and
`Quot.lift`

are identity functions, so they do not add much. However this axiom
cannot be explained in that way (it is false for that interpretation), so the
real power of quotient types come from this axiom.

It says that the quotient by `r`

maps elements which are related by `r`

to equal
values in the quotient. Together with `Quot.lift`

which says that functions
which respect `r`

can be lifted to functions on the quotient, we can deduce that
`Quot α r`

exactly consists of the equivalence classes with respect to `r`

.

It is important to note that `r`

need not be an equivalence relation in this axiom.
When `r`

is not an equivalence relation, we are actually taking a quotient with
respect to the equivalence relation generated by `r`

.

Dependent recursion principle for `Quot`

. This constructor can be tricky to use,
so you should consider the simpler versions if they apply:

`Quot.lift`

, for nondependent functions`Quot.ind`

, for theorems / proofs of propositions about quotients`Quot.recOnSubsingleton`

, when the target type is a`Subsingleton`

`Quot.hrecOn`

, which uses`HEq (f a) (f b)`

instead of a`sound p ▸ f a = f b`

assummption

## Instances For

Dependent recursion principle for `Quot`

. This constructor can be tricky to use,
so you should consider the simpler versions if they apply:

`Quot.lift`

, for nondependent functions`Quot.ind`

, for theorems / proofs of propositions about quotients`Quot.recOnSubsingleton`

, when the target type is a`Subsingleton`

`Quot.hrecOn`

, which uses`HEq (f a) (f b)`

instead of a`sound p ▸ f a = f b`

assummption

## Instances For

Dependent induction principle for a quotient, when the target type is a `Subsingleton`

.
In this case the quotient's side condition is trivial so any function can be lifted.

## Instances For

Heterogeneous dependent recursion principle for a quotient.
This may be easier to work with since it uses `HEq`

instead of
an `Eq.ndrec`

in the hypothesis.

## Instances For

The analogue of `Quot.sound`

: If `a`

and `b`

are related by the equivalence relation,
then they have equal equivalence classes.

## Instances For

The analogue of `Quot.ind`

: every element of `Quotient s`

is of the form `Quotient.mk s a`

.

The analogue of `Quot.liftOn`

: if `f : α → β`

respects the equivalence relation `≈`

,
then it lifts to a function on `Quotient s`

such that `lift (mk a) f h = f a`

.

## Instances For

The analogue of `Quot.inductionOn`

: every element of `Quotient s`

is of the form `Quotient.mk s a`

.

The analogue of `Quot.rec`

for `Quotient`

. See `Quot.rec`

.

## Instances For

The analogue of `Quot.recOn`

for `Quotient`

. See `Quot.recOn`

.

## Instances For

The analogue of `Quot.recOnSubsingleton`

for `Quotient`

. See `Quot.recOnSubsingleton`

.

## Instances For

The analogue of `Quot.hrecOn`

for `Quotient`

. See `Quot.hrecOn`

.

## Instances For

Lift a binary function to a quotient on both arguments.

## Instances For

Lift a binary function to a quotient on both arguments.

## Instances For

Lift a binary function to a quotient on both arguments.

## Instances For

# Function extensionality #

**Function extensionality** is the statement that if two functions take equal values
every point, then the functions themselves are equal: `(∀ x, f x = g x) → f = g`

.
It is called "extensionality" because it talks about how to prove two objects are equal
based on the properties of the object (compare with set extensionality,
which is `(∀ x, x ∈ s ↔ x ∈ t) → s = t`

).

This is often an axiom in dependent type theory systems, because it cannot be proved
from the core logic alone. However in lean's type theory this follows from the existence
of quotient types (note the `Quot.sound`

in the proof, as well as the `show`

line
which makes use of the definitional equality `Quot.lift f h (Quot.mk x) = f x`

).

# Squash #

`Squash α`

is the quotient of `α`

by the always true relation.
It is empty if `α`

is empty, otherwise it is a singleton.
(Thus it is unconditionally a `Subsingleton`

.)
It is the "universal `Subsingleton`

" mapped from `α`

.

It is similar to `Nonempty α`

, which has the same properties, but unlike
`Nonempty`

this is a `Type u`

, that is, it is "data", and the compiler
represents an element of `Squash α`

the same as `α`

itself
(as compared to `Nonempty α`

, whose elements are represented by a dummy value).

`Squash.lift`

will extract a value in any subsingleton `β`

from a function on `α`

,
while `Nonempty.rec`

can only do the same when `β`

is a proposition.

## Instances For

# Relations #

# Kernel reduction hints #

When the kernel tries to reduce a term `Lean.reduceBool c`

, it will invoke the Lean interpreter to evaluate `c`

.
The kernel will not use the interpreter if `c`

is not a constant.
This feature is useful for performing proofs by reflection.

Remark: the Lean frontend allows terms of the from `Lean.reduceBool t`

where `t`

is a term not containing
free variables. The frontend automatically declares a fresh auxiliary constant `c`

and replaces the term with
`Lean.reduceBool c`

. The main motivation is that the code for `t`

will be pre-compiled.

Warning: by using this feature, the Lean compiler and interpreter become part of your trusted code base. This is extra 30k lines of code. More importantly, you will probably not be able to check your development using external type checkers (e.g., Trepplein) that do not implement this feature. Keep in mind that if you are using Lean as programming language, you are already trusting the Lean compiler and interpreter. So, you are mainly losing the capability of type checking your development using external checkers.

Recall that the compiler trusts the correctness of all `[implemented_by ...]`

and `[extern ...]`

annotations.
If an extern function is executed, then the trusted code base will also include the implementation of the associated
foreign function.

Similar to `Lean.reduceBool`

for closed `Nat`

terms.

Remark: we do not have plans for supporting a generic `reduceValue {α} (a : α) : α := a`

.
The main issue is that it is non-trivial to convert an arbitrary runtime object back into a Lean expression.
We believe `Lean.reduceBool`

enables most interesting applications (e.g., proof by reflection).

The axiom `ofReduceBool`

is used to perform proofs by reflection. See `reduceBool`

.

This axiom is usually not used directly, because it has some syntactic restrictions.
Instead, the `native_decide`

tactic can be used to prove any proposition whose
decidability instance can be evaluated to `true`

using the lean compiler / interpreter.

Warning: by using this feature, the Lean compiler and interpreter become part of your trusted code base. This is extra 30k lines of code. More importantly, you will probably not be able to check your development using external type checkers (e.g., Trepplein) that do not implement this feature. Keep in mind that if you are using Lean as programming language, you are already trusting the Lean compiler and interpreter. So, you are mainly losing the capability of type checking your development using external checkers.

The axiom `ofReduceNat`

is used to perform proofs by reflection. See `reduceBool`

.

Warning: by using this feature, the Lean compiler and interpreter become part of your trusted code base. This is extra 30k lines of code. More importantly, you will probably not be able to check your development using external type checkers (e.g., Trepplein) that do not implement this feature. Keep in mind that if you are using Lean as programming language, you are already trusting the Lean compiler and interpreter. So, you are mainly losing the capability of type checking your development using external checkers.

- assoc : ∀ (a b c : α), op (op a b) c = op a (op b c)
An associative operation satisfies

`(a ∘ b) ∘ c = a ∘ (b ∘ c)`

.

`IsAssociative op`

says that `op`

is an associative operation,
i.e. `(a ∘ b) ∘ c = a ∘ (b ∘ c)`

. It is used by the `ac_rfl`

tactic.

## Instances

- comm : ∀ (a b : α), op a b = op b a
A commutative operation satisfies

`a ∘ b = b ∘ a`

.

`IsCommutative op`

says that `op`

is a commutative operation,
i.e. `a ∘ b = b ∘ a`

. It is used by the `ac_rfl`

tactic.

## Instances

- idempotent : ∀ (x : α), op x x = x
An idempotent operation satisfies

`a ∘ a = a`

.

`IsIdempotent op`

says that `op`

is an idempotent operation,
i.e. `a ∘ a = a`

. It is used by the `ac_rfl`

tactic
(which also simplifies up to idempotence when available).

## Instances

- left_neutral : ∀ (a : α), op neutral a = a
A neutral element can be cancelled on the left:

`e ∘ a = a`

. - right_neutral : ∀ (a : α), op a neutral = a
A neutral element can be cancelled on the right:

`a ∘ e = a`

.

`IsNeutral op e`

says that `e`

is a neutral operation for `op`

,
i.e. `a ∘ e = a = e ∘ a`

. It is used by the `ac_rfl`

tactic
(which also simplifies neutral elements when available).