halfway through Relations

This commit is contained in:
wadler 2018-03-07 13:25:35 -03:00
parent b088ee59cf
commit ee13c1c6ed
2 changed files with 97 additions and 66 deletions

View file

@ -746,6 +746,13 @@ Show that monus associates with addition, that is,
for all naturals `m`, `n`, and `p`.
## Standard library
Definitions from this chapter can be found in the standard library.
\begin{code}
import Data.Nat.Properties.Simple using (+-assoc; +-identityʳ; +-suc; +-comm)
\end{code}
## Unicode
This chapter introduces the following unicode.

View file

@ -10,15 +10,17 @@ the next step is to define relations, such as *less than or equal*.
## Imports
\begin{code}
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; cong; sym)
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
open import Data.Nat using (; zero; suc; _+_; _*_; _∸_)
open import Data.Nat.Properties.Simple using (+-comm)
open import Relation.Binary.PropositionalEquality using (_≡_; refl)
\end{code}
## Defining relations
The relation *less than or equal* has an infinite number of
instances. Here are just a few of them:
instances. Here are a few of them:
0 ≤ 0 0 ≤ 1 0 ≤ 2 0 ≤ 3 ...
1 ≤ 1 1 ≤ 2 1 ≤ 3 ...
@ -45,7 +47,7 @@ data _≤_ : → Set where
\end{code}
Here `z≤n` and `s≤s` (with no spaces) are constructor names,
while `m ≤ m`, and `m ≤ n` and `suc m ≤ suc n` (with spaces)
are propositions.
are types.
Both definitions above tell us the same two things:
@ -61,10 +63,6 @@ In fact, they each give us a bit more detail:
`s≤s` takes evidence that `m ≤ n` holds into evidence that
`suc m ≤ suc n` holds.
Here we have used the word *evidence* as interchangeable with the
word *proof*. We will tend to say *evidence* when we want to stress
that proofs are just terms in Agda.
For example, here in inference rule notation is the proof that
`2 ≤ 4`.
@ -77,32 +75,34 @@ For example, here in inference rule notation is the proof that
And here is the corresponding Agda proof.
\begin{code}
ex₁ : 2 ≤ 4
ex₁ = s≤s (s≤s z≤n)
_ : 2 ≤ 4
_ = s≤s (s≤s z≤n)
\end{code}
## Implicit arguments
In the Agda definition, the two lines defining the constructors
use `∀`, very similar to our use of `∀` in propositions such as:
com+ : ∀ (m n : ) → m + n ≡ n + m
+-comm : ∀ (m n : ) → m + n ≡ n + m
However, here the declarations are surrounded by curly braces `{ }`
rather than parentheses `( )`. This means that the arguments are
*implicit* and need not be written explicitly. Thus, we would write,
for instance, `com+ m n` for the proof that `m + n ≡ n + m`, but
here will write `z≤n` for the proof that `m ≤ m`, leaving the `m` implicit,
or if `m≤n` is evidence that `m ≤ n`, we write write `s≤s m≤n` for the
*implicit* and need not be written explicitly; instead, they are
*inferred* by Agda's typechecker. Thus, we write
`+-comm m n` for the proof that `m + n ≡ n + m`, but
`z≤n` for the proof that `m ≤ m`, leaving `m` implicit.
Similarly, if `m≤n` is evidence that `m ≤ n`, we write write `s≤s m≤n` for
evidence that `suc m ≤ suc n`, leaving both `m` and `n` implicit.
It is possible to provide implicit arguments explicitly if we wish, by
If we wish, it is possible to provide implicit arguments explicitly by
writing the arguments inside curly braces. For instance, here is the
Agda proof that `2 ≤ 4` repeated, with the implicit arguments made
explicit.
\begin{code}
ex₂ : 2 ≤ 4
ex₂ = s≤s {1} {3} (s≤s {0} {2} (z≤n {2}))
_ : 2 ≤ 4
_ = s≤s {1} {3} (s≤s {0} {2} (z≤n {2}))
\end{code}
## Precedence
@ -111,12 +111,11 @@ We declare the precedence for comparison as follows.
\begin{code}
infix 4 _≤_
\end{code}
We set the precedence of `_≤_` at level 4, which means it binds less
tightly that `_+_` at level 6 or `_*_` at level 7, meaning that `1 + 2
≤ 3` parses as `(1 + 2) ≤ 3`. We write `infix` to indicate that the
operator does not associate to either the left or right, as it makes
no sense to give `1 ≤ 2 ≤ 3` either the meaning `(1 ≤ 2) ≤ 3` or `1 ≤
(2 ≤ 3)`.
We set the precedence of `_≤_` at level 4, so it binds less tightly
that `_+_` at level 6 and hence `1 + 2 ≤ 3` parses as `(1 + 2) ≤ 3`.
We write `infix` to indicate that the operator does not associate to
either the left or right, as it makes no sense to parse `1 ≤ 2 ≤ 3` as
either `(1 ≤ 2) ≤ 3` or `1 ≤ (2 ≤ 3)`.
## Properties of ordering relations
@ -148,7 +147,7 @@ Less frivolously, if you ever bump into a relation while reading
a technical paper, this gives you an easy way to orient yourself,
by checking whether or not it is a preorder, partial order, or total order.
A careful author will often make it explicit, for instance by saying
that a given relation is a preoder but not a partial order, or a
that a given relation is a preorder but not a partial order, or a
partial order but not a total order. (Can you think of examples of
such relations?)
@ -184,12 +183,26 @@ p` hold, then `m ≤ p` holds.
Here the proof is most easily thought of as by induction on the
*evidence* that `m ≤ n`, so we have left `m`, `n`, and `p` implicit.
In the base case, the first inequality holds by `z≤n`, and so
arwe are given `zero ≤ n` and `n ≤ p` and must show `zero ≤ p`,
which follows immediately by `z≤n`. In this
case, the fact that `n ≤ p` is irrelevant, and we write `_` as the
pattern to indicate that the corresponding evidence is unused.
In the inductive case, the first inequality holds by `s≤s m≤n`
and the second inequality by `s≤s n≤p`, and so we are given
`suc m ≤ suc n` and `suc n ≤ suc p`, and must show `suc m ≤ suc p`.
The inductive hypothesis `≤-trans m≤n n≤p` establishes
that `m ≤ p`, and our goal follows by applying `s≤s`.
<!--
In the base case, `m ≤ n` holds by `z≤n`, so it must be that
`m` is `zero`, in which case `m ≤ p` also holds by `z≤n`. In this
case, the fact that `n ≤ p` is irrelevant, and we write `_` as the
pattern to indicate that the corresponding evidence is unused. We
could instead have written `n≤p` but not used that variable on the
right-hand side of the equation.
pattern to indicate that the corresponding evidence is unused.
In the inductive case, `m ≤ n` holds by `s≤s m≤n`, so it must be that `m`
is `suc m` and `n` is `suc n` for some `m` and `n`, and `m≤n` is
@ -199,10 +212,12 @@ evidence that `n ≤ p`. The inductive hypothesis `≤-trans m≤n n≤p`
provides evidence that `m ≤ p`, and applying `s≤s` to that gives
evidence of the desired conclusion, `suc m ≤ suc p`.
The case `≤-trans (s≤s m≤n) z≤n` cannot arise, since the first piece of
evidence implies `n` must be `suc n` for some `n` while the second
implies `n` must be `zero`. Agda can determine that such a case cannot
arise, and does not require it to be listed.
-->
The case `≤-trans (s≤s m≤n) z≤n` cannot arise, since the first
inequality implies the middle value is `suc n` while the second
inequality implies that it is `zero`. Agda can determine that
such a case cannot arise, and does not require it to be listed.
Alternatively, we could make the implicit parameters explicit.
\begin{code}
@ -210,9 +225,9 @@ Alternatively, we could make the implicit parameters explicit.
≤-trans zero n p z≤n _ = z≤n
≤-trans (suc m) (suc n) (suc p) (s≤s m≤n) (s≤s n≤p) = s≤s (≤-trans m n p m≤n n≤p)
\end{code}
One might argue that this is clearer, since it shows us the forms of `m`, `n`,
and `p`, or one might argue that the extra length obscures the essence of the
proof. We will usually opt for shorter proofs.
One might argue that this is clearer or one might argue that the extra
length obscures the essence of the proof. We will usually opt for
shorter proofs.
The technique of inducting on evidence that a property holds (e.g.,
inducting on evidence that `m ≤ n`)---rather than induction on the
@ -222,6 +237,7 @@ out to be immensely valuable, and one that we use often.
Again, it is a good exercise to prove transitivity interactively in Emacs,
using holes and the `^C ^C`, `^C ^,`, and `^C ^R` commands.
## Anti-symmetry
The third property to prove about comparison is that it is antisymmetric:
@ -230,22 +246,36 @@ for all naturals `m` and `n`, if both `m ≤ n` and `n ≤ m` hold, then
\begin{code}
≤-antisym : ∀ {m n : } → m ≤ n → n ≤ m → m ≡ n
≤-antisym z≤n z≤n = refl
≤-antisym (s≤s m≤n) (s≤s n≤m) rewrite ≤-antisym m≤n n≤m = refl
≤-antisym (s≤s m≤n) (s≤s n≤m) = cong suc (≤-antisym m≤n n≤m)
\end{code}
Again, the proof is by induction over the evidence that `m ≤ n`
and `n ≤ m` hold, and so we have left `m` and `n` implicit.
In the base case, both inequalities hold by `z≤n`,
and so we are given `zero ≤ zero` and `zero ≤ zero` and must
show `zero ≡ zero`, which follows by reflexivity. (Reflexivity
of equality, that is, not reflexivity of inequality.)
In the inductive case, the first inequality holds by `s≤s m≤n`
and the second inequality holds by `s≤s n≤m`, and so we are
given `suc m ≤ suc n` and `suc n ≤ suc m` and must show `suc m ≡ suc n`.
The inductive hypothesis `≤-antisym m≤n n≤m` establishes that `m ≡ n`,
and our goal follows by congruence.
<!--
In the base case, both relations hold by `z≤n`,
so it must be the case that `m` and `n` are both `zero`,
in which case `m ≡ n` holds by reflexivity. (The reflexivity
of equivalance, that is, not the reflexivity of comparison.)
of `_≡_`, that is, not the reflexivity of `_≤_`.)
In the inductive case, `m ≤ n` holds by `s≤s m≤n` and `n ≤ m` holds by
`s≤s n≤m`, so it must be that `m` is `suc m` and `n` is `suc n`, for
some `m` and `n`, where `m≤n` is evidence that `m ≤ n` and `n≤m`
is evidence that `n ≤ m`. The inductive hypothesis `≤-antisym m≤n n≤m`
establishes that `m ≡ n`, and rewriting by this equation establishes
that `m ≡ n` holds by reflexivity.
establishes that `m ≡ n`, and so the final result follows by congruence.
-->
## Disjunction
@ -254,18 +284,18 @@ the notion that given two propositions either one or the other holds.
In Agda, we do so by declaring a suitable inductive type.
\begin{code}
data _⊎_ : Set → Set → Set where
inj₁ : ∀ {A B : Set} → A → A ⊎ B
inj₁ : ∀ {A B : Set} → A → A ⊎ B
inj₂ : ∀ {A B : Set} → B → A ⊎ B
\end{code}
This tells us that if `A` and `B` are propositions then `A ⊎ B` is
also a proposition. Evidence that `A ⊎ B` holds is either of the form
`inj₁ a`, where `a` is evidence that `A` holds, or `inj₂ b`, where
`b` is evidence that `B` holds.
`inj₁ x`, where `x` is evidence that `A` holds, or `inj₂ y`, where
`y` is evidence that `B` holds.
We set the precedence of disjunction so that it binds less tightly
than comparison.
We set the precedence of disjunction so that it binds less tightly than
inequality.
\begin{code}
infix 1 _⊎_
infixr 1 _⊎_
\end{code}
Thus, `m ≤ n ⊎ n ≤ m` parses as `(m ≤ n) ⊎ (n ≤ m)`.
@ -306,10 +336,10 @@ and second arguments. We perform a case analysis:
proposition holds with `s≤s n≤m` as evidence that `suc n ≤ suc m`.
This is our first use of the `with` clause in Agda. The keyword
`with` is followed by an expression, and one or more subsequent lines.
`with` is followed by an expression and one or more subsequent lines.
Each line begins with an ellipsis (`...`) and a vertical bar (`|`),
followed by a pattern to be matched against the expression, an equal
sign, and the right-hand side of the equation.
followed by a pattern to be matched against the expression
and the right-hand side of the equation.
Every use of `with` is equivalent to defining a helper function. For
example, the definition above is equivalent to the following.
@ -323,18 +353,17 @@ example, the definition above is equivalent to the following.
helper (inj₁ m≤n) = inj₁ (s≤s m≤n)
helper (inj₂ n≤m) = inj₂ (s≤s n≤m)
\end{code}
This is also our first use of a `where` clause in Agda. The keyword
`where` is followed by one or more definitions, which must be
indented. Any identifiers bound in the nested definition are in scope
in the right-hand side of the preceding equation (in this case,
`helper`), and any variables bound of the left-hand side of the
preceding equation are in scope within the nested definition (in this
case, `m` and `n`).
This is also our first use of a `where` clause in Agda. The keyword `where` is
followed by one or more definitions, which must be indented. Any variables
bound of the left-hand side of the preceding equation (in this case, `m` and
`n`) are in scope within the nested definition, and any identifiers bound in the
nested definition (in this case, `helper`) are in scope in the right-hand side
of the preceding equation.
If both arguments are equal, then both the first and second disjuncts
hold and we could return evidence of either. In the code above we
always return the first disjunct, but there is a minor variant that
always returns the second disjunct.
return the first disjunct, but there is a minor variant that
returns the second disjunct.
\begin{code}
≤-total″ : ∀ (m n : ) → m ≤ n ⊎ n ≤ m
≤-total″ m zero = inj₂ z≤n
@ -347,17 +376,13 @@ always returns the second disjunct.
## Monotonicity
If one bumps into both an operator and an order relation at
If one bumps into both an operator and an ordering at
a party, one may ask if the operator is *monotonic* with regard
to the order relation. For example, addition is monotonic
with regard to comparison, meaning
to the ordering. For example, addition is monotonic
with regard to inequality, meaning
∀ {m n p q : } → m ≤ n → p ≤ q → m + p ≤ n + q
Addition (precedence level 6) binds more tightly than comparison
(precedence level 4), so `m + n ≤ p + q` parses as
`(m + n) ≤ (p + q)`.
The proof is straightforward using the techniques we have learned,
and is best broken into three parts. First, we deal with the special
case of showing addition is monotonic on the right.
@ -370,13 +395,12 @@ The proof is by induction on the first argument.
+ *Base case*: The first argument is `zero` in which case
`zero + p ≤ zero + q` simplifies to `p ≤ q`, the evidence
for which is given by the explicit argument `p≤q`.
for which is given by the argument `p≤q`.
+ *Inductive case*: The first argument is `suc m`, in which case
`suc m + p ≤ suc m + q` simplifies to `suc (m + p) ≤ suc (m + q)`.
The inductive hypothesis `+-monoʳ-≤ m p q p≤q` establishes that
`m + p ≤ m + q`, from which the desired conclusion follows
by an application of `s≤s`.
`m + p ≤ m + q`, and our goal follows by applying `s≤s`.
Second, we deal with the special case of showing addition is
monotonic on the left. This follows from the previous