Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
3.5 KiB
Lean Tutorial
Introduction
Lean is an automatic and interactive theorem prover. It can be used to create specifications, build mathematical libraries, and solve constraints. In this tutorial, we introduce basic concepts, the logic used in Lean, and the main commands.
Getting started
We can use Lean in interactive or batch mode.
The following example just displays the message hello world
.
print "hello world"
All we have to do to run your first example is to call the lean
executable
with the name of the text file that contains the command above.
If you saved the above command in the file hello.lean
, then you just have
to execute
lean hello.lean
As a more complex example, the next example defines a function that doubles the input value, and then evaluates it on different values.
-- defines the double function
definition double (x : Nat) := x + x
eval double 10
eval double 2
eval double 3 > 4
Every expression has a unique type in Lean. The command check
returns the
type of a given expression.
check double 3
check double
The last command returns Nat → Nat
. That is, the type of double is a function
from Nat
to Nat
, where Nat
is the type of the natural numbers.
The command import
loads existing libraries and extensions. For example,
the following command imports the command find
that searches the Lean environment
using regular expressions
import find
find "Nat" -- find all object that start with the prefix Nat
check Nat::ge -- display the signature of the Nat::ge definition
We say Nat::ge
is a hierarchical name comprised of two parts: Nat
and ge
The command using
creates aliases based on give prefix. For example, the following
command creates aliases for all objects starting with Nat
using Nat
check ge -- display the signature of the Nat::ge definition
In Lean, proofs are also expressions, and theorems are essentially definitions.
In the following example we prove that double x = 2 * x
theorem double_x_eq_2x (x : Nat) : double x = 2 * x :=
calc double x = x + x : refl (double x)
... = 1*x + 1*x : { symm (mul_onel x) }
... = (1 + 1)*x : symm (distributel 1 1 x)
... = 2 * x : { refl (1 + 1) }
In the example above, we provided the proof manually using a calculational proof style.
The terms after :
are proof terms. They justify the equalities in the left-hand-side.
The proof term refl (double x)
produces a proof for t = s
where t
and s
have the same
normal form of (double x)
. The proof term { symm (mul_onel x) }
is a justification for
the equality x = 1*x
. The curly braces instruct Lean to replace x
with 1*x
.
Similarly { symm (distributel 1 1 x) }
is a proof for 1*x + 1*x = (1 + 1)*x
.
The exact semantics of these expressions is not important at this point.
Objects
In each Lean session, we create an enviroment, a sequence of named
objects such as: definitions, axioms and theorems. Each object has
a unique name. We use hierarchical names
in Lean, i.e., a sequence
of regular identifiers separated by ::
. Hierarchical names provide
a cheap of simulating modules and namespaces in Lean.
Expressions
Each expression has a unique type in Lean. The command check
returns
the type of an expression.
check 1+2.