I had the pleasure of learning about Lean 4 with David Christiansen and Joachim Breitner at their tutorial at BOBKonf 2024. I‘m planning on doing a couple of formalizations with Lean and would love to share what I learn as a total newbie, working on macOS.
I‘m on macOS and use Homebrew extensively. My simple go-to approach to finding new software is to do brew search lean. This revealed lean as well as surface elan. Running brew info lean showed me that that package (at the time I write this) installs Lean 3. But I know, out-of-band, that Lean 4 is what I want to work with. Running brew info elan looked better, but the output reminds me that (1) the information is for the elan-init package, not the elan cask, and (2) elan-init conflicts with both the elan and the aforementioned lean. Yikes! This strikes me as a potential problem for the community, because I think Lean 3, though it still works, is presumably not where new Lean development should be taking place. Perhaps the Homebrew formula for Lean should be updated called lean3
, and a new lean4
package should be made available. I‘m not sure. The situation seems less than ideal, but in short, I have been successful with the elan-init package.
After installing elan-init, you‘ll have the elan tool available in your shell. elan is the tool used for maintaining different versions of Lean, similar to nvm in the Node.js world or pyenv.
When I did the Lean 4 tutorial at BOB, I worked entirely within VS Code and created a new standalone package using some in-editor functionality. At the command line, I use lake init to manually create a new Lean package. At first, I made the mistake of running this command, assuming it would create a new directory for me and set up any configuration and boilerplate code there. I was surprised to find, instead, that lake init sets things up in the current directory, in addition to creating a subdirectory and populating it. Using lake --help, I read about the lake new command, which does what I had in mind. So I might suggest using lake new rather than lake init.
What‘s in the new directory? Doing tree foobar reveals
1 2 3 4 5 6 7 | foobar ├── Foobar │ └── Basic.lean ├── Foobar.lean ├── Main.lean ├── lakefile.lean └── lean-toolchain |
Taking a look there, I see four .lean files. Here‘s what they contain:
Main.lean
1 2 3 4 | import «Foobar» def main : IO Unit := IO.println s!"Hello, {hello}!" |
Foobar.lean
1 2 3 | -- This module serves as the root of the `Foobar` library. -- Import modules here that should be built as part of the library. import «Foobar».Basic |
Foobar/Basic.lean
1 | def hello := "world" |
lakefile.lean
1 2 3 4 5 6 7 8 9 10 11 12 | import Lake open Lake DSL package «foobar» where -- add package configuration options here lean_lib «Foobar» where -- add library configuration options here @[default_target] lean_exe «foobar» where root := `Main |
It looks like there‘s a little module structure here, and a reference to the identifier hello, defined in Foobar/Basic.lean and made available via Foobar.lean. I’m not going to touch lakefile.lean for now; as a newbie, it looks scary enough that I think I’ll just stick to things like Basic.lean.
There‘s also an automatically created .git there, not shown in the directory output above.
Now that you‘ve got Lean 4 installed and set up a package, you‘re ready to dive in to one of the official tutorials. The one I‘m working through is David‘s Functional Programming in Lean. There‘s all sorts of additional things to learn, such as all the different lake commands. Enjoy!