In Martin-Löf dependent type theory, equality (the identity type) is itself a Dependent Type: for every type and pair of values there is a type , written , whose elements are proofs that equals (Curry–Howard). is a type, like Int; is hopefully uninhabited.
- Introduction rule: the dependent function — reflexivity, "". Applying to proves .
- Elimination rule (the J-rule): given a family over , and a function defined on the diagonal, there exists with the computation rule . There is no “step” as for induction: J extends from the diagonal to the whole -space by fiat — “a leap of faith”, comparable to parametricity (all polymorphic functions are natural) or analytic continuation.
- There is no uniqueness () rule for equality: there may be equality proofs not obtained from . This weakening is what makes homotopy type theory (HoTT) interesting: proofs are paths, proofs of equality of proofs are homotopies, and the univalence axiom states — equality is equivalent to equivalence, resolving the tension between category theorists’ preference for isomorphism and the convenience of substituting equals for equals.
Sources: DaoFP §11.5 (“Equality”: “Equational reasoning”, “Equality vs isomorphism”, “Equality types”, “Introduction rule”, “-reduction and -conversion”, “Induction principle for natural numbers”, “Equality elimination rule”).
Definitional vs propositional equality
Definitional equality is proved by rewriting — substituting equals for equals using the clauses of definitions, -reduction (\x -> x + x) 2 = 2 + 2 — which is the basis of equational reasoning about pure programs (impossible with side effects). E.g. with add n Z = n; add n (S m) = S (add n m) one computes add (S Z) (S Z) = S (S Z) and equal (S (S Z)) (S (S Z)) = True step by step. But add Z n = n for all n needs induction: a propositional equality requiring an actual proof term.
For products, the computation rule (: fst (x, y) = x) and the uniqueness rule (: (fst p, snd p) = p) both follow from the universal property in the categorical model; for and for the rule is absent.
import Mathlib
#check @Eq -- the identity type: Eq a b, notation a = b
#check @Eq.refl -- introduction: ∀ x, x = x
#check @Eq.rec -- the J-rule (elimination)
#check @Eq.subst -- substituting equals for equals
example : (1 : ℕ) + 1 = 2 := rfl -- definitional equality
theorem zero_add' (n : ℕ) : 0 + n = n := by -- propositional: needs induction
induction n with
| zero => rfl
| succ k ih => rw [Nat.add_succ, ih]-- Haskell cannot express proofs of equality, but supports equational reasoning:
data Nat = Z | S Nat
equal :: Nat -> Nat -> Bool
equal Z Z = True
equal (S m) (S n) = equal m n
equal _ _ = False
add :: Nat -> Nat -> Nat
add n Z = n
add n (S m) = S (add n m)
-- add (S Z) (S Z) = S (add (S Z) Z) = S (S Z) by rewriting with the clauses
-- With GADTs one can encode a propositional equality type:
-- data a :~: b where Refl :: a :~: a (Data.Type.Equality)