Formal Software Verification

2.1. Predicates and Quantifiers🔗

Lecture 1 excluded "x is even" from the propositions because its truth depends on the unbound variable x. A predicate makes this dependence explicit. A predicate on a type α assigns a proposition to each element of α, so in Lean a predicate is a function of type α → Prop.

fun n => n > 3 : Nat Prop#check fun n : Nat => n > 3
fun n => n > 3 : Nat  Prop

Quantifiers bind the variable of a predicate and produce a proposition, and Table 2.1.1 names the two.G. Frege, Begriffsschrift, eine der arithmetischen nachgebildete Formelsprache des reinen Denkens, Verlag von Louis Nebert, Halle, 1879. We write P x for the proposition that the predicate P yields at x.

Symbol

Name

Reading

∀ x, P x

universal quantifier

P x holds for every x

∃ x, P x

existential quantifier

P x holds for some x

Table 2.1.1. The two quantifiers, with their symbols and readings.

The quantifier binds its variable, so ∀ x, P x depends on no free variable and is a proposition. The variable ranges over a type. For example, ∃ n : Nat, n * n = 9 states that some natural number squares to 9. When the context determines the type, Lean infers it and we omit the annotation.

2.1.1. Examples🔗

The examples below write predicates and quantified propositions and read their types with #check. A predicate has type α → Prop, and a quantified proposition, which binds its variable, has type Prop. The command #eval reports the truth value of a decidable predicate at a concrete point through decide.

Example 1. Applying a predicate to an argument yields a proposition.

(fun n => n < 5) 3 : Prop#check (fun n : Nat => n < 5) 3
(fun n => n < 5) 3 : Prop

Example 2. A predicate may range over any type, strings among them.

fun s => s.length > 0 : String Prop#check fun s : String => s.length > 0
fun s => s.length > 0 : String  Prop

Example 3. A predicate of two arguments is a binary relation, a function into Prop in two stages.

fun m n => m n : Nat Nat Prop#check fun m n : Nat => m n
fun m n => m  n : Nat  Nat  Prop

Example 4. A universally quantified statement is a proposition.

(n : Nat), n + 0 = n : Prop#check n : Nat, n + 0 = n
 (n : Nat), n + 0 = n : Prop

Example 5. So is an existentially quantified one.

n, n > 100 : Prop#check n : Nat, n > 100
 n, n > 100 : Prop

Example 6. Nested quantifiers of different kinds still produce a proposition.

(m : Nat), n, m < n : Prop#check m : Nat, n : Nat, m < n
 (m : Nat),  n, m < n : Prop

Example 7. The bound variable of an existential may range over strings.

s, s.length = 3 : Prop#check s : String, s.length = 3
 s, s.length = 3 : Prop

Example 8. A binary relation applied to both of its arguments is again a proposition.

(fun m n => m n) 2 3 : Prop#check (fun m n : Nat => m n) 2 3
(fun m n => m  n) 2 3 : Prop

Example 9. At a concrete point a decidable predicate has a computable truth value, here true.

true#eval decide (3 < 5)
true

Example 10. The same computation reports false where the predicate does not hold.

false#eval decide (2 = 3)
false