···11# Glean
2233-Verify Gleam functions in Lean 4. `glean` translates the functions you mark with
33+Verify [Gleam](https://gleam.run) functions in [Lean 4](https://lean-lang.org/).
44+55+`glean` translates the functions you mark with
46a `/// @proof` doc comment into Lean 4 definitions (via
57[hax](https://github.com/cryspen/hax)), so you can prove properties about them.
6879Requires [Nix](https://nixos.org) with flakes. The engine is currently bundled.
81099-## Setup
1111+## Nix Setup
10121113Add glean to your project's `flake.nix` so `glean` is on your `PATH`:
1214···5658## 3. Extract
57595860```sh
5959-glean prove src/fibonacci.gleam
6161+glean prove
6062```
61636262-This writes two files under `proofs/lean/Proofs/`:
6464+With no argument, `glean prove` extracts every `@proof`-marked module under your
6565+project's `src/`. Under `proofs/lean/Proofs/` it writes, per module:
63666467- `fibonacci.lean`: the generated Lean definitions. **Do not edit**; glean
6568 regenerates it each run. Gleam `Int` is modeled as Lean's arbitrary-precision
6669 `Int` (as `gleam.Int`), so proofs reason about true integers, not fixed-width
6767- ones. glean injects a small prelude mapping the Gleam operators onto it. For the
6868- `fib` above it contains:
7070+ ones. The file imports the shared model library (below); for the `fib` above it
7171+ is:
69727073 ```lean
7174 import Hax
7272- -- (opens and set_options elided)
7373-7474- namespace gleam
7575- abbrev Int := _root_.Int
7676- end gleam
7777-7878- namespace gleam.int
7979- def add (a : gleam.Int) (b : gleam.Int) : RustM gleam.Int := pure (a + b)
8080- def sub (a : gleam.Int) (b : gleam.Int) : RustM gleam.Int := pure (a - b)
8181- -- (mul, div, comparisons, … elided)
8282- end gleam.int
7575+ import Proofs.GleamModels
7676+ -- (Std.Do imports, opens, and set_options elided)
83778478 namespace fibonacci
8579···9589 partial_fixpoint
96909791 end fibonacci
9292+ ```
9393+9494+- `GleamModels.lean`: a shared library, regenerated each run and imported by every
9595+ generated module, mapping Gleam types and operators onto Lean. It defines
9696+ `gleam.Int` and the arithmetic the code above calls:
9797+9898+ ```lean
9999+ namespace gleam
100100+ abbrev Int := _root_.Int
101101+ end gleam
102102+103103+ namespace gleam.int
104104+ def add (a : gleam.Int) (b : gleam.Int) : RustM gleam.Int := pure (a + b)
105105+ def sub (a : gleam.Int) (b : gleam.Int) : RustM gleam.Int := pure (a - b)
106106+ -- (mul, div, comparisons, … elided)
107107+ end gleam.int
98108 ```
99109100110- `fibonacciProofs.lean`: a stub for **your** theorems. glean creates it once and