diff --git a/src/plta/Lambda.lagda b/src/plta/Lambda.lagda index c722df21..d2cca691 100644 --- a/src/plta/Lambda.lagda +++ b/src/plta/Lambda.lagda @@ -11,7 +11,7 @@ module plta.Lambda where [This chapter was originally based on Chapter _Stlc_ of _Software Foundations_ (_Programming Language Foundations_). It has now been updated, but if you spot any plagiarism -please let me know. -- P] +please let me know. – P] The _lambda-calculus_, first published by the logician Alonzo Church in 1932, is a core calculus with only three syntactic constructs: @@ -67,7 +67,7 @@ open import Relation.Nullary.Negation using (¬?) Terms have seven constructs. Three are for the core lambda calculus: - * Variables `⌊ x ⌋` + * Variables `` x` * Abstractions `ƛ x ⇒ N` * Applications `L · M` @@ -94,7 +94,7 @@ correspond to introduction rules and deconstructors to eliminators. Here is the syntax of terms in BNF. L, M, N ::= - ⌊ x ⌋ | ƛ x ⇒ N | L · M | + ` x | ƛ x ⇒ N | L · M | `zero | `suc M | `case L [zero⇒ M |suc x ⇒ N] | μ x ⇒ M @@ -107,9 +107,10 @@ infix 6 ƛ_⇒_ infix 6 μ_⇒_ infixl 7 _·_ infix 8 `suc_ +infix 9 `_ data Term : Set where - ⌊_⌋ : Id → Term + `_ : Id → Term ƛ_⇒_ : Id → Term → Term _·_ : Term → Term → Term `zero : Term @@ -134,9 +135,9 @@ two = `suc `suc `zero plus : Term plus = μ "+" ⇒ ƛ "m" ⇒ ƛ "n" ⇒ - `case ⌊ "m" ⌋ - [zero⇒ ⌊ "n" ⌋ - |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) ] + `case ` "m" + [zero⇒ ` "n" + |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ] four : Term four = plus · two · two @@ -160,14 +161,14 @@ function that adds Church numerals, a function to compute successor, and a term that computes two plus two. \begin{code} twoᶜ : Term -twoᶜ = ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) +twoᶜ = ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z") plusᶜ : Term plusᶜ = ƛ "m" ⇒ ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒ - ⌊ "m" ⌋ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋) + ` "m" · ` "s" · (` "n" · ` "s" · ` "z") sucᶜ : Term -sucᶜ = ƛ "n" ⇒ `suc (⌊ "n" ⌋) +sucᶜ = ƛ "n" ⇒ `suc (` "n") fourᶜ : Term fourᶜ = plusᶜ · twoᶜ · twoᶜ · sucᶜ · `zero @@ -198,7 +199,7 @@ two natural numbers. ### Formal vs informal In informal presentation of formal semantics, one uses choice of -variable name to disambiguate and writes `x` rather than `⌊ x ⌋` +variable name to disambiguate and writes `x` rather than `` x` for a term that is a variable. Agda requires we distinguish. Similarly, informal presentation often use the same notation for @@ -218,10 +219,10 @@ and `N` the _body_ of the abstraction. A central feature of lambda calculus is that consistent renaming of bound variables leaves the meaning of a term unchanged. Thus the five terms -* `` ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) `` -* `` ƛ "f" ⇒ ƛ "x" ⇒ ⌊ "f" ⌋ · (⌊ "f" ⌋ · ⌊ "x" ⌋) `` -* `` ƛ "sam" ⇒ ƛ "zelda" ⇒ ⌊ "sam" ⌋ · (⌊ "sam" ⌋ · ⌊ "zelda" ⌋) `` -* `` ƛ "z" ⇒ ƛ "s" ⇒ ⌊ "z" ⌋ · (⌊ "z" ⌋ · ⌊ "s" ⌋) `` +* `` ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z") `` +* `` ƛ "f" ⇒ ƛ "x" ⇒ ` "f" · (` "f" · ` "x") `` +* `` ƛ "sam" ⇒ ƛ "zelda" ⇒ ` "sam" · (` "sam" · ` "zelda") `` +* `` ƛ "z" ⇒ ƛ "s" ⇒ ` "z" · (` "z" · ` "s") `` * `` ƛ "😇" ⇒ ƛ "😈" ⇒ # "😇" · (# "😇" · # "😈" ) `` are all considered equivalent. Following the convention introduced @@ -231,13 +232,13 @@ this equivalence relation is called _alpha renaming_. As we descend from a term into its subterms, variables that are bound may become free. Consider the following terms. -* `` ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) `` +* `` ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z") `` has both `s` and `z` as bound variables. -* `` ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) `` +* `` ƛ "z" ⇒ ` "s" · (` "s" · ` "z") `` has `s` bound and `z` free. -* `` ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) `` +* `` ` "s" · (` "s" · ` "z") `` has both `s` and `z` as free variables. We say that a term with no free variables is _closed_; otherwise it is @@ -247,12 +248,12 @@ two are open. Different occurrences of a variable may be bound and free. In the term - (ƛ "x" ⇒ ⌊ "x" ⌋) · ⌊ "x" ⌋ + (ƛ "x" ⇒ ` "x") · ` "x" the inner occurrence of `x` is bound while the outer occurrence is free. By alpha renaming, the term above is equivalent to - (ƛ "y" ⇒ ⌊ "y" ⌋) · ⌊ "x" ⌋ + (ƛ "y" ⇒ ` "y") · ` "x" in which `y` is bound and `x` is free. A common convention, called the _Barendregt convention_, is to use alpha renaming to ensure that the bound @@ -264,17 +265,17 @@ Case and recursion also introduce bound variables, which are also subject to alpha renaming. In the term μ "+" ⇒ ƛ "m" ⇒ ƛ "n" ⇒ - `case ⌊ "m" ⌋ - [zero⇒ ⌊ "n" ⌋ - |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) ] + `case ` "m" + [zero⇒ ` "n" + |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ] notice that there are two binding occurrences of `m`, one in the first line and one in the last line. It is equivalent to the following term, μ "plus" ⇒ ƛ "x" ⇒ ƛ "y" ⇒ - `case ⌊ "x" ⌋ - [zero⇒ ⌊ "y" ⌋ - |suc "x′" ⇒ `suc (⌊ "plus" ⌋ · ⌊ "x′" ⌋ · ⌊ "y" ⌋) ] + `case ` "x" + [zero⇒ ` "y" + |suc "x′" ⇒ `suc (` "plus" · ` "x′" · ` "y") ] where the two binding occurrences corresponding to `m` now have distinct names, `x` and `x′`. @@ -342,13 +343,13 @@ Substitution plays a key role in defining the operational semantics of function application. For instance, we have - (ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) · sucᶜ · `zero - ⟶ + (ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z")) · sucᶜ · `zero + ↦ (ƛ "z" ⇒ sucᶜ · (sucᶜ · "z")) · `zero - ⟶ + ↦ sucᶜ · (sucᶜ · `zero) -where we substitute `sucᶜ` for `` ⌊ "s" ⌋ `` and `` `zero `` for `` ⌊ "z" ⌋ `` +where we substitute `sucᶜ` for `` ` "s" `` and `` `zero `` for `` ` "z" `` in the body of the function abstraction. We write substitution as `N [ x := V ]`, meaning @@ -360,19 +361,19 @@ usually substitute values. Here are some examples: -* `` (sucᶜ · (sucᶜ · ⌊ "z" ⌋)) [ "z" := `zero ] `` yields +* `` (sucᶜ · (sucᶜ · ` "z")) [ "z" := `zero ] `` yields `` sucᶜ · (sucᶜ · `zero) `` -* `` (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) [ "s" := sucᶜ ] `` yields - ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋) `` -* `` (ƛ "x" ⇒ ⌊ "y" ⌋) [ "y" := `zero ] `` yields `` ƛ "x" ⇒ `zero `` -* `` (ƛ "x" ⇒ ⌊ "x" ⌋) [ "x" := `zero ] `` yields `` ƛ "x" ⇒ ⌊ "x" ⌋ `` -* `` (ƛ "y" ⇒ ⌊ "y" ⌋) [ "x" := `zero ] `` yields `` ƛ "x" ⇒ ⌊ "x" ⌋ `` +* `` (ƛ "z" ⇒ ` "s" · (` "s" · ` "z")) [ "s" := sucᶜ ] `` yields + ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z") `` +* `` (ƛ "x" ⇒ ` "y") [ "y" := `zero ] `` yields `` ƛ "x" ⇒ `zero `` +* `` (ƛ "x" ⇒ ` "x") [ "x" := `zero ] `` yields `` ƛ "x" ⇒ ` "x" `` +* `` (ƛ "y" ⇒ ` "y") [ "x" := `zero ] `` yields `` ƛ "x" ⇒ ` "x" `` In the last but one example, substituting `` `zero `` for `x` in -`` ƛ "x" ⇒ ⌊ "x" ⌋ `` does _not_ yield `` ƛ "x" ⇒ `zero ``, +`` ƛ "x" ⇒ ` "x" `` does _not_ yield `` ƛ "x" ⇒ `zero ``, since `x` is bound in the lambda abstraction. The choice of bound names is irrelevant: both -`` ƛ "x" ⇒ ⌊ "x" ⌋ `` and `` ƛ "y" ⇒ ⌊ "y" ⌋ `` stand for the +`` ƛ "x" ⇒ ` "x" `` and `` ƛ "y" ⇒ ` "y" `` stand for the identity function. One way to think of this is that `x` within the body of the abstraction stands for a _different_ variable than `x` outside the abstraction, they just happen to have the same name. @@ -382,13 +383,13 @@ when term substituted for the variable is closed. This is because substitution by terms that are _not_ closed may require renaming of bound variables. For example: -* `` (ƛ "x" ⇒ ⌊ "x" ⌋ · ⌊ "y" ⌋) [ "y" := ⌊ "x" ⌋ · ⌊ "y" ⌋ ] `` should not yield - `` ƛ "x" ⇒ ⌊ "x" ⌋ · (⌊ "x" ⌋ · ⌊ "y" ⌋) `` +* `` (ƛ "x" ⇒ ` "x" · ` "y") [ "y" := ` "x" · ` "y" ] `` should not yield + `` ƛ "x" ⇒ ` "x" · (` "x" · ` "y") `` Instead, we should rename the variables to avoid capture. -* `` (ƛ "x" ⇒ ⌊ "x" ⌋ · ⌊ "y" ⌋) [ "y" := ⌊ "x" ⌋ · ⌊ "y" ⌋ ] `` should yield - `` ƛ "z" ⇒ ⌊ "z" ⌋ · (⌊ "x" ⌋ · ⌊ "y" ⌋) `` +* `` (ƛ "x" ⇒ ` "x" · ` "y") [ "y" := ` "x" · ` "y" ] `` should yield + `` ƛ "z" ⇒ ` "z" · (` "x" · ` "y") `` Formal definition of substitution with suitable renaming is considerably more complex, so we avoid it by restricting to substitution by closed terms, @@ -400,9 +401,9 @@ Here is the formal definition of substitution by closed terms in Agda. infix 9 _[_:=_] _[_:=_] : Term → Id → Term → Term -⌊ x ⌋ [ y := V ] with x ≟ y +(` x) [ y := V ] with x ≟ y ... | yes _ = V -... | no _ = ⌊ x ⌋ +... | no _ = ` x (ƛ x ⇒ N) [ y := V ] with x ≟ y ... | yes _ = ƛ x ⇒ N ... | no _ = ƛ x ⇒ (N [ y := V ]) @@ -440,19 +441,19 @@ simply push substitution recursively into the subterms. Here is confirmation that the examples above are correct. \begin{code} -_ : (sucᶜ · sucᶜ · ⌊ "z" ⌋) [ "z" := `zero ] ≡ sucᶜ · sucᶜ · `zero +_ : (sucᶜ · sucᶜ · ` "z") [ "z" := `zero ] ≡ sucᶜ · sucᶜ · `zero _ = refl -_ : (ƛ "z" ⇒ ⌊ "s" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋) [ "s" := sucᶜ ] ≡ ƛ "z" ⇒ sucᶜ · sucᶜ · ⌊ "z" ⌋ +_ : (ƛ "z" ⇒ ` "s" · ` "s" · ` "z") [ "s" := sucᶜ ] ≡ ƛ "z" ⇒ sucᶜ · sucᶜ · ` "z" _ = refl -_ : (ƛ "x" ⇒ ⌊ "y" ⌋) [ "y" := `zero ] ≡ ƛ "x" ⇒ `zero +_ : (ƛ "x" ⇒ ` "y") [ "y" := `zero ] ≡ ƛ "x" ⇒ `zero _ = refl -_ : (ƛ "x" ⇒ ⌊ "x" ⌋) [ "x" := `zero ] ≡ ƛ "x" ⇒ ⌊ "x" ⌋ +_ : (ƛ "x" ⇒ ` "x") [ "x" := `zero ] ≡ ƛ "x" ⇒ ` "x" _ = refl -_ : (ƛ "y" ⇒ ⌊ "y" ⌋) [ "x" := `zero ] ≡ ƛ "y" ⇒ ⌊ "y" ⌋ +_ : (ƛ "y" ⇒ ` "y") [ "x" := `zero ] ≡ ƛ "y" ⇒ ` "y" _ = refl \end{code} @@ -460,11 +461,11 @@ _ = refl What is the result of the following substitution? - (ƛ "y" ⇒ ⌊ "x" ⌋ · (ƛ "x" ⇒ ⌊ "x" ⌋)) [ "x" := `zero ] + (ƛ "y" ⇒ ` "x" · (ƛ "x" ⇒ ` "x")) [ "x" := `zero ] -1. `` (ƛ "y" ⇒ ⌊ "x" ⌋ · (ƛ "x" ⇒ ⌊ "x" ⌋)) `` -2. `` (ƛ "y" ⇒ ⌊ "x" ⌋ · (ƛ "x" ⇒ `zero)) `` -3. `` (ƛ "y" ⇒ `zero · (ƛ "x" ⇒ ⌊ "x" ⌋)) `` +1. `` (ƛ "y" ⇒ ` "x" · (ƛ "x" ⇒ ` "x")) `` +2. `` (ƛ "y" ⇒ ` "x" · (ƛ "x" ⇒ `zero)) `` +3. `` (ƛ "y" ⇒ `zero · (ƛ "x" ⇒ ` "x")) `` 4. `` (ƛ "y" ⇒ `zero · (ƛ "x" ⇒ `zero)) `` @@ -479,16 +480,16 @@ the argument for the variable in the abstraction. In an informal presentation of the operational semantics, the rules for reduction of applications are written as follows. - L ⟶ L′ - --------------- ξ·₁ - L · M ⟶ L′ · M + L ↦ L′ + -------------- ξ-·₁ + L · M ↦ L′ · M - M ⟶ M′ - --------------- ξ·₂ - V · M ⟶ V · M′ + M ↦ M′ + -------------- ξ-·₂ + V · M ↦ V · M′ - --------------------------------- βλ· - (ƛ x ⇒ N) · V ⟶ N [ x := V ] + ---------------------------- β-ƛ + (ƛ x ⇒ N) · V ↦ N [ x := V ] The Agda version of the rules below will be similar, except that universal quantifications are made explicit, and so are the predicates that indicate @@ -513,75 +514,84 @@ the bound variable by the entire fixpoint term. Here are the rules formalised in Agda. \begin{code} -infix 4 _⟶_ +infix 4 _↦_ -data _⟶_ : Term → Term → Set where +data _↦_ : Term → Term → Set where ξ-·₁ : ∀ {L L′ M} - → L ⟶ L′ + → L ↦ L′ ----------------- - → L · M ⟶ L′ · M + → L · M ↦ L′ · M ξ-·₂ : ∀ {V M M′} → Value V - → M ⟶ M′ + → M ↦ M′ ----------------- - → V · M ⟶ V · M′ + → V · M ↦ V · M′ - β-ƛ· : ∀ {x N V} + β-ƛ : ∀ {x N V} → Value V ------------------------------ - → (ƛ x ⇒ N) · V ⟶ N [ x := V ] + → (ƛ x ⇒ N) · V ↦ N [ x := V ] ξ-suc : ∀ {M M′} - → M ⟶ M′ + → M ↦ M′ ------------------ - → `suc M ⟶ `suc M′ + → `suc M ↦ `suc M′ ξ-case : ∀ {x L L′ M N} - → L ⟶ L′ + → L ↦ L′ ----------------------------------------------------------------- - → `case L [zero⇒ M |suc x ⇒ N ] ⟶ `case L′ [zero⇒ M |suc x ⇒ N ] + → `case L [zero⇒ M |suc x ⇒ N ] ↦ `case L′ [zero⇒ M |suc x ⇒ N ] - β-case-zero : ∀ {x M N} + β-zero : ∀ {x M N} ---------------------------------------- - → `case `zero [zero⇒ M |suc x ⇒ N ] ⟶ M + → `case `zero [zero⇒ M |suc x ⇒ N ] ↦ M - β-case-suc : ∀ {x V M N} + β-suc : ∀ {x V M N} → Value V --------------------------------------------------- - → `case `suc V [zero⇒ M |suc x ⇒ N ] ⟶ N [ x := V ] + → `case `suc V [zero⇒ M |suc x ⇒ N ] ↦ N [ x := V ] β-μ : ∀ {x M} ------------------------------ - → μ x ⇒ M ⟶ M [ x := μ x ⇒ M ] + → μ x ⇒ M ↦ M [ x := μ x ⇒ M ] \end{code} +The reduction rules are carefully designed to ensure that subterms +of a term are reduced to values before the whole term is reduced. +This is referred to as _call by value_ reduction. + +Further, we have arranged that subterms are reduced in a +left-to-right order. This means that reduction is _deterministic_: +for any term, there is at most one other term to which it reduces. +Put another way, our reduction relation `↦` is in fact a function. + #### Quiz What does the following term step to? - (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) ⟶ ??? + (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") ↦ ??? -1. `` (ƛ "x" ⇒ ⌊ "x" ⌋) `` -2. `` (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) `` -3. `` (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) `` +1. `` (ƛ "x" ⇒ ` "x") `` +2. `` (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") `` +3. `` (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") `` What does the following term step to? - (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) ⟶ ??? + (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") ↦ ??? -1. `` (ƛ "x" ⇒ ⌊ "x" ⌋) `` -2. `` (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) `` -3. `` (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) `` +1. `` (ƛ "x" ⇒ ` "x") `` +2. `` (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") `` +3. `` (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") `` What does the following term step to? (Where `two` and `sucᶜ` are as defined above.) - two · sucᶜ · `zero ⟶ ??? + two · sucᶜ · `zero ↦ ??? 1. `` sucᶜ · (sucᶜ · `zero) `` -2. `` (ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · `zero `` +2. `` (ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · `zero `` 3. `` `zero `` @@ -589,170 +599,155 @@ What does the following term step to? (Where `two` and `sucᶜ` are as defined A single step is only part of the story. In general, we wish to repeatedly step a closed term until it reduces to a value. We do this by defining -the reflexive and transitive closure `⟶*` of the step function `⟶`. +the reflexive and transitive closure `↠` of the step relation `↦`. -The reflexive and transitive closure `⟶*` of an arbitrary relation `⟶` -is the smallest relation that includes `⟶` and is also reflexive -and transitive. We could define this directly, as follows. -\begin{code} -module Closure (A : Set) (_⟶_ : A → A → Set) where - - data _⟶*_ : A → A → Set where - - refl : ∀ {M} - -------- - → M ⟶* M - - trans : ∀ {L M N} - → L ⟶* M - → M ⟶* N - -------- - → L ⟶* N - - inc : ∀ {M N} - → M ⟶ N - -------- - → M ⟶* N -\end{code} -Here we use a module to define the reflexive and transitive -closure of an arbitrary relation. -The three clauses specify that `⟶*` is reflexive and transitive, -and that `⟶` implies `⟶*`. - -However, it will prove more convenient to define the transitive -closure as a sequence of zero or more steps of the underlying -relation, along lines similar to that for reasoning about -chains of equalities +We define reflexive and transitive closure as a sequence of zero or +more steps of the underlying relation, along lines similar to that for +reasoning about chains of equalities Chapter [Equality]({{ site.baseurl }}{% link out/plta/Equality.md %}). \begin{code} -module Chain (A : Set) (_⟶_ : A → A → Set) where +infix 2 _↠_ +infix 1 begin_ +infixr 2 _↦⟨_⟩_ +infix 3 _∎ - infix 2 _⟶*_ - infix 1 begin_ - infixr 2 _⟶⟨_⟩_ - infix 3 _∎ +data _↠_ : Term → Term → Set where + _∎ : ∀ M + --------- + → M ↠ M - data _⟶*_ : A → A → Set where - _∎ : ∀ M - --------- - → M ⟶* M + _↦⟨_⟩_ : ∀ L {M N} + → L ↦ M + → M ↠ N + --------- + → L ↠ N - _⟶⟨_⟩_ : ∀ L {M N} - → L ⟶ M - → M ⟶* N - --------- - → L ⟶* N - - begin_ : ∀ {M N} → (M ⟶* N) → (M ⟶* N) - begin M⟶*N = M⟶*N +begin_ : ∀ {M N} → (M ↠ N) → (M ↠ N) +begin M↠N = M↠N \end{code} We can read this as follows. -* From term `M`, we can take no steps, - giving a step of type `M ⟶* M`. +* From term `M`, we can take no steps, giving a step of type `M ↠ M`. It is written `M ∎`. -* From term `L` we can take a single of type `L ⟶ M` - followed by zero or more steps of type `M ⟶* N`, - giving a step of type `L ⟶* N`, - It is written `L ⟨ L⟶M ⟩ M⟶*N`, - where `L⟶M` and `M⟶*N` are steps of the appropriate type. +* From term `L` we can take a single of type `L ↦ M` followed by zero + or more steps of type `M ↠ N`, giving a step of type `L ↠ N`. It is + written `L ↦⟨ L↦M ⟩ M↠N`, where `L↦M` and `M↠N` are steps of the + appropriate type. -The notation is chosen to allow us to lay -out example reductions in an appealing way, -as we will see in the next section. +The notation is chosen to allow us to lay out example reductions in an +appealing way, as we will see in the next section. -We then instantiate the second module to our specific notion -of reduction step. +As alternative is to define reflexive and transitive closure directly, +as the smallest relation that includes `↦` and is also reflexive +and transitive. We could do so as follows. \begin{code} -open Chain (Term) (_⟶_) +data _↠′_ : Term → Term → Set where + + step : ∀ {M N} + → M ↦ N + ------ + → M ↠′ N + + refl : ∀ {M} + ------ + → M ↠′ M + + trans : ∀ {L M N} + → L ↠′ M + → M ↠′ N + ------ + → L ↠′ N \end{code} +The three constructors specify, respectively, that `↠` includes `↦` +and is reflexive and transitive. +It is a straightforward exercise to show the two are equivalent. -#### Exercise (`closure-equivalent`) +#### Exercise (`↠≃↠′`) Show that the two notions of reflexive and transitive closure -above are equivalent. +above are isomorphic. ## Examples Here is a sample reduction demonstrating that two plus two is four. \begin{code} -_ : four ⟶* `suc `suc `suc `suc `zero +_ : four ↠ `suc `suc `suc `suc `zero _ = begin plus · two · two - ⟶⟨ ξ-·₁ (ξ-·₁ β-μ) ⟩ + ↦⟨ ξ-·₁ (ξ-·₁ β-μ) ⟩ (ƛ "m" ⇒ ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ]) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ]) · two · two - ⟶⟨ ξ-·₁ (β-ƛ· (V-suc (V-suc V-zero))) ⟩ + ↦⟨ ξ-·₁ (β-ƛ (V-suc (V-suc V-zero))) ⟩ (ƛ "n" ⇒ - `case two [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ]) + `case two [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ]) · two - ⟶⟨ β-ƛ· (V-suc (V-suc V-zero)) ⟩ - `case two [zero⇒ two |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · two) ] - ⟶⟨ β-case-suc (V-suc V-zero) ⟩ + ↦⟨ β-ƛ (V-suc (V-suc V-zero)) ⟩ + `case two [zero⇒ two |suc "m" ⇒ `suc (plus · ` "m" · two) ] + ↦⟨ β-suc (V-suc V-zero) ⟩ `suc (plus · `suc `zero · two) - ⟶⟨ ξ-suc (ξ-·₁ (ξ-·₁ β-μ)) ⟩ + ↦⟨ ξ-suc (ξ-·₁ (ξ-·₁ β-μ)) ⟩ `suc ((ƛ "m" ⇒ ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ]) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ]) · `suc `zero · two) - ⟶⟨ ξ-suc (ξ-·₁ (β-ƛ· (V-suc V-zero))) ⟩ + ↦⟨ ξ-suc (ξ-·₁ (β-ƛ (V-suc V-zero))) ⟩ `suc ((ƛ "n" ⇒ - `case `suc `zero [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ]) + `case `suc `zero [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ]) · two) - ⟶⟨ ξ-suc (β-ƛ· (V-suc (V-suc V-zero))) ⟩ - `suc (`case `suc `zero [zero⇒ two |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · two) ]) - ⟶⟨ ξ-suc (β-case-suc V-zero) ⟩ + ↦⟨ ξ-suc (β-ƛ (V-suc (V-suc V-zero))) ⟩ + `suc (`case `suc `zero [zero⇒ two |suc "m" ⇒ `suc (plus · ` "m" · two) ]) + ↦⟨ ξ-suc (β-suc V-zero) ⟩ `suc `suc (plus · `zero · two) - ⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ β-μ))) ⟩ + ↦⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ β-μ))) ⟩ `suc `suc ((ƛ "m" ⇒ ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ]) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ]) · `zero · two) - ⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (β-ƛ· V-zero))) ⟩ + ↦⟨ ξ-suc (ξ-suc (ξ-·₁ (β-ƛ V-zero))) ⟩ `suc `suc ((ƛ "n" ⇒ - `case `zero [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ]) + `case `zero [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ]) · two) - ⟶⟨ ξ-suc (ξ-suc (β-ƛ· (V-suc (V-suc V-zero)))) ⟩ - `suc `suc (`case `zero [zero⇒ two |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · two) ]) - ⟶⟨ ξ-suc (ξ-suc β-case-zero) ⟩ + ↦⟨ ξ-suc (ξ-suc (β-ƛ (V-suc (V-suc V-zero)))) ⟩ + `suc `suc (`case `zero [zero⇒ two |suc "m" ⇒ `suc (plus · ` "m" · two) ]) + ↦⟨ ξ-suc (ξ-suc β-zero) ⟩ `suc (`suc (`suc (`suc `zero))) ∎ \end{code} And here is a similar sample reduction for Church numerals. \begin{code} -_ : fourᶜ ⟶* `suc `suc `suc `suc `zero +_ : fourᶜ ↠ `suc `suc `suc `suc `zero _ = begin - (ƛ "m" ⇒ ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "m" ⌋ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋)) + (ƛ "m" ⇒ ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒ ` "m" · ` "s" · (` "n" · ` "s" · ` "z")) · twoᶜ · twoᶜ · sucᶜ · `zero - ⟶⟨ ξ-·₁ (ξ-·₁ (ξ-·₁ (β-ƛ· V-ƛ))) ⟩ - (ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒ twoᶜ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋)) + ↦⟨ ξ-·₁ (ξ-·₁ (ξ-·₁ (β-ƛ V-ƛ))) ⟩ + (ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒ twoᶜ · ` "s" · (` "n" · ` "s" · ` "z")) · twoᶜ · sucᶜ · `zero - ⟶⟨ ξ-·₁ (ξ-·₁ (β-ƛ· V-ƛ)) ⟩ - (ƛ "s" ⇒ ƛ "z" ⇒ twoᶜ · ⌊ "s" ⌋ · (twoᶜ · ⌊ "s" ⌋ · ⌊ "z" ⌋)) · sucᶜ · `zero - ⟶⟨ ξ-·₁ (β-ƛ· V-ƛ) ⟩ - (ƛ "z" ⇒ twoᶜ · sucᶜ · (twoᶜ · sucᶜ · ⌊ "z" ⌋)) · `zero - ⟶⟨ β-ƛ· V-zero ⟩ + ↦⟨ ξ-·₁ (ξ-·₁ (β-ƛ V-ƛ)) ⟩ + (ƛ "s" ⇒ ƛ "z" ⇒ twoᶜ · ` "s" · (twoᶜ · ` "s" · ` "z")) · sucᶜ · `zero + ↦⟨ ξ-·₁ (β-ƛ V-ƛ) ⟩ + (ƛ "z" ⇒ twoᶜ · sucᶜ · (twoᶜ · sucᶜ · ` "z")) · `zero + ↦⟨ β-ƛ V-zero ⟩ twoᶜ · sucᶜ · (twoᶜ · sucᶜ · `zero) - ⟶⟨ ξ-·₁ (β-ƛ· V-ƛ) ⟩ - (ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · (twoᶜ · sucᶜ · `zero) - ⟶⟨ ξ-·₂ V-ƛ (ξ-·₁ (β-ƛ· V-ƛ)) ⟩ - (ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · ((ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · `zero) - ⟶⟨ ξ-·₂ V-ƛ (β-ƛ· V-zero) ⟩ - (ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · (sucᶜ · (sucᶜ · `zero)) - ⟶⟨ ξ-·₂ V-ƛ (ξ-·₂ V-ƛ (β-ƛ· V-zero)) ⟩ - (ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · (sucᶜ · (`suc `zero)) - ⟶⟨ ξ-·₂ V-ƛ (β-ƛ· (V-suc V-zero)) ⟩ - (ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · (`suc `suc `zero) - ⟶⟨ β-ƛ· (V-suc (V-suc V-zero)) ⟩ + ↦⟨ ξ-·₁ (β-ƛ V-ƛ) ⟩ + (ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · (twoᶜ · sucᶜ · `zero) + ↦⟨ ξ-·₂ V-ƛ (ξ-·₁ (β-ƛ V-ƛ)) ⟩ + (ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · ((ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · `zero) + ↦⟨ ξ-·₂ V-ƛ (β-ƛ V-zero) ⟩ + (ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · (sucᶜ · (sucᶜ · `zero)) + ↦⟨ ξ-·₂ V-ƛ (ξ-·₂ V-ƛ (β-ƛ V-zero)) ⟩ + (ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · (sucᶜ · (`suc `zero)) + ↦⟨ ξ-·₂ V-ƛ (β-ƛ (V-suc V-zero)) ⟩ + (ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · (`suc `suc `zero) + ↦⟨ β-ƛ (V-suc (V-suc V-zero)) ⟩ sucᶜ · (sucᶜ · `suc `suc `zero) - ⟶⟨ ξ-·₂ V-ƛ (β-ƛ· (V-suc (V-suc V-zero))) ⟩ + ↦⟨ ξ-·₂ V-ƛ (β-ƛ (V-suc (V-suc V-zero))) ⟩ sucᶜ · (`suc `suc `suc `zero) - ⟶⟨ β-ƛ· (V-suc (V-suc (V-suc V-zero))) ⟩ + ↦⟨ β-ƛ (V-suc (V-suc (V-suc V-zero))) ⟩ `suc (`suc (`suc (`suc `zero))) ∎ \end{code} @@ -803,7 +798,7 @@ Thus, * What is the type of the following term? - ƛ "s" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · `zero) + ƛ "s" ⇒ ` "s" · (` "s" · `zero) 1. `` (`ℕ ⇒ `ℕ) ⇒ (`ℕ ⇒ `ℕ) `` 2. `` (`ℕ ⇒ `ℕ) ⇒ `ℕ `` @@ -816,7 +811,7 @@ Thus, * What is the type of the following term? - (ƛ "s" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · `zero)) · sucᵐ + (ƛ "s" ⇒ ` "s" · (` "s" · `zero)) · sucᵐ 1. `` (`ℕ ⇒ `ℕ) ⇒ (`ℕ ⇒ `ℕ) `` 2. `` (`ℕ ⇒ `ℕ) ⇒ `ℕ `` @@ -910,9 +905,9 @@ and indicates in context `Γ` that term `M` has type `A`. Context `Γ` provides types for all the free variables in `M`. For example -* `` ∅ , "s" ⦂ `ℕ ⇒ `ℕ , "z" ⦂ `ℕ ⊢ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ⦂ `ℕ `` -* `` ∅ , "s" ⦂ `ℕ ⇒ `ℕ ⊢ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) ⦂ `ℕ ⇒ `ℕ `` -* `` ∅ ⊢ ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) ⦂ (`ℕ ⇒ `ℕ) ⇒ `ℕ ⇒ `ℕ `` +* `` ∅ , "s" ⦂ `ℕ ⇒ `ℕ , "z" ⦂ `ℕ ⊢ ` "s" · (` "s" · ` "z") ⦂ `ℕ `` +* `` ∅ , "s" ⦂ `ℕ ⇒ `ℕ ⊢ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z")) ⦂ `ℕ ⇒ `ℕ `` +* `` ∅ ⊢ ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z")) ⦂ (`ℕ ⇒ `ℕ) ⇒ `ℕ ⇒ `ℕ `` Typing is formalised as follows. \begin{code} @@ -923,7 +918,7 @@ data _⊢_⦂_ : Context → Term → Type → Set where Ax : ∀ {Γ x A} → Γ ∋ x ⦂ A ------------- - → Γ ⊢ ⌊ x ⌋ ⦂ A + → Γ ⊢ ` x ⦂ A -- ⇒-I ⊢ƛ : ∀ {Γ x N A B} @@ -998,7 +993,7 @@ Here `_≟_` is the function that tests two identifiers for equality. We intend to apply the function only when the two arguments are indeed unequal, and indicate that the second case should never arise by postulating a term `impossible` of -with the empty type `⊥`. If we use ^C ^N to normalise the term +with the empty type `⊥`. If we use `C `N to normalise the term "a" ≠ "a" @@ -1016,17 +1011,17 @@ evidence of _any_ proposition whatsoever, regardless of its truth. Type derivations correspond to trees. In informal notation, here is a type derivation for the Church numberal two: - ∋s ∋s ∋z - ------------------- ⌊_⌋ ------------------- ⌊_⌋ --------------- ⌊_⌋ - Γ₂ ⊢ ⌊ "s" ⌋ ⦂ A ⇒ A Γ₂ ⊢ ⌊ "s" ⌋ ⦂ A ⇒ A Γ₂ ⊢ ⌊ "z" ⌋ ⦂ A - ------------------- ⌊_⌋ ------------------------------------------ _·_ - Γ₂ ⊢ ⌊ "s" ⌋ ⦂ A ⇒ A Γ₂ ⊢ ⌊ "s" ⌋ · ⌊ "z" ⌋ ⦂ A + ∋s ∋s ∋z + ------------------- `_ ------------------- `_ --------------- `_ + Γ₂ ⊢ ` "s" ⦂ A ⇒ A Γ₂ ⊢ ` "s" ⦂ A ⇒ A Γ₂ ⊢ ` "z" ⦂ A + ------------------- `_ ------------------------------------------ _·_ + Γ₂ ⊢ ` "s" ⦂ A ⇒ A Γ₂ ⊢ ` "s" · ` "z" ⦂ A -------------------------------------------------- _·_ - Γ₂ ⊢ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ⦂ A + Γ₂ ⊢ ` "s" · (` "s" · ` "z") ⦂ A ---------------------------------------------- ⊢ƛ - Γ₁ ⊢ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ⦂ A ⇒ A + Γ₁ ⊢ ƛ "z" ⇒ ` "s" · (` "s" · ` "z") ⦂ A ⇒ A ---------------------------------------------------------- ⊢ƛ - ∅ ⊢ ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ⦂ A ⇒ A + ∅ ⊢ ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z") ⦂ A ⇒ A where `∋s` and `∋z` abbreviate the two derivations: @@ -1113,12 +1108,12 @@ the outermost term in `sucᶜ` in `⊢ƛ`, which is typed using `ƛ`. The `ƛ` rule in turn takes one argument, which Agda leaves as a hole. ⊢sucᶜ = ⊢ƛ { }1 - ?1 : ∅ , "n" ⦂ `ℕ ⊢ `suc ⌊ "n" ⌋ ⦂ `ℕ + ?1 : ∅ , "n" ⦂ `ℕ ⊢ `suc ` "n" ⦂ `ℕ We can fill in the hole by type C-c C-r again. ⊢sucᶜ = ⊢ƛ (⊢suc { }2) - ?2 : ∅ , "n" ⦂ `ℕ ⊢ ⌊ "n" ⌋ ⦂ `ℕ + ?2 : ∅ , "n" ⦂ `ℕ ⊢ ` "n" ⦂ `ℕ And again. @@ -1157,10 +1152,10 @@ the term `ƛ "x" ⇒ "x"` has type `A ⇒ A` for any type `A`. ### Non-examples We can also show that terms are _not_ typeable. For example, here is -a formal proof that it is not possible to type the term `` `zero · -`suc `zero ``. In other words, no type `A` is the type of this term. It -cannot be typed, because doing so requires that the first term in the -application is both a natural and a function. +a formal proof that it is not possible to type the term +`` `zero · `suc `zero ``. It cannot be typed, because doing so +requires that the first term in the application is both a natural and +a function. \begin{code} nope₁ : ∀ {A} → ¬ (∅ ⊢ `zero · `suc `zero ⦂ A) @@ -1168,11 +1163,11 @@ nope₁ (() · _) \end{code} As a second example, here is a formal proof that it is not possible to -type `` ƛ "x" ⇒ ⌊ "x" ⌋ · ⌊ "x" ⌋ `` It cannot be typed, because +type `` ƛ "x" ⇒ ` "x" · ` "x" `` It cannot be typed, because doing so requires types `A` and `B` such that `A ⇒ B ≡ A`. \begin{code} -nope₂ : ∀ {A} → ¬ (∅ ⊢ ƛ "x" ⇒ ⌊ "x" ⌋ · ⌊ "x" ⌋ ⦂ A) +nope₂ : ∀ {A} → ¬ (∅ ⊢ ƛ "x" ⇒ ` "x" · ` "x" ⦂ A) nope₂ (⊢ƛ (Ax ∋x · Ax ∋x′)) = contradiction (∋-injective ∋x ∋x′) where contradiction : ∀ {A B} → ¬ (A ⇒ B ≡ A) @@ -1185,15 +1180,15 @@ nope₂ (⊢ƛ (Ax ∋x · Ax ∋x′)) = contradiction (∋-injective ∋x For each of the following, given a type `A` for which it is derivable, or explain why there is no such `A`. -1. `` ∅ , "y" ⦂ `ℕ ⇒ `ℕ , "x" ⦂ `ℕ ⊢ ⌊ "y" ⌋ · ⌊ "x" ⌋ ⦂ A `` -2. `` ∅ , "y" ⦂ `ℕ ⇒ `ℕ , "x" ⦂ `ℕ ⊢ ⌊ "x" ⌋ · ⌊ "y" ⌋ ⦂ A `` -3. `` ∅ , "y" ⦂ `ℕ ⇒ `ℕ ⊢ ƛ "x" ⇒ ⌊ "y" ⌋ · ⌊ "x" ⌋ ⦂ A `` +1. `` ∅ , "y" ⦂ `ℕ ⇒ `ℕ , "x" ⦂ `ℕ ⊢ ` "y" · ` "x" ⦂ A `` +2. `` ∅ , "y" ⦂ `ℕ ⇒ `ℕ , "x" ⦂ `ℕ ⊢ ` "x" · ` "y" ⦂ A `` +3. `` ∅ , "y" ⦂ `ℕ ⇒ `ℕ ⊢ ƛ "x" ⇒ ` "y" · ` "x" ⦂ A `` For each of the following, give type `A`, `B`, and `C` for which it is derivable, or explain why there are no such types. -1. `` ∅ , "x" ⦂ A ⊢ ⌊ "x" ⌋ · ⌊ "x" ⌋ ⦂ B `` -2. `` ∅ , "x" ⦂ A , "y" ⦂ B ⊢ ƛ "z" ⇒ ⌊ "x" ⌋ · (⌊ "y" ⌋ · ⌊ "z" ⌋) ⦂ C `` +1. `` ∅ , "x" ⦂ A ⊢ ` "x" · ` "x" ⦂ B `` +2. `` ∅ , "x" ⦂ A , "y" ⦂ B ⊢ ƛ "z" ⇒ ` "x" · (` "y" · ` "z") ⦂ C `` #### Exercise (`mul-type`) @@ -1211,7 +1206,8 @@ This chapter uses the following unicode · U+00B7: MIDDLE DOT (\cdot) 😇 U+1F607: SMILING FACE WITH HALO 😈 U+1F608: SMILING FACE WITH HORNS - ⟶ U+27F9: LONG RIGHTWARDS ARROW (\r5, \-->) + ↦ U+21A6: RIGHTWARDS ARROW FROM BAR (\mapsto, \r-|) + ↠ U+21A0: RIGHTWARDS TWO HEADED ARROW (\rr-) ξ U+03BE: GREEK SMALL LETTER XI (\Gx or \xi) β U+03B2: GREEK SMALL LETTER BETA (\Gb or \beta) ∋ U+220B: CONTAINS AS MEMBER (\ni) diff --git a/src/plta/PandP.lagda b/src/plta/PandP.lagda index e66bae7b..bf147146 100644 --- a/src/plta/PandP.lagda +++ b/src/plta/PandP.lagda @@ -15,7 +15,7 @@ Those parts will be revised.] The last chapter formalised simply-typed lambda calculus and introduced several important relations over it. We write `Value M` if term `M` is a value. -We write `M ⟶ N` if term `M` reduces to term `N`. +We write `M ↦ N` if term `M` reduces to term `N`. And we write `Γ ⊢ M ⦂ A` if in context `Γ` the term `M` has type `A`. We are particularly concerned with terms typed in the empty context `∅`, which must be _closed_ (that is, have no _free variables_). @@ -40,7 +40,7 @@ a reduction step. As we will see, this property does _not_ hold for every term, but it does hold for every closed, well-typed term. _Progress_: If `∅ ⊢ M ⦂ A` then either `M` is a value or there is an `N` such -that `M ⟶ N`. +that `M ↦ N`. So, either we have a value, and we are done, or we can take a reduction step. In the latter case, we would like to apply progress again. But first we need @@ -48,7 +48,7 @@ to know that the term yielded by the reduction is itself closed and well-typed. It turns out that this property holds whenever we start with a closed, well-typed term. -_Preservation_: If `∅ ⊢ M ⦂ A` and `M ⟶ N` then `∅ ⊢ N ⦂ A`. +_Preservation_: If `∅ ⊢ M ⦂ A` and `M ↦ N` then `∅ ⊢ N ⦂ A`. This gives us a recipe for evaluation. Start with a closed and well-typed term. By progress, it is either a value, in which case we are done, or it reduces @@ -87,7 +87,6 @@ open import Relation.Nullary using (¬_; Dec; yes; no) open import Function using (_∘_) open import plta.Isomorphism open import plta.Lambda -open Chain (Term) (_⟶_) \end{code} @@ -192,7 +191,7 @@ second has a free variable. Every term that is well-typed and closed has the desired property. _Progress_: If `∅ ⊢ M ⦂ A` then either `M` is a value or there is an `N` such -that `M ⟶ N`. +that `M ↦ N`. To formulate this property, we first introduce a relation that captures what it means for a term `M` to make progess. @@ -200,7 +199,7 @@ captures what it means for a term `M` to make progess. data Progress (M : Term) : Set where step : ∀ {N} - → M ⟶ N + → M ↦ N ---------- → Progress M @@ -210,7 +209,7 @@ data Progress (M : Term) : Set where → Progress M \end{code} A term `M` makes progress if either it can take a step, meaning there -exists a term `N` such that `M ⟶ N`, or if it is done, meaning that +exists a term `N` such that `M ↦ N`, or if it is done, meaning that `M` is a value. If a term is well-typed in the empty context then it is a value. @@ -220,23 +219,23 @@ progress : ∀ {M A} ---------- → Progress M progress (Ax ()) -progress (⊢ƛ ⊢N) = done V-ƛ +progress (⊢ƛ ⊢N) = done V-ƛ progress (⊢L · ⊢M) with progress ⊢L -... | step L⟶L′ = step (ξ-·₁ L⟶L′) +... | step L↦L′ = step (ξ-·₁ L↦L′) ... | done VL with progress ⊢M -... | step M⟶M′ = step (ξ-·₂ VL M⟶M′) +... | step M↦M′ = step (ξ-·₂ VL M↦M′) ... | done VM with canonical ⊢L VL -... | C-ƛ _ = step (β-ƛ· VM) -progress ⊢zero = done V-zero +... | C-ƛ _ = step (β-ƛ VM) +progress ⊢zero = done V-zero progress (⊢suc ⊢M) with progress ⊢M -... | step M⟶M′ = step (ξ-suc M⟶M′) -... | done VM = done (V-suc VM) +... | step M↦M′ = step (ξ-suc M↦M′) +... | done VM = done (V-suc VM) progress (⊢case ⊢L ⊢M ⊢N) with progress ⊢L -... | step L⟶L′ = step (ξ-case L⟶L′) +... | step L↦L′ = step (ξ-case L↦L′) ... | done VL with canonical ⊢L VL -... | C-zero = step β-case-zero -... | C-suc CL = step (β-case-suc (value CL)) -progress (⊢μ ⊢M) = step β-μ +... | C-zero = step β-zero +... | C-suc CL = step (β-suc (value CL)) +progress (⊢μ ⊢M) = step β-μ \end{code} We induct on the evidence that `M` is well-typed. Let's unpack the first three cases. @@ -249,7 +248,7 @@ Let's unpack the first three cases. * If the term is an application `L · M`, recursively apply progress to the derivation that `L` is well-typed. - + If the term steps, we have evidence that `L ⟶ L′`, + + If the term steps, we have evidence that `L ↦ L′`, which by `ξ-·₁` means that our original term steps to `L′ · M` @@ -257,7 +256,7 @@ Let's unpack the first three cases. a value. Recursively apply progress to the derivation that `M` is well-typed. - - If the term steps, we have evidence that `M ⟶ M′`, + - If the term steps, we have evidence that `M ↦ M′`, which by `ξ-·₂` means that our original term steps to `L · M′`. Step `ξ-·₂` applies only if we have evidence that `L` is a value, but progress on that @@ -269,7 +268,7 @@ Let's unpack the first three cases. since we are in an application leads to the conclusion that `L` must be a lambda abstraction. We also have evidence that `M` is - a value, so our original term steps by `β-ƛ·`. + a value, so our original term steps by `β-ƛ`. The remaining cases are similar. If by induction we have a `step` case we apply a `ξ` rule, and if we have a `done` case @@ -289,11 +288,11 @@ Instead of defining a data type for `Progress M`, we could have formulated progress using disjunction and existentials: \begin{code} postulate - progress′ : ∀ M {A} → ∅ ⊢ M ⦂ A → Value M ⊎ ∃[ N ](M ⟶ N) + progress′ : ∀ M {A} → ∅ ⊢ M ⦂ A → Value M ⊎ ∃[ N ](M ↦ N) \end{code} This leads to a less perspicous proof. Instead of the mnemonic `done` and `step` we use `inj₁` and `inj₂`, and the term `N` is no longer -implicit and so must be written out in full. In the case for `β-ƛ·` +implicit and so must be written out in full. In the case for `β-ƛ` this requires that we match against the lambda expression `L` to determine its bound variable and body, `ƛ x ⇒ N`, so we can show that `L · M` reduces to `N [ x := M ]`. @@ -305,7 +304,7 @@ proof of `progress` above. #### Exercise (`Progress-iso`) -Show that `Progress M` is isomorphic to `Value M ⊎ ∃[ N ](M ⟶ N)`. +Show that `Progress M` is isomorphic to `Value M ⊎ ∃[ N ](M ↦ N)`. ## Prelude to preservation @@ -370,7 +369,7 @@ the same result as if we first substitute and then type the result. The third step is to show preservation. _Preservation_: -If `∅ ⊢ M ⦂ A` and `M ⟶ N` then `∅ ⊢ N ⦂ A`. +If `∅ ⊢ M ⦂ A` and `M ↦ N` then `∅ ⊢ N ⦂ A`. The proof is by induction over the possible reductions, and the substitution lemma is crucial in showing that each of the @@ -404,7 +403,6 @@ ext : ∀ {Γ Δ} → (∀ {x A} → Γ ∋ x ⦂ A → Δ ∋ x ⦂ A) ----------------------------------------------------- → (∀ {x y A B} → Γ , y ⦂ B ∋ x ⦂ A → Δ , y ⦂ B ∋ x ⦂ A) - ext ρ Z = Z ext ρ (S x≢y ∋x) = S x≢y (ρ ∋x) \end{code} @@ -595,9 +593,9 @@ Now that naming is resolved, let's unpack the first three cases. * In the variable case, we must show ∅ ⊢ V ⦂ B - Γ , y ⦂ B ⊢ ⌊ x ⌋ ⦂ A + Γ , y ⦂ B ⊢ ` x ⦂ A ------------------------ - Γ ⊢ ⌊ x ⌋ [ y := V ] ⦂ A + Γ ⊢ ` x [ y := V ] ⦂ A where the second hypothesis follows from: @@ -645,7 +643,7 @@ Now that naming is resolved, let's unpack the first three cases. x ≢ y Γ ∋ x ⦂ A ------------- - Γ ⊢ ⌊ x ⌋ ⦂ A + Γ ⊢ ` x ⦂ A which follows by the typing rule for variables. @@ -735,20 +733,20 @@ that reduction preserves types is straightforward. \begin{code} preserve : ∀ {M N A} → ∅ ⊢ M ⦂ A - → M ⟶ N + → M ↦ N ---------- → ∅ ⊢ N ⦂ A preserve (Ax ()) preserve (⊢ƛ ⊢N) () -preserve (⊢L · ⊢M) (ξ-·₁ L⟶L′) = (preserve ⊢L L⟶L′) · ⊢M -preserve (⊢L · ⊢M) (ξ-·₂ VL M⟶M′) = ⊢L · (preserve ⊢M M⟶M′) -preserve ((⊢ƛ ⊢N) · ⊢V) (β-ƛ· VV) = subst ⊢V ⊢N +preserve (⊢L · ⊢M) (ξ-·₁ L↦L′) = (preserve ⊢L L↦L′) · ⊢M +preserve (⊢L · ⊢M) (ξ-·₂ VL M↦M′) = ⊢L · (preserve ⊢M M↦M′) +preserve ((⊢ƛ ⊢N) · ⊢V) (β-ƛ VV) = subst ⊢V ⊢N preserve ⊢zero () -preserve (⊢suc ⊢M) (ξ-suc M⟶M′) = ⊢suc (preserve ⊢M M⟶M′) -preserve (⊢case ⊢L ⊢M ⊢N) (ξ-case L⟶L′) = ⊢case (preserve ⊢L L⟶L′) ⊢M ⊢N -preserve (⊢case ⊢zero ⊢M ⊢N) β-case-zero = ⊢M -preserve (⊢case (⊢suc ⊢V) ⊢M ⊢N) (β-case-suc VV) = subst ⊢V ⊢N -preserve (⊢μ ⊢M) (β-μ) = subst (⊢μ ⊢M) ⊢M +preserve (⊢suc ⊢M) (ξ-suc M↦M′) = ⊢suc (preserve ⊢M M↦M′) +preserve (⊢case ⊢L ⊢M ⊢N) (ξ-case L↦L′) = ⊢case (preserve ⊢L L↦L′) ⊢M ⊢N +preserve (⊢case ⊢zero ⊢M ⊢N) β-zero = ⊢M +preserve (⊢case (⊢suc ⊢V) ⊢M ⊢N) (β-suc VV) = subst ⊢V ⊢N +preserve (⊢μ ⊢M) (β-μ) = subst (⊢μ ⊢M) ⊢M \end{code} The proof never mentions the types of `M` or `N`, so in what follows we choose type name as convenient. @@ -757,9 +755,9 @@ Let's unpack the cases for two of the reduction rules. * Rule `ξ-·₁`. We have - L ⟶ L′ + L ↦ L′ ---------------- - L · M ⟶ L′ · M + L · M ↦ L′ · M where the left-hand side is typed by @@ -771,13 +769,13 @@ Let's unpack the cases for two of the reduction rules. By induction, we have Γ ⊢ L ⦂ A ⇒ B - L ⟶ L′ + L ↦ L′ -------------- Γ ⊢ L′ ⦂ A ⇒ B from which the typing of the right-hand side follows immediately. -* Rule `β-ƛ·`. We have +* Rule `β-ƛ`. We have Value V ---------------------------- @@ -813,15 +811,17 @@ well-typed term to its value, if it has one. Some terms may reduce forever. Here is a simple example. \begin{code} +sucμ = μ "x" ⇒ `suc (` "x") + _ = begin - μ "x" ⇒ `suc ⌊ "x" ⌋ - ⟶⟨ β-μ ⟩ - `suc (μ "x" ⇒ `suc ⌊ "x" ⌋) - ⟶⟨ ξ-suc β-μ ⟩ - `suc `suc (μ "x" ⇒ `suc ⌊ "x" ⌋) - ⟶⟨ ξ-suc (ξ-suc β-μ) ⟩ - `suc `suc `suc (μ "x" ⇒ `suc ⌊ "x" ⌋) + sucμ + ↦⟨ β-μ ⟩ + `suc sucμ + ↦⟨ ξ-suc β-μ ⟩ + `suc `suc sucμ + ↦⟨ ξ-suc (ξ-suc β-μ) ⟩ + `suc `suc `suc sucμ -- ... ∎ \end{code} @@ -871,7 +871,7 @@ well-typed and an indication of whether reduction finished. data Steps (L : Term) (A : Type) : Set where steps : ∀ {N} - → L ⟶* N + → L ↠ N → ∅ ⊢ N ⦂ A → Finished N ---------- @@ -886,18 +886,18 @@ eval : ∀ {L A} → ∅ ⊢ L ⦂ A --------- → Steps L A -eval {L} (gas zero) ⊢L = steps (L ∎) ⊢L out-of-gas +eval {L} (gas zero) ⊢L = steps (L ∎) ⊢L out-of-gas eval {L} (gas (suc m)) ⊢L with progress ⊢L -... | done VL = steps (L ∎) ⊢L (done VL) -... | step L⟶M with eval (gas m) (preserve ⊢L L⟶M) -... | steps M⟶*N ⊢N fin = steps (L ⟶⟨ L⟶M ⟩ M⟶*N) ⊢N fin +... | done VL = steps (L ∎) ⊢L (done VL) +... | step L↦M with eval (gas m) (preserve ⊢L L↦M) +... | steps M↠N ⊢N fin = steps (L ↦⟨ L↦M ⟩ M↠N) ⊢N fin \end{code} 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 remaining. There are two possibilities. * It is zero, so we stop early. We return the trivial reduction - sequence `L ⟶* L`, evidence that `L` is well-typed, and an + sequence `L ↠ L`, evidence that `L` is well-typed, and an indication that we are out of gas. * It is non-zero and after the next step we have `m` gas remaining. @@ -905,165 +905,187 @@ remaining. There are two possibilities. are two possibilities. + Term `L` is a value, so we are done. We return the - trivial reduction sequence `L ⟶* L`, evidence that `L` is + trivial reduction sequence `L ↠ L`, evidence that `L` is well-typed, and the evidence that `L` is a value. + Term `L` steps to another term `M`. Preservation provides evidence that `M` is also well-typed, and we recursively invoke `eval` on the remaining gas. The result is evidence that - `M ⟶* N`, together with evidence that `N` is well-typed and an + `M ↠ N`, together with evidence that `N` is well-typed and an indication of whether reduction finished. We combine the evidence - that `L ⟶ M` and `M ⟶* N` to return evidence that `L ⟶* N`, + that `L ↦ M` and `M ↠ N` to return evidence that `L ↠ N`, together with the other relevant evidence. ### Examples -We can now use Agda to compute the reduction sequence for two plus two -given in the preceding chapter. +We can now use Agda to compute the non-terminating reduction +sequence given earlier. First, we show that the term `sucμ` +is well-typed. +\begin{code} +⊢sucμ : ∅ ⊢ μ "x" ⇒ `suc ` "x" ⦂ `ℕ +⊢sucμ = ⊢μ (⊢suc (Ax ∋x)) + where + ∋x = Z +\end{code} +To show the first three steps of the infinite reduction +sequence, we evaluate with three steps worth of gas. +\begin{code} +_ : eval (gas 3) ⊢sucμ ≡ + steps + (μ "x" ⇒ `suc ` "x" ↦⟨ β-μ ⟩ + `suc (μ "x" ⇒ `suc ` "x") ↦⟨ ξ-suc β-μ ⟩ + `suc (`suc (μ "x" ⇒ `suc ` "x")) ↦⟨ ξ-suc (ξ-suc β-μ) ⟩ + `suc (`suc (`suc (μ "x" ⇒ `suc ` "x"))) ∎) + (⊢suc (⊢suc (⊢suc (⊢μ (⊢suc (Ax Z)))))) out-of-gas +_ = refl +\end{code} + +Similarly, we can use Agda to compute the reduction sequence for two plus two +given in the preceding chapter. Supplying 100 steps of gas is more than enough. \begin{code} _ : eval (gas 100) ⊢four ≡ steps ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) · `suc (`suc `zero) · `suc (`suc `zero) - ⟶⟨ ξ-·₁ (ξ-·₁ β-μ) ⟩ + ↦⟨ ξ-·₁ (ξ-·₁ β-μ) ⟩ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) - · ⌊ "m" ⌋ - · ⌊ "n" ⌋) + · ` "m" + · ` "n") ])) · `suc (`suc `zero) · `suc (`suc `zero) - ⟶⟨ ξ-·₁ (β-ƛ· (V-suc (V-suc V-zero))) ⟩ + ↦⟨ ξ-·₁ (β-ƛ (V-suc (V-suc V-zero))) ⟩ (ƛ "n" ⇒ - `case `suc (`suc `zero) [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ + `case `suc (`suc `zero) [zero⇒ ` "n" |suc "m" ⇒ `suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) - · ⌊ "m" ⌋ - · ⌊ "n" ⌋) + · ` "m" + · ` "n") ]) · `suc (`suc `zero) - ⟶⟨ β-ƛ· (V-suc (V-suc V-zero)) ⟩ + ↦⟨ β-ƛ (V-suc (V-suc V-zero)) ⟩ `case `suc (`suc `zero) [zero⇒ `suc (`suc `zero) |suc "m" ⇒ `suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) - · ⌊ "m" ⌋ + · ` "m" · `suc (`suc `zero)) ] - ⟶⟨ β-case-suc (V-suc V-zero) ⟩ + ↦⟨ β-suc (V-suc V-zero) ⟩ `suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) · `suc `zero · `suc (`suc `zero)) - ⟶⟨ ξ-suc (ξ-·₁ (ξ-·₁ β-μ)) ⟩ + ↦⟨ ξ-suc (ξ-·₁ (ξ-·₁ β-μ)) ⟩ `suc ((ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) - · ⌊ "m" ⌋ - · ⌊ "n" ⌋) + · ` "m" + · ` "n") ])) · `suc `zero · `suc (`suc `zero)) - ⟶⟨ ξ-suc (ξ-·₁ (β-ƛ· (V-suc V-zero))) ⟩ + ↦⟨ ξ-suc (ξ-·₁ (β-ƛ (V-suc V-zero))) ⟩ `suc ((ƛ "n" ⇒ - `case `suc `zero [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ + `case `suc `zero [zero⇒ ` "n" |suc "m" ⇒ `suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) - · ⌊ "m" ⌋ - · ⌊ "n" ⌋) + · ` "m" + · ` "n") ]) · `suc (`suc `zero)) - ⟶⟨ ξ-suc (β-ƛ· (V-suc (V-suc V-zero))) ⟩ + ↦⟨ ξ-suc (β-ƛ (V-suc (V-suc V-zero))) ⟩ `suc `case `suc `zero [zero⇒ `suc (`suc `zero) |suc "m" ⇒ `suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) - · ⌊ "m" ⌋ + · ` "m" · `suc (`suc `zero)) ] - ⟶⟨ ξ-suc (β-case-suc V-zero) ⟩ + ↦⟨ ξ-suc (β-suc V-zero) ⟩ `suc (`suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) · `zero · `suc (`suc `zero))) - ⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ β-μ))) ⟩ + ↦⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ β-μ))) ⟩ `suc (`suc ((ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) - · ⌊ "m" ⌋ - · ⌊ "n" ⌋) + · ` "m" + · ` "n") ])) · `zero · `suc (`suc `zero))) - ⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (β-ƛ· V-zero))) ⟩ + ↦⟨ ξ-suc (ξ-suc (ξ-·₁ (β-ƛ V-zero))) ⟩ `suc (`suc ((ƛ "n" ⇒ - `case `zero [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ + `case `zero [zero⇒ ` "n" |suc "m" ⇒ `suc ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) - · ⌊ "m" ⌋ - · ⌊ "n" ⌋) + · ` "m" + · ` "n") ]) · `suc (`suc `zero))) - ⟶⟨ ξ-suc (ξ-suc (β-ƛ· (V-suc (V-suc V-zero)))) ⟩ + ↦⟨ ξ-suc (ξ-suc (β-ƛ (V-suc (V-suc V-zero)))) ⟩ `suc (`suc `case `zero [zero⇒ `suc (`suc `zero) |suc "m" ⇒ @@ -1071,21 +1093,21 @@ _ : eval (gas 100) ⊢four ≡ ((μ "+" ⇒ (ƛ "m" ⇒ (ƛ "n" ⇒ - `case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) + `case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]))) - · ⌊ "m" ⌋ + · ` "m" · `suc (`suc `zero)) ]) - ⟶⟨ ξ-suc (ξ-suc β-case-zero) ⟩ `suc (`suc (`suc (`suc `zero))) ∎) + ↦⟨ ξ-suc (ξ-suc β-zero) ⟩ `suc (`suc (`suc (`suc `zero))) ∎) (⊢suc (⊢suc (⊢suc (⊢suc ⊢zero)))) (done (V-suc (V-suc (V-suc (V-suc V-zero))))) _ = refl \end{code} -The example above was generated by using ^C ^N to normalise the +The example above was generated by using `C `N to normalise the left-hand side of the equation and pasting in the result as the -right-hand side of the equation. The result was then edited to give -the example reduction of the previous chapter, by writing `plus` -and `two` in place of the corresponding terms and reformatting. +right-hand side of the equation. The example reduction of the +previous chapter was derived from this result, by writing `plus` and +`two` in place of their corresponding expansions and reformatting. Similarly, can evaluate the corresponding term for Church numerals. \begin{code} @@ -1093,88 +1115,73 @@ _ : eval (gas 100) ⊢fourᶜ ≡ steps ((ƛ "m" ⇒ (ƛ "n" ⇒ - (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "m" ⌋ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋))))) - · (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) - · (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) - · (ƛ "n" ⇒ `suc ⌊ "n" ⌋) + (ƛ "s" ⇒ (ƛ "z" ⇒ ` "m" · ` "s" · (` "n" · ` "s" · ` "z"))))) + · (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) + · (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) + · (ƛ "n" ⇒ `suc ` "n") · `zero - ⟶⟨ ξ-·₁ (ξ-·₁ (ξ-·₁ (β-ƛ· V-ƛ))) ⟩ + ↦⟨ ξ-·₁ (ξ-·₁ (ξ-·₁ (β-ƛ V-ƛ))) ⟩ (ƛ "n" ⇒ (ƛ "s" ⇒ (ƛ "z" ⇒ - (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · ⌊ "s" ⌋ · - (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋)))) - · (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) - · (ƛ "n" ⇒ `suc ⌊ "n" ⌋) + (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · ` "s" · + (` "n" · ` "s" · ` "z")))) + · (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) + · (ƛ "n" ⇒ `suc ` "n") · `zero - ⟶⟨ ξ-·₁ (ξ-·₁ (β-ƛ· V-ƛ)) ⟩ + ↦⟨ ξ-·₁ (ξ-·₁ (β-ƛ V-ƛ)) ⟩ (ƛ "s" ⇒ (ƛ "z" ⇒ - (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · ⌊ "s" ⌋ · - ((ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · ⌊ "s" ⌋ · ⌊ "z" ⌋))) - · (ƛ "n" ⇒ `suc ⌊ "n" ⌋) + (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · ` "s" · + ((ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · ` "s" · ` "z"))) + · (ƛ "n" ⇒ `suc ` "n") · `zero - ⟶⟨ ξ-·₁ (β-ƛ· V-ƛ) ⟩ + ↦⟨ ξ-·₁ (β-ƛ V-ƛ) ⟩ (ƛ "z" ⇒ - (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋) + (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n") · - ((ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋) - · ⌊ "z" ⌋)) + ((ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n") + · ` "z")) · `zero - ⟶⟨ β-ƛ· V-zero ⟩ - (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋) + ↦⟨ β-ƛ V-zero ⟩ + (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n") · - ((ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋) + ((ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n") · `zero) - ⟶⟨ ξ-·₁ (β-ƛ· V-ƛ) ⟩ - (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) · - ((ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋) + ↦⟨ ξ-·₁ (β-ƛ V-ƛ) ⟩ + (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) · + ((ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n") · `zero) - ⟶⟨ ξ-·₂ V-ƛ (ξ-·₁ (β-ƛ· V-ƛ)) ⟩ - (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) · - ((ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) · + ↦⟨ ξ-·₂ V-ƛ (ξ-·₁ (β-ƛ V-ƛ)) ⟩ + (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) · + ((ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) · `zero) - ⟶⟨ ξ-·₂ V-ƛ (β-ƛ· V-zero) ⟩ - (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) · - ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · `zero)) - ⟶⟨ ξ-·₂ V-ƛ (ξ-·₂ V-ƛ (β-ƛ· V-zero)) ⟩ - (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) · - ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · `suc `zero) - ⟶⟨ ξ-·₂ V-ƛ (β-ƛ· (V-suc V-zero)) ⟩ - (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) · + ↦⟨ ξ-·₂ V-ƛ (β-ƛ V-zero) ⟩ + (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) · + ((ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · `zero)) + ↦⟨ ξ-·₂ V-ƛ (ξ-·₂ V-ƛ (β-ƛ V-zero)) ⟩ + (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) · + ((ƛ "n" ⇒ `suc ` "n") · `suc `zero) + ↦⟨ ξ-·₂ V-ƛ (β-ƛ (V-suc V-zero)) ⟩ + (ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) · `suc (`suc `zero) - ⟶⟨ β-ƛ· (V-suc (V-suc V-zero)) ⟩ - (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · `suc (`suc `zero)) - ⟶⟨ ξ-·₂ V-ƛ (β-ƛ· (V-suc (V-suc V-zero))) ⟩ - (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · `suc (`suc (`suc `zero)) ⟶⟨ - β-ƛ· (V-suc (V-suc (V-suc V-zero))) ⟩ + ↦⟨ β-ƛ (V-suc (V-suc V-zero)) ⟩ + (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · `suc (`suc `zero)) + ↦⟨ ξ-·₂ V-ƛ (β-ƛ (V-suc (V-suc V-zero))) ⟩ + (ƛ "n" ⇒ `suc ` "n") · `suc (`suc (`suc `zero)) ↦⟨ + β-ƛ (V-suc (V-suc (V-suc V-zero))) ⟩ `suc (`suc (`suc (`suc `zero))) ∎) (⊢suc (⊢suc (⊢suc (⊢suc ⊢zero)))) (done (V-suc (V-suc (V-suc (V-suc V-zero))))) _ = refl \end{code} - -We can also derive the non-terminating example. -\begin{code} -⊢sucμ : ∅ ⊢ μ "x" ⇒ `suc ⌊ "x" ⌋ ⦂ `ℕ -⊢sucμ = ⊢μ (⊢suc (Ax ∋x)) - where - ∋x = Z - -_ : eval (gas 3) ⊢sucμ ≡ - steps - (μ "x" ⇒ `suc ⌊ "x" ⌋ Chain.⟶⟨ β-μ ⟩ - `suc (μ "x" ⇒ `suc ⌊ "x" ⌋) Chain.⟶⟨ ξ-suc β-μ ⟩ - `suc (`suc (μ "x" ⇒ `suc ⌊ "x" ⌋)) Chain.⟶⟨ ξ-suc (ξ-suc β-μ) ⟩ - `suc (`suc (`suc (μ "x" ⇒ `suc ⌊ "x" ⌋))) Chain.∎) - (⊢suc (⊢suc (⊢suc (⊢μ (⊢suc (Ax Z)))))) out-of-gas -_ = refl -\end{code} +Again, the example in the previous section was derived by editing the +above. #### Exercise `subject_expansion` -We say that `M` _reduces_ to `N` if `M ⟶ N`, -and conversely that `M` _expands_ to `N` if `N ⟶ M`. +We say that `M` _reduces_ to `N` if `M ↦ N`, +and conversely that `M` _expands_ to `N` if `N ↦ M`. The preservation property is sometimes called _subject reduction_. Its opposite is _subject expansion_, which holds if `M ==> N` and `∅ ⊢ N ⦂ A` imply `∅ ⊢ M ⦂ A`. @@ -1186,7 +1193,7 @@ with case expressions and one not involving case expressions. A term is _normal_ if it cannot reduce. \begin{code} Normal : Term → Set -Normal M = ∀ {N} → ¬ (M ⟶ N) +Normal M = ∀ {N} → ¬ (M ↦ N) \end{code} A term is _stuck_ if it is normal yet not a value. @@ -1200,7 +1207,7 @@ Using progress and preservation, it is easy to show that well-typed terms don't postulate wttdgs : ∀ {M N A} → ∅ ⊢ M ⦂ A - → M ⟶* N + → M ↠ N ----------- → ¬ (Stuck M) \end{code} @@ -1223,8 +1230,8 @@ unstuck : ∀ {M A} → ∅ ⊢ M ⦂ A ----------- → ¬ (Stuck M) -unstuck ⊢M ⟨ ¬M⟶N , ¬VM ⟩ with progress ⊢M -... | step M⟶N = ¬M⟶N M⟶N +unstuck ⊢M ⟨ ¬M↦N , ¬VM ⟩ with progress ⊢M +... | step M↦N = ¬M↦N M↦N ... | done VM = ¬VM VM \end{code} @@ -1232,21 +1239,21 @@ Any descendant of a well-typed term is well-typed. \begin{code} preserve* : ∀ {M N A} → ∅ ⊢ M ⦂ A - → M ⟶* N + → M ↠ N --------- → ∅ ⊢ N ⦂ A preserve* ⊢M (M ∎) = ⊢M -preserve* ⊢L (L ⟶⟨ L⟶M ⟩ M⟶*N) = preserve* (preserve ⊢L L⟶M) M⟶*N +preserve* ⊢L (L ↦⟨ L↦M ⟩ M↠N) = preserve* (preserve ⊢L L↦M) M↠N \end{code} Combining the above gives us the desired result. \begin{code} wttdgs′ : ∀ {M N A} → ∅ ⊢ M ⦂ A - → M ⟶* N + → M ↠ N ----------- → ¬ (Stuck N) -wttdgs′ ⊢M M⟶*N = unstuck (preserve* ⊢M M⟶*N) +wttdgs′ ⊢M M↠N = unstuck (preserve* ⊢M M↠N) \end{code} @@ -1261,7 +1268,7 @@ and preservation theorems for the simply typed lambda-calculus. Suppose we add a new term `zap` with the following reduction rule --------- β-zap - M ⟶ zap + M ↦ zap and the following typing rule: @@ -1286,10 +1293,10 @@ Suppose instead that we add a new term `foo` with the following reduction rules: --------------------- β-foo₁ - (λ x ⇒ ⌊ x ⌋) ⟶ foo + (λ x ⇒ ` x) ↦ foo ------------ β-foo₂ - foo ⟶ zero + foo ↦ zero Which of the following properties remain true in the presence of this rule? For each one, write either @@ -1305,7 +1312,7 @@ false, give a counterexample. #### Quiz -Suppose instead that we remove the rule `ξ·₁` from the `⟶` +Suppose instead that we remove the rule `ξ·₁` from the step relation. Which of the following properties remain true in the absence of this rule? For each one, write either "remains true" or else "becomes false." If a property becomes