<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=Lean_theorem_prover%2FExplainers%2FPrograms_and_proofs_in_one_language</id>
	<title>Lean theorem prover/Explainers/Programs and proofs in one language - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=Lean_theorem_prover%2FExplainers%2FPrograms_and_proofs_in_one_language"/>
	<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=Lean_theorem_prover/Explainers/Programs_and_proofs_in_one_language&amp;action=history"/>
	<updated>2026-10-21T08:15:52Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://invarians.org/index.php?title=Lean_theorem_prover/Explainers/Programs_and_proofs_in_one_language&amp;diff=6771&amp;oldid=prev</id>
		<title>PMA Publisher: Published from the Principia Machina source</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=Lean_theorem_prover/Explainers/Programs_and_proofs_in_one_language&amp;diff=6771&amp;oldid=prev"/>
		<updated>2026-10-15T19:34:42Z</updated>

		<summary type="html">&lt;p&gt;Published from the Principia Machina source&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 19:34, 15 October 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{DISPLAYTITLE:Programs and proofs in one language}}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{DISPLAYTITLE:Programs and proofs in one language}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Technical|Lean theorem prover/System/The compiler and runtime|Lean theorem prover/System/Monads and do-notation|Lean theorem prover/System/Syntax extension and hygienic macros}}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Technical|Lean theorem prover/System/The compiler and runtime|Lean theorem prover/System/Monads and do-notation|Lean theorem prover/System/Syntax extension and hygienic macros}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;{{Lean theorem prover map}}&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Lean is a programming language as well as a proof checker. A definition written in Lean can be run&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Lean is a programming language as well as a proof checker. A definition written in Lean can be run&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>PMA Publisher</name></author>
	</entry>
	<entry>
		<id>https://invarians.org/index.php?title=Lean_theorem_prover/Explainers/Programs_and_proofs_in_one_language&amp;diff=6564&amp;oldid=prev</id>
		<title>PMA Publisher: Published from the Principia Machina source</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=Lean_theorem_prover/Explainers/Programs_and_proofs_in_one_language&amp;diff=6564&amp;oldid=prev"/>
		<updated>2026-10-14T18:00:55Z</updated>

		<summary type="html">&lt;p&gt;Published from the Principia Machina source&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{DISPLAYTITLE:Programs and proofs in one language}}&lt;br /&gt;
{{Technical|Lean theorem prover/System/The compiler and runtime|Lean theorem prover/System/Monads and do-notation|Lean theorem prover/System/Syntax extension and hygienic macros}}&lt;br /&gt;
&lt;br /&gt;
Lean is a programming language as well as a proof checker. A definition written in Lean can be run&lt;br /&gt;
as a program and reasoned about in a theorem, and it is written once for both. This page shows&lt;br /&gt;
that, says how Lean turns definitions into programs, marks the places where running and proving&lt;br /&gt;
part company, and says how the project this wiki records relies on the property.&lt;br /&gt;
&lt;br /&gt;
== One definition, two uses ==&lt;br /&gt;
&lt;br /&gt;
Here is a definition of the sum of the numbers from 1 to &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt;, a command that runs it,&lt;br /&gt;
and a theorem about it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean&amp;quot; style=&amp;quot;background: #f8f9fa; border: 1px solid #c8ccd1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
def sumTo : Nat → Nat&lt;br /&gt;
  | 0 =&amp;gt; 0&lt;br /&gt;
  | n + 1 =&amp;gt; sumTo n + (n + 1)&lt;br /&gt;
&lt;br /&gt;
#eval sumTo 100&lt;br /&gt;
&lt;br /&gt;
theorem sumTo_formula (n : Nat) : 2 * sumTo n = n * (n + 1) := by&lt;br /&gt;
  induction n with&lt;br /&gt;
  | zero =&amp;gt; rfl&lt;br /&gt;
  | succ k ih =&amp;gt; grind [sumTo]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lean 4.34.1 prints &amp;lt;code&amp;gt;5050&amp;lt;/code&amp;gt; and accepts the theorem. The two uses answer different&lt;br /&gt;
questions. Running the definition gives the answer for one number at a time; however many numbers&lt;br /&gt;
are tried, some remain untried. The theorem covers every natural number at once, by induction&lt;br /&gt;
(see [[Lean theorem prover/Explainers/Induction, as the machine sees it|induction, as the machine sees it]]).&lt;br /&gt;
Because both rest on the same definition, there is no second copy that could drift from the first:&lt;br /&gt;
the program that is run is the object the theorem is about.&lt;br /&gt;
&lt;br /&gt;
== From definition to program ==&lt;br /&gt;
&lt;br /&gt;
Lean runs definitions in one of two ways. An interpreter can run them directly. Or Lean can&lt;br /&gt;
compile them: Lean&amp;#039;s compiler translates them into C,&lt;br /&gt;
one C file for each Lean source file, and a C compiler that ships with Lean turns that into native&lt;br /&gt;
code for the machine.&amp;lt;ref name=&amp;quot;refelab&amp;quot;&amp;gt;&amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version for Lean 4.34.0, section &amp;quot;Elaboration and Compilation&amp;quot;. [https://lean-lang.org/doc/reference/4.34.0/Elaboration-and-Compilation/ lean-lang.org/doc/reference/4.34.0/Elaboration-and-Compilation], consulted 14 October 2026.&amp;lt;/ref&amp;gt;&lt;br /&gt;
The paper that introduced Lean 4 describes it as an efficient functional programming language, and&lt;br /&gt;
names one reason efficiency matters: people write their own proof automation in Lean, and that&lt;br /&gt;
automation has to be fast.&amp;lt;ref name=&amp;quot;lean4&amp;quot;&amp;gt;Leonardo de Moura and Sebastian Ullrich, &amp;quot;The Lean 4 Theorem Prover and Programming Language (System Description)&amp;quot;, in &amp;#039;&amp;#039;Automated Deduction – CADE 28&amp;#039;&amp;#039;, Lecture Notes in Computer Science, Springer, 2021, pp. 625–635. [https://doi.org/10.1007/978-3-030-79876-5_37 doi:10.1007/978-3-030-79876-5_37]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lean 4 is itself largely a Lean program. The same paper describes it as a reimplementation of the&lt;br /&gt;
Lean theorem prover in Lean, in which users can extend the parser, the elaborator, the tactics and&lt;br /&gt;
the code generator from Lean.&amp;lt;ref name=&amp;quot;lean4&amp;quot; /&amp;gt; The Lean kernel is the exception: it is written&lt;br /&gt;
in C++.&amp;lt;ref name=&amp;quot;refelab&amp;quot; /&amp;gt; So the tools that help a person write proofs are Lean programs,&lt;br /&gt;
while the part that judges them is kept separate (see&lt;br /&gt;
[[Lean theorem prover/Explainers/The small trusted core|the small trusted core]]).&lt;br /&gt;
&lt;br /&gt;
There is a free book on using Lean as a programming language, &amp;#039;&amp;#039;Functional Programming in Lean&amp;#039;&amp;#039;;&lt;br /&gt;
the code in its current edition was tested with Lean 4.33.0.&amp;lt;ref name=&amp;quot;fpil&amp;quot;&amp;gt;David Thrane Christiansen, &amp;#039;&amp;#039;Functional Programming in Lean&amp;#039;&amp;#039;. [https://lean-lang.org/functional_programming_in_lean/ lean-lang.org/functional_programming_in_lean], consulted 14 October 2026.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programs that act on the world ==&lt;br /&gt;
&lt;br /&gt;
A program has to read input and print output. A proof does neither. Lean keeps the two apart by&lt;br /&gt;
type: an action such as printing a line has a type of its own, &amp;lt;code&amp;gt;IO&amp;lt;/code&amp;gt;, and a sequence of&lt;br /&gt;
actions is written in a block that begins with &amp;lt;code&amp;gt;do&amp;lt;/code&amp;gt; (see&lt;br /&gt;
[[Lean theorem prover/System/Monads and do-notation|monads and do-notation]]). Continuing the&lt;br /&gt;
same file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean lean-cont&amp;quot; style=&amp;quot;background: #f8f9fa; border: 1px solid #c8ccd1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
def main : IO Unit := do&lt;br /&gt;
  for n in [10, 100, 1000] do&lt;br /&gt;
    IO.println s!&amp;quot;the sum up to {n} is {sumTo n}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#eval main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lean prints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean-output&amp;quot; style=&amp;quot;background: #ffffff; border: 1px dashed #a2a9b1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
the sum up to 10 is 55&lt;br /&gt;
the sum up to 100 is 5050&lt;br /&gt;
the sum up to 1000 is 500500&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The action &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; uses &amp;lt;code&amp;gt;sumTo&amp;lt;/code&amp;gt;, and the theorem above is about that same&lt;br /&gt;
function; to believe it of the values printed is also to trust the compiler that turned&lt;br /&gt;
&amp;lt;code&amp;gt;sumTo&amp;lt;/code&amp;gt; into a program.&amp;lt;ref name=&amp;quot;tcl4&amp;quot;&amp;gt;&amp;#039;&amp;#039;Type Checking in Lean 4&amp;#039;&amp;#039;, online book, chapter &amp;quot;Trust&amp;quot;. [https://ammkrn.github.io/type_checking_in_lean4/trust/trust.html ammkrn.github.io/type_checking_in_lean4], consulted 14 October 2026.&amp;lt;/ref&amp;gt;&lt;br /&gt;
The part that talks to the world is thin; the part that computes is the part that is proved.&lt;br /&gt;
&lt;br /&gt;
== Where running and proving part ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Programs that may never stop.&amp;#039;&amp;#039;&amp;#039; Lean&amp;#039;s logic needs every function to give an answer, so a&lt;br /&gt;
definition that calls itself has to be shown to finish (see&lt;br /&gt;
[[Lean theorem prover/Explainers/Functions that always finish|functions that always finish]]).&lt;br /&gt;
A program does not always come with such a proof. Here is one for which nobody has one: starting&lt;br /&gt;
from a number, halve it if it is even, otherwise triple it and add one, and count the steps until&lt;br /&gt;
it reaches 1. Whether this ends for every starting number is a famous open question, the Collatz&lt;br /&gt;
problem. Lean accepts the program if it is marked &amp;lt;code&amp;gt;partial&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean lean-cont&amp;quot; style=&amp;quot;background: #f8f9fa; border: 1px solid #c8ccd1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
partial def collatz (n : Nat) (steps : Nat := 0) : Nat :=&lt;br /&gt;
  if n ≤ 1 then steps&lt;br /&gt;
  else if n % 2 == 0 then collatz (n / 2) (steps + 1)&lt;br /&gt;
  else collatz (3 * n + 1) (steps + 1)&lt;br /&gt;
&lt;br /&gt;
#eval collatz 27&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It runs, and prints &amp;lt;code&amp;gt;111&amp;lt;/code&amp;gt;. But the program says nothing to the logic. Lean&amp;#039;s reference&lt;br /&gt;
states that the Lean kernel treats a function marked &amp;lt;code&amp;gt;partial&amp;lt;/code&amp;gt; as an opaque constant,&lt;br /&gt;
which it neither unfolds nor computes with; all that soundness requires is that its result type&lt;br /&gt;
has at least one value.&amp;lt;ref name=&amp;quot;recdefs&amp;quot;&amp;gt;&amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version for Lean 4.34.0, section &amp;quot;Recursive Definitions&amp;quot;. [https://lean-lang.org/doc/reference/4.34.0/Definitions/Recursive-Definitions/ lean-lang.org/doc/reference/4.34.0/Definitions/Recursive-Definitions], consulted 14 October 2026.&amp;lt;/ref&amp;gt;&lt;br /&gt;
Even the plainest fact about it cannot be proved by looking inside:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean lean-cont lean-fails&amp;quot; style=&amp;quot;background: #f8f9fa; border: 1px solid #c8ccd1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
example : collatz 1 = 0 := by&lt;br /&gt;
  unfold collatz&lt;br /&gt;
  rfl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lean refuses, with the message &amp;quot;Tactic `unfold` failed to unfold `collatz` in&amp;quot;, followed by the&lt;br /&gt;
goal &amp;lt;code&amp;gt;collatz 1 = 0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Programs run in place of definitions.&amp;#039;&amp;#039;&amp;#039; Lean lets a library say that, when a definition is&lt;br /&gt;
run, another function should be run instead, usually a faster one. The theorems are about the&lt;br /&gt;
definition; the program runs the replacement. If the two disagree, the program and the proofs no&lt;br /&gt;
longer describe the same thing.&amp;lt;ref name=&amp;quot;recdefs&amp;quot; /&amp;gt; [[Lean theorem prover/Explainers/What has to be trusted|What has to be trusted]]&lt;br /&gt;
shows this happening, and what it costs when a proof relies on the compiled program.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;New notation.&amp;#039;&amp;#039;&amp;#039; Lean&amp;#039;s syntax can be extended from Lean, through a system of macros designed so&lt;br /&gt;
that names introduced by a macro cannot collide with names in the surrounding text.&amp;lt;ref name=&amp;quot;lean4&amp;quot; /&amp;gt;&lt;br /&gt;
This serves programmers and mathematicians alike, and it is one more thing a reader has to know&lt;br /&gt;
when reading a statement (see [[Lean theorem prover/Explainers/Stating the right thing|stating the right thing]]).&lt;br /&gt;
&lt;br /&gt;
== The project this wiki records ==&lt;br /&gt;
&lt;br /&gt;
Principia Machina depends on this property. Its earlier version kept its rules in prose and&lt;br /&gt;
computed them in two hand-written copies, one for the wiki&amp;#039;s server and one for the agents that&lt;br /&gt;
do research, held in agreement by a large set of test cases. The new version writes the rules once,&lt;br /&gt;
as Lean definitions and theorems, and compiles the same sources into one program, the Calculator,&lt;br /&gt;
which is to compute every value the specification defines, on the server and beside each agent.&lt;br /&gt;
As of 14 October 2026 a first Calculator exists. A test has shown that a compiled Lean program runs&lt;br /&gt;
on the wiki&amp;#039;s server when started as a command, though not inside a web request, so the server&amp;#039;s gatekeeper, Custos, is to call the Calculator outside the web request.&lt;br /&gt;
These are the project&amp;#039;s own statements, on [[Principia Machina/Lean transition|the move to Lean]];&lt;br /&gt;
[[Lean theorem prover/Applications/Principia Machina|Principia Machina]] describes the project in&lt;br /&gt;
this edition.&lt;br /&gt;
&lt;br /&gt;
== Next ==&lt;br /&gt;
&lt;br /&gt;
[[Lean theorem prover/Explainers/A library of mathematics|A library of mathematics]] describes&lt;br /&gt;
Mathlib and the libraries that come with Lean.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>PMA Publisher</name></author>
	</entry>
</feed>