module Padova2025.ProvingBasics.Equality.Base where
Definition
In blackboard mathematics, βxβ=βyβ is an
assertion, a statement. For instance, this assertion
might be true, or it might be false. In the Agda community,
x β‘ y
is a typeβthe type of witnesses that x
and y
are equal. For instance, this type could be
inhabited, or it could be empty.
If in blackboard mathematics we would prove that xβ=βy, in Agda we exhibit a
value of type x β‘ y
.
The following three lines set up these types:
infix 4 _β‘_ data _β‘_ {X : Set} : X β X β Set where refl : {a : X} β a β‘ a
The basic equality symbol =
is used in Agda only for
definitions. For formulating assumptions or results involing equality,
we use β‘
.
Example: Our first identities
open import Padova2025.ProgrammingBasics.Naturals.Base open import Padova2025.ProgrammingBasics.Naturals.Arithmetic open import Padova2025.ProgrammingBasics.DependentFunctions
With the definition of equality at hand, we can state and prove that
zero
equals zero
:
zero-equals-zero : zero β‘ zero zero-equals-zero = refl
In exactly the same fashion, we can state and prove that
two + two
equals four
:
grande-teorema : two + two β‘ four -- fully parenthesized as follows: grande-teorema : ((two + two) β‘ four) grande-teorema = refl
We can use refl
in exactly those situations, where the
two sides of the alleged identity are manifestly equal,
i.e.Β equal in a way which just requires unfolding all definitions and
simplifying by computation, but no actual insights, to become convinced
of the equality.
For instance, as zero + b
equals b
by
definition, refl
can be used in the following
proof:
trivial : (b : β) β zero + b β‘ b -- fully parenthesized: lemma : (b : β) β ((zero + b) β‘ b) trivial b = refl
This piece of code can (as all pieces of Agda code!) be both read in a logical and in a computational sense:
(logical reading)
βlemmaβ is the result that for every numberb
,zero + b
equalsb
.(computational reading)
βlemmaβ is a function which reads as input a numberb
, and outputs a witness thatzero + b
equalsb
.
It is also true that a + zero
equals a
.
However, this identity does not hold by definition; instead it
requires a nontrivial
(inductive) argument. For this reason, Agda rejects
refl
in the following attempt:
nontrivial : (a : β) β a + zero β‘ a
nontrivial a = refl
-- ERROR:
-- a + zero != a of type β
-- when checking that the expression refl has type a + zero β‘ a
Example: One not zero
It is not the case that one
equals zero
.
And indeed, the hole in the following piece of Agda code cannot be
filled:
outrageous : one β‘ zero
outrageous = ?
It is instructive to understand why this is the case. At the end of
the day, for constructing an inhabitant of the type
one β‘ zero
, we will need to use a constructor of this type.
But the only constructor is refl
. This constructor only
provides us with elements of types of the for x β‘ x
, where
the two sides are literally the same. But succ zero
is (by
definition) a freshly-minted new natural number, distint from
zero
.
The only way to fill in this hole would be to change the definition
of β‘
. For instance, we could add a constructor
bailout
:
data _β‘'_ {X : Set} : X β X β Set where refl : {x : X} β x β‘' x bailout : {x y : X} β x β‘' y outrageous' : one β‘' zero outrageous' = bailout
Exercise: Predecessor of successor
Prove that the predecessor of a successor of a number is the original number again.
lemma-pred-succ : (a : β) β pred (succ a) β‘ a lemma-pred-succ a = {!!}
Unit tests
If a definition is not used in the remainder of a development, Agda
supports giving it the reusable dummy name β_
β. This
feature is used in the Agda community to document expected results as
rigorously verified unit tests, instead of merely putting examples in
comments.
_ : twice two β‘ four _ = refl