1. Using Lean¶
1.1. Using Lean Online¶
You can run a Javascript version of Lean online in your browser. It is much slower than running a version of Lean installed on your computer, but it provides a convenient way to experiment with the system.
The online version of Lean checks your input continuously. Error messages, warnings, and output appear in the window on the right-hand side. The editor shares a number of features with Visual Studio Code; for example, you can type unicode characters with a backslash, so \and
yields the unicode symbol for conjunction, and \a
, \b
, and \g
yield the unicode α
, β
, and γ
respectively.
1.2. Using Lean with VSCode¶
Assuming you have installed Lean and Visual Studio Code, you can add the Lean extension to VSCode by clicking the extension icon in the view bar at left and searching for lean
. Once you have installed the extension, clicking on lean
in the extensions panel provides additional information.
With the extension installed, if you create a file with the extension .lean
and edit it, Lean will check the file continuously as you type. For example, if you type the words #check id
, the word #check
is underlined in green to indicate a response from the Lean server. Hovering over the word #check
displays the response, in this case, the type of the identity function.
1.2.1. Features¶
VSCode Intellisense suggests completions as you type. These are context sensitive: if you are typing an identifier, it suggests suitable completions for identifiers, after import
, it suggests modules to import, after set_option
, it suggests suitable options, and so on.
You can enter Unicode characters with a backslash. For example, \a
inserts an α
. You can see the commands provided by the Lean extension by typing ctrl-shift-P
on Windows/Linux or cmd-shift-P
on a Mac, and then typing lean
into the search bar to filter the list. Typing ctrl-shift-enter
opens up a message window which shows you error messages, warnings, output, and goal information when in tactic mode.
Typing an underscore in an expression asks Lean to infer a suitable value for the expression and fill it in automatically. In cases where Lean is unable to determine a value for the argument, the underscore is highlighted, and the error message indicates the type of the “hole” that needs to be filled. This can be extremely useful when constructing proofs incrementally. You can start typing a proof sketch, using either sorry
or an underscore for details you intend to fill in later. Assuming the proof is correct modulo these missing pieces of information, the error message at an unfilled underscore tells you the type of the term you need to construct, typically an assertion you need to justify.
1.2.2. Multi-file Projects¶
If you want to work on a project with multiple files, use the package_manager to set up a project folder, and then use Open Folder
in the VSCode File
menu to open the root directory for the project.
1.3. Using Lean with Emacs¶
Assuming you have installed Lean, Emacs, and the Lean Emacs mode according to the instructions on the Lean Download page, you simply need to create a file with the extension .lean
and edit it in Emacs. The file will be checked continuously as you type. For example, if you type the words #check id
, the word #check
is underlined in green to indicate a response from the Lean server. Hovering over the word #check
displays the response, in this case, the type of the identity function.
1.3.1. Features¶
Lean mode uses an Emacs package named Flycheck, as evidenced by the letters FlyC
that appear in the information line. Flycheck offers a number of commands that begin with C-c !
. For example, C-c ! n
moves the cursor to the next error, and C-c ! p
moves the cursor to the previous error. You can get to a help menu that lists these key bindings by clicking on the FlyC
tag.
It is often inconvenient to have to put the cursor on a highlighted identifier to see an error message or the outcome of a #print
or #check
command. The keystrokes C-c C-n
toggle Lean-Next-Error
mode, in which the next message (or all the messages that occur on the line that the cursor is on, if there are any) appears in a buffer named lean-info
. You can position this window anywhere you want using Emacs commands for splitting windows and loading buffers. Pressing C-c C-n
again toggles the mode off.
As with VSCode, the Emacs mode provides context-sensitive tab completion. Typing an underscore in an expression asks Lean to infer a suitable value for the expression and fill it in automatically. As described in the previous section, this provides a convenient way to construct terms and proof interactively.
If you put your cursor on an identifier and hit M-.
, Emacs will take you to the identifier’s definition, whether it is in the same file, in another file in your project , or in the library. This works even in an autocompletion popup window: if you start typing an identifier, press the tab key, choose a completion from the list of options, and press M-.
, you are taken to the symbol’s definition. If you have Emacs 25 or later, you can then press M-,
to go back to the original location.
In tactic mode, if you put your cursor on a tactic (or the keyword begin
or end
) and type C-c C-g
, Emacs will show you the goal in the lean-info
buffer. Here is another useful trick: if you see some notation in a Lean file and you want to know how to enter it from the keyboard, put the cursor on the symbol and type C-c C-k
.
If for some reason the Lean background process does not seem to be responding (for example, the information line no longer shows you type information), type C-c C-r
or M-x lean-server-restart-process
, or choose “restart lean process” from the Lean menu, and with luck that will set things right again.
In Lean, the #exit
command halts processing of a file abruptly. Inserting an #exit
therefore prevents Lean from checking the file beyond that point.
Some of the main key bindings are summarized in the table below.
Key | Function |
M-. |
jump to definition in source file (lean-find-definition ) |
M-, |
return to original position (requires Emacs 25) |
TAB |
tab complete identifier, option, filename, etc. (lean-tab-indent-or-complete ) |
C-c C-k |
shows the keystroke needed to input the symbol under the cursor |
C-c C-g |
show goal in tactic proof (lean-show-goal-at-pos ) |
C-c C-x |
execute lean in stand-alone mode (lean-std-exe ) |
C-c C-n |
toggle next-error-mode: shows next error in dedicated lean-info buffer |
C-c C-r |
restart the lean server |
C-c ! n |
flycheck: go to next error |
C-c ! p |
flycheck: go to previous error |
C-c ! l |
flycheck: show list of errors |
1.3.2. Multi-file Projects¶
If you want to work on a project with multiple files, use the package_manager to set up a project folder, and use Open Folder
in the VSCode File
menu to open the root directory for the project.
1.4. Using the Package Manager¶
leanpkg
is the package manager for the Lean theorem prover. It downloads dependencies and manages what modules you can import in your Lean files.
This section explains the general concepts of leanpkg
. For more information on a specific leanpkg
command, execute leanpkg help <command>
as a command line.
1.4.1. Directory Layout¶
A Lean package is a directory containing the following items:
src
: a directory in which the package’s Lean files are stored. Imports from other packages are resolved relative to this directory.leanpkg.toml
: a manifest describing the package name, version, and dependencies. Dependencies can be either local paths or git URLs. Git dependencies are pinned to a specific commit and can be upgraded with leanpkg upgrade.leanpkg.path
and_target/deps
: these items are created byleanpkg configure
and should not be added to git. They contain the paths to the dependencies on the current machine, and their git checkouts, respectively.
1.4.2. Using Lean in a Lean package¶
- Running the
lean
command-line tool from a directory inside your package will automatically use theleanpkg.path
file for import resolution. - In Emacs,
lean-mode
will automatically start a new Lean server process for each visited package. - In VSCode, open the package as a folder.
1.4.3. Creating new packages¶
The leanpkg new
command creates a new package. You can use leanpkg add
to add dependencies (or add them manually if you prefer):
leanpkg new my_awesome_pkg
cd my_awesome_pkg
leanpkg add leanprover/mathlib
# shorthand for `leanpkg add https://github.com/leanprover/mathlib`
You can now add new .lean
files inside the src
directory.
1.4.4. Scratch files¶
It is reasonably common to have thousands of “scratch” files lying around that are not part of a package. Files that are not inside a package themselves can still use dependencies fetched via leanpkg
. These dependencies are stored in ~/.lean/leanpkg.toml
and can be modified with leanpkg install
:
leanpkg install https://github.com/leanprover/smt2_interface
After this, you can use the smt2_interface
package in all files that do not belong to a package themselves.
For experimenting inside a Lean package, you can use a directory separate from src
, say scratch
. Files in this folder will still be able to import the package’s Lean modules, but will not interfere with leanpkg build
etc.
1.4.5. Import resolution¶
Lean supports two kinds of imports:
import theory.set_theory -- absolute
import .basic -- relative
Relative imports are always relative to the current file name.
Absolute imports are resolved according to the entries in the leanpkg.path
file. That is, when executing import theory.set_theory
, Lean looks for a file called theory/set_theory.lean
in the src directories of all (transitive) dependencies as well as the current package.
1.4.6. Format of leanpkg.toml¶
[package]
name = "my_awesome_pkg"
version = "0.1" # no semantic significance currently
lean_version = "3.3.0" # optional, prints a warning on mismatch with Lean executable
path = "src" # hard-coded, will be removed in the future
timeout = 100 # optional, passed to `lean` as `-T` parameter
[dependencies]
# local dependency
demopkg = { path = "relative/path/to/demopkg" }
# git dependency
mathlib =
{ git = "https://github.com/leanprover/mathlib",
rev = "62f7883d937861b618ae8bd645ee16ec137dd0bd" }