API documentation: ericeallen.github.io/lambda-s,
generated by doc-gen4 on every push to main.
Λs is a typed lambda calculus in which conversion between units of the same dimension is a primitive, and the price of admitting it is characterized exactly. This repository is the full mechanization: statics, dynamics, denotational semantics, two abstraction theorems, adequacy, erasure, and the Pi theorem of dimensional analysis, in Lean 4.
The theoretical literature on units, beginning with Kennedy, obtains parametricity theorems for calculi in which no operation can observe a unit. The practical literature provides conversion, which is what programmers ask of units, and no invariance theory, because conversion breaks the parametricity such theories rest on. Λs has both. Every parametric term is invariant under the rescalings that respect dimension, and a first-order program with nonzero denotation is invariant under all rescalings precisely when its accumulated conversion ratio is trivial: a decidable condition, which the development turns into a compiler diagnostic.
The development is 9,400 lines of definitions and proofs and 5,900 lines
of documentation (17,700 lines of source in all; scripts/count_lines.py
is the method, and CI checks these figures and the table below against it), and stays that small
because of one representational decision: units and dimensions are exponent
vectors over ℚ, so substitution is a linear map, every substitution lemma is
a reordering of finite sums, and no normalization pass over unit syntax
exists anywhere in the system.
| Lean | 4.33.0 (pinned in lean-toolchain) |
| mathlib | pinned in lake-manifest.json |
sorry / admit |
none |
| lines of definitions and proofs | 9,400 |
| lines of documentation | 5,900 |
| theorem and lemma declarations | 484 |
| axioms | propext, Classical.choice, Quot.sound |
Examples.lean, QM.lean, and Algorithms.lean run the checker, the
drift analysis, and the evaluator at build time through #guard; if a
stated result were different, the library would not compile. The two
demonstrations whose arithmetic reaches the BLAS stubs (the particle in a
box and the two-state system, both in QM.lean) cannot run at build time,
so the compiled binary checks them instead, and CI asserts its output.
Prerequisites: elan (which installs the pinned Lean toolchain on first use) and a C compiler.
lake exe cache get # fetch prebuilt mathlib oleans (multi-GB, needs network)
lake build # build the library and check every proof
lake exe lambdas # print the worked reports with their numeric self-checkslake exe cache get is the slow step; with the cache in place, a full
build of this library takes a few minutes on a laptop. The BLAS shim in
c/ links against Accelerate's cblas on macOS (through the Command Line
Tools SDK's libblas, since Lean's bundled linker has no framework search
path; if your Mac has only Xcode, adjust moreLinkArgs in lakefile.lean)
and falls back to portable C loops elsewhere; no separate BLAS installation
is required, and the binary reports which backend it is running.
The algebra. Uom defines a unit as a ℚ-valued exponent vector and
proves the group laws. Scaling gives rescalings and the pullback laws that
make substitution commute with them. Unify verifies elimination and
solution preservation for rational unit equations. It has no assembled unifier
or principal-type inference theorem; inference with conversion's dimension
constraints remains open in this development.
Space, Map, and Density give dimensioned vectors, Hart-style
rank-one matrices, and densities.
Statics. Syntax gives types and terms, scope-indexed so ill-scoped
syntax is unrepresentable. Typing gives both the declarative judgment
HasTy and the checker, and the checker returns derivations: soundness
holds by construction, and completeness and decidability are proved.
Notation makes programs readable.
Dynamics. Dynamics is a definitional interpreter instrumented with
units. Soundness is type soundness, and Normalization is strong
normalization by Tait reducibility on type skeletons, so the fuel a
definitional interpreter carries is produced by a theorem rather than
assumed.
Semantics. Parametricity builds the logical relation, Fundamental
proves both abstraction theorems and that coherence is the exact price of
conversion. Adequacy joins the declaration oracle to the evaluator, and
Erasure strips units and every dynamic check from run-time values without
moving the numbers.
Conversion. Conversion gives the operator, Declare the consistency
criterion for declaration sets, proved in both directions in exact rational
arithmetic, Ratio the
first-order syntax of accumulated ratios, and Twist the drift analysis and
its decision procedure.
Dimensional analysis. Pi and PiTheorem derive Buckingham factorization
and descent to n - rank A rational dimensionless coordinates. The factorization
allows arbitrary signed outputs on positive inputs. PiCoherent supplies the
dimension-level law for converting programs in closed external unit/dimension
scope, including internal polymorphism. The stronger unit-level law applies to
parametric convert-free or drift-free programs. Definability and NonDefinability prove
that rational powers must be primitive.
Programs. Examples, QM, and Algorithms are the worked examples,
including the yard/foot/meter declarations end to end and the pendulum.
Each module carries a header docstring explaining what it is for and why it exists; those are the intended entry points for a reader, and the groups above are the intended reading order.
THEOREMS.md maps every artifact identifier the accompanying paper cites
to its Lean name, file, and line. Line numbers are re-derived from the
sources by scripts/verify_theorems_index.py (CI fails on drift;
--fix repairs the index in place). scripts/count_lines.py is the
method behind the size figures above (--check fails CI when the status
table stops matching the sources; --fix rewrites it).
lake env lean scripts/Audit.leanprints the axiom dependencies of every declaration THEOREMS.md indexes
(scripts/verify_theorems_index.py fails if any indexed declaration is
missing from the audit). CI builds the library, greps the sources for
sorry, fails if any audited theorem depends on more than the three
standard axioms, and runs the compiled binary, asserting its numeric
self-checks and the declared-conversion report.
A reader who believes a theorem trusts the Lean kernel and the three
axioms above. A reader who believes a number the binary prints trusts, in
addition, Lean's compiler and runtime, the Float carrier, and the three C
functions in c/lambdas_blas.c (lambdas_ddot, lambdas_dgemv,
lambdas_blas_backend) that reach BLAS. The abstraction and adequacy theorems use real
arithmetic and do not equate it with compiled floating-point arithmetic.
Rounding affects defined operations. The carriers also totalize partial
operations differently: for example, Float.pow returns NaN on negative
bases with non-integer exponents, while Real.rpow uses the real part of
the principal complex power. Concrete #guard checks execute through Lean's
compiler; they are distinct from kernel-checked theorem proofs. The binary
checks selected arithmetic and boundary cases, not a general correspondence.
Apache-2.0; see LICENSE.