From 043280415040d044b7e9671a2393f005ad487552 Mon Sep 17 00:00:00 2001 From: Philip Wadler Date: Fri, 14 Jul 2017 18:43:01 +0100 Subject: [PATCH] added material on free and bound variables to Stlc --- out/Stlc.md | 4679 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 3078 insertions(+), 1601 deletions(-) diff --git a/out/Stlc.md b/out/Stlc.md index 209fa194..a3a71733 100644 --- a/out/Stlc.md +++ b/out/Stlc.md @@ -609,2944 +609,4421 @@ And here it is formalised in Agda. -CONTINUE FROM HERE +#### Special characters + +We use the following special characters + + ⇒ U+21D2: RIGHTWARDS DOUBLE ARROW (\=>) + ` U+0060: GRAVE ACCENT + λ U+03BB: GREEK SMALL LETTER LAMBDA (\Gl or \lambda) + ∶ U+2236: RATIO (\:) + · U+00B7: MIDDLE DOT (\cdot) + +Note that ∶ (U+2236 RATIO) is not the same as : (U+003A COLON). +Colon is reserved in Agda for declaring types. Everywhere that we +declare a type in the object language rather than Agda we use +ratio in place of colon. + +Using ratio for this purpose is arguably a bad idea, because one must use context +rather than appearance to distinguish it from colon. Arguably, it might be +better to use a different symbol, such as `∈` or `::`. We reserve `∈` +for use later to indicate that a variable appears free in a term, and +eschew `::` because we consider it too ugly. -Example terms. +#### Formal vs informal + +In informal presentation of formal semantics, one uses choice of +variable name to disambiguate and writes `x` rather than `` ` x `` +for a term that is a variable. Agda requires we distinguish. +Often researchers use `var x` rather than `` ` x ``, but we chose +the latter since it is closer to the informal notation `x`. + +Similarly, informal presentation often use the notations `A → B` for +functions, `λ x . N` for abstractions, and `L M` for applications. We +cannot use these, because they overlap with the notation used by Agda. +In `λ[ x ∶ A ] N`, recall that Agda treats square brackets `[]` as +ordinary symbols, while round parentheses `()` and curly braces `{}` +have special meaning. We would use `L @ M` for application, but +`@` has a reserved meaning in Agda. + + +#### Examples + +Here are a couple of example terms, `not` of type +`𝔹 ⇒ 𝔹`, which complements its argument, and `two` of type +`(𝔹 ⇒ 𝔹) ⇒ 𝔹 ⇒ 𝔹` which takes a function and a boolean +and applies the function to the boolean twice. +
 
-f x y : Id
 f  =  id 0
 x  =  id 1
+y  =  id 2
 
 not two : Term 
 not =  λ[ x  𝔹 ] (if ` x then false else true)
 two =  λ[ f  𝔹  𝔹 ] λ[ x  𝔹 ] ` f · (` f · ` x)
 
 
+ +#### Bound and free variables + +In an abstraction `λ[ x ∶ A ] N` we call `x` the _bound_ variable +and `N` the _body_ of the abstraction. One of the most important +aspects of lambda calculus is that names of bound variables are +irrelevant. Thus the two terms + + λ[ f ∶ 𝔹 ⇒ 𝔹 ] λ[ x ∶ 𝔹 ] ` f · (` f · ` x) + +and + + λ[ g ∶ 𝔹 ⇒ 𝔹 ] λ[ y ∶ 𝔹 ] ` g · (` g · ` y) + +and + + λ[ fred ∶ 𝔹 ⇒ 𝔹 ] λ[ xander ∶ 𝔹 ] ` fred · (` fred · ` xander) + +and even + + λ[ x ∶ 𝔹 ⇒ 𝔹 ] λ[ f ∶ 𝔹 ] ` x · (` x · ` f) + +are all considered equivalent. This equivalence relation +is sometimes called _alpha renaming_. + +As we descend from a term into its subterms, variables +that are bound may become free. Consider the following terms. + +* `` λ[ f ∶ 𝔹 ⇒ 𝔹 ] λ[ x ∶ 𝔹 ] ` f · (` f · ` x) `` + Both variable `f` and `x` are bound. + +* `` λ[ x ∶ 𝔹 ] ` f · (` f · ` x) `` + has `x` as a bound variable but `f` as a free variable. + +* `` ` f · (` f · ` x) `` + has both `f` and `x` as free variables. + +We say that a term with no free variables is _closed_; otherwise it is +_open_. Of the three terms above, the first is closed and the other +two are open. A formal definition of bound and free variables will be +given in the next chapter. + +Different occurrences of a variable may be bound and free. +In the term + + (λ[ x ∶ 𝔹 ] ` x) · ` x + +the inner occurrence of `x` is bound while the outer occurrence is free. +Note that by alpha renaming, the term above is equivalent to + + (λ[ 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 +variables in a term are distinct from the free variables, which can +avoid confusions that may arise if bound and free variables have the +same names. + + +#### Precedence + +As in Agda, functions of two or more arguments are represented via +currying. This is made more convenient by declaring `_⇒_` to +associate to the right and `_·_` to associate to the left. +Thus, + +> `(𝔹 ⇒ 𝔹) ⇒ 𝔹 ⇒ 𝔹` abbreviates `(𝔹 ⇒ 𝔹) ⇒ (𝔹 ⇒ 𝔹)`, + +and similarly, + +> `two · not · true` abbreviates `(two · not) · true`. + +We choose the binding strength for abstractions and conditionals +to be weaker than application. For instance, + +> `` λ[ f ∶ 𝔹 ⇒ 𝔹 ] λ[ x ∶ 𝔹 ] ` f · (` f · ` x) `` abbreviates +> `` (λ[ f ∶ 𝔹 ⇒ 𝔹 ] (λ[ x ∶ 𝔹 ] (` f · (` f · ` x)))) `` and not +> `` (λ[ f ∶ 𝔹 ⇒ 𝔹 ] (λ[ x ∶ 𝔹 ] ` f)) · (` f · ` x) ``. + +
+
+ex₁ : (𝔹  𝔹)  𝔹  𝔹  (𝔹  𝔹)  (𝔹  𝔹)
+ex₁ = refl
+
+ex₂ : two · not · true  (two · not) · true
+ex₂ = refl
+
+ex₃ : λ[ f  𝔹  𝔹 ] λ[ x  𝔹 ] ` f · (` f · ` x)
+       (λ[ f  𝔹  𝔹 ] (λ[ x  𝔹 ] (` f · (` f · ` x))))
+ex₃ = refl
+
+
+ +#### Quiz + +* What is the type of the following term? + + λ[ f ∶ 𝔹 ⇒ 𝔹 ] ` f · (` f · true) + + 1. `𝔹 ⇒ (𝔹 ⇒ 𝔹)` + 2. `(𝔹 ⇒ 𝔹) ⇒ 𝔹` + 3. `𝔹 ⇒ 𝔹 ⇒ 𝔹` + 4. `𝔹 ⇒ 𝔹` + 5. `𝔹` + + Give more than one answer if appropriate. + +* What is the type of the following term? + + (λ[ f ∶ 𝔹 ⇒ 𝔹 ] ` f · (` f · true)) · not + + 1. `𝔹 ⇒ (𝔹 ⇒ 𝔹)` + 2. `(𝔹 ⇒ 𝔹) ⇒ 𝔹` + 3. `𝔹 ⇒ 𝔹 ⇒ 𝔹` + 4. `𝔹 ⇒ 𝔹` + 5. `𝔹` + + Give more than one answer if appropriate. + ## Values +We only consider reduction of _closed_ terms, +those that contain no free variables. We consider +a precise definition of free variables in +[StlcProp]({{ "StlcProp" | relative_url }}). + +A term is a value if it is fully reduced. +For booleans, the situation is clear, `true` and +`false` are values, while conditionals are not. +For functions, applications are not values, because +we expect them to further reduce, and variables are +not values, because we focus on closed terms. +Following convention, we treat all abstractions +as values. + +The predicate `Value M` holds if term `M` is a value. +
 
-data Value : Term  Set where
   value-λ     :  {x A N}  Value (λ[ x  A ] N)
   value-true  : Value true
   value-false : Value false
 
 
+We let `V` and `W` range over values. + + +#### Formal vs informal + +In informal presentations of formal semantics, using +`V` as the name of a metavariable is sufficient to +indicate that it is a value. In Agda, we must explicitly +invoke the `Value` predicate. + +#### Other approaches + +An alternative is not to focus on closed terms, +to treat variables as values, and to treat +`λ[ x ∶ A ] N` as a value only if `N` is a value. +Indeed, this is how Agda normalises terms. +Formalising this approach requires a more sophisticated +definition of substitution, which permits substituting +closed terms for values. + ## Substitution +The heart of lambda calculus is the operation of +substituting one term for a variable in another term. +Substitution plays a key role in defining the +operational semantics of function application. +For instance, we have + + (λ[ f ∶ 𝔹 ⇒ 𝔹 ] `f · (`f · true)) · not + ⟹ + not · (not · true) + +where we substitute `false` for `` `x `` in the body +of the function abstraction. + +We write substitution as `N [ x := V ]`, meaning +substitute term `V` for free occurrences of variable `x` in term `V`, +or, more compactly, substitute `V` for `x` in `N`. +Substitution works if `V` is any closed term; +it need not be a value, but we use `V` since we +always substitute values. + +Here are some examples. + +* `` ` f [ f := not ] `` yields `` not `` +* `` true [ f := not ] `` yields `` true `` +* `` (` f · true) [ f := not ] `` yields `` not · true `` +* `` (` f · (` f · true)) [ f := not ] `` yields `` not · (not · true) `` +* `` (λ[ x ∶ 𝔹 ] ` f · (` f · ` x)) [ f := not ] `` yields `` λ[ x ∶ 𝔹 ] not · (not · ` x) `` +* `` (λ[ y ∶ 𝔹 ] ` y) [ x := true ] `` yields `` λ[ y ∶ 𝔹 ] ` y `` +* `` (λ[ x ∶ 𝔹 ] ` x) [ x := true ] `` yields `` λ[ x ∶ 𝔹 ] ` x `` + +The last example is important: substituting `true` for `x` in +`` (λ[ x ∶ 𝔹 ] ` x) `` does _not_ yield `` (λ[ x ∶ 𝔹 ] true) ``. +The reason for this is that `x` in the body of `` (λ[ x ∶ 𝔹 ] ` x) `` +is _bound_ by the abstraction. An important feature of abstraction +is that the choice of bound names is irrelevant: both +`` (λ[ x ∶ 𝔹 ] ` x) `` and `` (λ[ y ∶ 𝔹 ] ` y) `` stand for the +identity function. The 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 both just happen to have the same +name. + +Here is the formal definition in Agda. +
 
-_[_:=_] : Term  Id  Term  Term
 (` x′) [ x := V ] with x  x′
 ... | yes _ = V
 ... | no  _ = ` x′
 (λ[ x′  A′ ] N′) [ x := V ] with x  x′
 ... | yes _ = λ[ x′  A′ ] N′
 ... | no  _ = λ[ x′  A′ ] (N′ [ x := V ])
 (L′ · M′) [ x := V ] =  (L′ [ x := V ]) · (M′ [ x := V ])
 (true) [ x := V ] = true
 (false) [ x := V ] = false
 (if L′ then M′ else N′) [ x := V ] = 
+  if (L′ [ x := V ]) then (M′ [ x := V ]) else (N′ [ x := V ])
 
 
-## Reduction rules +The two key cases are variables and abstraction. + +* For variables, we compare `x`, the variable we are substituting for, +with `x′`, the variable in the term. If they are the same, +we yield `V`, otherwise we yield `x′` unchanged. + +* For abstractions, we compare `x`, the variable we are substituting for, +with `x′`, the variable bound in the abstraction. If they are the same, +we yield abstraction unchanged, otherwise we subsititute inside the body. + +In all other cases, we push substitution recursively into +the subterms. + +#### Special characters + + ′ U+2032: PRIME (\') + +Note that ′ (U+2032: PRIME) is not the same as ' (U+0027: APOSTROPHE). + + +#### Examples + +Here is confirmation that the examples above are correct.
 
-ex₁₁ : ` f [ f := not ]   not
+ex₁₁ = refl
+
+ex₁₂ : true [ f := not ]  true
+ex₁₂ = refl
+
+ex₁₃ : (` f · true) [ f := not ]  not · true
+ex₁₃ = refl
+
+ex₁₄ : (` f · (` f · true)) [ f := not ]  not · (not · true)
+ex₁₄ = refl
+
+ex₁₅ : (λ[ x  𝔹 ] ` f · (` f · ` x)) [ f := not ]  λ[ x  𝔹 ] not · (not · ` x)
+ex₁₅ = refl
+
+ex₁₆ : (λ[ y  𝔹 ] ` y) [ x := true ]  λ[ y  𝔹 ] ` y
+ex₁₆ = refl
+
+ex₁₇ : (λ[ x  𝔹 ] ` x) [ x := true ]  λ[ x  𝔹 ] ` x
+ex₁₇ = refl
+
+
+ +#### Quiz + +What is the result of the following substitution? + + (λ[ y ∶ 𝔹 ] ` x · (λ[ x ∶ 𝔹 ] ` x)) [ x := true ] + +1. `` (λ[ y ∶ 𝔹 ] ` x · (λ[ x ∶ 𝔹 ] ` x)) `` +2. `` (λ[ y ∶ 𝔹 ] ` x · (λ[ x ∶ 𝔹 ] true)) `` +3. `` (λ[ y ∶ 𝔹 ] true · (λ[ x ∶ 𝔹 ] ` x)) `` +4. `` (λ[ y ∶ 𝔹 ] true · (λ[ x ∶ 𝔹 ] ` true)) `` + + +## Reduction + +We give the reduction rules for call-by-value lambda calculus. To +reduce an application, first we reduce the left-hand side until it +becomes a value (which must be an abstraction); then we reduce the +right-hand side until it becomes a value; and finally we substitute +the argument for the variable in the abstraction. To reduce a +conditional, we first reduce the condition until it becomes a value; +if the condition is true the conditional reduces to the first +branch and if false it reduces to the second branch.a + +In an informal presentation of the formal semantics, the rules +are written as follows. + + L ⟹ L′ + --------------- ξ·₁ + L · M ⟹ L′ · M + + Value V + M ⟹ M′ + --------------- ξ·₂ + V · M ⟹ V · M′ + + Value V + --------------------------------- βλ· + (λ[ x ∶ A ] N) · V ⟹ N [ x := V ] + + L ⟹ L′ + ----------------------------------------- ξif + if L then M else N ⟹ if L′ then M else N + + -------------------------- βif-true + if true then M else N ⟹ M + + --------------------------- βif-false + if false then M else N ⟹ N + +As we will show later, the rules are deterministic, in that +at most one rule applies to every term. As we will also show +later, for every well-typed term either a reduction applies +or it is a value. + +The rules break into two sorts. Compatibility rules +direct us to reduce some part of a term. +We give them names starting with the Greek letter xi, `ξ`. +Once a term is sufficiently +reduced, it will consist of a constructor and +a deconstructor, in our case `λ` and `·`, or +`if` and `true`, or `if` and `false`. +We give them names starting with the Greek letter beta, `β`, +and indeed such rules are traditionally called beta rules. + +
+
+infix 10 _⟹_ 
 
 data _⟹_ : Term  Term  Set where
   βλ· :  {x A N V}  Value V 
-    (λ[ x  A ] N) · V  N [ x := V ]
-  ξ·₁ :  {L L′ M} 
     L  L′ 
     L · M  L′ · M
   ξ·₂ :  {V M M′} 
     Value V 
     M  M′ 
     V · M  V · M′
   βif-trueβλ· :  {Mx A N} V}  Value V 
     if(λ[ truex then MA else] N) · V  MN [ x := V ]
   βif-false :  {M N} 
-    if false then M else N  N
-  ξif :  {L L′ M N} 
     L  L′     
     if L then M else N  if L′ then M else N
+  βif-true :  {M N} 
+    if true then M else N  M
+  βif-false :  {M N} 
+    if false then M else N  N
 
 
+#### Special characters + +We use the following special characters + + ⟹ U+27F9: LONG RIGHTWARDS DOUBLE ARROW (\r6) + ξ U+03BE: GREEK SMALL LETTER XI (\Gx or \xi) + β U+03B2: GREEK SMALL LETTER BETA (\Gb or \beta) + +#### Quiz + +What does the following term step to? + + (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) · (λ [ x ∶ 𝔹 ] ` x) ⟹ ??? + +1. `` (λ [ x ∶ 𝔹 ] ` x) `` +2. `` (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) `` +3. `` (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) · (λ [ x ∶ 𝔹 ] ` x) `` + +What does the following term step to? + + (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) · ((λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) (λ [ x ∶ 𝔹 ] ` x)) ⟹ ??? + +1. `` (λ [ x ∶ 𝔹 ] ` x) `` +2. `` (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) `` +3. `` (λ[ x ∶ 𝔹 ⇒ 𝔹 ] ` x) · (λ [ x ∶ 𝔹 ] ` x) `` + +What does the following term step to? (Where `not` is as defined above.) + + not · true ⟹ ??? + +1. `` if ` x then false else true `` +2. `` if true then false else true `` +3. `` true `` +4. `` false `` + +What does the following term step to? (Where `two` and `not` are as defined above.) + + two · not · true ⟹ ??? + +1. `` not · (not · true) `` +2. `` (λ[ x ∶ 𝔹 ] not · (not · ` x)) · true `` +4. `` true `` +5. `` false `` + ## Reflexive and transitive closure +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 `⟹`. +In an informal presentation of the formal semantics, the rules +are written as follows. + + ------- done + M ⟹* M + + L ⟹ M + M ⟹* N + ------- step + L ⟹* N + +Here it is formalised in Agda.
 
-infix 10 _⟹*_ 
 infixr 2 _⟹⟨_⟩_
 infix  3 _∎
 
 data _⟹*_ : Term  Term  Set where
   _∎ :  M  M ⟹* M
   _⟹⟨_⟩_ :  L {M N}  L  M  M ⟹* N  L ⟹* N  
+      >
 
-
+
+We can read this as follows.
+
+* From term `M`, we can take no steps, giving `M ∎` of type `M ⟹* M`.
+
+* From term `L` we can take a single step `L⟹M` of type `L ⟹ M`
+  followed by zero or more steps `M⟹*N` of type `M ⟹* N`,
+  giving `L ⟨ L⟹M ⟩ M⟹*N` of type `L ⟹* N`.
+
+The names of the two clauses in the definition of reflexive
+and transitive closure have been chosen to allow us to lay
+out example reductions in an appealing way.
+
+
+
+reduction₁ : not · true ⟹* false
 reduction₁ =
     not · true
   ⟹⟨ βλ· value-true 
     if true then false else true
   ⟹⟨ βif-true 
     false
   
 
 reduction₂ : two · not · true ⟹* true
 reduction₂ =
     two · not · true
   ⟹⟨ ξ·₁ (βλ· value-λ) 
     (λ[ x  𝔹 ] not · (not · ` x)) · true
   ⟹⟨ βλ· value-true 
     not · (not · true)
   ⟹⟨ ξ·₂ value-λ (βλ· value-true) 
     not · (if true then false else true)
   ⟹⟨ ξ·₂ value-λ βif-true  
     not · false
   ⟹⟨ βλ· value-false 
     if false then false else true
   ⟹⟨ βif-false 
     true
   
 
 
+ +#### Special characters +We use the following special characters + + ∎ U+220E: END OF PROOF (\qed) + ⟨ U+27E8: MATHEMATICAL LEFT ANGLE BRACKET (\<) + ⟩ U+27E9: MATHEMATICAL RIGHT ANGLE BRACKET (\>) + +## Typing + +While reduction considers only closed terms, typing must +consider terms with free variables. To type a term, +we must first type its subterms, and in particular in the +body of an abstraction its bound variable may appear free. + +In general, we use typing _judgements_ of the form + + Γ ⊢ M ∶ A + +which asserts in type environment `Γ` that term `M` has type `A`. +Here `Γ` provides types for all the free variables in `M`. + +Here are three examples. + +* `` ∅ ⊢ (λ[ f ∶ 𝔹 ⇒ 𝔹 ] λ[ x ∶ 𝔹 ] ` f · (` f · ` x)) ∶ (𝔹 ⇒ 𝔹) ⇒ 𝔹 ⇒ 𝔹 `` + +* `` ∅ , f ∶ 𝔹 ⇒ 𝔹 ⊢ (λ[ x ∶ 𝔹 ] ` f · (` f · ` x)) ∶ 𝔹 ⇒ 𝔹 `` + +* `` ∅ , f ∶ 𝔹 ⇒ 𝔹 , x ∶ 𝔹 ⊢ ` f · (` f · ` x) ∶ 𝔹 `` + +Environments are maps from free variables to types, built using `∅` +for the empty map, and `Γ , x ∶ A` for the map that extends +environment `Γ` by mapping variable `x` to type `A`. -## Type rules
 
-Context : Set
 Context = PartialMap Type
 
 infix 10 _⊢_∶_
 
 data _⊢_∶_ : Context  Term  Type  Set where
   Ax :  {Γ x A} 
     Γ x  just A 
     Γ  ` x  A
   ⇒-I :  {Γ x N A B} 
     Γ , x  A  N  B 
     Γ  λ[ x  A ] N  A  B
   ⇒-E :  {Γ L M A B} 
     Γ  L  A  B 
     Γ  M  A 
     Γ  L · M  B
   𝔹-I₁ :  {Γ} 
     Γ  true  𝔹
   𝔹-I₂ :  {Γ} 
     Γ  false  𝔹
   𝔹-E :  {Γ L M N A} 
     Γ  L  𝔹 
     Γ  M  A 
     Γ  N  A 
     Γ  if L then M else N  A
 
@@ -3556,205 +5033,205 @@ Much of the above, though not all, can be filled in using C-c C-r and C-c C-s.
 
 
 
-typing₁ :   not  𝔹  𝔹
 typing₁ = ⇒-I (𝔹-E (Ax refl) 𝔹-I₂ 𝔹-I₁)
 
 typing₂ :   two  (𝔹  𝔹)  𝔹  𝔹
 typing₂ = ⇒-I (⇒-I (⇒-E (Ax refl) (⇒-E (Ax refl) (Ax refl))))