further revisions to Naturals

This commit is contained in:
wadler 2018-03-05 18:34:22 -03:00
parent a6f413ecb4
commit 929da32c56
2 changed files with 197 additions and 65 deletions

View file

@ -123,7 +123,7 @@ Let's look again at the rules that define the natural numbers:
natural number. natural number.
Hold on! The second line defines natural numbers in terms of natural Hold on! The second line defines natural numbers in terms of natural
numbers. How can that posssibly be allowed? Isn't this as meaningless numbers. How can that possibly be allowed? Isn't this as meaningless
as the claim "Brexit means Brexit"? as the claim "Brexit means Brexit"?
In fact, it is possible to assign our definition a meaning without In fact, it is possible to assign our definition a meaning without
@ -294,7 +294,7 @@ zero + n = n -- (i)
\end{code} \end{code}
Let's unpack this definition. Addition is an infix operator. It is Let's unpack this definition. Addition is an infix operator. It is
written with underbars where the arguement go, hence its name is written with underbars where the argument go, hence its name is
`_+_`. It's type, ``, indicates that it accepts two naturals `_+_`. It's type, ``, indicates that it accepts two naturals
and returns a natural. There are two ways to construct a natural, and returns a natural. There are two ways to construct a natural,
with `zero` or with `suc`, so there are two lines defining addition, with `zero` or with `suc`, so there are two lines defining addition,
@ -329,6 +329,7 @@ numbers. Such a definition is called *well founded*.
For example, let's add two and three. For example, let's add two and three.
\begin{code} \begin{code}
_ : 2 + 3 ≡ 5
_ = _ =
begin begin
2 + 3 2 + 3
@ -344,14 +345,11 @@ _ =
5 5
\end{code} \end{code}
Here we have written an Agda term, bound to the dummy name `_`,
which we will use for all examples.
The type of the term is `2 + 3 ≡ 5`,
that is, the term provides *evidence* for the corresponding equivalence.
We can write the same derivation more compactly by only We can write the same derivation more compactly by only
expanding shorthand as needed. expanding shorthand as needed.
\begin{code} \begin{code}
_ : 2 + 3 ≡ 5
_ = _ =
begin begin
2 + 3 2 + 3
@ -369,17 +367,23 @@ The first use of (ii) matches by taking `m = 1` and `n = 3`,
The second use of (ii) matches by taking `m = 0` and `n = 3`, The second use of (ii) matches by taking `m = 0` and `n = 3`,
and the use of (i) matches by taking `n = 3`. and the use of (i) matches by taking `n = 3`.
Agda uses two different symbols for equality. Definitions are written In both cases, we write a type (after a colon) and a term of that type
with `=`, while assertions that two already defined things are the (after an equal sign), both assigned to the dummy name `_`. The dummy
same are written with `≡`. Here, we have written out our evidence name can be assigned many times, and is convenient for examples. One
that `2` and `3` sum to `5` as a chain of equivalences. The chain can also use other names, but each must be used only once in a module.
starts with `begin` and finishes with `∎` (pronounced "qed" or Note that definitions are written with `=`, while assertions that two
"tombstone", the latter from its appearance), and consists of a series already defined things are the same are written with `≡`.
of terms separated by `≡⟨⟩`. We take equivalence and the notations
for chains of equivalences as given for now, but will see how they are
defined in Chapter [Equivalence](Equivalence).
The same proof can also be written out even more compactly. Here the type is `2 + 3 ≡ 5` and the term provides *evidence* for the
corresponding equation, here written as a chain of equations. The
chain starts with `begin` and finishes with `∎` (pronounced "qed" or
"tombstone", the latter from its appearance), and consists of a series
of terms separated by `≡⟨⟩`. We take equivalence and chains as givens
for now, but will see how they are defined in Chapter
[Equivalence](Equivalence).
In fact, both proofs are longer than need be, and Agda is satisfied
with the following.
\begin{code} \begin{code}
_ : 2 + 3 ≡ 5 _ : 2 + 3 ≡ 5
_ = refl _ = refl
@ -388,18 +392,40 @@ Agda knows how to compute the value of `2 + 3`, and so can immediately
check it is the same as `5`. Evidence that a value is equal to check it is the same as `5`. Evidence that a value is equal to
itself is written `refl`, which is short for *reflexivity*. itself is written `refl`, which is short for *reflexivity*.
Here `2 + 3 ≡ 5` is a type, and `refl` is a term of the given type; In the chains of equations, all Agda checks is that each of the terms
alternatively, one can think of `refl` as *evidence* for the assertion `2 + 3 ≡ 5`. computes to the same value. If we jumble the equations, omit lines, or
We could have preceded the other two examples also with the line `_ : 2 + 3 ≡ 5`, add extraneous lines it will still pass, because all Agda does is
but it was redundant; here it is required because otherwise one would not know check that each term in the chain computes to the same value.
which equivalence `refl` was providing evidence for. \begin{code}
This duality of interpretation---as a term of a type, or as evidence _ : 2 + 3 ≡ 5
for an assertion---is central to how we formalise concepts in Agda. _ =
begin
2 + 3
≡⟨⟩
4 + 1
≡⟨⟩
5
≡⟨⟩
suc (suc (0 + 3))
\end{code}
Of course, writing a proof in this way would be misleading and confusing,
so we won't do it.
Here `2 + 3 ≡ 5` is a type, and the chain of equations (or `refl`) is
a term of the given type; alternatively, one can think of the term as
*evidence* for the assertion `2 + 3 ≡ 5`. This duality of
interpretation---as a term of a type, or as evidence for an
assertion---is central to how we formalise concepts in Agda. When we
use the word *evidence* it is nothing equivocal. It is not like
testimony in a court which must be weighed to determine whether the
witness is trustworthy. Rather, it is ironclad. The other word for
evidence, which we may use interchangeably, is *proof*.
### Exercise (`3+4`) ### Exercise (`3+4`)
Compute `3 + 4`, writing it out in the same style as above. Compute `3 + 4`, writing out your reasoning as a chain of equations.
## Multiplication ## Multiplication
@ -630,14 +656,14 @@ indicate that parentheses are always required to disambiguate.
## More pragmas ## More pragmas
Inluding the lines Including the lines
\begin{code} \begin{code}
{-# BUILTIN NATPLUS _+_ #-} {-# BUILTIN NATPLUS _+_ #-}
{-# BUILTIN NATTIMES _*_ #-} {-# BUILTIN NATTIMES _*_ #-}
{-# BUILTIN NATMINUS _∸_ #-} {-# BUILTIN NATMINUS _∸_ #-}
\end{code} \end{code}
tells Agda that these three operators correspond to the usual ones, tells Agda that these three operators correspond to the usual ones,
and enables it to perform these computations using the corresponing and enables it to perform these computations using the corresponding
Haskell operators on the integer type. Representing naturals with Haskell operators on the integer type. Representing naturals with
`zero` and `suc` requires time proportional to *m* to add *m* and *n*, `zero` and `suc` requires time proportional to *m* to add *m* and *n*,
whereas representing naturals as integers in Haskell requires time whereas representing naturals as integers in Haskell requires time
@ -652,35 +678,32 @@ of the logarithms of *m* and *n*.
## Standard library ## Standard library
At the end of each chapter, we will show where to find relevant At the end of each chapter, we will show where to find relevant
definitions in the standard library. definitions in the standard library. The naturals, constructors for
them, and basic operators upon them, are defined in the standard
library module `Data.Nat`.
import Data.Nat using (; zero; suc; _+_; _*_; _^_; _∸_) import Data.Nat using (; zero; suc; _+_; _*_; _^_; _∸_)
The naturals, constructors for them, and basic operators upon them, Normally, we will show an import as running code, so Agda will
are defined in the standard library module `Data.Nat`. complain if we attempt to import a definition that is not available.
This time, however, we have only shown the import as a comment. Both
Normally, we will show a "live" import, so Agda will complain if we this chapter and the standard library invoke the `NATURAL` pragma, the
attempt to import a definition that is not available. This time, former on ``, and the latter on the equivalent type `Data.Nat.`.
however, we have only shown the import as a comment, without attempting to Such a pragma can only be invoked once, as invoking it twice would
execute it. This is because both this chapter and the standard library raise confusion as to whether `2` is a value of type `` or type
invoke the `NATURAL` pragma on two copies of the same type, `` as `Data.Nat.`. Similar confusions arise if other pragmas are invoked
defined here and as defined in `Data.Nat`, and such a pragma can only twice. For this reason, we will not invoke pragmas in future chapters,
be invoked once. Invoking it twice would raise confusion as to whether leaving that to the standard library. More information on available
`2` is a value of type `` or type `Data.Nat.`. Similarly for other pragmas can be found in the Agda documentation.
pragmas. For this reason, we will not invoke pragmas in future
chapters. More information on available pragmas can be found in the
Agda documentation.
## Unicode ## Unicode
At the end of each chapter, we will also list relevant unicode. At the end of each chapter, we will list relevant unicode.
U+2115 DOUBLE-STRUCK CAPITAL N (\bN) U+2115 DOUBLE-STRUCK CAPITAL N (\bN)
→ U+2192 RIGHTWARDS ARROW (\to, \r) → U+2192 RIGHTWARDS ARROW (\to, \r)
∸ U+2238 DOT MINUS (\.-) ∸ U+2238 DOT MINUS (\.-)
∎ U+220E END OF PROOF (\qed) ∎ U+220E END OF PROOF (\qed)
U+2032 PRIME (\')
″ U+2033 DOUBLE PRIME (\')
Each line consists of the Unicode character (``), the corresponding Each line consists of the Unicode character (``), the corresponding
code point (`U+2115`), the name of the character (`DOUBLE-STRUCK CAPITAL N`), code point (`U+2115`), the name of the character (`DOUBLE-STRUCK CAPITAL N`),
@ -688,10 +711,9 @@ and the sequence to type into Emacs to generate the character (`\bN`).
The command `\r` gives access to a wide variety of rightward arrows. The command `\r` gives access to a wide variety of rightward arrows.
After typing `\r`, one can access the many available arrows by using After typing `\r`, one can access the many available arrows by using
the left, right, up, and down keys to navigate. Similarly, `\'` gives the left, right, up, and down keys to navigate. The command remembers
access to several primes, which one can access by using the left and where you navigated to the last time, and starts with the same
right keys to navigate. The commands remember where you navigated to character next time.
the last time, and start with the same character next time.
In place of left, right, up, and down keys, one may also use control characters. In place of left, right, up, and down keys, one may also use control characters.

View file

@ -16,7 +16,7 @@ We require equivalence as in the previous chapter, plus the naturals
and some operations upon them. and some operations upon them.
\begin{code} \begin{code}
import Relation.Binary.PropositionalEquality as Eq import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl) open Eq using (_≡_; refl; cong)
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎) open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
open import Data.Nat using (; zero; suc; _+_; _*_; _∸_) open import Data.Nat using (; zero; suc; _+_; _*_; _∸_)
\end{code} \end{code}
@ -159,8 +159,48 @@ we must show to hold, become:
--------------------------------- ---------------------------------
(suc m + n) + p ≡ (suc m + n) + p (suc m + n) + p ≡ (suc m + n) + p
In the inference rules, `n` and `p` are any arbitary natural numbers, so when we In the inference rules, `n` and `p` are arbitary natural numbers, so
are done with the proof we know it holds for any `n` and `p` as well as any `m`. when we are done with the proof we know the equation hold for any `n`
and `p` as well as any `m`.
Here is the proof, written out in full.
\begin{code}
+-assoc : ∀ (m n p : ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p =
begin
(zero + n) + p
≡⟨⟩ -- (i)
n + p
≡⟨⟩ -- (i)
zero + (n + p)
+-assoc (suc m) n p =
begin
(suc m + n) + p
≡⟨⟩ -- (ii)
suc (m + n) + p
≡⟨⟩ -- (ii)
suc ((m + n) + p)
≡⟨ cong suc (+-assoc m n p) ⟩ -- (induction hypothesis)
suc (m + (n + p))
≡⟨⟩ -- (ii)
suc m + (n + p)
\end{code}
We have named the proof `+-assoc`. In Agda, identifiers can consist of
any sequence of characters not including spaces or the characters `@.(){};_`.
Let's unpack this code. The first line states that we are
defining the identifier `+-assoc` which is a proof of the
proposition
∀ (m n p : ) → (m + n) + p ≡ m + (n + p)
The upside down A is pronounced "for all", and the proposition
asserts that for all natural numbers `m`, `n`, and `p` that
the equations `(m + n) + p ≡ m + (n + p)` holds. Such a proof
is a function that accepts three natural numbers---corresponding to
to `m`, `n`, and `p`---and returns a proof of the equation.
Recall the definition of addition has two clauses. Recall the definition of addition has two clauses.
@ -215,11 +255,11 @@ induction hypothesis.
## Encoding the proof in Agda ## Encoding the proof in Agda
We encode this proof in Agda as follows. We encode this proof in Agda as follows.
\begin{code}
+-assoc : ∀ (m n p : ) → (m + n) + p ≡ m + (n + p) +-assoc : ∀ (m n p : ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p = refl +-assoc zero n p = refl
+-assoc (suc m) n p rewrite +-assoc m n p = refl +-assoc (suc m) n p rewrite +-assoc m n p = refl
\end{code}
Here we have named the proof `assoc+`. In Agda, identifiers can consist of Here we have named the proof `assoc+`. In Agda, identifiers can consist of
any sequence of characters not including spaces or the characters `@.(){};_`. any sequence of characters not including spaces or the characters `@.(){};_`.
@ -236,7 +276,7 @@ is a function that accepts three natural numbers---corresponding to
to `m`, `n`, and `p`---and returns a proof of the equation. to `m`, `n`, and `p`---and returns a proof of the equation.
Proof by induction corresponds exactly to a recursive definition. Proof by induction corresponds exactly to a recursive definition.
Here we are induct on the first argument `m`, and leave the other two Here we induct on the first argument `m`, and leave the other two
arguments `n` and `p` fixed. arguments `n` and `p` fixed.
The base case corresponds to instantiating `m` by The base case corresponds to instantiating `m` by
@ -435,7 +475,7 @@ we must show to hold, become:
--------------------- ---------------------
suc m + n ≡ n + suc m suc m + n ≡ n + suc m
In the inference rules, `n` is any arbitary natural number, so when we In the inference rules, `n` is an arbitary natural number, so when we
are done with the proof we know it holds for any `n` as well as any `m`. are done with the proof we know it holds for any `n` as well as any `m`.
By equation (i) of the definition of addition, the left-hand side of By equation (i) of the definition of addition, the left-hand side of
@ -537,19 +577,82 @@ QED.
## Encoding the proofs in Agda ## Encoding the proofs in Agda
These proofs can be encoded concisely in Agda.
\begin{code} \begin{code}
+-identity : ∀ (n : ) → n + zero ≡ n +-identity : ∀ (n : ) → n + zero ≡ n
+-identity zero = refl +-identity zero =
+-identity (suc n) rewrite +-identity n = refl begin
zero + zero
≡⟨⟩
zero
+-identity (suc n) =
begin
suc n + zero
≡⟨⟩
suc (n + zero)
≡⟨ cong suc (+-identity n) ⟩
suc n
\end{code}
\begin{code}
+-suc : ∀ (m n : ) → m + suc n ≡ suc (m + n) +-suc : ∀ (m n : ) → m + suc n ≡ suc (m + n)
+-suc zero n = refl +-suc zero n =
+-suc (suc m) n rewrite +-suc m n = refl begin
zero + suc n
≡⟨⟩
suc n
≡⟨⟩
suc (zero + n)
+-suc (suc m) n =
begin
suc m + suc n
≡⟨⟩
suc (m + suc n)
≡⟨ cong suc (+-suc m n) ⟩
suc (suc (m + n))
≡⟨⟩
suc (suc m + n)
\end{code}
\begin{code}
+-comm : ∀ (m n : ) → m + n ≡ n + m +-comm : ∀ (m n : ) → m + n ≡ n + m
+-comm zero n rewrite +-identity n = refl +-comm m zero =
+-comm (suc m) n rewrite +-suc n m | +-comm m n = refl begin
m + zero
≡⟨ +-identity m ⟩
m
≡⟨⟩
zero + m
+-comm m (suc n) =
begin
m + suc n
≡⟨ +-suc m n ⟩
suc (m + n)
≡⟨ cong suc (+-comm m n) ⟩
suc (n + m)
≡⟨⟩
suc n + m
\end{code}
These proofs can be encoded concisely in Agda.
\begin{code}
+-identity : ∀ (n : ) → n + zero ≡ n
+-identity zero = refl
+-identity (suc n) rewrite +-identity n = refl
+-suc : ∀ (m n : ) → m + suc n ≡ suc (m + n)
+-suc zero n = refl
+-suc (suc m) n rewrite +-suc m n = refl
+-comm : ∀ (m n : ) → m + n ≡ n + m
+-comm m zero rewrite +-identity m = refl
+-comm m (suc n) rewrite +-suc m n | +-comm m n = refl
\end{code} \end{code}
Here we have renamed Lemma (x) and (xi) to `+-identity` and `+-suc`, Here we have renamed Lemma (x) and (xi) to `+-identity` and `+-suc`,
respectively. In the final line, rewriting with two equations is respectively. In the final line, rewriting with two equations is
@ -613,3 +716,10 @@ This chapter introduces the following unicode.
≡ U+2261 IDENTICAL TO (\==) ≡ U+2261 IDENTICAL TO (\==)
∀ U+2200 FOR ALL (\forall) ∀ U+2200 FOR ALL (\forall)
U+2032 PRIME (\')
″ U+2033 DOUBLE PRIME (\')
Like `\r`, after typing `\'`, one can access different primes (single,
double, triple, quadruple) by using the left, right, up, and down keys
to navigate. The command remembers where you navigated to the last
time, and starts with the same character next time.