I am interested in strategies for representing proof terms inside the kernel of a proof assistant, specifically proofs of equality.
What are the different strategies that are available for representing proofs of equality inside the kernel of a proof assistant?
My question is motivated by learning about nth_rewrite
in Lean for use in the natural numbers game, which made me realize I don't actually know what rewrite
-like tactics are doing under the hood in the kernel of a "prototypical" proof assistant.
Note that this question is deliberately agnostic about whether my underlying logic is constructive or classical, but I just assume that we have the deduction theorem so I can paraphrase away uses of non-modus-ponens-like inference rules. My question is also agnostic about whether I have equality types or a separate notion of an equality judgment that is not part of the type hierarchy (I don't know the technical merits of one choice vs the other (or if any serious proof assistants have equality judgments that are not types)).
I think that rules like modus ponens $\frac{A \to B \;\; \text{and} \;\; A}{B}$ and universal instantiation $\frac{\forall x : S \mathop. \varphi(x) \;\;\text{and}\;\; \text{$t$ is a term of sort $S$}}{\varphi(t)}$ can be represented internally as something kind of like a function application.
Other inference rules like $\frac{A \land B}{A}$ can be represented as axioms $A \land B \to A$ and modus ponens.
However, I have no idea how one would represent proofs of equalities like $s = t$.
For example, suppose I knew $s = t$ and I wanted to prove that $s * s = s * t$.
I know that $s * s = s * s$ holds by reflexivity, so I probably need something like $\text{refl}(\alpha) : \alpha = \alpha$ for all $\alpha$.
Cool, I have my proof, $\text{refl}{s * s} : s * s = s * s$.
However, I now need to change that into $s * s = s * t$. If I naively apply $s * t$ as a rewrite, I will end up with $t * t = t * t$ or something, I need to control which part of $s * s$ gets rewritten.
In Coq, as a user, I would use setoid_rewrite
or similar to achieve this and to target just the site that I'm interested in.
Inside a kernel, I can imagine having $\text{nthRewrite}(\beta, 47, \alpha : s = t)$ as a proof of $\beta = \beta[s :=^ {47} t]$ where $[s :=^ {47} t]$ denotes replacing the $47$th occurrence of $s$ with $t$ in $\beta$. My number could also just indicate which position in the wff to replace according to some numbering scheme instead of counting unification sites.
I think that such a primitive term would actually suffice for any possible rewrite that I might want to represent, but it would be horrifically inconvenient to "reindex" the rewrites if I want to normalize proof terms.
I cloud also imagine using something similar to the Leibniz inference rule in equational logic, but I don't know how the details would work out.
f : A -> B, x : C
,A = C
is checked when checkingf x
. The equality we actually care about proving is usually a different thing. This "propositional equality" (as opposed to "definitional equality") can be defined as an ordinary inductive type, if those are available:Inductive eq {A} (x : A) : A -> Type := eq_refl : forall x, eq x x.
(as in Coq). Pattern matching/induction is how you use aneq x y
hypothesis in a proof. If the linked question does not answer your specific question, OP, you can reopen this one. $\endgroup$