<?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%2FPropositional_equality</id>
	<title>Lean theorem prover/Foundations/Propositional equality - 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%2FPropositional_equality"/>
	<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=Lean_theorem_prover/Foundations/Propositional_equality&amp;action=history"/>
	<updated>2026-10-21T13:47:40Z</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/Propositional_equality&amp;diff=6780&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/Propositional_equality&amp;diff=6780&amp;oldid=prev"/>
		<updated>2026-10-15T19:34:55Z</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:Propositional 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;{{DISPLAYTITLE:Propositional equality}}&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;&amp;#039;&amp;#039;&amp;#039;Propositional equality&amp;#039;&amp;#039;&amp;#039; is the proposition &amp;lt;code&amp;gt;a = b&amp;lt;/code&amp;gt;. A proof of it is a term&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;&amp;#039;&amp;#039;&amp;#039;Propositional equality&amp;#039;&amp;#039;&amp;#039; is the proposition &amp;lt;code&amp;gt;a = b&amp;lt;/code&amp;gt;. A proof of it is a term&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/Propositional_equality&amp;diff=6573&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/Propositional_equality&amp;diff=6573&amp;oldid=prev"/>
		<updated>2026-10-14T18:01:00Z</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:Propositional equality}}&lt;br /&gt;
{{Plebeian|Lean theorem prover/Explainers/Two kinds of equality}}&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Propositional equality&amp;#039;&amp;#039;&amp;#039; is the proposition &amp;lt;code&amp;gt;a = b&amp;lt;/code&amp;gt;. A proof of it is a term&lt;br /&gt;
of that type, built and used like any other proof. It is distinct from&lt;br /&gt;
[[Lean theorem prover/Foundations/Definitional equality|definitional equality]], which is a&lt;br /&gt;
judgment the checker tests by computation and which no term records. Lean defines&lt;br /&gt;
propositional equality as an inductive family with a single constructor. Symmetry,&lt;br /&gt;
transitivity, substitution and congruence are all derived from its eliminator. Function&lt;br /&gt;
extensionality is a theorem, proved from quotient types. Uniqueness of identity proofs&lt;br /&gt;
holds with no axiom at all.&lt;br /&gt;
&lt;br /&gt;
== Equality as an inductive family ==&lt;br /&gt;
&lt;br /&gt;
Lean&amp;#039;s core library defines &amp;lt;code&amp;gt;Eq&amp;lt;/code&amp;gt; as an inductive type in &amp;lt;code&amp;gt;Prop&amp;lt;/code&amp;gt; with&lt;br /&gt;
one constructor, &amp;lt;code&amp;gt;Eq.refl&amp;lt;/code&amp;gt;.&amp;lt;ref name=&amp;quot;prelude&amp;quot;&amp;gt;Lean 4 source, file &amp;lt;code&amp;gt;src/Init/Prelude.lean&amp;lt;/code&amp;gt;, version 4.34.1: the definitions of &amp;lt;code&amp;gt;Eq&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HEq&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cast&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;congrArg&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;congr&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;congrFun&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;funext&amp;lt;/code&amp;gt;, with their documentation comments. Apache License 2.0. https://github.com/leanprover/lean4/blob/v4.34.1/src/Init/Prelude.lean&amp;lt;/ref&amp;gt; Lean prints it so:&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;
#print Eq&lt;br /&gt;
example : 2 + 2 = 4 := rfl&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;
inductive Eq.{u_1} : {α : Sort u_1} → α → α → Prop&lt;br /&gt;
number of parameters: 2&lt;br /&gt;
constructors:&lt;br /&gt;
Eq.refl : ∀ {α : Sort u_1} (a : α), a = a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two parameters are the type &amp;lt;code&amp;gt;α&amp;lt;/code&amp;gt; and the left-hand side &amp;lt;code&amp;gt;a&amp;lt;/code&amp;gt;. The&lt;br /&gt;
right-hand side is an &amp;#039;&amp;#039;&amp;#039;index&amp;#039;&amp;#039;&amp;#039;: it varies between the type and the constructor&amp;#039;s result,&lt;br /&gt;
and the constructor fixes it to &amp;lt;code&amp;gt;a&amp;lt;/code&amp;gt;. The constructor alone therefore proves only&lt;br /&gt;
statements of the form &amp;lt;code&amp;gt;a = a&amp;lt;/code&amp;gt;; every other equation needs an argument that ends&lt;br /&gt;
in one. Written as rules, formation and introduction are&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\Gamma \vdash A : \mathrm{Sort}\,u \quad \Gamma \vdash a : A \quad \Gamma \vdash b : A}{\Gamma \vdash a = b : \mathrm{Prop}} \qquad \frac{\Gamma \vdash a : A}{\Gamma \vdash \mathrm{Eq.refl}\,a : a = a}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The term &amp;lt;code&amp;gt;rfl&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;Eq.refl&amp;lt;/code&amp;gt; with its argument left implicit. The&lt;br /&gt;
example &amp;lt;code&amp;gt;2 + 2 = 4 := rfl&amp;lt;/code&amp;gt; is accepted because the checker finds&lt;br /&gt;
&amp;lt;code&amp;gt;2 + 2&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; definitionally equal; &amp;lt;code&amp;gt;rfl&amp;lt;/code&amp;gt; then has the&lt;br /&gt;
type the statement asks for. Every proof by &amp;lt;code&amp;gt;rfl&amp;lt;/code&amp;gt; is a definitional equality&lt;br /&gt;
packaged as a propositional one. Not every propositional equality is definitional: most&lt;br /&gt;
equations in mathematics need an argument, because no amount of computation turns one side&lt;br /&gt;
into the other.&lt;br /&gt;
&lt;br /&gt;
== The eliminator ==&lt;br /&gt;
&lt;br /&gt;
The recursor that [[Lean theorem prover/Foundations/Inductive types and recursors|every inductive type receives]]&lt;br /&gt;
is, for &amp;lt;code&amp;gt;Eq&amp;lt;/code&amp;gt;, the principle that makes equality useful.&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;
set_option pp.proofs true in&lt;br /&gt;
#check @Eq.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;
@Eq.rec : {α : Sort u_2} →&lt;br /&gt;
  {a : α} → {motive : (a_1 : α) → a = a_1 → Sort u_1} → motive a (Eq.refl a) → {a_1 : α} → (t : a = a_1) → motive a_1 t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The motive, written &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; below, is a family over every right-hand side &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt; and every&lt;br /&gt;
proof that &amp;lt;code&amp;gt;a = y&amp;lt;/code&amp;gt;. To produce an element of &amp;lt;code&amp;gt;C b h&amp;lt;/code&amp;gt; it suffices to&lt;br /&gt;
produce one at the constructor, &amp;lt;code&amp;gt;C a (Eq.refl a)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\Gamma \vdash C : \Pi (y : A).\, a = y \to \mathrm{Sort}\,v \quad \Gamma \vdash c : C\,a\,(\mathrm{Eq.refl}\,a) \quad \Gamma \vdash h : a = b}{\Gamma \vdash \mathrm{Eq.rec}\,c\,h : C\,b\,h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with the computation rule&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\mathrm{Eq.rec}\,c\,(\mathrm{Eq.refl}\,a) \equiv c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;The motive may land in any universe, not only in &amp;lt;code&amp;gt;Prop&amp;lt;/code&amp;gt;.&amp;#039;&amp;#039;&amp;#039; A proof of an&lt;br /&gt;
equation can therefore change the type of a piece of data. This is unusual for a&lt;br /&gt;
proposition: Lean permits it only because &amp;lt;code&amp;gt;Eq&amp;lt;/code&amp;gt; passes the test for subsingleton&lt;br /&gt;
elimination, which is the subject of&lt;br /&gt;
[[Lean theorem prover/Foundations/Proof irrelevance and subsingleton elimination|proof irrelevance and subsingleton elimination]].&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; (the recursor of &amp;lt;code&amp;gt;Eq&amp;lt;/code&amp;gt;). https://lean-lang.org/doc/reference/4.34.0/The-Type-System/Inductive-Types/#subsingleton-elimination&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport ==&lt;br /&gt;
&lt;br /&gt;
Applying the eliminator with a motive that does not depend on the proof gives&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;transport&amp;#039;&amp;#039;&amp;#039;: from &amp;lt;code&amp;gt;h : a = b&amp;lt;/code&amp;gt; and a term whose type mentions &amp;lt;code&amp;gt;a&amp;lt;/code&amp;gt;,&lt;br /&gt;
obtain the same term at &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. Lean&amp;#039;s core library defines &amp;lt;code&amp;gt;Eq.subst&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;cast&amp;lt;/code&amp;gt; this way.&amp;lt;ref name=&amp;quot;prelude&amp;quot; /&amp;gt; The triangle &amp;lt;code&amp;gt;h ▸ e&amp;lt;/code&amp;gt; is a&lt;br /&gt;
macro over &amp;lt;code&amp;gt;Eq.rec&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Eq.symm&amp;lt;/code&amp;gt;: it tries both orientations of&lt;br /&gt;
&amp;lt;code&amp;gt;h&amp;lt;/code&amp;gt;, and rewrites the expected type when there is one, otherwise the type of&lt;br /&gt;
&amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&amp;lt;ref name=&amp;quot;parser&amp;quot;&amp;gt;Lean 4 source, file &amp;lt;code&amp;gt;src/Lean/Parser/Term.lean&amp;lt;/code&amp;gt;, version 4.34.1: the documentation comment of the &amp;lt;code&amp;gt;h ▸ e&amp;lt;/code&amp;gt; syntax. Apache License 2.0. https://github.com/leanprover/lean4/blob/v4.34.1/src/Lean/Parser/Term.lean&amp;lt;/ref&amp;gt; With it the familiar laws of equality are one line&lt;br /&gt;
each:&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 symm&amp;#039; {α : Sort u} {a b : α} (h : a = b) : b = a :=&lt;br /&gt;
  h ▸ rfl&lt;br /&gt;
&lt;br /&gt;
theorem trans&amp;#039; {α : Sort u} {a b c : α} (h₁ : a = b) (h₂ : b = c) : a = c :=&lt;br /&gt;
  h₂ ▸ h₁&lt;br /&gt;
&lt;br /&gt;
theorem subst&amp;#039; {α : Sort u} {a b : α} (p : α → Prop) (h : a = b) (ha : p a) : p b :=&lt;br /&gt;
  h ▸ ha&lt;br /&gt;
&lt;br /&gt;
theorem congrArg&amp;#039; {α : Sort u} {β : Sort v} {a₁ a₂ : α} (f : α → β) (h : a₁ = a₂) :&lt;br /&gt;
    f a₁ = f a₂ :=&lt;br /&gt;
  h ▸ rfl&lt;br /&gt;
&lt;br /&gt;
def castAlong {α β : Type} (h : α = β) (x : α) : β :=&lt;br /&gt;
  h ▸ x&lt;br /&gt;
&lt;br /&gt;
#print axioms trans&amp;#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last command prints &amp;lt;code&amp;gt;&amp;#039;trans&amp;#039;&amp;#039; does not depend on any axioms&amp;lt;/code&amp;gt;. Nothing beyond&lt;br /&gt;
the inductive definition is used. The definition &amp;lt;code&amp;gt;castAlong&amp;lt;/code&amp;gt; is the case that&lt;br /&gt;
needs the large motive: its result is data of type &amp;lt;code&amp;gt;β&amp;lt;/code&amp;gt;, obtained from data of&lt;br /&gt;
type &amp;lt;code&amp;gt;α&amp;lt;/code&amp;gt; by a proof that the two types are equal.&lt;br /&gt;
&lt;br /&gt;
== Congruence ==&lt;br /&gt;
&lt;br /&gt;
The theorem &amp;lt;code&amp;gt;congrArg&amp;lt;/code&amp;gt; above is the first congruence principle: equal arguments&lt;br /&gt;
give equal values. The core library adds &amp;lt;code&amp;gt;congrFun&amp;lt;/code&amp;gt; (equal functions give equal&lt;br /&gt;
values at one argument) and &amp;lt;code&amp;gt;congr&amp;lt;/code&amp;gt; (both at once), each proved by transport in&lt;br /&gt;
the same way. The library&amp;#039;s documentation notes that tactics such as &amp;lt;code&amp;gt;congr&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;simp&amp;lt;/code&amp;gt; use &amp;lt;code&amp;gt;congrArg&amp;lt;/code&amp;gt; internally to apply equalities inside&lt;br /&gt;
subterms.&amp;lt;ref name=&amp;quot;prelude&amp;quot; /&amp;gt; &amp;lt;code&amp;gt;congrArg&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;congr&amp;lt;/code&amp;gt; are stated for non-dependent functions. When the type of the&lt;br /&gt;
result depends on the argument, &amp;lt;code&amp;gt;f a₁&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;f a₂&amp;lt;/code&amp;gt; have different&lt;br /&gt;
types, and the statement &amp;lt;code&amp;gt;f a₁ = f a₂&amp;lt;/code&amp;gt; cannot even be formed. That case needs a&lt;br /&gt;
different relation.&lt;br /&gt;
&lt;br /&gt;
== Heterogeneous equality ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Heterogeneous equality&amp;#039;&amp;#039;&amp;#039; relates terms whose types are not known to be definitionally&lt;br /&gt;
equal. It is a second inductive family, written &amp;lt;code&amp;gt;a ≍ b&amp;lt;/code&amp;gt; in Lean 4.34.1:&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;
#print HEq&lt;br /&gt;
#check fun (n m : Nat) (x : Fin (n + m)) (y : Fin (m + n)) =&amp;gt; x ≍ y&lt;br /&gt;
#check @type_eq_of_heq&lt;br /&gt;
#check @eq_of_heq&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;
inductive HEq.{u} : {α : Sort u} → α → {β : Sort u} → β → Prop&lt;br /&gt;
number of parameters: 2&lt;br /&gt;
constructors:&lt;br /&gt;
HEq.refl : ∀ {α : Sort u} (a : α), a ≍ a&lt;br /&gt;
fun n m x y =&amp;gt; x ≍ y : (n m : Nat) → Fin (n + m) → Fin (m + n) → Prop&lt;br /&gt;
@type_eq_of_heq : ∀ {α β : Sort u_1} {a : α} {b : β}, a ≍ b → α = β&lt;br /&gt;
@eq_of_heq : ∀ {α : Sort u_1} {a a&amp;#039; : α}, a ≍ a&amp;#039; → a = a&amp;#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The statement &amp;lt;code&amp;gt;x ≍ y&amp;lt;/code&amp;gt; is well formed even though &amp;lt;code&amp;gt;Fin (n + m)&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;Fin (m + n)&amp;lt;/code&amp;gt; are equal only by a theorem about addition. The same statement&lt;br /&gt;
with &amp;lt;code&amp;gt;=&amp;lt;/code&amp;gt; is rejected:&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;
#check fun (n m : Nat) (x : Fin (n + m)) (y : Fin (m + n)) =&amp;gt; x = y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lean reports &amp;lt;code&amp;gt;Type mismatch&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt; has type &amp;lt;code&amp;gt;Fin (m + n)&amp;lt;/code&amp;gt; but&lt;br /&gt;
is expected to have type &amp;lt;code&amp;gt;Fin (n + m)&amp;lt;/code&amp;gt;. A proof of &amp;lt;code&amp;gt;x ≍ y&amp;lt;/code&amp;gt; carries a&lt;br /&gt;
proof that the types agree, which &amp;lt;code&amp;gt;type_eq_of_heq&amp;lt;/code&amp;gt; extracts, and at a single type&lt;br /&gt;
it collapses to ordinary equality by &amp;lt;code&amp;gt;eq_of_heq&amp;lt;/code&amp;gt;. The core library&amp;#039;s own&lt;br /&gt;
documentation advises avoiding &amp;lt;code&amp;gt;HEq&amp;lt;/code&amp;gt; where possible: the analogue of&lt;br /&gt;
&amp;lt;code&amp;gt;congr&amp;lt;/code&amp;gt; fails for it, since from &amp;lt;code&amp;gt;f ≍ g&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;x ≍ y&amp;lt;/code&amp;gt; it does&lt;br /&gt;
not follow that &amp;lt;code&amp;gt;f x ≍ g y&amp;lt;/code&amp;gt;; the equality of types that &amp;lt;code&amp;gt;HEq&amp;lt;/code&amp;gt; carries is&lt;br /&gt;
often too weak.&amp;lt;ref name=&amp;quot;prelude&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Function extensionality ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Function extensionality&amp;#039;&amp;#039;&amp;#039; says that functions which agree at every argument are equal.&lt;br /&gt;
The eliminator of &amp;lt;code&amp;gt;Eq&amp;lt;/code&amp;gt; offers no way to compare two lambda terms by their&lt;br /&gt;
values. The Lean reference manual notes that function extensionality would have to be an&lt;br /&gt;
axiom in Lean, were it not for quotient types, whose lifting operator has a definitional&lt;br /&gt;
computation rule.&amp;lt;ref name=&amp;quot;refman-quot&amp;quot;&amp;gt;&amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version 4.34.0, §4.5.6 &amp;quot;Quotients and Function Extensionality&amp;quot;. https://lean-lang.org/doc/reference/4.34.0/The-Type-System/Quotients/#quotient-funext&amp;lt;/ref&amp;gt; The proof in the&lt;br /&gt;
core library forms the quotient of the function type by pointwise equality and applies each&lt;br /&gt;
class to an argument:&amp;lt;ref name=&amp;quot;prelude&amp;quot; /&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;
theorem funext&amp;#039; {α : Sort u} {β : α → Sort v} {f g : (x : α) → β x}&lt;br /&gt;
    (h : ∀ x, f x = g x) : f = g :=&lt;br /&gt;
  let eqv (f g : (x : α) → β x) : Prop := ∀ x, f x = g x&lt;br /&gt;
  let app (q : Quot eqv) (x : α) : β x := Quot.lift (fun f =&amp;gt; f x) (fun _ _ h =&amp;gt; h x) q&lt;br /&gt;
  congrArg app (Quot.sound h)&lt;br /&gt;
&lt;br /&gt;
#print axioms funext&amp;#039;&lt;br /&gt;
#print axioms funext&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;
&amp;#039;funext&amp;#039;&amp;#039; depends on axioms: [Quot.sound]&lt;br /&gt;
&amp;#039;funext&amp;#039; depends on axioms: [Quot.sound]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The axiom &amp;lt;code&amp;gt;Quot.sound&amp;lt;/code&amp;gt; makes the classes of &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;g&amp;lt;/code&amp;gt;&lt;br /&gt;
equal, and &amp;lt;code&amp;gt;congrArg&amp;lt;/code&amp;gt; carries that equality through &amp;lt;code&amp;gt;app&amp;lt;/code&amp;gt;. The proof&lt;br /&gt;
type-checks only because &amp;lt;code&amp;gt;app (Quot.mk eqv f)&amp;lt;/code&amp;gt; reduces, by the computation rule&lt;br /&gt;
for &amp;lt;code&amp;gt;Quot.lift&amp;lt;/code&amp;gt;, to &amp;lt;code&amp;gt;fun x =&amp;gt; f x&amp;lt;/code&amp;gt;, which is &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; up to&lt;br /&gt;
η. A merely propositional computation rule would not do: rewriting under the binder would&lt;br /&gt;
already need function extensionality.&amp;lt;ref name=&amp;quot;refman-quot&amp;quot; /&amp;gt; The axiom itself, and why&lt;br /&gt;
it is one, are on [[Lean theorem prover/Foundations/The three axioms|the three axioms]].&lt;br /&gt;
&lt;br /&gt;
== Uniqueness of identity proofs ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Uniqueness of identity proofs&amp;#039;&amp;#039;&amp;#039; (UIP) says that any two proofs of&lt;br /&gt;
&amp;lt;code&amp;gt;a = b&amp;lt;/code&amp;gt; are equal. Streicher&amp;#039;s &amp;#039;&amp;#039;&amp;#039;axiom K&amp;#039;&amp;#039;&amp;#039; is the special case that every&lt;br /&gt;
proof of &amp;lt;code&amp;gt;a = a&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;Eq.refl a&amp;lt;/code&amp;gt;, and the two are equivalent.&amp;lt;ref name=&amp;quot;hott&amp;quot;&amp;gt;The Univalent Foundations Program, &amp;#039;&amp;#039;Homotopy Type Theory: Univalent Foundations of Mathematics&amp;#039;&amp;#039;, Institute for Advanced Study, 2013; Notes to Chapter 1, Example 3.1.9 and §7.2. https://homotopytypetheory.org/book/&amp;lt;/ref&amp;gt;&lt;br /&gt;
In Lean both hold by definition:&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 uip {α : Sort u} {a b : α} (h₁ h₂ : a = b) : h₁ = h₂ := rfl&lt;br /&gt;
&lt;br /&gt;
theorem axiomK {α : Sort u} {a : α} (C : α → Sort v) (h : a = a) (x : C a) :&lt;br /&gt;
    h ▸ x = x := rfl&lt;br /&gt;
&lt;br /&gt;
#print axioms uip&lt;br /&gt;
#print axioms axiomK&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both report that they do not depend on any axioms. The first is definitional proof&lt;br /&gt;
irrelevance: &amp;lt;code&amp;gt;a = b&amp;lt;/code&amp;gt; is a proposition, so any two of its proofs are definitionally&lt;br /&gt;
equal. The second is what Carneiro calls K-like reduction: for a subsingleton eliminator,&lt;br /&gt;
proof irrelevance lets the major premise be replaced by the constructor, after which the&lt;br /&gt;
ordinary computation rule applies. For &amp;lt;code&amp;gt;Eq&amp;lt;/code&amp;gt; this means that transport along&lt;br /&gt;
&amp;lt;code&amp;gt;h : a = a&amp;lt;/code&amp;gt; reduces to the identity, whatever &amp;lt;code&amp;gt;h&amp;lt;/code&amp;gt; is.&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; p. 4 (UIP and univalence), p. 12 (K-like reduction), p. 15 (proof irrelevance and axiom K in Lean and Coq). https://github.com/digama0/lean-type-theory/releases/tag/v1.0&amp;lt;/ref&amp;gt;&lt;br /&gt;
Carneiro lists proof irrelevance and axiom K among the axioms commonly added to Coq, and&lt;br /&gt;
observes that they hold in Lean with no axioms.&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Homotopy type theory takes the opposite course. It reads a proof of equality as a path,&lt;br /&gt;
keeps proofs of equality relevant, and treats UIP as a property some types have rather&lt;br /&gt;
than an axiom.&amp;lt;ref name=&amp;quot;hott&amp;quot; /&amp;gt; Its univalence axiom identifies equivalent types. The&lt;br /&gt;
two-element type then has a non-trivial self-equality, the swap, so the universe is not a&lt;br /&gt;
set, and univalence is inconsistent with UIP.&amp;lt;ref name=&amp;quot;hott&amp;quot; /&amp;gt;&amp;lt;ref name=&amp;quot;carneiro&amp;quot; /&amp;gt;&lt;br /&gt;
Because Lean&amp;#039;s UIP is part of definitional equality rather than an axiom that could be&lt;br /&gt;
left out, univalence cannot be added to Lean without making it inconsistent.&lt;br /&gt;
&lt;br /&gt;
== Next ==&lt;br /&gt;
&lt;br /&gt;
[[Lean theorem prover/Foundations/Quotient types|Quotient types]] treats the construction&lt;br /&gt;
that the proof of function extensionality used.&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>