Formal Software Verification

4.4. Reasoning about Equality🔗

The tactic rfl proves a conclusion l = r when the two sides become syntactically identical under computation, and it succeeds roughly where a mathematician says "by definition". The term rfl of Lecture 3 is its term-level form. Computation here names six conversions.

Conversion

What it does

α

renames a bound variable

β

applies an anonymous function to its argument

δ

unfolds a definition

ζ

substitutes a let

η

identifies fun x => f x with f

ι

projects a constructor application

Equality is also a set of rules. Eq.refl introduces it, Eq.symm and Eq.trans say that it is an equivalence relation, and Eq.subst replaces equals for equals in a context that a metavariable represents. A parsing note: = binds more tightly than the connectives, so a = b ∧ c = d reads (a = b) ∧ (c = d).

Eq.refl  : ∀ (a : ?α), a = a
Eq.symm  : ?a = ?b → ?b = ?a
Eq.trans : ?a = ?b → ?b = ?c → ?a = ?c
Eq.subst : ?a = ?b → ?P ?a → ?P ?b
namespace Backward theorem Eq_trans_symm {α : Type} (a b c : α) (hab : a = b) (hcb : c = b) : a = c := α:Typea:αb:αc:αhab:a = bhcb:c = ba = c α:Typea:αb:αc:αhab:a = bhcb:c = ba = ?bα:Typea:αb:αc:αhab:a = bhcb:c = b?b = cα:Typea:αb:αc:αhab:a = bhcb:c = bα α:Typea:αb:αc:αhab:a = bhcb:c = ba = ?b All goals completed! 🐙 α:Typea:αb:αc:αhab:a = bhcb:c = bb = c α:Typea:αb:αc:αhab:a = bhcb:c = bc = b All goals completed! 🐙 end Backward

The tactic ac_rfl extends rfl with associativity and commutativity for the operators registered as associative and commutative, and §4.6 registers our add among them.

4.4.1. Examples🔗

The examples below name the conversion that each rfl performs, then reason with the equality rules. The definition of double supports the δ-conversion.

namespace Backward def double (n : ) : := n + n end Backward

Example 1. α-conversion renames the bound variable.

namespace Backward theorem α_example {α β : Type} (f : α β) : (fun x => f x) = (fun y => f y) := α:Typeβ:Typef:α β(fun x => f x) = fun y => f y All goals completed! 🐙 end Backward

Example 2. β-conversion applies an anonymous function to its argument.

namespace Backward theorem β_example {α β : Type} (f : α β) (a : α) : (fun x => f x) a = f a := α:Typeβ:Typef:α βa:α(fun x => f x) a = f a All goals completed! 🐙 end Backward

Example 3. δ-conversion unfolds the definition of double.

namespace Backward theorem δ_example : double 5 = 5 + 5 := double 5 = 5 + 5 All goals completed! 🐙 end Backward

Example 4. ζ-conversion substitutes the locally scoped let.

namespace Backward theorem ζ_example : (let n : := 2 n + n) = 4 := (let n := 2; n + n) = 4 All goals completed! 🐙 end Backward

Example 5. η-conversion identifies fun x => f x with f itself.

namespace Backward theorem η_example {α β : Type} (f : α β) : (fun x => f x) = f := α:Typeβ:Typef:α β(fun x => f x) = f All goals completed! 🐙 end Backward

Example 6. ι-conversion projects a component out of a constructor application.

namespace Backward theorem ι_example {α β : Type} (a : α) (b : β) : Prod.fst (a, b) = a := α:Typeβ:Typea:αb:β(a, b).1 = a All goals completed! 🐙 end Backward

Example 7. rfl proves add m 0 = m and not add 0 m = m, since add recurses on its second argument, as the third worked example of Lecture 3 showed. The second statement waits for §4.6.

example (m : ) : add m 0 = m := m:add m 0 = m All goals completed! 🐙 declaration uses `sorry`example (m : ) : add 0 m = m := m:add 0 m = m All goals completed! 🐙

Example 8. ac_rfl proves an equation up to associativity and commutativity of +.

example (a b c : ) : a + b + c = c + b + a := a:b:c:a + b + c = c + b + a All goals completed! 🐙

Example 9. The same shape holds for *, which is also registered as associative and commutative.

example (a b c : ) : a * b * c = c * b * a := a:b:c:a * b * c = c * b * a All goals completed! 🐙

Example 10. apply Eq.subst replaces equals for equals under an arbitrary predicate, which unification recovers.

example (α : Type) (P : α Prop) (a b : α) (hab : a = b) (hPa : P a) : P b := α:TypeP:α Propa:αb:αhab:a = bhPa:P aP b α:TypeP:α Propa:αb:αhab:a = bhPa:P aP a All goals completed! 🐙