Formal Software Verification

1.6. The Syntax of Lean🔗

The sections that follow read and write Lean, so this one fixes the notation. It explains how a declaration is spelled, not what makes a proof correct, which is the subject of the sections after it.

A declaration names a statement and gives its proof. The keyword comes first, then the name, then the hypotheses in parentheses, then the statement after the colon, then the proof after :=.

theorem and_swap (P Q : Prop) (h : P Q) : Q P := h.right, h.left

Here theorem names the result and_swap. The binders (P Q : Prop) and (h : P ∧ Q) introduce two propositions and one hypothesis. The statement to prove is Q ∧ P, and the proof is the term after :=. The keyword example replaces theorem when the result needs no name.

Table 1.6.1 lists the pieces of syntax that the following sections use.

Written

Read as

example (h : P) : Q := e

anonymous statement with hypothesis h, proved by e

fun h => e

the function that takes h to e

f a

f applied to a, written without parentheses

⟨a, b⟩

the anonymous constructor, here a pair

h.left, h.right

the two components of a conjunction

by

enter tactic mode, one tactic per line

·

focus the next goal inside a tactic block

sorry

placeholder for a missing proof

-- text

comment to the end of the line

Table 1.6.1. The syntax of declarations, terms and tactic blocks.

The logical symbols are unicode, and Table 1.6.2 gives the abbreviation that types each one. Typing the backslash abbreviation and then space or tab inserts the character in VS Code.

Symbol

Meaning

Typed as

implication

\to

conjunction

\and

disjunction

\or

¬

negation

\not

biconditional

\iff

absurdity

\bot

⟨ ⟩

anonymous constructor

\langle, \rangle

·

goal focus

\.

Table 1.6.2. The logical symbols and the abbreviations that type them.

The same statement can be proved by a term or in tactic mode, and the two produce the same underlying proof. The sections that follow use both.

example (P Q : Prop) (h : P Q) : Q P := h.right, h.left example (P Q : Prop) (h : P Q) : Q P := P:PropQ:Proph:P QQ P All goals completed! 🐙

The commands that inspect a declaration begin with #. The command #check prints the type of a term, which for a proof is the proposition it proves.

fun P Q h => h.right, h.left : (P Q : Prop), P Q Q P#check fun (P Q : Prop) (h : P Q) => (h.right, h.left : Q P)
fun P Q h => h.right, h.left :  (P Q : Prop), P  Q  Q  P