merge
This commit is contained in:
commit
91a2dd4bf8
24 changed files with 265 additions and 206 deletions
17
.travis.yml
17
.travis.yml
|
@ -28,26 +28,29 @@ addons:
|
||||||
env:
|
env:
|
||||||
- SH=bash
|
- SH=bash
|
||||||
|
|
||||||
before_install:
|
install:
|
||||||
# Install Stack:
|
# Install Stack:
|
||||||
- mkdir -p ~/.local/bin
|
- mkdir -p ~/.local/bin
|
||||||
- export PATH=$HOME/.local/bin:$PATH
|
- export PATH=$HOME/.local/bin:$PATH
|
||||||
- travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
|
- travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
|
||||||
# Install Pandoc:
|
# Install Pandoc:
|
||||||
- travis_retry curl -L https://github.com/jgm/pandoc/releases/download/2.9.2.1/pandoc-2.9.2.1-1-amd64.deb -o $HOME/pandoc.deb && sudo dpkg -i $HOME/pandoc.deb
|
- travis_retry curl -L https://github.com/jgm/pandoc/releases/download/2.9.2.1/pandoc-2.9.2.1-1-amd64.deb -o $HOME/pandoc.deb && sudo dpkg -i $HOME/pandoc.deb
|
||||||
# Install agda, agda-stdlib, and agda2html:
|
# Install agda, agda-stdlib, and acknowledgements:
|
||||||
- make travis-setup
|
- travis_wait 60 make travis-install-agda
|
||||||
|
- make travis-install-agda-stdlib
|
||||||
|
- make travis-install-acknowledgements
|
||||||
|
- ruby -S bundle install
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- agda --version
|
- agda --version
|
||||||
- acknowledgements --version
|
- acknowledgements --version
|
||||||
- pandoc --version
|
- pandoc --version
|
||||||
- acknowledgements -i _config.yml >> _config.yml
|
- acknowledgements -i _config.yml >> _config.yml
|
||||||
- make build # build website
|
- make build # build website
|
||||||
- make build-history # build previous releases
|
- make build-history # build previous releases
|
||||||
- make test-offline # test website
|
- make test-offline # test website
|
||||||
- make epub # build EPUB
|
- make epub # build EPUB
|
||||||
- make epubcheck # test EPUB
|
- make epubcheck # test EPUB
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- make clean
|
- make clean
|
||||||
|
|
3
Gemfile
3
Gemfile
|
@ -8,6 +8,9 @@ group :development do
|
||||||
gem 'guard'
|
gem 'guard'
|
||||||
gem 'guard-shell'
|
gem 'guard-shell'
|
||||||
gem 'html-proofer'
|
gem 'html-proofer'
|
||||||
|
# ffi-1.13.1 is broken on macos
|
||||||
|
# https://github.com/ffi/ffi/issues/791
|
||||||
|
gem 'ffi', '~> 1.12.2'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :epub do
|
group :epub do
|
||||||
|
|
19
Makefile
19
Makefile
|
@ -165,7 +165,7 @@ out/epub/plfa.epub: $(AGDA_FILES) $(LUA_FILES) epub/main.css out/epub/acknowledg
|
||||||
|
|
||||||
out/epub/acknowledgements.md: src/plfa/acknowledgements.md _config.yml
|
out/epub/acknowledgements.md: src/plfa/acknowledgements.md _config.yml
|
||||||
@mkdir -p out/epub/
|
@mkdir -p out/epub/
|
||||||
$(BUNDLE) exec ruby epub/render-liquid-template.rb _config.yml $< $@
|
$(BUNDLE) exec ruby epub/render-liquid-template.rb _config.yml $< $@
|
||||||
|
|
||||||
.phony: epub epubcheck
|
.phony: epub epubcheck
|
||||||
|
|
||||||
|
@ -187,14 +187,11 @@ clobber: clean
|
||||||
.phony: clean clobber
|
.phony: clean clobber
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Setup Travis
|
# Setup Travis
|
||||||
travis-setup:\
|
travis-setup:\
|
||||||
$(HOME)/.local/bin/agda\
|
travis-install-agda\
|
||||||
$(HOME)/.local/bin/acknowledgements\
|
travis-install-agda-stdlib\
|
||||||
$(HOME)/agda-stdlib-$(AGDA_STDLIB_VERSION)/src\
|
travis-install-acknowledgements
|
||||||
$(HOME)/.agda/defaults\
|
|
||||||
$(HOME)/.agda/libraries
|
|
||||||
|
|
||||||
.phony: travis-setup
|
.phony: travis-setup
|
||||||
|
|
||||||
|
@ -215,11 +212,11 @@ $(HOME)/.agda/libraries:
|
||||||
echo "$(PLFA_DIR)/plfa.agda-lib" >> $(HOME)/.agda/libraries
|
echo "$(PLFA_DIR)/plfa.agda-lib" >> $(HOME)/.agda/libraries
|
||||||
|
|
||||||
$(HOME)/.local/bin/agda:
|
$(HOME)/.local/bin/agda:
|
||||||
travis_retry curl -L https://github.com/agda/agda/archive/v$(AGDA_VERSION).zip\
|
curl -L https://github.com/agda/agda/archive/v$(AGDA_VERSION).zip\
|
||||||
-o $(HOME)/agda-$(AGDA_VERSION).zip
|
-o $(HOME)/agda-$(AGDA_VERSION).zip
|
||||||
unzip -qq $(HOME)/agda-$(AGDA_VERSION).zip -d $(HOME)
|
unzip -qq $(HOME)/agda-$(AGDA_VERSION).zip -d $(HOME)
|
||||||
cd $(HOME)/agda-$(AGDA_VERSION);\
|
cd $(HOME)/agda-$(AGDA_VERSION);\
|
||||||
stack install --stack-yaml=stack-8.0.2.yaml
|
stack install --stack-yaml=stack-$(GHC_VERSION).yaml
|
||||||
|
|
||||||
travis-uninstall-agda:
|
travis-uninstall-agda:
|
||||||
rm -rf $(HOME)/agda-$(AGDA_VERSION)/
|
rm -rf $(HOME)/agda-$(AGDA_VERSION)/
|
||||||
|
@ -236,7 +233,7 @@ travis-reinstall-agda: travis-uninstall-agda travis-install-agda
|
||||||
travis-install-agda-stdlib: $(HOME)/agda-stdlib-$(AGDA_STDLIB_VERSION)/src
|
travis-install-agda-stdlib: $(HOME)/agda-stdlib-$(AGDA_STDLIB_VERSION)/src
|
||||||
|
|
||||||
$(HOME)/agda-stdlib-$(AGDA_STDLIB_VERSION)/src:
|
$(HOME)/agda-stdlib-$(AGDA_STDLIB_VERSION)/src:
|
||||||
travis_retry curl -L https://github.com/agda/agda-stdlib/archive/v$(AGDA_STDLIB_VERSION).zip\
|
curl -L https://github.com/agda/agda-stdlib/archive/v$(AGDA_STDLIB_VERSION).zip\
|
||||||
-o $(HOME)/agda-stdlib-$(AGDA_STDLIB_VERSION).zip
|
-o $(HOME)/agda-stdlib-$(AGDA_STDLIB_VERSION).zip
|
||||||
unzip -qq $(HOME)/agda-stdlib-$(AGDA_STDLIB_VERSION).zip -d $(HOME)
|
unzip -qq $(HOME)/agda-stdlib-$(AGDA_STDLIB_VERSION).zip -d $(HOME)
|
||||||
mkdir -p $(HOME)/.agda
|
mkdir -p $(HOME)/.agda
|
||||||
|
@ -256,7 +253,7 @@ travis-reinstall-agda-stdlib: travis-uninstall-agda-stdlib travis-install-agda-s
|
||||||
travis-install-acknowledgements: $(HOME)/.local/bin/acknowledgements
|
travis-install-acknowledgements: $(HOME)/.local/bin/acknowledgements
|
||||||
|
|
||||||
$(HOME)/.local/bin/acknowledgements:
|
$(HOME)/.local/bin/acknowledgements:
|
||||||
travis_retry curl -L https://github.com/plfa/acknowledgements/archive/master.zip\
|
curl -L https://github.com/plfa/acknowledgements/archive/master.zip\
|
||||||
-o $(HOME)/acknowledgements-master.zip
|
-o $(HOME)/acknowledgements-master.zip
|
||||||
unzip -qq $(HOME)/acknowledgements-master.zip -d $(HOME)
|
unzip -qq $(HOME)/acknowledgements-master.zip -d $(HOME)
|
||||||
cd $(HOME)/acknowledgements-master;\
|
cd $(HOME)/acknowledgements-master;\
|
||||||
|
|
26
README.md
26
README.md
|
@ -6,6 +6,7 @@ permalink: /GettingStarted/
|
||||||
|
|
||||||
<!-- Links -->
|
<!-- Links -->
|
||||||
|
|
||||||
|
[epub]: https://plfa.github.io/out/epub/plfa.epub
|
||||||
[plfa]: http://plfa.inf.ed.ac.uk
|
[plfa]: http://plfa.inf.ed.ac.uk
|
||||||
[plfa-dev]: https://github.com/plfa/plfa.github.io/archive/dev.zip
|
[plfa-dev]: https://github.com/plfa/plfa.github.io/archive/dev.zip
|
||||||
[plfa-status]: https://travis-ci.org/plfa/plfa.github.io.svg?branch=dev
|
[plfa-status]: https://travis-ci.org/plfa/plfa.github.io.svg?branch=dev
|
||||||
|
@ -14,14 +15,14 @@ permalink: /GettingStarted/
|
||||||
[plfa-latest]: https://github.com/plfa/plfa.github.io/releases/latest
|
[plfa-latest]: https://github.com/plfa/plfa.github.io/releases/latest
|
||||||
[plfa-master]: https://github.com/plfa/plfa.github.io/archive/master.zip
|
[plfa-master]: https://github.com/plfa/plfa.github.io/archive/master.zip
|
||||||
|
|
||||||
[agda]: https://github.com/agda/agda/releases/tag/v2.6.0.1
|
[agda]: https://github.com/agda/agda/releases/tag/v2.6.1
|
||||||
[agda-version]: https://img.shields.io/badge/agda-v2.6.0.1-blue.svg
|
[agda-version]: https://img.shields.io/badge/agda-v2.6.1-blue.svg
|
||||||
[agda-docs-emacs-mode]: https://agda.readthedocs.io/en/v2.6.0.1/tools/emacs-mode.html
|
[agda-docs-emacs-mode]: https://agda.readthedocs.io/en/v2.6.1/tools/emacs-mode.html
|
||||||
[agda-docs-emacs-notation]: https://agda.readthedocs.io/en/v2.6.0.1/tools/emacs-mode.html#notation-for-key-combinations
|
[agda-docs-emacs-notation]: https://agda.readthedocs.io/en/v2.6.1/tools/emacs-mode.html#notation-for-key-combinations
|
||||||
[agda-docs-package-system]: https://agda.readthedocs.io/en/v2.6.0.1/tools/package-system.html#example-using-the-standard-library
|
[agda-docs-package-system]: https://agda.readthedocs.io/en/v2.6.1/tools/package-system.html#example-using-the-standard-library
|
||||||
|
|
||||||
[agda-stdlib-version]: https://img.shields.io/badge/agda--stdlib-v1.1-blue.svg
|
[agda-stdlib-version]: https://img.shields.io/badge/agda--stdlib-v1.3-blue.svg
|
||||||
[agda-stdlib]: https://github.com/agda/agda-stdlib/releases/tag/v1.1
|
[agda-stdlib]: https://github.com/agda/agda-stdlib/releases/tag/v1.3
|
||||||
|
|
||||||
[haskell-stack]: https://docs.haskellstack.org/en/stable/README/
|
[haskell-stack]: https://docs.haskellstack.org/en/stable/README/
|
||||||
[haskell-ghc]: https://www.haskell.org/ghc/
|
[haskell-ghc]: https://www.haskell.org/ghc/
|
||||||
|
@ -44,9 +45,6 @@ permalink: /GettingStarted/
|
||||||
[![Agda][agda-version]][agda]
|
[![Agda][agda-version]][agda]
|
||||||
[![agda-stdlib][agda-stdlib-version]][agda-stdlib]
|
[![agda-stdlib][agda-stdlib-version]][agda-stdlib]
|
||||||
|
|
||||||
|
|
||||||
# Getting Started with PLFA
|
|
||||||
|
|
||||||
## Dependencies for users
|
## Dependencies for users
|
||||||
|
|
||||||
You can read PLFA [online][plfa] without installing anything.
|
You can read PLFA [online][plfa] without installing anything.
|
||||||
|
@ -64,11 +62,11 @@ The easiest way to install any specific version of Agda is using [Stack][haskell
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/agda/agda.git
|
git clone https://github.com/agda/agda.git
|
||||||
cd agda
|
cd agda
|
||||||
git checkout v2.6.0.1
|
git checkout v2.6.1
|
||||||
```
|
```
|
||||||
To install Agda, run Stack from the Agda source directory:
|
To install Agda, run Stack from the Agda source directory:
|
||||||
```bash
|
```bash
|
||||||
stack install --stack-yaml stack-8.6.5.yaml
|
stack install --stack-yaml stack-8.8.3.yaml
|
||||||
```
|
```
|
||||||
If you want Stack to use you system installation of GHC, you can pass the `--system-ghc` flag and select the appropriate `stack-*.yaml` file. For instance, if you have GHC 8.2.2 installed, run:
|
If you want Stack to use you system installation of GHC, you can pass the `--system-ghc` flag and select the appropriate `stack-*.yaml` file. For instance, if you have GHC 8.2.2 installed, run:
|
||||||
```bash
|
```bash
|
||||||
|
@ -81,7 +79,7 @@ You can get the required version of the Agda standard library from GitHub, eithe
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/agda/agda-stdlib.git
|
git clone https://github.com/agda/agda-stdlib.git
|
||||||
cd agda-stdlib
|
cd agda-stdlib
|
||||||
git checkout v1.1
|
git checkout v1.3
|
||||||
```
|
```
|
||||||
You can get the latest version of Programming Language Foundations in Agda from GitHub, either by cloning the repository, or by downloading [the zip archive][plfa-dev]:
|
You can get the latest version of Programming Language Foundations in Agda from GitHub, either by cloning the repository, or by downloading [the zip archive][plfa-dev]:
|
||||||
```bash
|
```bash
|
||||||
|
@ -227,7 +225,7 @@ bundle exec jekyll serve
|
||||||
|
|
||||||
### Building the EPUB
|
### Building the EPUB
|
||||||
|
|
||||||
The EPUB version of the book is built using Pandoc. Here's how to build the EPUB:
|
The [EPUB version][epub] of the book is built using Pandoc. Here's how to build the EPUB:
|
||||||
|
|
||||||
1. Install a recent version of Pandoc, [available here][pandoc].
|
1. Install a recent version of Pandoc, [available here][pandoc].
|
||||||
We recommend their official installer (on the linked page),
|
We recommend their official installer (on the linked page),
|
||||||
|
|
|
@ -47,7 +47,7 @@ yourself, or your group in the case of group practicals).
|
||||||
```
|
```
|
||||||
import Relation.Binary.PropositionalEquality as Eq
|
import Relation.Binary.PropositionalEquality as Eq
|
||||||
open Eq using (_≡_; refl; cong; sym)
|
open Eq using (_≡_; refl; cong; sym)
|
||||||
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
|
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; step-≡; _∎)
|
||||||
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _∸_; _≤_; z≤n; s≤s)
|
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _∸_; _≤_; z≤n; s≤s)
|
||||||
open import Data.Nat.Properties using (+-assoc; +-identityʳ; +-suc; +-comm;
|
open import Data.Nat.Properties using (+-assoc; +-identityʳ; +-suc; +-comm;
|
||||||
≤-refl; ≤-trans; ≤-antisym; ≤-total; +-monoʳ-≤; +-monoˡ-≤; +-mono-≤)
|
≤-refl; ≤-trans; ≤-antisym; ≤-total; +-monoʳ-≤; +-monoˡ-≤; +-mono-≤)
|
||||||
|
@ -142,7 +142,7 @@ Give an example of an operator that has an identity and is
|
||||||
associative but is not commutative.
|
associative but is not commutative.
|
||||||
|
|
||||||
|
|
||||||
#### Exercise `finite-+-assoc` (stretch) {#finite-plus-assoc}
|
#### Exercise `finite-|-assoc` (stretch) {#finite-plus-assoc}
|
||||||
|
|
||||||
Write out what is known about associativity of addition on each of the first four
|
Write out what is known about associativity of addition on each of the first four
|
||||||
days using a finite story of creation, as
|
days using a finite story of creation, as
|
||||||
|
@ -196,7 +196,7 @@ Show
|
||||||
|
|
||||||
for all naturals `n`. Did your proof require induction?
|
for all naturals `n`. Did your proof require induction?
|
||||||
|
|
||||||
#### Exercise `∸-+-assoc` (practice) {#monus-plus-assoc}
|
#### Exercise `∸-|-assoc` (practice) {#monus-plus-assoc}
|
||||||
|
|
||||||
Show that monus associates with addition, that is,
|
Show that monus associates with addition, that is,
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ yourself, or your group in the case of group practicals).
|
||||||
```
|
```
|
||||||
import Relation.Binary.PropositionalEquality as Eq
|
import Relation.Binary.PropositionalEquality as Eq
|
||||||
open Eq using (_≡_; refl; cong; sym)
|
open Eq using (_≡_; refl; cong; sym)
|
||||||
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
|
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; step-≡; _∎)
|
||||||
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _∸_; _≤_; z≤n; s≤s)
|
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _∸_; _≤_; z≤n; s≤s)
|
||||||
open import Data.Nat.Properties using (+-assoc; +-identityʳ; +-suc; +-comm;
|
open import Data.Nat.Properties using (+-assoc; +-identityʳ; +-suc; +-comm;
|
||||||
≤-refl; ≤-trans; ≤-antisym; ≤-total; +-monoʳ-≤; +-monoˡ-≤; +-mono-≤)
|
≤-refl; ≤-trans; ≤-antisym; ≤-total; +-monoʳ-≤; +-monoˡ-≤; +-mono-≤)
|
||||||
|
@ -481,4 +481,3 @@ postulate
|
||||||
```
|
```
|
||||||
-- Your code goes here
|
-- Your code goes here
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ yourself, or your group in the case of group practicals).
|
||||||
```
|
```
|
||||||
import Relation.Binary.PropositionalEquality as Eq
|
import Relation.Binary.PropositionalEquality as Eq
|
||||||
open Eq using (_≡_; refl; cong; sym)
|
open Eq using (_≡_; refl; cong; sym)
|
||||||
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
|
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; step-≡; _∎)
|
||||||
open import Data.Bool.Base using (Bool; true; false; T; _∧_; _∨_; not)
|
open import Data.Bool.Base using (Bool; true; false; T; _∧_; _∨_; not)
|
||||||
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _∸_; _≤_; s≤s; z≤n)
|
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _∸_; _≤_; s≤s; z≤n)
|
||||||
open import Data.Nat.Properties using
|
open import Data.Nat.Properties using
|
||||||
|
@ -538,4 +538,3 @@ Provide proofs of the three postulates, `unstuck`, `preserves`, and `wttdgs` abo
|
||||||
```
|
```
|
||||||
-- Your code goes here
|
-- Your code goes here
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -632,8 +632,10 @@ not fixed by the given arguments.
|
||||||
## Evaluation
|
## Evaluation
|
||||||
|
|
||||||
```
|
```
|
||||||
data Gas : Set where
|
record Gas : Set where
|
||||||
gas : ℕ → Gas
|
constructor gas
|
||||||
|
field
|
||||||
|
amount : ℕ
|
||||||
|
|
||||||
data Finished {Γ A} (N : Γ ⊢ A) : Set where
|
data Finished {Γ A} (N : Γ ⊢ A) : Set where
|
||||||
|
|
||||||
|
|
|
@ -351,8 +351,10 @@ module Problem2 where
|
||||||
### Evaluation
|
### Evaluation
|
||||||
|
|
||||||
```
|
```
|
||||||
data Gas : Set where
|
record Gas : Set where
|
||||||
gas : ℕ → Gas
|
constructor gas
|
||||||
|
field
|
||||||
|
amount : ℕ
|
||||||
|
|
||||||
data Finished {Γ A} (N : Γ ⊢ A) : Set where
|
data Finished {Γ A} (N : Γ ⊢ A) : Set where
|
||||||
|
|
||||||
|
|
|
@ -573,7 +573,7 @@ from `m` only if `n ≤ m`:
|
||||||
```
|
```
|
||||||
minus : (m n : ℕ) (n≤m : n ≤ m) → ℕ
|
minus : (m n : ℕ) (n≤m : n ≤ m) → ℕ
|
||||||
minus m zero _ = m
|
minus m zero _ = m
|
||||||
minus (suc m) (suc n) (s≤s m≤n) = minus m n m≤n
|
minus (suc m) (suc n) (s≤s n≤m) = minus m n n≤m
|
||||||
```
|
```
|
||||||
|
|
||||||
Unfortunately, it is painful to use, since we have to explicitly provide
|
Unfortunately, it is painful to use, since we have to explicitly provide
|
||||||
|
@ -595,8 +595,8 @@ fill in an implicit of an *empty* record type, since there aren't any fields
|
||||||
after all. This is why `⊤` is defined as an empty record.
|
after all. This is why `⊤` is defined as an empty record.
|
||||||
|
|
||||||
The trick is to have an implicit argument of the type `T ⌊ n ≤? m ⌋`. Let's go
|
The trick is to have an implicit argument of the type `T ⌊ n ≤? m ⌋`. Let's go
|
||||||
through what this means step-by-step. First, we run the decision procedure, `n
|
through what this means step-by-step. First, we run the decision procedure,
|
||||||
≤? m`. This provides us with evidence whether `n ≤ m` holds or not. We erase the
|
`n ≤? m`. This provides us with evidence whether `n ≤ m` holds or not. We erase the
|
||||||
evidence to a boolean. Finally, we apply `T`. Recall that `T` maps booleans into
|
evidence to a boolean. Finally, we apply `T`. Recall that `T` maps booleans into
|
||||||
the world of evidence: `true` becomes the unit type `⊤`, and `false` becomes the
|
the world of evidence: `true` becomes the unit type `⊤`, and `false` becomes the
|
||||||
empty type `⊥`. Operationally, an implicit argument of this type works as a
|
empty type `⊥`. Operationally, an implicit argument of this type works as a
|
||||||
|
|
|
@ -696,23 +696,27 @@ _∘_ : ∀ {ℓ₁ ℓ₂ ℓ₃ : Level} {A : Set ℓ₁} {B : Set ℓ₂} {C
|
||||||
(g ∘ f) x = g (f x)
|
(g ∘ f) x = g (f x)
|
||||||
```
|
```
|
||||||
|
|
||||||
Further information on levels can be found in the [Agda Wiki][wiki].
|
Further information on levels can be found in the [Agda docs][docs].
|
||||||
|
|
||||||
[wiki]: http://wiki.portal.chalmers.se/agda/pmwiki.php?n=ReferenceManual.UniversePolymorphism
|
[docs]: https://agda.readthedocs.io/en/v2.6.1/language/universe-levels.html
|
||||||
|
|
||||||
|
|
||||||
## Standard library
|
## Standard library
|
||||||
|
|
||||||
Definitions similar to those in this chapter can be found in the
|
Definitions similar to those in this chapter can be found in the standard
|
||||||
standard library:
|
library. The Agda standard library defines `_≡⟨_⟩_` as `step-≡`, [which reverses
|
||||||
|
the order of the arguments][step-≡]. The standard library also defines a syntax
|
||||||
|
macro, which is automatically imported whenever you import `step-≡`, which
|
||||||
|
recovers the original argument order:
|
||||||
```
|
```
|
||||||
-- import Relation.Binary.PropositionalEquality as Eq
|
-- import Relation.Binary.PropositionalEquality as Eq
|
||||||
-- open Eq using (_≡_; refl; trans; sym; cong; cong-app; subst)
|
-- open Eq using (_≡_; refl; trans; sym; cong; cong-app; subst)
|
||||||
-- open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
|
-- open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; step-≡; _∎)
|
||||||
```
|
```
|
||||||
Here the imports are shown as comments rather than code to avoid
|
Here the imports are shown as comments rather than code to avoid
|
||||||
collisions, as mentioned in the introduction.
|
collisions, as mentioned in the introduction.
|
||||||
|
|
||||||
|
[step-≡]: https://github.com/agda/agda-stdlib/blob/master/CHANGELOG/v1.3.md#changes-to-how-equational-reasoning-is-implemented
|
||||||
|
|
||||||
## Unicode
|
## Unicode
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ and some operations upon them. We also import a couple of new operations,
|
||||||
```
|
```
|
||||||
import Relation.Binary.PropositionalEquality as Eq
|
import Relation.Binary.PropositionalEquality as Eq
|
||||||
open Eq using (_≡_; refl; cong; sym)
|
open Eq using (_≡_; refl; cong; sym)
|
||||||
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
|
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; step-≡; _∎)
|
||||||
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _∸_)
|
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _∸_)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -656,7 +656,7 @@ time we are concerned with judgments asserting associativity:
|
||||||
|
|
||||||
Now, we apply the rules to all the judgments we know about. The base
|
Now, we apply the rules to all the judgments we know about. The base
|
||||||
case tells us that `(zero + n) + p ≡ zero + (n + p)` for every natural
|
case tells us that `(zero + n) + p ≡ zero + (n + p)` for every natural
|
||||||
`n` and `p`. The inductive case tells us that if
|
`n` and `p`. The inductive case tells us that if
|
||||||
`(m + n) + p ≡ m + (n + p)` (on the day before today) then
|
`(m + n) + p ≡ m + (n + p)` (on the day before today) then
|
||||||
`(suc m + n) + p ≡ suc m + (n + p)` (today).
|
`(suc m + n) + p ≡ suc m + (n + p)` (today).
|
||||||
We didn't know any judgments about associativity before today, so that
|
We didn't know any judgments about associativity before today, so that
|
||||||
|
|
|
@ -1106,8 +1106,8 @@ with their corresponding proofs.
|
||||||
Definitions similar to those in this chapter can be found in the standard library:
|
Definitions similar to those in this chapter can be found in the standard library:
|
||||||
```
|
```
|
||||||
import Data.List using (List; _++_; length; reverse; map; foldr; downFrom)
|
import Data.List using (List; _++_; length; reverse; map; foldr; downFrom)
|
||||||
import Data.List.All using (All; []; _∷_)
|
import Data.List.Relation.Unary.All using (All; []; _∷_)
|
||||||
import Data.List.Any using (Any; here; there)
|
import Data.List.Relation.Unary.Any using (Any; here; there)
|
||||||
import Data.List.Membership.Propositional using (_∈_)
|
import Data.List.Membership.Propositional using (_∈_)
|
||||||
import Data.List.Properties
|
import Data.List.Properties
|
||||||
using (reverse-++-commute; map-compose; map-++-commute; foldr-++)
|
using (reverse-++-commute; map-compose; map-++-commute; foldr-++)
|
||||||
|
|
|
@ -941,7 +941,7 @@ Such a pragma can only be invoked once, as invoking it twice would
|
||||||
raise confusion as to whether `2` is a value of type `ℕ` or type
|
raise confusion as to whether `2` is a value of type `ℕ` or type
|
||||||
`Data.Nat.ℕ`. Similar confusions arise if other pragmas are invoked
|
`Data.Nat.ℕ`. Similar confusions arise if other pragmas are invoked
|
||||||
twice. For this reason, we will usually avoid pragmas in future chapters.
|
twice. For this reason, we will usually avoid pragmas in future chapters.
|
||||||
Information on pragmas can be found in the Agda documentation.
|
Information on pragmas can be found in the (Agda documentation)[https://agda.readthedocs.io/en/v2.6.1/language/pragmas.html].
|
||||||
|
|
||||||
|
|
||||||
## Unicode
|
## Unicode
|
||||||
|
|
|
@ -34,8 +34,8 @@ as implication of false:
|
||||||
¬_ : Set → Set
|
¬_ : Set → Set
|
||||||
¬ A = A → ⊥
|
¬ A = A → ⊥
|
||||||
```
|
```
|
||||||
This is a form of _proof by contradiction_: if assuming `A` leads
|
This is a form of _reductio ad absurdum_: if assuming `A` leads
|
||||||
to the conclusion `⊥` (a contradiction), then we must have `¬ A`.
|
to the conclusion `⊥` (an absurdity), then we must have `¬ A`.
|
||||||
|
|
||||||
Evidence that `¬ A` holds is of the form
|
Evidence that `¬ A` holds is of the form
|
||||||
|
|
||||||
|
|
|
@ -401,14 +401,92 @@ sub-par : ∀{Γ A B} {N N′ : Γ , A ⊢ B} {M M′ : Γ ⊢ A}
|
||||||
sub-par pn pm = subst-par (par-subst-zero pm) pn
|
sub-par pn pm = subst-par (par-subst-zero pm) pn
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Parallel reduction satisfies the diamond property
|
## Parallel reduction satisfies the diamond property
|
||||||
|
|
||||||
The heart of the confluence proof is made of stone, or rather, of
|
The heart of the confluence proof is made of stone, or rather, of
|
||||||
diamond! We show that parallel reduction satisfies the diamond
|
diamond! We show that parallel reduction satisfies the diamond
|
||||||
property: that if `M ⇛ N` and `M ⇛ N′`, then `N ⇛ L` and `N′ ⇛ L` for
|
property: that if `M ⇛ N` and `M ⇛ N′`, then `N ⇛ L` and `N′ ⇛ L` for
|
||||||
some `L`. The proof is relatively easy; it is parallel reduction's
|
some `L`. The typical proof is an induction on `M ⇛ N` and `M ⇛ N′`
|
||||||
_raison d'etre_.
|
so that every possible pair gives rise to a witeness `L` given by
|
||||||
|
performing enough beta reductions in parallel.
|
||||||
|
|
||||||
|
However, a simpler approach is to perform as many beta reductions in
|
||||||
|
parallel as possible on `M`, say `M ⁺`, and then show that `N` also
|
||||||
|
parallel reduces to `M ⁺`. This is the idea of Takahashi's _complete
|
||||||
|
development_. The desired property may be illustrated as
|
||||||
|
|
||||||
|
M
|
||||||
|
/|
|
||||||
|
/ |
|
||||||
|
/ |
|
||||||
|
N 2
|
||||||
|
\ |
|
||||||
|
\ |
|
||||||
|
\|
|
||||||
|
M⁺
|
||||||
|
|
||||||
|
where downward lines are instances of `⇛`, so we call it the _triangle
|
||||||
|
property_.
|
||||||
|
|
||||||
|
```
|
||||||
|
_⁺ : ∀ {Γ A}
|
||||||
|
→ Γ ⊢ A → Γ ⊢ A
|
||||||
|
(` x) ⁺ = ` x
|
||||||
|
(ƛ M) ⁺ = ƛ (M ⁺)
|
||||||
|
((ƛ N) · M) ⁺ = N ⁺ [ M ⁺ ]
|
||||||
|
(L · M) ⁺ = L ⁺ · (M ⁺)
|
||||||
|
|
||||||
|
par-triangle : ∀ {Γ A} {M N : Γ ⊢ A}
|
||||||
|
→ M ⇛ N
|
||||||
|
-------
|
||||||
|
→ N ⇛ M ⁺
|
||||||
|
par-triangle pvar = pvar
|
||||||
|
par-triangle (pabs p) = pabs (par-triangle p)
|
||||||
|
par-triangle (pbeta p1 p2) = sub-par (par-triangle p1) (par-triangle p2)
|
||||||
|
par-triangle (papp {L = ƛ _ } (pabs p1) p2) =
|
||||||
|
pbeta (par-triangle p1) (par-triangle p2)
|
||||||
|
par-triangle (papp {L = ` _} p1 p2) = papp (par-triangle p1) (par-triangle p2)
|
||||||
|
par-triangle (papp {L = _ · _} p1 p2) = papp (par-triangle p1) (par-triangle p2)
|
||||||
|
```
|
||||||
|
|
||||||
|
The proof of the triangle property is an induction on `M ⇛ N`.
|
||||||
|
|
||||||
|
* Suppose `x ⇛ x`. Clearly `x ⁺ = x`, so `x ⇛ x`.
|
||||||
|
|
||||||
|
* Suppose `ƛ M ⇛ ƛ N`. By the induction hypothesis we have `N ⇛ M ⁺`
|
||||||
|
and by definition `(λ M) ⁺ = λ (M ⁺)`, so we conclude that `λ N ⇛ λ
|
||||||
|
(M ⁺)`.
|
||||||
|
|
||||||
|
* Suppose `(λ N) · M ⇛ N′ [ M′ ]`. By the induction hypothesis, we have
|
||||||
|
`N′ ⇛ N ⁺` and `M′ ⇛ M ⁺`. Since substitution respects parallel reduction,
|
||||||
|
it follows that `N′ [ M′ ] ⇛ N ⁺ [ M ⁺ ]`, but the right hand side
|
||||||
|
is exactly `((λ N) · M) ⁺`, hence `N′ [ M′ ] ⇛ ((λ N) · M) ⁺`.
|
||||||
|
|
||||||
|
* Suppose `(λ L) · M ⇛ (λ L′) · M′`. By the induction hypothesis
|
||||||
|
we have `L′ ⇛ L ⁺` and `M′ ⇛ M ⁺`; by definition `((λ L) · M) ⁺ = L ⁺ [ M ⁺ ]`.
|
||||||
|
It follows `(λ L′) · M′ ⇛ L ⁺ [ M ⁺ ]`.
|
||||||
|
|
||||||
|
* Suppose `x · M ⇛ x · M′`. By the induction hypothesis we have `M′ ⇛ M ⁺`
|
||||||
|
and `x ⇛ x ⁺` so that `x · M′ ⇛ x · M ⁺`.
|
||||||
|
The remaining case is proved in the same way, so we ignore it. (As
|
||||||
|
there is currently no way in Agda to expand the catch-all pattern in
|
||||||
|
the definition of `_⁺` for us before checking the right-hand side,
|
||||||
|
we have to write down the remaining case explicitly.)
|
||||||
|
|
||||||
|
The diamond property then follows by halving the diamond into two triangles.
|
||||||
|
|
||||||
|
M
|
||||||
|
/|\
|
||||||
|
/ | \
|
||||||
|
/ | \
|
||||||
|
N 2 N′
|
||||||
|
\ | /
|
||||||
|
\ | /
|
||||||
|
\|/
|
||||||
|
M⁺
|
||||||
|
|
||||||
|
That is, the diamond property is proved by applying the
|
||||||
|
triangle property on each side with the same confluent term `M ⁺`.
|
||||||
|
|
||||||
```
|
```
|
||||||
par-diamond : ∀{Γ A} {M N N′ : Γ ⊢ A}
|
par-diamond : ∀{Γ A} {M N N′ : Γ ⊢ A}
|
||||||
|
@ -416,90 +494,24 @@ par-diamond : ∀{Γ A} {M N N′ : Γ ⊢ A}
|
||||||
→ M ⇛ N′
|
→ M ⇛ N′
|
||||||
---------------------------------
|
---------------------------------
|
||||||
→ Σ[ L ∈ Γ ⊢ A ] (N ⇛ L) × (N′ ⇛ L)
|
→ Σ[ L ∈ Γ ⊢ A ] (N ⇛ L) × (N′ ⇛ L)
|
||||||
par-diamond (pvar{x = x}) pvar = ⟨ ` x , ⟨ pvar , pvar ⟩ ⟩
|
par-diamond {M = M} p1 p2 = ⟨ M ⁺ , ⟨ par-triangle p1 , par-triangle p2 ⟩ ⟩
|
||||||
par-diamond (pabs p1) (pabs p2)
|
|
||||||
with par-diamond p1 p2
|
|
||||||
... | ⟨ L′ , ⟨ p3 , p4 ⟩ ⟩ =
|
|
||||||
⟨ ƛ L′ , ⟨ pabs p3 , pabs p4 ⟩ ⟩
|
|
||||||
par-diamond{Γ}{A}{L · M}{N}{N′} (papp{Γ}{L}{L₁}{M}{M₁} p1 p3)
|
|
||||||
(papp{Γ}{L}{L₂}{M}{M₂} p2 p4)
|
|
||||||
with par-diamond p1 p2
|
|
||||||
... | ⟨ L₃ , ⟨ p5 , p6 ⟩ ⟩
|
|
||||||
with par-diamond p3 p4
|
|
||||||
... | ⟨ M₃ , ⟨ p7 , p8 ⟩ ⟩ =
|
|
||||||
⟨ (L₃ · M₃) , ⟨ (papp p5 p7) , (papp p6 p8) ⟩ ⟩
|
|
||||||
par-diamond (papp (pabs p1) p3) (pbeta p2 p4)
|
|
||||||
with par-diamond p1 p2
|
|
||||||
... | ⟨ N₃ , ⟨ p5 , p6 ⟩ ⟩
|
|
||||||
with par-diamond p3 p4
|
|
||||||
... | ⟨ M₃ , ⟨ p7 , p8 ⟩ ⟩ =
|
|
||||||
⟨ N₃ [ M₃ ] , ⟨ pbeta p5 p7 , sub-par p6 p8 ⟩ ⟩
|
|
||||||
par-diamond (pbeta p1 p3) (papp (pabs p2) p4)
|
|
||||||
with par-diamond p1 p2
|
|
||||||
... | ⟨ N₃ , ⟨ p5 , p6 ⟩ ⟩
|
|
||||||
with par-diamond p3 p4
|
|
||||||
... | ⟨ M₃ , ⟨ p7 , p8 ⟩ ⟩ =
|
|
||||||
⟨ (N₃ [ M₃ ]) , ⟨ sub-par p5 p7 , pbeta p6 p8 ⟩ ⟩
|
|
||||||
par-diamond {Γ}{A} (pbeta p1 p3) (pbeta p2 p4)
|
|
||||||
with par-diamond p1 p2
|
|
||||||
... | ⟨ N₃ , ⟨ p5 , p6 ⟩ ⟩
|
|
||||||
with par-diamond p3 p4
|
|
||||||
... | ⟨ M₃ , ⟨ p7 , p8 ⟩ ⟩ =
|
|
||||||
⟨ N₃ [ M₃ ] , ⟨ sub-par p5 p7 , sub-par p6 p8 ⟩ ⟩
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The proof is by induction on both premises.
|
This step is optional, though, in the presence of triangle property.
|
||||||
|
|
||||||
* Suppose `x ⇛ x` and `x ⇛ x`.
|
|
||||||
We choose `L = x` and immediately have `x ⇛ x` and `x ⇛ x`.
|
|
||||||
|
|
||||||
* Suppose `ƛ N ⇛ ƛ N₁` and `ƛ N ⇛ ƛ N₂`.
|
|
||||||
By the induction hypothesis, there exists `L′` such that
|
|
||||||
`N₁ ⇛ L′` and `N₂ ⇛ L′`. We choose `L = ƛ L′` and
|
|
||||||
by `pabs` conclude that `ƛ N₁ ⇛ ƛ L′` and `ƛ N₂ ⇛ ƛ L′.
|
|
||||||
|
|
||||||
* Suppose that `L · M ⇛ L₁ · M₁` and `L · M ⇛ L₂ · M₂`.
|
|
||||||
By the induction hypothesis we have
|
|
||||||
`L₁ ⇛ L₃` and `L₂ ⇛ L₃` for some `L₃`.
|
|
||||||
Likewise, we have
|
|
||||||
`M₁ ⇛ M₃` and `M₂ ⇛ M₃` for some `M₃`.
|
|
||||||
We choose `L = L₃ · M₃` and conclude with two uses of `papp`.
|
|
||||||
|
|
||||||
* Suppose that `(ƛ N) · M ⇛ (ƛ N₁) · M₁` and `(ƛ N) · M ⇛ N₂ [ M₂ ]`
|
|
||||||
By the induction hypothesis we have
|
|
||||||
`N₁ ⇛ N₃` and `N₂ ⇛ N₃` for some `N₃`.
|
|
||||||
Likewise, we have
|
|
||||||
`M₁ ⇛ M₃` and `M₂ ⇛ M₃` for some `M₃`.
|
|
||||||
We choose `L = N₃ [ M₃ ]`.
|
|
||||||
We have `(ƛ N₁) · M₁ ⇛ N₃ [ M₃ ]` by rule `pbeta`
|
|
||||||
and conclude that `N₂ [ M₂ ] ⇛ N₃ [ M₃ ]` because
|
|
||||||
substitution respects parallel reduction.
|
|
||||||
|
|
||||||
* Suppose that `(ƛ N) · M ⇛ N₁ [ M₁ ]` and `(ƛ N) · M ⇛ (ƛ N₂) · M₂`.
|
|
||||||
The proof of this case is the mirror image of the last one.
|
|
||||||
|
|
||||||
* Suppose that `(ƛ N) · M ⇛ N₁ [ M₁ ]` and `(ƛ N) · M ⇛ N₂ [ M₂ ]`.
|
|
||||||
By the induction hypothesis we have
|
|
||||||
`N₁ ⇛ N₃` and `N₂ ⇛ N₃` for some `N₃`.
|
|
||||||
Likewise, we have
|
|
||||||
`M₁ ⇛ M₃` and `M₂ ⇛ M₃` for some `M₃`.
|
|
||||||
We choose `L = N₃ [ M₃ ]`.
|
|
||||||
We have both `(ƛ N₁) · M₁ ⇛ N₃ [ M₃ ]`
|
|
||||||
and `(ƛ N₂) · M₂ ⇛ N₃ [ M₃ ]`
|
|
||||||
by rule `pbeta`
|
|
||||||
|
|
||||||
#### Exercise (practice)
|
#### Exercise (practice)
|
||||||
|
|
||||||
Draw pictures that represent the proofs of each of the six cases in
|
* Prove the diamond property `par-diamond` directly by induction on `M ⇛ N` and `M ⇛ N′`.
|
||||||
the above proof of `par-diamond`. The pictures should consist of nodes
|
|
||||||
and directed edges, where each node is labeled with a term and each
|
|
||||||
edge represents parallel reduction.
|
|
||||||
|
|
||||||
|
* Draw pictures that represent the proofs of each of the six cases in
|
||||||
|
the direct proof of `par-diamond`. The pictures should consist of nodes
|
||||||
|
and directed edges, where each node is labeled with a term and each
|
||||||
|
edge represents parallel reduction.
|
||||||
|
|
||||||
## Proof of confluence for parallel reduction
|
## Proof of confluence for parallel reduction
|
||||||
|
|
||||||
As promised at the beginning, the proof that parallel reduction is
|
As promised at the beginning, the proof that parallel reduction is
|
||||||
confluent is easy now that we know it satisfies the diamond property.
|
confluent is easy now that we know it satisfies the triangle property.
|
||||||
We just need to prove the strip lemma, which states that
|
We just need to prove the strip lemma, which states that
|
||||||
if `M ⇛ N` and `M ⇛* N′`, then
|
if `M ⇛ N` and `M ⇛* N′`, then
|
||||||
`N ⇛* L` and `N′ ⇛ L` for some `L`.
|
`N ⇛* L` and `N′ ⇛ L` for some `L`.
|
||||||
|
@ -519,7 +531,7 @@ where downward lines are instances of `⇛` or `⇛*`, depending on how
|
||||||
they are marked.
|
they are marked.
|
||||||
|
|
||||||
The proof of the strip lemma is a straightforward induction on `M ⇛* N′`,
|
The proof of the strip lemma is a straightforward induction on `M ⇛* N′`,
|
||||||
using the diamond property in the induction step.
|
using the triangle property in the induction step.
|
||||||
|
|
||||||
```
|
```
|
||||||
strip : ∀{Γ A} {M N N′ : Γ ⊢ A}
|
strip : ∀{Γ A} {M N N′ : Γ ⊢ A}
|
||||||
|
@ -529,11 +541,8 @@ strip : ∀{Γ A} {M N N′ : Γ ⊢ A}
|
||||||
→ Σ[ L ∈ Γ ⊢ A ] (N ⇛* L) × (N′ ⇛ L)
|
→ Σ[ L ∈ Γ ⊢ A ] (N ⇛* L) × (N′ ⇛ L)
|
||||||
strip{Γ}{A}{M}{N}{N′} mn (M ∎) = ⟨ N , ⟨ N ∎ , mn ⟩ ⟩
|
strip{Γ}{A}{M}{N}{N′} mn (M ∎) = ⟨ N , ⟨ N ∎ , mn ⟩ ⟩
|
||||||
strip{Γ}{A}{M}{N}{N′} mn (M ⇛⟨ mm' ⟩ m'n')
|
strip{Γ}{A}{M}{N}{N′} mn (M ⇛⟨ mm' ⟩ m'n')
|
||||||
with par-diamond mn mm'
|
with strip (par-triangle mm') m'n'
|
||||||
... | ⟨ L , ⟨ nl , m'l ⟩ ⟩
|
... | ⟨ L , ⟨ ll' , n'l' ⟩ ⟩ = ⟨ L , ⟨ N ⇛⟨ par-triangle mn ⟩ ll' , n'l' ⟩ ⟩
|
||||||
with strip m'l m'n'
|
|
||||||
... | ⟨ L′ , ⟨ ll' , n'l' ⟩ ⟩ =
|
|
||||||
⟨ L′ , ⟨ (N ⇛⟨ nl ⟩ ll') , n'l' ⟩ ⟩
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The proof of confluence for parallel reduction is now proved by
|
The proof of confluence for parallel reduction is now proved by
|
||||||
|
@ -605,19 +614,16 @@ Broadly speaking, this proof of confluence, based on parallel
|
||||||
reduction, is due to W. Tait and P. Martin-Lof (see Barendredgt 1984,
|
reduction, is due to W. Tait and P. Martin-Lof (see Barendredgt 1984,
|
||||||
Section 3.2). Details of the mechanization come from several sources.
|
Section 3.2). Details of the mechanization come from several sources.
|
||||||
The `subst-par` lemma is the "strong substitutivity" lemma of Shafer,
|
The `subst-par` lemma is the "strong substitutivity" lemma of Shafer,
|
||||||
Tebbi, and Smolka (ITP 2015). The proofs of `par-diamond`, `strip`,
|
Tebbi, and Smolka (ITP 2015). The proofs of `par-triangle`, `strip`,
|
||||||
and `par-confluence` are based on Pfenning's 1992 technical report
|
and `par-confluence` are based on the notion of complete development
|
||||||
about the Church-Rosser theorem. In addition, we consulted Nipkow and
|
by Takahashi (1995) and Pfenning's 1992 technical report about the
|
||||||
|
Church-Rosser theorem. In addition, we consulted Nipkow and
|
||||||
Berghofer's mechanization in Isabelle, which is based on an earlier
|
Berghofer's mechanization in Isabelle, which is based on an earlier
|
||||||
article by Nipkow (JAR 1996). We opted not to use the "complete
|
article by Nipkow (JAR 1996).
|
||||||
developments" approach of Takahashi (1995) because we felt that the
|
|
||||||
proof was simple enough based solely on parallel reduction. There are
|
|
||||||
many more mechanizations of the Church-Rosser theorem that we have not
|
|
||||||
yet had the time to read, including Shankar's (J. ACM 1988) and
|
|
||||||
Homeier's (TPHOLs 2001).
|
|
||||||
|
|
||||||
## Unicode
|
## Unicode
|
||||||
|
|
||||||
This chapter uses the following unicode:
|
This chapter uses the following unicode:
|
||||||
|
|
||||||
⇛ U+3015 RIGHTWARDS TRIPLE ARROW (\r== or \Rrightarrow)
|
⇛ U+21DB RIGHTWARDS TRIPLE ARROW (\r== or \Rrightarrow)
|
||||||
|
⁺ U+207A SUPERSCRIPT PLUS SIGN (\^+)
|
||||||
|
|
|
@ -1043,8 +1043,10 @@ refer to preservation, since it is built-in to the definition of reduction.
|
||||||
|
|
||||||
As previously, gas is specified by a natural number:
|
As previously, gas is specified by a natural number:
|
||||||
```
|
```
|
||||||
data Gas : Set where
|
record Gas : Set where
|
||||||
gas : ℕ → Gas
|
constructor gas
|
||||||
|
field
|
||||||
|
amount : ℕ
|
||||||
```
|
```
|
||||||
When our evaluator returns a term `N`, it will either give evidence that
|
When our evaluator returns a term `N`, it will either give evidence that
|
||||||
`N` is a value or indicate that it ran out of gas:
|
`N` is a value or indicate that it ran out of gas:
|
||||||
|
@ -1375,4 +1377,3 @@ This chapter uses the following unicode:
|
||||||
₆ U+2086 SUBSCRIPT SIX (\_6)
|
₆ U+2086 SUBSCRIPT SIX (\_6)
|
||||||
₇ U+2087 SUBSCRIPT SEVEN (\_7)
|
₇ U+2087 SUBSCRIPT SEVEN (\_7)
|
||||||
≠ U+2260 NOT EQUAL TO (\=n)
|
≠ U+2260 NOT EQUAL TO (\=n)
|
||||||
|
|
||||||
|
|
|
@ -1089,8 +1089,10 @@ progress (case× L M) with progress L
|
||||||
## Evaluation
|
## Evaluation
|
||||||
|
|
||||||
```
|
```
|
||||||
data Gas : Set where
|
record Gas : Set where
|
||||||
gas : ℕ → Gas
|
constructor gas
|
||||||
|
field
|
||||||
|
amount : ℕ
|
||||||
|
|
||||||
data Finished {Γ A} (N : Γ ⊢ A) : Set where
|
data Finished {Γ A} (N : Γ ⊢ A) : Set where
|
||||||
|
|
||||||
|
|
|
@ -382,7 +382,7 @@ which is well typed in the empty context is also well typed in an arbitrary
|
||||||
context. The _drop_ lemma asserts that a term which is well typed in a context
|
context. The _drop_ lemma asserts that a term which is well typed in a context
|
||||||
where the same variable appears twice remains well typed if we drop the shadowed
|
where the same variable appears twice remains well typed if we drop the shadowed
|
||||||
occurrence. The _swap_ lemma asserts that a term which is well typed in a
|
occurrence. The _swap_ lemma asserts that a term which is well typed in a
|
||||||
context remains well typed if we swap two variables.
|
context remains well typed if we swap two variables.
|
||||||
|
|
||||||
(Renaming is similar to the _context invariance_ lemma in _Software
|
(Renaming is similar to the _context invariance_ lemma in _Software
|
||||||
Foundations_, but it does not require the definition of
|
Foundations_, but it does not require the definition of
|
||||||
|
@ -775,7 +775,7 @@ Where the construct introduces a bound variable we need to compare it
|
||||||
with the substituted variable, applying the drop lemma if they are
|
with the substituted variable, applying the drop lemma if they are
|
||||||
equal and the swap lemma if they are distinct.
|
equal and the swap lemma if they are distinct.
|
||||||
|
|
||||||
For Agda it makes a difference whether we write `x ≟ y` or
|
For Agda it makes a difference whether we write `x ≟ y` or
|
||||||
`y ≟ x`. In an interactive proof, Agda will show which residual `with`
|
`y ≟ x`. In an interactive proof, Agda will show which residual `with`
|
||||||
clauses in the definition of `_[_:=_]` need to be simplified, and the
|
clauses in the definition of `_[_:=_]` need to be simplified, and the
|
||||||
`with` clauses in `subst` need to match these exactly. The guideline is
|
`with` clauses in `subst` need to match these exactly. The guideline is
|
||||||
|
@ -918,8 +918,10 @@ per unit of gas.
|
||||||
By analogy, we will use the name _gas_ for the parameter which puts a
|
By analogy, we will use the name _gas_ for the parameter which puts a
|
||||||
bound on the number of reduction steps. `Gas` is specified by a natural number:
|
bound on the number of reduction steps. `Gas` is specified by a natural number:
|
||||||
```
|
```
|
||||||
data Gas : Set where
|
record Gas : Set where
|
||||||
gas : ℕ → Gas
|
constructor gas
|
||||||
|
field
|
||||||
|
amount : ℕ
|
||||||
```
|
```
|
||||||
When our evaluator returns a term `N`, it will either give evidence that
|
When our evaluator returns a term `N`, it will either give evidence that
|
||||||
`N` is a value or indicate that it ran out of gas:
|
`N` is a value or indicate that it ran out of gas:
|
||||||
|
@ -950,17 +952,16 @@ data Steps (L : Term) : Set where
|
||||||
The evaluator takes gas and evidence that a term is well typed,
|
The evaluator takes gas and evidence that a term is well typed,
|
||||||
and returns the corresponding steps:
|
and returns the corresponding steps:
|
||||||
```
|
```
|
||||||
{-# TERMINATING #-}
|
|
||||||
eval : ∀ {L A}
|
eval : ∀ {L A}
|
||||||
→ Gas
|
→ Gas
|
||||||
→ ∅ ⊢ L ⦂ A
|
→ ∅ ⊢ L ⦂ A
|
||||||
---------
|
---------
|
||||||
→ Steps L
|
→ Steps L
|
||||||
eval {L} (gas zero) ⊢L = steps (L ∎) out-of-gas
|
eval {L} (gas zero) ⊢L = steps (L ∎) out-of-gas
|
||||||
eval {L} (gas (suc m)) ⊢L with progress ⊢L
|
eval {L} (gas (suc m)) ⊢L with progress ⊢L
|
||||||
... | done VL = steps (L ∎) (done VL)
|
... | done VL = steps (L ∎) (done VL)
|
||||||
... | step L—→M with eval (gas m) (preserve ⊢L L—→M)
|
... | step {M} L—→M with eval (gas m) (preserve ⊢L L—→M)
|
||||||
... | steps M—↠N fin = steps (L —→⟨ L—→M ⟩ M—↠N) fin
|
... | steps M—↠N fin = steps (L —→⟨ L—→M ⟩ M—↠N) fin
|
||||||
```
|
```
|
||||||
Let `L` be the name of the term we are reducing, and `⊢L` be the
|
Let `L` be the name of the term we are reducing, and `⊢L` be the
|
||||||
evidence that `L` is well typed. We consider the amount of gas
|
evidence that `L` is well typed. We consider the amount of gas
|
||||||
|
|
|
@ -48,7 +48,7 @@ system that _decides_ whether any two substitutions are equal.
|
||||||
```
|
```
|
||||||
import Relation.Binary.PropositionalEquality as Eq
|
import Relation.Binary.PropositionalEquality as Eq
|
||||||
open Eq using (_≡_; refl; sym; cong; cong₂; cong-app)
|
open Eq using (_≡_; refl; sym; cong; cong₂; cong-app)
|
||||||
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
|
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; step-≡; _∎)
|
||||||
open import Function using (_∘_)
|
open import Function using (_∘_)
|
||||||
open import plfa.part2.Untyped
|
open import plfa.part2.Untyped
|
||||||
using (Type; Context; _⊢_; ★; _∋_; ∅; _,_; Z; S_; `_; ƛ_; _·_;
|
using (Type; Context; _⊢_; ★; _∋_; ∅; _,_; Z; S_; `_; ƛ_; _·_;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title : "Subtyping: records"
|
title : "Subtyping: Records"
|
||||||
layout : page
|
layout : page
|
||||||
prev : /More/
|
prev : /More/
|
||||||
permalink : /Subtyping/
|
permalink : /Subtyping/
|
||||||
|
@ -30,7 +30,7 @@ can also have type `B` if `A` is a subtype of `B`.
|
||||||
|
|
||||||
⊢<: : ∀{Γ M A B}
|
⊢<: : ∀{Γ M A B}
|
||||||
→ Γ ⊢ M ⦂ A
|
→ Γ ⊢ M ⦂ A
|
||||||
→ A <: B
|
→ A <: B
|
||||||
-----------
|
-----------
|
||||||
→ Γ ⊢ M ⦂ B
|
→ Γ ⊢ M ⦂ B
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ written `M # l`, and whose dynamic semantics is defined by the
|
||||||
following reduction rule, which says that accessing the field `lⱼ`
|
following reduction rule, which says that accessing the field `lⱼ`
|
||||||
returns the value stored at that field.
|
returns the value stored at that field.
|
||||||
|
|
||||||
{l₁=v₁, ..., lⱼ=vⱼ, ..., lᵢ=vᵢ} # lⱼ —→ vⱼ
|
{l₁=v₁, ..., lⱼ=vⱼ, ..., lᵢ=vᵢ} # lⱼ —→ vⱼ
|
||||||
|
|
||||||
In this chapter we add records and record types to the simply typed
|
In this chapter we add records and record types to the simply typed
|
||||||
lambda calculus (STLC) and prove type safety. It is instructive to see
|
lambda calculus (STLC) and prove type safety. It is instructive to see
|
||||||
|
@ -138,14 +138,14 @@ Name = String
|
||||||
A record is traditionally written as follows
|
A record is traditionally written as follows
|
||||||
|
|
||||||
{ l₁ = M₁, ..., lᵢ = Mᵢ }
|
{ l₁ = M₁, ..., lᵢ = Mᵢ }
|
||||||
|
|
||||||
so a natural representation is a list of label-term pairs.
|
so a natural representation is a list of label-term pairs.
|
||||||
However, we find it more convenient to represent records as a pair of
|
However, we find it more convenient to represent records as a pair of
|
||||||
vectors (Agda's `Vec` type), one vector of fields and one vector of terms:
|
vectors (Agda's `Vec` type), one vector of fields and one vector of terms:
|
||||||
|
|
||||||
l₁, ..., lᵢ
|
l₁, ..., lᵢ
|
||||||
M₁, ..., Mᵢ
|
M₁, ..., Mᵢ
|
||||||
|
|
||||||
This representation has the advantage that the traditional subscript
|
This representation has the advantage that the traditional subscript
|
||||||
notation `lᵢ` corresponds to indexing into a vector.
|
notation `lᵢ` corresponds to indexing into a vector.
|
||||||
|
|
||||||
|
@ -244,9 +244,9 @@ If one vector `ns` is a subset of another `ms`, then for any element
|
||||||
lookup-⊆ : ∀{n m : ℕ}{ns : Vec Name n}{ms : Vec Name m}{i : Fin n}
|
lookup-⊆ : ∀{n m : ℕ}{ns : Vec Name n}{ms : Vec Name m}{i : Fin n}
|
||||||
→ ns ⊆ ms
|
→ ns ⊆ ms
|
||||||
→ Σ[ k ∈ Fin m ] lookup ns i ≡ lookup ms k
|
→ Σ[ k ∈ Fin m ] lookup ns i ≡ lookup ms k
|
||||||
lookup-⊆ {suc n} {m} {x ∷ ns} {ms} {zero} ns⊆ms
|
lookup-⊆ {suc n} {m} {x ∷ ns} {ms} {zero} ns⊆ms
|
||||||
with lookup-∈ (ns⊆ms x (here refl))
|
with lookup-∈ (ns⊆ms x (here refl))
|
||||||
... | ⟨ k , ms[k]=x ⟩ =
|
... | ⟨ k , ms[k]=x ⟩ =
|
||||||
⟨ k , (sym ms[k]=x) ⟩
|
⟨ k , (sym ms[k]=x) ⟩
|
||||||
lookup-⊆ {suc n} {m} {x ∷ ns} {ms} {suc i} x∷ns⊆ms =
|
lookup-⊆ {suc n} {m} {x ∷ ns} {ms} {suc i} x∷ns⊆ms =
|
||||||
lookup-⊆ {n} {m} {ns} {ms} {i} (λ x z → x∷ns⊆ms x (there z))
|
lookup-⊆ {n} {m} {ns} {ms} {i} (λ x z → x∷ns⊆ms x (there z))
|
||||||
|
@ -258,7 +258,7 @@ lookup-⊆ {suc n} {m} {x ∷ ns} {ms} {suc i} x∷ns⊆ms =
|
||||||
data Type : Set where
|
data Type : Set where
|
||||||
_⇒_ : Type → Type → Type
|
_⇒_ : Type → Type → Type
|
||||||
`ℕ : Type
|
`ℕ : Type
|
||||||
{_⦂_} : {n : ℕ} (ls : Vec Name n) (As : Vec Type n) → .{d : distinct ls} → Type
|
{_⦂_} : {n : ℕ} (ls : Vec Name n) (As : Vec Type n) → .{d : distinct ls} → Type
|
||||||
```
|
```
|
||||||
|
|
||||||
In addition to function types `A ⇒ B` and natural numbers `ℕ`, we
|
In addition to function types `A ⇒ B` and natural numbers `ℕ`, we
|
||||||
|
@ -366,7 +366,7 @@ Here is the proof of reflexivity, by induction on the size of the type.
|
||||||
with ty-size-pos {A}
|
with ty-size-pos {A}
|
||||||
... | pos rewrite n≤0⇒n≡0 m
|
... | pos rewrite n≤0⇒n≡0 m
|
||||||
with pos
|
with pos
|
||||||
... | ()
|
... | ()
|
||||||
<:-refl-aux {suc n}{`ℕ}{m} = <:-nat
|
<:-refl-aux {suc n}{`ℕ}{m} = <:-nat
|
||||||
<:-refl-aux {suc n}{A ⇒ B}{m} =
|
<:-refl-aux {suc n}{A ⇒ B}{m} =
|
||||||
let A<:A = <:-refl-aux {n}{A}{m+n≤o⇒m≤o _ (≤-pred m) } in
|
let A<:A = <:-refl-aux {n}{A}{m+n≤o⇒m≤o _ (≤-pred m) } in
|
||||||
|
@ -376,7 +376,7 @@ Here is the proof of reflexivity, by induction on the size of the type.
|
||||||
where
|
where
|
||||||
G : ls ⦂ As <: ls ⦂ As
|
G : ls ⦂ As <: ls ⦂ As
|
||||||
G {i}{j} lij rewrite distinct-lookup-inj (distinct-relevant d) lij =
|
G {i}{j} lij rewrite distinct-lookup-inj (distinct-relevant d) lij =
|
||||||
let As[i]≤n = ≤-trans (lookup-vec-ty-size {As = As}{i}) (≤-pred m) in
|
let As[i]≤n = ≤-trans (lookup-vec-ty-size {As = As}{i}) (≤-pred m) in
|
||||||
<:-refl-aux {n}{lookup As i}{As[i]≤n}
|
<:-refl-aux {n}{lookup As i}{As[i]≤n}
|
||||||
```
|
```
|
||||||
The theorem statement uses `n` as an upper bound on the size of the type `A`
|
The theorem statement uses `n` as an upper bound on the size of the type `A`
|
||||||
|
@ -394,7 +394,7 @@ and proceeds by induction on `n`.
|
||||||
Regarding the latter, we need to show that for any `i` and `j`,
|
Regarding the latter, we need to show that for any `i` and `j`,
|
||||||
`lookup ls j ≡ lookup ls i` implies `lookup As j <: lookup As i`.
|
`lookup ls j ≡ lookup ls i` implies `lookup As j <: lookup As i`.
|
||||||
Because `lookup` is injective on distinct vectors, we have `i ≡ j`.
|
Because `lookup` is injective on distinct vectors, we have `i ≡ j`.
|
||||||
We then use the induction hypothesis to show that
|
We then use the induction hypothesis to show that
|
||||||
`lookup As i <: lookup As i`, noting that the size of
|
`lookup As i <: lookup As i`, noting that the size of
|
||||||
`lookup As i` is less-than-or-equal to the size of `As`, which
|
`lookup As i` is less-than-or-equal to the size of `As`, which
|
||||||
is one smaller than the size of `{ ls ⦂ As }`.
|
is one smaller than the size of `{ ls ⦂ As }`.
|
||||||
|
@ -421,7 +421,7 @@ The following corollary packages up reflexivity for ease of use.
|
||||||
where
|
where
|
||||||
As<:Cs : ls ⦂ As <: ns ⦂ Cs
|
As<:Cs : ls ⦂ As <: ns ⦂ Cs
|
||||||
As<:Cs {i}{j} ls[j]=ns[i]
|
As<:Cs {i}{j} ls[j]=ns[i]
|
||||||
with lookup-⊆ {i = i} ns⊆ms
|
with lookup-⊆ {i = i} ns⊆ms
|
||||||
... | ⟨ k , ns[i]=ms[k] ⟩ =
|
... | ⟨ k , ns[i]=ms[k] ⟩ =
|
||||||
let As[j]<:Bs[k] = As<:Bs {k}{j} (trans ls[j]=ns[i] ns[i]=ms[k]) in
|
let As[j]<:Bs[k] = As<:Bs {k}{j} (trans ls[j]=ns[i] ns[i]=ms[k]) in
|
||||||
let Bs[k]<:Cs[i] = Bs<:Cs {i}{k} (sym ns[i]=ms[k]) in
|
let Bs[k]<:Cs[i] = Bs<:Cs {i}{k} (sym ns[i]=ms[k]) in
|
||||||
|
@ -450,7 +450,7 @@ The proof is by induction on the derivations of `A <: B` and `B <: C`.
|
||||||
if we can prove that `lookup ls j ≡ lookup ms k`.
|
if we can prove that `lookup ls j ≡ lookup ms k`.
|
||||||
We already have `lookup ls j ≡ lookup ns i` and we
|
We already have `lookup ls j ≡ lookup ns i` and we
|
||||||
obtain `lookup ns i ≡ lookup ms k` by use of the lemma `lookup-⊆`,
|
obtain `lookup ns i ≡ lookup ms k` by use of the lemma `lookup-⊆`,
|
||||||
noting that `ns ⊆ ms`.
|
noting that `ns ⊆ ms`.
|
||||||
We can obtain the later, that `lookup Bs k <: lookup Cs i`,
|
We can obtain the later, that `lookup Bs k <: lookup Cs i`,
|
||||||
from `{ ms ⦂ Bs } <: { ns ⦂ Cs }`.
|
from `{ ms ⦂ Bs } <: { ns ⦂ Cs }`.
|
||||||
It suffices to show that `lookup ms k ≡ lookup ns i`,
|
It suffices to show that `lookup ms k ≡ lookup ns i`,
|
||||||
|
@ -527,7 +527,7 @@ The typing judgment takes the form `Γ ⊢ M ⦂ A` and relies on an
|
||||||
auxiliary judgment `Γ ⊢* Ms ⦂ As` for typing a vector of terms.
|
auxiliary judgment `Γ ⊢* Ms ⦂ As` for typing a vector of terms.
|
||||||
|
|
||||||
```
|
```
|
||||||
data _⊢*_⦂_ : Context → ∀ {n} → Vec Term n → Vec Type n → Set
|
data _⊢*_⦂_ : Context → ∀ {n} → Vec Term n → Vec Type n → Set
|
||||||
|
|
||||||
data _⊢_⦂_ : Context → Term → Type → Set where
|
data _⊢_⦂_ : Context → Term → Type → Set where
|
||||||
|
|
||||||
|
@ -607,7 +607,7 @@ chapter. Here we discuss the three new rules.
|
||||||
|
|
||||||
* Rule `⊢<:`: (Subsumption) If a term `M` has type `A`, and `A <: B`,
|
* Rule `⊢<:`: (Subsumption) If a term `M` has type `A`, and `A <: B`,
|
||||||
then term `M` also has type `B`.
|
then term `M` also has type `B`.
|
||||||
|
|
||||||
|
|
||||||
## Renaming and Substitution
|
## Renaming and Substitution
|
||||||
|
|
||||||
|
@ -712,7 +712,7 @@ data Value : Term → Set where
|
||||||
→ Value (`suc V)
|
→ Value (`suc V)
|
||||||
|
|
||||||
V-rcd : ∀{n}{ls : Vec Name n}{Ms : Vec Term n}
|
V-rcd : ∀{n}{ls : Vec Name n}{Ms : Vec Term n}
|
||||||
→ Value { ls := Ms }
|
→ Value { ls := Ms }
|
||||||
```
|
```
|
||||||
|
|
||||||
## Reduction
|
## Reduction
|
||||||
|
@ -827,10 +827,10 @@ canonical ⊢zero V-zero = C-zero
|
||||||
canonical (⊢suc ⊢V) (V-suc VV) = C-suc (canonical ⊢V VV)
|
canonical (⊢suc ⊢V) (V-suc VV) = C-suc (canonical ⊢V VV)
|
||||||
canonical (⊢case ⊢L ⊢M ⊢N) ()
|
canonical (⊢case ⊢L ⊢M ⊢N) ()
|
||||||
canonical (⊢μ ⊢M) ()
|
canonical (⊢μ ⊢M) ()
|
||||||
canonical (⊢rcd ⊢Ms d) VV = C-rcd {dls = d} ⊢Ms d <:-refl
|
canonical (⊢rcd ⊢Ms d) VV = C-rcd {dls = d} ⊢Ms d <:-refl
|
||||||
canonical (⊢<: ⊢V <:-nat) VV = canonical ⊢V VV
|
canonical (⊢<: ⊢V <:-nat) VV = canonical ⊢V VV
|
||||||
canonical (⊢<: ⊢V (<:-fun {A}{B}{C}{D} C<:A B<:D)) VV
|
canonical (⊢<: ⊢V (<:-fun {A}{B}{C}{D} C<:A B<:D)) VV
|
||||||
with canonical ⊢V VV
|
with canonical ⊢V VV
|
||||||
... | C-ƛ {N}{A′}{B′}{A}{B} ⊢N AB′<:AB = C-ƛ ⊢N (<:-trans AB′<:AB (<:-fun C<:A B<:D))
|
... | C-ƛ {N}{A′}{B′}{A}{B} ⊢N AB′<:AB = C-ƛ ⊢N (<:-trans AB′<:AB (<:-fun C<:A B<:D))
|
||||||
canonical (⊢<: ⊢V (<:-rcd {ks = ks}{ls = ls}{d2 = dls} ls⊆ks ls⦂Ss<:ks⦂Ts)) VV
|
canonical (⊢<: ⊢V (<:-rcd {ks = ks}{ls = ls}{d2 = dls} ls⊆ks ls⦂Ss<:ks⦂Ts)) VV
|
||||||
with canonical ⊢V VV
|
with canonical ⊢V VV
|
||||||
|
@ -915,8 +915,8 @@ progress (⊢· ⊢L ⊢M)
|
||||||
... | done VL
|
... | done VL
|
||||||
with progress ⊢M
|
with progress ⊢M
|
||||||
... | step M—→M′ = step (ξ-·₂ VL M—→M′)
|
... | step M—→M′ = step (ξ-·₂ VL M—→M′)
|
||||||
... | done VM
|
... | done VM
|
||||||
with canonical ⊢L VL
|
with canonical ⊢L VL
|
||||||
... | C-ƛ ⊢N _ = step (β-ƛ VM)
|
... | C-ƛ ⊢N _ = step (β-ƛ VM)
|
||||||
progress ⊢zero = done V-zero
|
progress ⊢zero = done V-zero
|
||||||
progress (⊢suc ⊢M) with progress ⊢M
|
progress (⊢suc ⊢M) with progress ⊢M
|
||||||
|
@ -950,7 +950,7 @@ progress (⊢<: {A = A}{B} ⊢M A<:B) = progress ⊢M
|
||||||
* Case `⊢rcd`: we immediately characterize the record as a value.
|
* Case `⊢rcd`: we immediately characterize the record as a value.
|
||||||
|
|
||||||
* Case `⊢<:`: we invoke the induction hypothesis on sub-derivation of `Γ ⊢ M ⦂ A`.
|
* Case `⊢<:`: we invoke the induction hypothesis on sub-derivation of `Γ ⊢ M ⦂ A`.
|
||||||
|
|
||||||
|
|
||||||
## Preservation <a name="subtyping-preservation"></a>
|
## Preservation <a name="subtyping-preservation"></a>
|
||||||
|
|
||||||
|
@ -1047,9 +1047,9 @@ subst-pres : ∀ {Γ Δ σ N A}
|
||||||
-----------------
|
-----------------
|
||||||
→ Δ ⊢ subst σ N ⦂ A
|
→ Δ ⊢ subst σ N ⦂ A
|
||||||
subst-pres σ⦂ (⊢` eq) = σ⦂ eq
|
subst-pres σ⦂ (⊢` eq) = σ⦂ eq
|
||||||
subst-pres {σ = σ} σ⦂ (⊢ƛ ⊢N) = ⊢ƛ (subst-pres{σ = exts σ}(exts-pres {σ = σ} σ⦂) ⊢N)
|
subst-pres {σ = σ} σ⦂ (⊢ƛ ⊢N) = ⊢ƛ (subst-pres{σ = exts σ}(exts-pres {σ = σ} σ⦂) ⊢N)
|
||||||
subst-pres {σ = σ} σ⦂ (⊢· ⊢L ⊢M) = ⊢· (subst-pres{σ = σ} σ⦂ ⊢L) (subst-pres{σ = σ} σ⦂ ⊢M)
|
subst-pres {σ = σ} σ⦂ (⊢· ⊢L ⊢M) = ⊢· (subst-pres{σ = σ} σ⦂ ⊢L) (subst-pres{σ = σ} σ⦂ ⊢M)
|
||||||
subst-pres {σ = σ} σ⦂ (⊢μ ⊢M) = ⊢μ (subst-pres{σ = exts σ} (exts-pres{σ = σ} σ⦂) ⊢M)
|
subst-pres {σ = σ} σ⦂ (⊢μ ⊢M) = ⊢μ (subst-pres{σ = exts σ} (exts-pres{σ = σ} σ⦂) ⊢M)
|
||||||
subst-pres σ⦂ (⊢rcd ⊢Ms dls) = ⊢rcd (subst-vec-pres σ⦂ ⊢Ms ) dls
|
subst-pres σ⦂ (⊢rcd ⊢Ms dls) = ⊢rcd (subst-vec-pres σ⦂ ⊢Ms ) dls
|
||||||
subst-pres {σ = σ} σ⦂ (⊢# {d = d} ⊢M lif liA) =
|
subst-pres {σ = σ} σ⦂ (⊢# {d = d} ⊢M lif liA) =
|
||||||
⊢# {d = d} (subst-pres {σ = σ} σ⦂ ⊢M) lif liA
|
⊢# {d = d} (subst-pres {σ = σ} σ⦂ ⊢M) lif liA
|
||||||
|
@ -1097,7 +1097,7 @@ The proof is by induction on the typing derivation.
|
||||||
* Case `⊢-*-∷`: So we have `∅ ⊢ M ⦂ B` and `∅ ⊢* Ms ⦂ As`. We proceed by cases on `i`.
|
* Case `⊢-*-∷`: So we have `∅ ⊢ M ⦂ B` and `∅ ⊢* Ms ⦂ As`. We proceed by cases on `i`.
|
||||||
|
|
||||||
* If it is `0`, then lookup yields term `M` and `A ≡ B`, so we conclude that `∅ ⊢ M ⦂ A`.
|
* If it is `0`, then lookup yields term `M` and `A ≡ B`, so we conclude that `∅ ⊢ M ⦂ A`.
|
||||||
|
|
||||||
* If it is `suc i`, then we conclude by the induction hypothesis.
|
* If it is `suc i`, then we conclude by the induction hypothesis.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1144,7 +1144,7 @@ with cases on `M —→ N`.
|
||||||
* Case `⊢#` and `ξ-#`: So `∅ ⊢ M ⦂ { ls ⦂ As }`, `lookup ls i ≡ l`, `lookup As i ≡ A`,
|
* Case `⊢#` and `ξ-#`: So `∅ ⊢ M ⦂ { ls ⦂ As }`, `lookup ls i ≡ l`, `lookup As i ≡ A`,
|
||||||
and `M —→ M′`. We apply the induction hypothesis to obtain `∅ ⊢ M′ ⦂ { ls ⦂ As }`
|
and `M —→ M′`. We apply the induction hypothesis to obtain `∅ ⊢ M′ ⦂ { ls ⦂ As }`
|
||||||
and then conclude by rule `⊢#`.
|
and then conclude by rule `⊢#`.
|
||||||
|
|
||||||
* Case `⊢#` and `β-#`. We have `∅ ⊢ { ks := Ms } ⦂ { ls ⦂ As }`, `lookup ls i ≡ l`,
|
* Case `⊢#` and `β-#`. We have `∅ ⊢ { ks := Ms } ⦂ { ls ⦂ As }`, `lookup ls i ≡ l`,
|
||||||
`lookup As i ≡ A`, `lookup ks j ≡ l`, and `{ ks := Ms } # l —→ lookup Ms j`.
|
`lookup As i ≡ A`, `lookup ks j ≡ l`, and `{ ks := Ms } # l —→ lookup Ms j`.
|
||||||
By the canonical forms lemma, we have `∅ ⊢* Ms ⦂ Bs`, `ls ⊆ ks` and `ks ⦂ Bs <: ls ⦂ As`.
|
By the canonical forms lemma, we have `∅ ⊢* Ms ⦂ Bs`, `ls ⊆ ks` and `ks ⦂ Bs <: ls ⦂ As`.
|
||||||
|
@ -1230,7 +1230,7 @@ The non-algorithmic subtyping rules for variants are
|
||||||
∀i∈1..u, ∃j∈1..u, kⱼ = lᵢ and Aⱼ = Bᵢ
|
∀i∈1..u, ∃j∈1..u, kⱼ = lᵢ and Aⱼ = Bᵢ
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
〈k₁=A₁, ..., kᵤ=Aᵤ〉 <: 〈l₁=B₁, ..., lᵤ=Bᵤ〉
|
〈k₁=A₁, ..., kᵤ=Aᵤ〉 <: 〈l₁=B₁, ..., lᵤ=Bᵤ〉
|
||||||
|
|
||||||
Come up with an algorithmic subtyping rule for variant types.
|
Come up with an algorithmic subtyping rule for variant types.
|
||||||
|
|
||||||
#### Exercise `<:-alternative` (stretch)
|
#### Exercise `<:-alternative` (stretch)
|
||||||
|
@ -1260,7 +1260,7 @@ of the form:
|
||||||
|
|
||||||
If S <: { lᵢ : Tᵢ | i ∈ 1..n }, then S ≡ { kⱼ : Sⱼ | j ∈ 1..m }
|
If S <: { lᵢ : Tᵢ | i ∈ 1..n }, then S ≡ { kⱼ : Sⱼ | j ∈ 1..m }
|
||||||
and { lᵢ | i ∈ 1..n } ⊆ { kⱼ | j ∈ 1..m }
|
and { lᵢ | i ∈ 1..n } ⊆ { kⱼ | j ∈ 1..m }
|
||||||
and Sⱼ <: Tᵢ for every i and j such that lᵢ = kⱼ.
|
and Sⱼ <: Tᵢ for every i and j such that lᵢ = kⱼ.
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
|
@ -1274,6 +1274,5 @@ of the form:
|
||||||
|
|
||||||
* Barbara H. Liskov and Jeannette M. Wing. A Behavioral Notion of
|
* Barbara H. Liskov and Jeannette M. Wing. A Behavioral Notion of
|
||||||
Subtyping. In ACM Trans. Program. Lang. Syst. Volume 16, 1994.
|
Subtyping. In ACM Trans. Program. Lang. Syst. Volume 16, 1994.
|
||||||
|
|
||||||
* Types and Programming Languages. Benjamin C. Pierce. The MIT Press. 2002.
|
|
||||||
|
|
||||||
|
* Types and Programming Languages. Benjamin C. Pierce. The MIT Press. 2002.
|
||||||
|
|
|
@ -467,7 +467,7 @@ _ =
|
||||||
∎
|
∎
|
||||||
```
|
```
|
||||||
After just two steps the top-level term is an abstraction,
|
After just two steps the top-level term is an abstraction,
|
||||||
and `ζ` rules drive the rest of the normalisation.
|
and `ζ` rules drive the rest of the normalisation.
|
||||||
|
|
||||||
|
|
||||||
## Progress
|
## Progress
|
||||||
|
@ -547,8 +547,10 @@ As previously, progress immediately yields an evaluator.
|
||||||
|
|
||||||
Gas is specified by a natural number:
|
Gas is specified by a natural number:
|
||||||
```
|
```
|
||||||
data Gas : Set where
|
record Gas : Set where
|
||||||
gas : ℕ → Gas
|
constructor gas
|
||||||
|
field
|
||||||
|
amount : ℕ
|
||||||
```
|
```
|
||||||
When our evaluator returns a term `N`, it will either give evidence that
|
When our evaluator returns a term `N`, it will either give evidence that
|
||||||
`N` is normal or indicate that it ran out of gas:
|
`N` is normal or indicate that it ran out of gas:
|
||||||
|
|
|
@ -54,9 +54,6 @@ down a denotational semantics of the lambda calculus.
|
||||||
|
|
||||||
## Imports
|
## Imports
|
||||||
|
|
||||||
<!-- JGS: for equational reasoning
|
|
||||||
open import Relation.Binary using (Setoid)
|
|
||||||
-->
|
|
||||||
```
|
```
|
||||||
open import Agda.Primitive using (lzero; lsuc)
|
open import Agda.Primitive using (lzero; lsuc)
|
||||||
open import Data.Empty using (⊥-elim)
|
open import Data.Empty using (⊥-elim)
|
||||||
|
@ -589,7 +586,7 @@ denotation-setoid Γ = record
|
||||||
-->
|
-->
|
||||||
<!--
|
<!--
|
||||||
The following went inside the module ≃-Reasoning:
|
The following went inside the module ≃-Reasoning:
|
||||||
|
|
||||||
open import Relation.Binary.Reasoning.Setoid (denotation-setoid Γ)
|
open import Relation.Binary.Reasoning.Setoid (denotation-setoid Γ)
|
||||||
renaming (begin_ to start_; _≈⟨_⟩_ to _≃⟨_⟩_; _∎ to _☐) public
|
renaming (begin_ to start_; _≈⟨_⟩_ to _≃⟨_⟩_; _∎ to _☐) public
|
||||||
-->
|
-->
|
||||||
|
@ -854,7 +851,7 @@ Dᶜ n (a[n] ∷ ls) = (D^suc n (a[n] ∷ ls)) ↦ (vec-last (a[n] ∷ ls)) ↦
|
||||||
a successor function whose denotation is given by `D^suc`,
|
a successor function whose denotation is given by `D^suc`,
|
||||||
and the start of the path (last of the vector).
|
and the start of the path (last of the vector).
|
||||||
It returns the `n + 1` vertex in the path.
|
It returns the `n + 1` vertex in the path.
|
||||||
|
|
||||||
(D^suc (suc n) (a[n+1] ∷ a[n] ∷ ls)) ↦ (vec-last (a[n] ∷ ls)) ↦ a[n+1]
|
(D^suc (suc n) (a[n+1] ∷ a[n] ∷ ls)) ↦ (vec-last (a[n] ∷ ls)) ↦ a[n+1]
|
||||||
|
|
||||||
The exercise is to prove that for any path `ls`, the meaning of the
|
The exercise is to prove that for any path `ls`, the meaning of the
|
||||||
|
@ -870,7 +867,7 @@ apply-n zero = # 0
|
||||||
apply-n (suc n) = # 1 · apply-n n
|
apply-n (suc n) = # 1 · apply-n n
|
||||||
|
|
||||||
church : (n : ℕ) → ∅ ⊢ ★
|
church : (n : ℕ) → ∅ ⊢ ★
|
||||||
church n = ƛ ƛ apply-n n
|
church n = ƛ ƛ apply-n n
|
||||||
```
|
```
|
||||||
|
|
||||||
Prove the following theorem.
|
Prove the following theorem.
|
||||||
|
|
44
travis-build-cache.sh
Executable file
44
travis-build-cache.sh
Executable file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Dependencies:
|
||||||
|
# - curl <https://curl.haxx.se/>
|
||||||
|
# - yq <https://github.com/mikefarah/yq>
|
||||||
|
|
||||||
|
# Modify .travis.yml:
|
||||||
|
# - Remove 'script' and 'deploy' phases;
|
||||||
|
# - Add 'merge_mode';
|
||||||
|
# - Create JSON request.
|
||||||
|
#
|
||||||
|
body=$(cat .travis.yml \
|
||||||
|
| yq w - script "echo 'Done'"\
|
||||||
|
| yq d - before_deploy \
|
||||||
|
| yq d - deploy \
|
||||||
|
| yq p - config \
|
||||||
|
| yq w - message "Build cache" \
|
||||||
|
| yq w - branch dev \
|
||||||
|
| yq w - merge_mode replace \
|
||||||
|
| yq p - request -j)
|
||||||
|
|
||||||
|
# Send request to Travis.
|
||||||
|
#
|
||||||
|
resp=$(curl -s -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Accept: application/json" \
|
||||||
|
-H "Travis-API-Version: 3" \
|
||||||
|
-H "Authorization: token $TRAVIS_TOKEN" \
|
||||||
|
-d "$body" \
|
||||||
|
https://api.travis-ci.org/repo/plfa%2Fplfa.github.io/requests)
|
||||||
|
|
||||||
|
# Output response.
|
||||||
|
#
|
||||||
|
echo "$resp" \
|
||||||
|
| yq d - request.configs \
|
||||||
|
| yq d - request.config \
|
||||||
|
| yq r - --prettyPrint
|
||||||
|
|
||||||
|
# Output configuration.
|
||||||
|
#
|
||||||
|
echo "$resp" \
|
||||||
|
| yq r - request.config \
|
||||||
|
| yq p - config \
|
||||||
|
| yq r - --prettyPrint
|
Loading…
Reference in a new issue