<?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%2FTactics</id>
	<title>Lean theorem prover/Explainers/Tactics - 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%2FTactics"/>
	<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=Lean_theorem_prover/Explainers/Tactics&amp;action=history"/>
	<updated>2026-10-21T12:02:42Z</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/Tactics&amp;diff=6762&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/Tactics&amp;diff=6762&amp;oldid=prev"/>
		<updated>2026-10-15T19:34:31Z</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:Tactics}}&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:Tactics}}&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 tactic framework|Lean theorem prover/System/Metaprogramming in Lean}}&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 tactic framework|Lean theorem prover/System/Metaprogramming in Lean}}&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;A proof in Lean can be written in two ways: as a &amp;#039;&amp;#039;&amp;#039;term&amp;#039;&amp;#039;&amp;#039;, an expression whose type is the&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;A proof in Lean can be written in two ways: as a &amp;#039;&amp;#039;&amp;#039;term&amp;#039;&amp;#039;&amp;#039;, an expression whose type is the&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/Tactics&amp;diff=6555&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/Tactics&amp;diff=6555&amp;oldid=prev"/>
		<updated>2026-10-14T18:00:51Z</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:Tactics}}&lt;br /&gt;
{{Technical|Lean theorem prover/System/The tactic framework|Lean theorem prover/System/Metaprogramming in Lean}}&lt;br /&gt;
&lt;br /&gt;
A proof in Lean can be written in two ways: as a &amp;#039;&amp;#039;&amp;#039;term&amp;#039;&amp;#039;&amp;#039;, an expression whose type is the&lt;br /&gt;
statement, or as a sequence of &amp;#039;&amp;#039;&amp;#039;tactics&amp;#039;&amp;#039;&amp;#039;, commands that tell Lean how to construct that&lt;br /&gt;
expression. This page explains what a tactic is, where the idea came from, which tactics are&lt;br /&gt;
met most often, and why no tactic has to be trusted.&lt;br /&gt;
&lt;br /&gt;
== Two ways to write the same proof ==&lt;br /&gt;
&lt;br /&gt;
In Lean a proof is a value, and the statement it proves is its type (see&lt;br /&gt;
[[Lean theorem prover/Explainers/Propositions as types|propositions as types]]). Here is a&lt;br /&gt;
proof that &amp;quot;p and q&amp;quot; gives &amp;quot;q and p&amp;quot;, written both ways:&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;
theorem swap_term (p q : Prop) (h : p ∧ q) : q ∧ p :=&lt;br /&gt;
  ⟨h.2, h.1⟩&lt;br /&gt;
&lt;br /&gt;
theorem swap_tactic (p q : Prop) (h : p ∧ q) : q ∧ p := by&lt;br /&gt;
  constructor&lt;br /&gt;
  · exact h.2&lt;br /&gt;
  · exact h.1&lt;br /&gt;
&lt;br /&gt;
#print swap_term&lt;br /&gt;
#print swap_tactic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first proof is a term. The brackets make a pair, and the pair is the second part of&lt;br /&gt;
&amp;lt;code&amp;gt;h&amp;lt;/code&amp;gt; followed by the first. The second proof begins with &amp;lt;code&amp;gt;by&amp;lt;/code&amp;gt;, which&lt;br /&gt;
switches to tactics. &amp;lt;code&amp;gt;constructor&amp;lt;/code&amp;gt; splits the goal &amp;quot;q and p&amp;quot; into two goals, q and&lt;br /&gt;
p, and each &amp;lt;code&amp;gt;exact&amp;lt;/code&amp;gt; supplies one of them.&lt;br /&gt;
&lt;br /&gt;
The two &amp;lt;code&amp;gt;#print&amp;lt;/code&amp;gt; lines answer with the same proof, word for word:&lt;br /&gt;
&amp;lt;code&amp;gt;fun p q h =&amp;amp;gt; ⟨h.right, h.left⟩&amp;lt;/code&amp;gt;. The tactic script was a way of arriving at the&lt;br /&gt;
term. The term is what Lean keeps. Theorem Proving in Lean 4 calls the two styles&lt;br /&gt;
&amp;quot;term-style&amp;quot; and &amp;quot;tactic-style&amp;quot; proofs.&amp;lt;ref name=&amp;quot;tpil-tac&amp;quot;&amp;gt;Jeremy Avigad, Leonardo de&lt;br /&gt;
Moura, Soonho Kong and Sebastian Ullrich, &amp;#039;&amp;#039;Theorem Proving in Lean 4&amp;#039;&amp;#039; (online edition for&lt;br /&gt;
Lean 4.33.0, lean-lang.org), chapter 5, &amp;quot;Tactics&amp;quot;.&lt;br /&gt;
https://lean-lang.org/theorem_proving_in_lean4/Tactics/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What a tactic is ==&lt;br /&gt;
&lt;br /&gt;
A tactic is a small program that works on a &amp;#039;&amp;#039;&amp;#039;proof state&amp;#039;&amp;#039;&amp;#039;: the list of goals still to be&lt;br /&gt;
proved, each with the facts available for it. A tactic either fails, or succeeds and leaves&lt;br /&gt;
some number of new goals, possibly none. When no goals remain, the proof is complete. Behind&lt;br /&gt;
the scenes, each step fills in part of the proof term, and each open goal stands for a part&lt;br /&gt;
not yet filled.&amp;lt;ref name=&amp;quot;ref-tactics&amp;quot;&amp;gt;&amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version for Lean&lt;br /&gt;
4.34.0 (lean-lang.org, 2026), chapter 14, &amp;quot;Tactic Proofs&amp;quot;.&lt;br /&gt;
https://lean-lang.org/doc/reference/4.34.0/Tactic-Proofs/&amp;lt;/ref&amp;gt; How goals are shown and&lt;br /&gt;
filled is the subject of [[Lean theorem prover/Explainers/Holes and goals|holes and goals]].&lt;br /&gt;
&lt;br /&gt;
Lean 4&amp;#039;s tactics are themselves Lean programs. Lean 4 is a reimplementation of Lean written&lt;br /&gt;
in Lean itself, and its users can extend it with tactics and decision procedures of their&lt;br /&gt;
own; many write their proof automation in Lean.&amp;lt;ref name=&amp;quot;cade&amp;quot;&amp;gt;Leonardo de Moura and&lt;br /&gt;
Sebastian Ullrich, &amp;quot;The Lean 4 Theorem Prover and Programming Language&amp;quot;, in &amp;#039;&amp;#039;Automated&lt;br /&gt;
Deduction – CADE 28&amp;#039;&amp;#039;, Lecture Notes in Computer Science 12699, Springer, 2021, pp. 625–635.&lt;br /&gt;
doi:10.1007/978-3-030-79876-5_37&amp;lt;/ref&amp;gt; A new tactic can be an abbreviation that expands into&lt;br /&gt;
existing tactics, or a program that acts on the proof state directly.&amp;lt;ref name=&amp;quot;ref-custom&amp;quot;&amp;gt;&amp;#039;&amp;#039;The&lt;br /&gt;
Lean Language Reference&amp;#039;&amp;#039;, version for Lean 4.34.0 (lean-lang.org, 2026), section 14.8,&lt;br /&gt;
&amp;quot;Custom Tactics&amp;quot;. https://lean-lang.org/doc/reference/4.34.0/Tactic-Proofs/Custom-Tactics/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Where the idea came from ==&lt;br /&gt;
&lt;br /&gt;
Tactics come from LCF, a proof-checking program begun by Robin Milner at Stanford in 1972 and&lt;br /&gt;
developed further at Edinburgh. In Edinburgh LCF the logic was set up as a protected type in&lt;br /&gt;
the programming language ML, so that theorems could be produced only by the rules of&lt;br /&gt;
inference. Strategies for breaking a goal into subgoals were ordinary ML functions, which&lt;br /&gt;
Milner called tactics, and functions that combine strategies were called&lt;br /&gt;
tacticals.&amp;lt;ref name=&amp;quot;gordon&amp;quot;&amp;gt;Michael J. C. Gordon, &amp;quot;From LCF to HOL: a short history&amp;quot;, in&lt;br /&gt;
Gordon Plotkin, Colin Stirling and Mads Tofte (eds), &amp;#039;&amp;#039;Proof, Language, and Interaction:&lt;br /&gt;
Essays in Honour of Robin Milner&amp;#039;&amp;#039;, MIT Press, 2000.&lt;br /&gt;
https://www.cl.cam.ac.uk/~mjcg/papers/HolHistory.html&amp;lt;/ref&amp;gt; Lean keeps the first idea, that&lt;br /&gt;
proof strategies are ordinary programs, and secures the second in its own way, by checking&lt;br /&gt;
the finished term, as described below. The history is told in&lt;br /&gt;
[[Lean theorem prover/History/LCF and the tactic idea|LCF and the tactic idea]].&lt;br /&gt;
&lt;br /&gt;
== The tactics met most often ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;intro&amp;lt;/code&amp;gt;: to prove &amp;quot;if A then B&amp;quot;, assume A, give it a name, and prove B.&lt;br /&gt;
* &amp;lt;code&amp;gt;apply&amp;lt;/code&amp;gt;: to prove a goal with a fact of the form &amp;quot;if A then the goal&amp;quot;, switch to proving A.&lt;br /&gt;
* &amp;lt;code&amp;gt;exact&amp;lt;/code&amp;gt;: finish the goal by giving a proof of exactly that statement.&lt;br /&gt;
* &amp;lt;code&amp;gt;rw&amp;lt;/code&amp;gt;: rewrite the goal with an equation, replacing one side by the other.&lt;br /&gt;
* &amp;lt;code&amp;gt;simp&amp;lt;/code&amp;gt;: simplify with a large stock of known equations.&lt;br /&gt;
* &amp;lt;code&amp;gt;induction&amp;lt;/code&amp;gt;: split a goal about every value of a type into one goal for each way a value can be made, with induction hypotheses (see [[Lean theorem prover/Explainers/Induction, as the machine sees it|induction, as the machine sees it]]).&lt;br /&gt;
* &amp;lt;code&amp;gt;cases&amp;lt;/code&amp;gt;: split by how a value was made, without induction hypotheses. A proof of &amp;quot;p or q&amp;quot;, for instance, was made either from a proof of p or from a proof of q.&lt;br /&gt;
* &amp;lt;code&amp;gt;omega&amp;lt;/code&amp;gt;: settle a problem of linear arithmetic over whole numbers.&lt;br /&gt;
* &amp;lt;code&amp;gt;decide&amp;lt;/code&amp;gt;: settle a statement by computing whether it is true.&lt;br /&gt;
&lt;br /&gt;
The last two, with &amp;lt;code&amp;gt;simp&amp;lt;/code&amp;gt;, are automation, treated in&lt;br /&gt;
[[Lean theorem prover/Explainers/Automation and its limits|automation and its limits]] and&lt;br /&gt;
[[Lean theorem prover/Explainers/Computation inside proofs|computation inside&lt;br /&gt;
proofs]].&amp;lt;ref name=&amp;quot;ref-tacref&amp;quot;&amp;gt;&amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version for Lean 4.34.0&lt;br /&gt;
(lean-lang.org, 2026), section 14.5, &amp;quot;Tactic Reference&amp;quot;.&lt;br /&gt;
https://lean-lang.org/doc/reference/4.34.0/Tactic-Proofs/Tactic-Reference/&amp;lt;/ref&amp;gt; The first&lt;br /&gt;
three are enough for a short chain of reasoning:&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;
theorem chain (p q r : Prop) : (p → q) → (q → r) → p → r := by&lt;br /&gt;
  intro hpq hqr hp&lt;br /&gt;
  apply hqr&lt;br /&gt;
  exact hpq hp&lt;br /&gt;
&lt;br /&gt;
#print chain&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The statement says: if p gives q, and q gives r, then p gives r. &amp;lt;code&amp;gt;intro&amp;lt;/code&amp;gt; names&lt;br /&gt;
the three assumptions, and the goal becomes r. &amp;lt;code&amp;gt;apply hqr&amp;lt;/code&amp;gt; uses the fact that q&lt;br /&gt;
gives r, so it is enough to prove q. &amp;lt;code&amp;gt;exact hpq hp&amp;lt;/code&amp;gt; finishes: applying &amp;quot;p gives&lt;br /&gt;
q&amp;quot; to the proof of p yields a proof of q. Lean prints the term that the script produced:&lt;br /&gt;
&amp;lt;code&amp;gt;fun p q r hpq hqr hp =&amp;amp;gt; hqr (hpq hp)&amp;lt;/code&amp;gt;. It is the same argument, read from the&lt;br /&gt;
inside out.&lt;br /&gt;
&lt;br /&gt;
== Why a tactic need not be trusted ==&lt;br /&gt;
&lt;br /&gt;
Whatever a tactic does, its product is a term, and the term goes to the Lean kernel to be&lt;br /&gt;
checked like any other. A tactic with a bug can fail, or produce a term that the Lean kernel&lt;br /&gt;
rejects. It cannot make Lean accept a false theorem. The Lean Language Reference puts it this&lt;br /&gt;
way: the worst a bug in a tactic can cause is a confusing error message, not an incorrect&lt;br /&gt;
proof.&amp;lt;ref name=&amp;quot;ref-tactics&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is why tactics may be large, clever and written by anyone, including programs that&lt;br /&gt;
search for proofs on their own, while the part that must be trusted stays small (see&lt;br /&gt;
[[Lean theorem prover/Explainers/The small trusted core|the small trusted core]]). The&lt;br /&gt;
exceptions are visible. A tactic that rests on an extra axiom, such as&lt;br /&gt;
&amp;lt;code&amp;gt;native_decide&amp;lt;/code&amp;gt; or the placeholder &amp;lt;code&amp;gt;sorry&amp;lt;/code&amp;gt;, leaves that axiom&amp;#039;s name in&lt;br /&gt;
the list that &amp;lt;code&amp;gt;#print axioms&amp;lt;/code&amp;gt; shows for the theorem.&amp;lt;ref name=&amp;quot;ref-validating&amp;quot;&amp;gt;&amp;#039;&amp;#039;The&lt;br /&gt;
Lean Language Reference&amp;#039;&amp;#039;, version for Lean 4.34.0 (lean-lang.org, 2026), &amp;quot;Validating a Lean&lt;br /&gt;
Proof&amp;quot;. https://lean-lang.org/doc/reference/4.34.0/ValidatingProofs/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Terms or tactics? ==&lt;br /&gt;
&lt;br /&gt;
Neither style is more rigorous than the other; both end in the same kind of term. Tactic&lt;br /&gt;
proofs are often shorter and easier to write, and they open the way to automation, since the&lt;br /&gt;
automatic procedures are tactics too. They can be harder to read, because the reader has to&lt;br /&gt;
picture the goal after every step.&amp;lt;ref name=&amp;quot;tpil-tac&amp;quot; /&amp;gt; A term shows the whole argument at&lt;br /&gt;
once but can be laborious to write by hand. In practice the two are mixed: a term may contain&lt;br /&gt;
a &amp;lt;code&amp;gt;by&amp;lt;/code&amp;gt; block, and a tactic such as &amp;lt;code&amp;gt;exact&amp;lt;/code&amp;gt; takes a term.&lt;br /&gt;
&lt;br /&gt;
== Next ==&lt;br /&gt;
&lt;br /&gt;
* [[Lean theorem prover/Explainers/Holes and goals|Holes and goals]]: the proof state, and the parts of a proof still missing.&lt;br /&gt;
* [[Lean theorem prover/System/The tactic framework|The tactic framework]]: the technical treatment.&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>