<?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%2FFoundations%2FProof_irrelevance_and_subsingleton_elimination</id>
	<title>Lean theorem prover/Foundations/Proof irrelevance and subsingleton elimination - 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%2FFoundations%2FProof_irrelevance_and_subsingleton_elimination"/>
	<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=Lean_theorem_prover/Foundations/Proof_irrelevance_and_subsingleton_elimination&amp;action=history"/>
	<updated>2026-10-21T06:37:07Z</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/Foundations/Proof_irrelevance_and_subsingleton_elimination&amp;diff=6784&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/Foundations/Proof_irrelevance_and_subsingleton_elimination&amp;diff=6784&amp;oldid=prev"/>
		<updated>2026-10-15T19:35:01Z</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:35, 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:Proof irrelevance and subsingleton elimination}}&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:Proof irrelevance and subsingleton elimination}}&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;{{Plebeian|Lean theorem prover/Explainers/Two kinds of equality}}&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;{{Plebeian|Lean theorem prover/Explainers/Two kinds of equality}}&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;Two rules govern how proofs behave in Lean. &amp;#039;&amp;#039;&amp;#039;Definitional proof irrelevance&amp;#039;&amp;#039;&amp;#039; makes any&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;Two rules govern how proofs behave in Lean. &amp;#039;&amp;#039;&amp;#039;Definitional proof irrelevance&amp;#039;&amp;#039;&amp;#039; makes any&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/Foundations/Proof_irrelevance_and_subsingleton_elimination&amp;diff=6577&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/Foundations/Proof_irrelevance_and_subsingleton_elimination&amp;diff=6577&amp;oldid=prev"/>
		<updated>2026-10-14T18:01:03Z</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:Proof irrelevance and subsingleton elimination}}&lt;br /&gt;
{{Plebeian|Lean theorem prover/Explainers/Two kinds of equality}}&lt;br /&gt;
&lt;br /&gt;
Two rules govern how proofs behave in Lean. &amp;#039;&amp;#039;&amp;#039;Definitional proof irrelevance&amp;#039;&amp;#039;&amp;#039; makes any&lt;br /&gt;
two proofs of the same proposition definitionally equal. &amp;#039;&amp;#039;&amp;#039;Restricted elimination&amp;#039;&amp;#039;&amp;#039; allows&lt;br /&gt;
a proof to be taken apart to produce data only when the proposition is a&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;subsingleton&amp;#039;&amp;#039;&amp;#039;, one that by its shape can have at most one proof. The first rule says&lt;br /&gt;
that the content of a proof never matters; the second is what keeps that consistent. This&lt;br /&gt;
page states both rules, lists which propositions pass the test, explains why the test is&lt;br /&gt;
needed, and sets out the cost: together with the accessibility predicate, the two rules make&lt;br /&gt;
Lean&amp;#039;s definitional equality undecidable.&lt;br /&gt;
&lt;br /&gt;
== Definitional proof irrelevance ==&lt;br /&gt;
&lt;br /&gt;
Carneiro&amp;#039;s presentation of Lean&amp;#039;s type theory includes the rule&amp;lt;ref name=&amp;quot;carneiro&amp;quot;&amp;gt;Mario Carneiro, &amp;#039;&amp;#039;The Type Theory of Lean&amp;#039;&amp;#039;, Master&amp;#039;s thesis, Carnegie Mellon University, 2019; §2.2 (pp. 6–7), §2.6.2 (pp. 10–11), §2.6.4 (p. 12), §2.8 (p. 15), §3.1 (pp. 16–17), Lemma 3.4 (pp. 18–19) and Corollary 6.8 (p. 41). https://github.com/digama0/lean-type-theory/releases/tag/v1.0&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\Gamma \vdash p : \mathrm{Prop} \quad \Gamma \vdash h : p \quad \Gamma \vdash h&amp;#039; : p}{\Gamma \vdash h \equiv h&amp;#039;}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a rule of definitional equality, so the checker applies it during conversion, without&lt;br /&gt;
any proof term. The reference manual lists it among the defining properties of&lt;br /&gt;
&amp;lt;code&amp;gt;Prop&amp;lt;/code&amp;gt;, beside the erasure of propositions from compiled code.&amp;lt;ref name=&amp;quot;refman-props&amp;quot;&amp;gt;&amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version 4.34.0, §4.2 &amp;quot;Propositions&amp;quot;. https://lean-lang.org/doc/reference/4.34.0/The-Type-System/Propositions/&amp;lt;/ref&amp;gt;&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;
example (p : Prop) (h₁ h₂ : p) : h₁ = h₂ := rfl&lt;br /&gt;
&lt;br /&gt;
example (h₁ h₂ : 0 &amp;amp;lt; 5) : (⟨5, h₁⟩ : {n : Nat // 0 &amp;amp;lt; n}) = ⟨5, h₂⟩ := rfl&lt;br /&gt;
&lt;br /&gt;
example (α : Type) (h₁ h₂ : Nonempty α) : Classical.choice h₁ = Classical.choice h₂ := rfl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All three are accepted. The second shows the practical use: elements of a subtype are equal&lt;br /&gt;
as soon as their values are, whatever proofs they carry. The third shows that global choice&lt;br /&gt;
returns one element per type, not one per proof. Carneiro, writing in 2019, notes that Coq&lt;br /&gt;
then had proof irrelevance only as an axiom asserting a propositional equality, and calls&lt;br /&gt;
Lean&amp;#039;s definitional version &amp;quot;a major departure for the theory&amp;quot;.&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Why elimination must be restricted ==&lt;br /&gt;
&lt;br /&gt;
Suppose a program could inspect which constructor built a proof of a disjunction, and so&lt;br /&gt;
return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;Or.inl trivial : True ∨ True&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
on &amp;lt;code&amp;gt;Or.inr trivial&amp;lt;/code&amp;gt;. Those two proofs have the same type, so proof irrelevance&lt;br /&gt;
makes them definitionally equal, the two results would be definitionally equal, and&lt;br /&gt;
&amp;lt;code&amp;gt;true = false&amp;lt;/code&amp;gt; would follow by &amp;lt;code&amp;gt;rfl&amp;lt;/code&amp;gt;. One of the two rules has to&lt;br /&gt;
give way. Lean keeps proof irrelevance and forbids the inspection: having been given a&lt;br /&gt;
proof, a program must not be able to tell which proof it received.&amp;lt;ref name=&amp;quot;refman-ind&amp;quot;&amp;gt;&amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version 4.34.0, §4.4 &amp;quot;Inductive Types&amp;quot;, subsection &amp;quot;Subsingleton Elimination&amp;quot;. https://lean-lang.org/doc/reference/4.34.0/The-Type-System/Inductive-Types/#subsingleton-elimination&amp;lt;/ref&amp;gt;&lt;br /&gt;
Lean refuses the function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean 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;
def which (h : True ∨ True) : Bool :=&lt;br /&gt;
  match h with&lt;br /&gt;
  | .inl _ =&amp;gt; true&lt;br /&gt;
  | .inr _ =&amp;gt; false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The message begins &amp;lt;code&amp;gt;Tactic `cases` failed with a nested error:&amp;lt;/code&amp;gt; and continues&lt;br /&gt;
&amp;lt;code&amp;gt;Tactic `induction` failed: recursor `Or.casesOn` can only eliminate into `Prop`&amp;lt;/code&amp;gt;.&lt;br /&gt;
The restriction is visible in the recursors themselves. The motive of &amp;lt;code&amp;gt;Or.rec&amp;lt;/code&amp;gt;&lt;br /&gt;
and of &amp;lt;code&amp;gt;Exists.rec&amp;lt;/code&amp;gt; returns &amp;lt;code&amp;gt;Prop&amp;lt;/code&amp;gt;, while the motives of&lt;br /&gt;
&amp;lt;code&amp;gt;True.rec&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;False.rec&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;And.rec&amp;lt;/code&amp;gt; return an arbitrary&lt;br /&gt;
&amp;lt;code&amp;gt;Sort u_1&amp;lt;/code&amp;gt;:&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;
#check @True.rec&lt;br /&gt;
#check @False.rec&lt;br /&gt;
#check @And.rec&lt;br /&gt;
#check @Or.rec&lt;br /&gt;
#check @Exists.rec&lt;br /&gt;
&amp;lt;/pre&amp;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;
@True.rec : {motive : True → Sort u_1} → motive True.intro → (t : True) → motive t&lt;br /&gt;
False.rec : (motive : False → Sort u_1) → (t : False) → motive t&lt;br /&gt;
@And.rec : {a b : Prop} → {motive : a ∧ b → Sort u_1} → ((left : a) → (right : b) → motive ⋯) → (t : a ∧ b) → motive t&lt;br /&gt;
@Or.rec : ∀ {a b : Prop} {motive : a ∨ b → Prop},&lt;br /&gt;
  (∀ (h : a), motive ⋯) → (∀ (h : b), motive ⋯) → ∀ (t : a ∨ b), motive t&lt;br /&gt;
@Exists.rec : ∀ {α : Sort u_1} {p : α → Prop} {motive : Exists p → Prop},&lt;br /&gt;
  (∀ (w : α) (h : p w), motive ⋯) → ∀ (t : Exists p), motive t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The rule ==&lt;br /&gt;
&lt;br /&gt;
An inductive type in &amp;lt;code&amp;gt;Prop&amp;lt;/code&amp;gt; may be eliminated into any universe, which is&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;large elimination&amp;#039;&amp;#039;&amp;#039;, when it is a syntactic subsingleton. The reference manual states&lt;br /&gt;
the test as two conditions: there is at most one constructor, and every argument of that&lt;br /&gt;
constructor either has a proposition as its type or is a parameter or an index of the&lt;br /&gt;
type.&amp;lt;ref name=&amp;quot;refman-ind&amp;quot; /&amp;gt; Carneiro&amp;#039;s formulation is that there is at most one constructor&lt;br /&gt;
and every non-recursive argument of it either has a proposition as its type or appears&lt;br /&gt;
directly in the constructor&amp;#039;s output type.&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt; Otherwise the motive of the recursor must return&lt;br /&gt;
&amp;lt;code&amp;gt;Prop&amp;lt;/code&amp;gt;. The test is deliberately conservative: it does not ask for a proof that&lt;br /&gt;
the proposition has at most one proof, only for a shape that guarantees it.&amp;lt;ref name=&amp;quot;refman-ind&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The standard cases:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; has one constructor with no arguments, and &amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; has none. From &amp;lt;code&amp;gt;h : False&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;h.elim&amp;lt;/code&amp;gt; produces an element of any type.&amp;lt;ref name=&amp;quot;refman-ind&amp;quot; /&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;And&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; has one constructor whose arguments are proofs.&amp;lt;ref name=&amp;quot;refman-ind&amp;quot; /&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;Eq&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; has one constructor, &amp;lt;code&amp;gt;Eq.refl a&amp;lt;/code&amp;gt;, whose argument is fixed by the type&amp;#039;s parameters. This is why a proof of an equation can rewrite the type of data, the operation called transport on [[Lean theorem prover/Foundations/Propositional equality|propositional equality]].&amp;lt;ref name=&amp;quot;refman-ind&amp;quot; /&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;Acc&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;, the accessibility predicate, has one constructor &amp;lt;code&amp;gt;Acc.intro x h&amp;lt;/code&amp;gt;. Its argument &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; appears in the result type &amp;lt;code&amp;gt;Acc r x&amp;lt;/code&amp;gt; and its argument &amp;lt;code&amp;gt;h&amp;lt;/code&amp;gt; is a proof, so it too eliminates into any universe. Carneiro singles it out as the source of proof by well-founded recursion.&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Or&amp;lt;/code&amp;gt; fails because it has two constructors. &amp;lt;code&amp;gt;Exists&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;Nonempty&amp;lt;/code&amp;gt; fail because their constructor stores a witness that is neither a&lt;br /&gt;
proof nor part of the type. Their proofs therefore cannot yield the witness as data; that&lt;br /&gt;
requires &amp;lt;code&amp;gt;Classical.choose&amp;lt;/code&amp;gt;, as on&lt;br /&gt;
[[Lean theorem prover/Foundations/Classical logic from choice|classical logic from choice]].&lt;br /&gt;
Where the witness is wanted as data, the subtype &amp;lt;code&amp;gt;{x // p x}&amp;lt;/code&amp;gt;, which lives in&lt;br /&gt;
&amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;, carries 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 fromFalse (h : False) : Nat := h.elim&lt;br /&gt;
&lt;br /&gt;
def castAlong {α β : Type} (h : α = β) (x : α) : β := h ▸ x&lt;br /&gt;
&lt;br /&gt;
def bothThen {p q : Prop} (h : p ∧ q) (f : p → q → Nat) : Nat :=&lt;br /&gt;
  match h with&lt;br /&gt;
  | ⟨hp, hq⟩ =&amp;gt; f hp hq&lt;br /&gt;
&lt;br /&gt;
set_option pp.proofs true in&lt;br /&gt;
#check @Acc.rec&lt;br /&gt;
&amp;lt;/pre&amp;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;
@Acc.rec : {α : Sort u_2} →&lt;br /&gt;
  {r : α → α → Prop} →&lt;br /&gt;
    {motive : (a : α) → Acc r a → Sort u_1} →&lt;br /&gt;
      ((x : α) →&lt;br /&gt;
          (h : ∀ (y : α), r y x → Acc r y) → ((y : α) → (a : r y x) → motive y (h y a)) → motive x (Acc.intro x h)) →&lt;br /&gt;
        {a : α} → (t : Acc r a) → motive a t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For subsingletons the checker also applies an extra reduction, which Carneiro calls K-like&lt;br /&gt;
reduction: by proof irrelevance the major premise may be replaced by the constructor, and&lt;br /&gt;
the ordinary computation rule then fires. It applies only when every argument of the&lt;br /&gt;
constructor can be read off the type, which is the reason for the shape of the&lt;br /&gt;
test.&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt; For &amp;lt;code&amp;gt;Eq&amp;lt;/code&amp;gt; it makes transport along any proof of&lt;br /&gt;
&amp;lt;code&amp;gt;a = a&amp;lt;/code&amp;gt; reduce to the identity.&lt;br /&gt;
&lt;br /&gt;
== The cost: definitional equality is undecidable ==&lt;br /&gt;
&lt;br /&gt;
Proof irrelevance and the large eliminator of &amp;lt;code&amp;gt;Acc&amp;lt;/code&amp;gt; together break the&lt;br /&gt;
decidability of definitional equality. Carneiro&amp;#039;s argument runs as follows.&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt;&lt;br /&gt;
From a proof &amp;lt;code&amp;gt;a : Acc r x&amp;lt;/code&amp;gt; one can project, with the eliminator, a function&lt;br /&gt;
giving accessibility of every smaller element; call it &amp;lt;code&amp;gt;a.inv&amp;lt;/code&amp;gt;. Rebuilding with&lt;br /&gt;
the constructor gives a proof of the same proposition, so by proof irrelevance&lt;br /&gt;
&amp;lt;code&amp;gt;a&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Acc.intro x a.inv&amp;lt;/code&amp;gt; are definitionally equal:&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;
example {α : Sort u} {r : α → α → Prop} {x : α} (a : Acc r x) :&lt;br /&gt;
    a = Acc.intro x (fun _ h =&amp;gt; a.inv h) := rfl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That step turns any proof, even an opaque variable, into a constructor on which the&lt;br /&gt;
recursor can compute. Now take a decidable predicate &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; on the natural&lt;br /&gt;
numbers, such as &amp;quot;machine &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; runs for at least &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; steps without&lt;br /&gt;
halting&amp;quot;, and a function &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; defined by recursion on &amp;lt;code&amp;gt;Acc&amp;lt;/code&amp;gt; for the&lt;br /&gt;
relation &amp;lt;math&amp;gt;&amp;gt;&amp;lt;/math&amp;gt;, which at &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; returns a fixed value if&lt;br /&gt;
&amp;lt;math&amp;gt;P(n)&amp;lt;/math&amp;gt; fails and otherwise calls itself at &amp;lt;math&amp;gt;n+1&amp;lt;/math&amp;gt;. The relation&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;gt;&amp;lt;/math&amp;gt; on the natural numbers is not well founded, so a hypothesis&lt;br /&gt;
&amp;lt;math&amp;gt;a : \mathrm{Acc}\,(&amp;gt;)\,0&amp;lt;/math&amp;gt; is unprovable, but definitional equality is&lt;br /&gt;
judged in every context, inconsistent ones included. In that context each use of the&lt;br /&gt;
equation above lets &amp;lt;math&amp;gt;f\,0\,a&amp;lt;/math&amp;gt; take one more step of the search. If&lt;br /&gt;
&amp;lt;math&amp;gt;P(n)&amp;lt;/math&amp;gt; fails for some &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, the search ends and &amp;lt;math&amp;gt;f\,0\,a&amp;lt;/math&amp;gt; is&lt;br /&gt;
definitionally equal to the fixed value; if &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; holds everywhere, every term&lt;br /&gt;
definitionally equal to &amp;lt;math&amp;gt;f\,0\,a&amp;lt;/math&amp;gt; still contains a call of &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt;.&lt;br /&gt;
Deciding that one definitional equality would decide whether &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; halts.&lt;br /&gt;
&lt;br /&gt;
Lean&amp;#039;s checker cannot implement an undecidable relation. It implements a decidable&lt;br /&gt;
approximation, which Carneiro calls algorithmic equality, and the two must differ: the&lt;br /&gt;
chain of equalities above holds step by step, but the checker, which does not perform the&lt;br /&gt;
&amp;quot;creative&amp;quot; re-expansion of a normal term, does not relate its two ends. Algorithmic&lt;br /&gt;
equality is therefore not transitive.&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt; The reference manual records&lt;br /&gt;
the same fact: definitional equality as Lean checks it is reflexive and symmetric, but not&lt;br /&gt;
transitive.&amp;lt;ref name=&amp;quot;refman-ts&amp;quot;&amp;gt;&amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version 4.34.0, §4 &amp;quot;The Type System&amp;quot; (definitional equality). https://lean-lang.org/doc/reference/4.34.0/The-Type-System/&amp;lt;/ref&amp;gt; Carneiro also shows that, measured against the&lt;br /&gt;
algorithmic relation, typing fails subject reduction: a term can be well typed and reduce&lt;br /&gt;
to one that the checker rejects.&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
None of this lets the checker accept a false theorem. Algorithmic equality implies the&lt;br /&gt;
ideal definitional equality for well-typed terms, so whatever the checker accepts is&lt;br /&gt;
derivable in the theory; Carneiro uses exactly this step in his consistency proof. The&lt;br /&gt;
defect is incompleteness, not unsoundness.&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt;&lt;br /&gt;
Abel and Coquand later showed a related failure: with an impredicative &amp;lt;code&amp;gt;Prop&amp;lt;/code&amp;gt;&lt;br /&gt;
and proof-irrelevant equality, reduction need not terminate at all.&amp;lt;ref name=&amp;quot;abel-coquand&amp;quot;&amp;gt;Andreas Abel and Thierry Coquand, &amp;quot;Failure of normalization in impredicative type theory with proof-irrelevant propositional equality&amp;quot;, &amp;#039;&amp;#039;Logical Methods in Computer Science&amp;#039;&amp;#039; 16(2) (2020), paper 14. https://doi.org/10.23638/LMCS-16(2:14)2020&amp;lt;/ref&amp;gt;&lt;br /&gt;
That result, and why the checker remains sound regardless, are treated on&lt;br /&gt;
[[Lean theorem prover/Foundations/Consistency and the metatheory|consistency and the metatheory]].&lt;br /&gt;
Abel and Coquand also note the other design: Agda and Coq had recently gained a proof-irrelevant universe&lt;br /&gt;
of strict propositions in which equality can be defined but cannot be eliminated into types&lt;br /&gt;
that are not themselves strict propositions, and under that restriction normalisation and&lt;br /&gt;
decidable type checking have been proved for the predicative case.&amp;lt;ref name=&amp;quot;abel-coquand&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Next ==&lt;br /&gt;
&lt;br /&gt;
[[Lean theorem prover/Foundations/Consistency and the metatheory|Consistency and the metatheory]]&lt;br /&gt;
asks what is known about the soundness of the whole system.&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>