The Lean Language Reference

18.11. Booleans

🔗inductive type
Bool : Type

The Boolean values, true and false.

Logically speaking, this is equivalent to Prop (the type of propositions). The distinction is important for programming: both propositions and their proofs are erased in the code generator, while Bool corresponds to the Boolean type in most programming languages and carries precisely one bit of run-time information.

Constructors

false : Bool

The Boolean value false, not to be confused with the proposition False.

true : Bool

The Boolean value true, not to be confused with the proposition True.

The constructors Bool.true and Bool.false are exported from the Bool namespace, so they can be written true and false.

18.11.1. Run-Time Representation

Because Bool is an enum inductive type, it is represented by a single byte in compiled code.

18.11.2. Booleans and Propositions

Both Bool and Prop represent notions of truth. From a purely logical perspective, they are equivalent: propositional extensionality means that there are fundamentally only two propositions, namely True and False. However, there is an important pragmatic difference: Bool classifies values that can be computed by programs, while Prop classifies statements for which code generation doesn't make sense. In other words, Bool is the notion of truth and falsehood that's appropriate for programs, while Prop is the notion that's appropriate for mathematics. Because proofs are erased from compiled programs, keeping Bool and Prop distinct makes it clear which parts of a Lean file are intended for computation.

A Bool can be used wherever a Prop is expected. There is a coercion from every Bool b to the proposition b = true. By propext, true = true is equal to True, and false = true is equal to False.

Not every proposition can be used by programs to make run-time decisions. Otherwise, a program could branch on whether the Collatz conjecture is true or false! Many propositions, however, can be checked algorithmically. These propositions are called decidable propositions, and have instances of the Decidable type class. The function Decidable.decide converts a proof-carrying Decidable result into a Bool. This function is also a coercion from decidable propositions to Bool, so (2 = 2 : Bool) evaluates to true.

18.11.3. Syntax

syntaxBoolean Infix Operators

The infix operators &&, ||, and ^^ are notations for Bool.and, Bool.or, and Bool.xor, respectively.

term ::= ...
    | Boolean “and”, also known as conjunction. `and x y` can be written `x && y`.

The corresponding propositional connective is `And : Prop → Prop → Prop`, written with the `∧`
operator.

The Boolean `and` is a `@[macro_inline]` function in order to give it short-circuiting evaluation:
if `x` is `false` then `y` is not evaluated at runtime.


Conventions for notations in identifiers:

 * The recommended spelling of `&&` in identifiers is `and`.term && term
term ::= ...
    | Boolean “or”, also known as disjunction. `or x y` can be written `x || y`.

The corresponding propositional connective is `Or : Prop → Prop → Prop`, written with the `∨`
operator.

The Boolean `or` is a `@[macro_inline]` function in order to give it short-circuiting evaluation:
if `x` is `true` then `y` is not evaluated at runtime.


Conventions for notations in identifiers:

 * The recommended spelling of `||` in identifiers is `or`.term || term
term ::= ...
    | Boolean “exclusive or”. `xor x y` can be written `x ^^ y`.

`x ^^ y` is `true` when precisely one of `x` or `y` is `true`. Unlike `and` and `or`, it does not
have short-circuiting behavior, because one argument's value never determines the final value. Also
unlike `and` and `or`, there is no commonly-used corresponding propositional connective.

Examples:
 * `false ^^ false = false`
 * `true ^^ false = true`
 * `false ^^ true = true`
 * `true ^^ true = false`


Conventions for notations in identifiers:

 * The recommended spelling of `^^` in identifiers is `xor`.term ^^ term
syntaxBoolean Negation

The prefix operator ! is notation for Bool.not.

term ::= ...
    | Boolean negation, also known as Boolean complement. `not x` can be written `!x`.

This is a function that maps the value `true` to `false` and the value `false` to `true`. The
propositional connective is `Not : Prop → Prop`.


Conventions for notations in identifiers:

 * The recommended spelling of `!` in identifiers is `not`.!term

18.11.4. API Reference

18.11.4.1. Logical Operations

The functions cond, and, and or are short-circuiting. In other words, false && BIG_EXPENSIVE_COMPUTATION does not need to execute BIG_EXPENSIVE_COMPUTATION before returning false. These functions are defined using the macro_inline attribute, which causes the compiler to replace calls to them with their definitions while generating code, and the definitions use nested pattern matching to achieve the short-circuiting behavior.

🔗def
cond.{u} {α : Sort u} (c : Bool) (x y : α) : α

The conditional function.

cond c x y is the same as if c then x else y, but optimized for a Boolean condition rather than a decidable proposition. It can also be written using the notation bif c then x else y.

Just like ite, cond is declared @[macro_inline], which causes applications of cond to be unfolded. As a result, x and y are not evaluated at runtime until one of them is selected, and only the selected branch is evaluated.

🔗def
Bool.dcond.{u} {α : Sort u} (c : Bool)
  (x : c = trueα) (y : c = falseα) : α

The dependent conditional function, in which each branch is provided with a local assumption about the condition's value. This allows the value to be used in proofs as well as for control flow.

dcond c (fun h => x) (fun h => y) is the same as if h : c then x else y, but optimized for a Boolean condition rather than a decidable proposition. Unlike the non-dependent version cond, there is no special notation for dcond.

Just like ite, dite, and cond, dcond is declared @[macro_inline], which causes applications of dcond to be unfolded. As a result, x and y are not evaluated at runtime until one of them is selected, and only the selected branch is evaluated. dcond is intended for metaprogramming use, rather than for use in verified programs, so behavioral lemmas are not provided.

🔗def
Bool.not : BoolBool

Boolean negation, also known as Boolean complement. not x can be written !x.

This is a function that maps the value true to false and the value false to true. The propositional connective is Not : Prop Prop.

Conventions for notations in identifiers:

  • The recommended spelling of ! in identifiers is not.

🔗def
Bool.and (x y : Bool) : Bool

Boolean “and”, also known as conjunction. and x y can be written x && y.

The corresponding propositional connective is And : Prop Prop Prop, written with the operator.

The Boolean and is a @[macro_inline] function in order to give it short-circuiting evaluation: if x is false then y is not evaluated at runtime.

Conventions for notations in identifiers:

  • The recommended spelling of && in identifiers is and.

  • The recommended spelling of || in identifiers is or.

🔗def
Bool.or (x y : Bool) : Bool

Boolean “or”, also known as disjunction. or x y can be written x || y.

The corresponding propositional connective is Or : Prop Prop Prop, written with the operator.

The Boolean or is a @[macro_inline] function in order to give it short-circuiting evaluation: if x is true then y is not evaluated at runtime.

🔗def
Bool.xor : BoolBoolBool

Boolean “exclusive or”. xor x y can be written x ^^ y.

x ^^ y is true when precisely one of x or y is true. Unlike and and or, it does not have short-circuiting behavior, because one argument's value never determines the final value. Also unlike and and or, there is no commonly-used corresponding propositional connective.

Examples:

Conventions for notations in identifiers:

  • The recommended spelling of ^^ in identifiers is xor.

18.11.4.2. Comparisons

Most comparisons on Booleans should be performed using the DecidableEq Bool, LT Bool, LE Bool instances.

🔗def
Bool.decEq (a b : Bool) : Decidable (a = b)

Decides whether two Booleans are equal.

This function should normally be called via the DecidableEq Bool instance that it exists to support.

18.11.4.3. Conversions

🔗def
Bool.toISize (b : Bool) : ISize

Converts true to 1 and false to 0.

🔗def
Bool.toUInt8 (b : Bool) : UInt8

Converts true to 1 and false to 0.

🔗def
Bool.toUInt16 (b : Bool) : UInt16

Converts true to 1 and false to 0.

🔗def
Bool.toUInt32 (b : Bool) : UInt32

Converts true to 1 and false to 0.

🔗def
Bool.toUInt64 (b : Bool) : UInt64

Converts true to 1 and false to 0.

🔗def
Bool.toUSize (b : Bool) : USize

Converts true to 1 and false to 0.

🔗def
Bool.toInt8 (b : Bool) : Int8

Converts true to 1 and false to 0.

🔗def
Bool.toInt16 (b : Bool) : Int16

Converts true to 1 and false to 0.

🔗def
Bool.toInt32 (b : Bool) : Int32

Converts true to 1 and false to 0.

🔗def
Bool.toInt64 (b : Bool) : Int64

Converts true to 1 and false to 0.

🔗def
Bool.toNat (b : Bool) : Nat

Converts true to 1 and false to 0.

🔗def
Bool.toInt (b : Bool) : Int

Converts true to 1 and false to 0.