2 The simply-typed lambda calculus λ-st
2.1 Syntax
2.2 Dynamic semantics
eval() =
if
2.3 Static semantics
To type λ-st, we define typing contexts mapping variables to types:
Exercise 8. Extend λ-st with a product type . You will need a form for constructing products and projections for getting the components out. Add the necessary reduction and typing rules.
Exercise 9. Extend λ-st with a sum type . You will need two injection forms and to create sums, and one case analysis form to eliminate them, . The case analysis form takes a step once reduces to a sum value: , and similarly for . Add the necessary reduction and typing rules.
2.3.1 Type safety
Before we can prove type safety, we need to prove several standard lemmas.
We use the judgment with no context to mean that types in an empty context: .
Lemma (Replacement). If then for some . Furthermore, for any other term , .
Proof. By induction on the structure of :
: Then trivially, with = .
: By inspection of the typing rules, we know that if has a type, that type is . By inversion, we know that has type as well. Then by the induction hypothesis, has some type , and for any having type , . Then by rule [succ], .
: The whole term has a type only if there is some type such that and . Then by the induction hypothesis, , and for any term having type , . Then .
: The whole term has a type only if there is some type such that and . Then by the induction hypothesis, , and for any term having type , . Then .
Lemma (Substitution). If and then .
Proof. By induction on the type derivation for :
: If = then = , and = , which has type . If ≠ , then = , which must type in .
: This types in an environment.
: Then it must be the case that . Then by induction, , and reapplying rule [succ], we have that .
cases are similar.
: This can be the case only if . Without loss of generality, ≠ , so we can swap them, yielding . Then by induction . Then apply rule [abs], to get .
Lemma (Preservation). If and then .
Proof. By cases on the reduction relation. There is one case:
. By the replacement lemma, we know that . This only types if and . The former is only the case if . Then by the substitution lemma, , and by replacement, .
QED.
Lemma (Canonical forms).
If then:
If is , then is either or or for some .
If is , then is some lambda abstraction .
Proof. By induction on the structure of the typing derivation. Only three rules form values, and those three rules correspond to the conditions of the lemma.
Lemma (Progress). If then either is a value or for some .
Proof. By induction on the structure of the typing derivation, considering the terms:
: Vacuous, open terms don’t type.
: A value.
: By induction, steps or is a value of type . If the former then the whole term steps; if the latter then the whole term is a value.
: By induction, each subterm steps or is a value. If the first subterm steps, then the whole term steps. If the first subterm is a value and the second steps, then the whole thing steps. If both are values, then by inversion of the [app] rule, has a function type, and by the canonical forms lemma, that means it is a lambda abstraction . Then the whole term steps to .
: A value.
Theorem (Safety). 1) If and then . 2) If then either is a value or for some .
Exercise 10. Extend the type safety theorem to cover product and/or sum types.
2.4 An extension
pred =
add =
Exercise 11. Implement multiplication using the recursor.
Exercise 12. Implement factorial using the recursor.
Exercise 13. Implement a function that divides a natural number by two (rounding down).
Exercise 14. Extend the type safety theorem for the recursor.
Exercise 15. The recursor is currently call-by-name, in the sense that it substitutes the whole recursive expression of for in the non-zero case. The call-by-value form would compute the value of that subterm first and then subtitute the value, but making it call-by-value requires introducing an additional form. will do. (Why can’t we just use λ?) Show how to add to λ-st and how that can be used to make the recursor call-by-value.
2.5 Normalization
A normal form is a form that doesn’t reduce any further, which for our purposes (since we have eliminated stuck states) is a value. A term normalizes, written if it reduces to a normal form, that is, a value.
Historically, when working with lambda calculi that allow free conversion (that is, redexes can by identified anywhere in a term, without a notion of evaluation contexts) authors have distinguished weak from strong normalization. A term weakly normalizes if it has some reduction sequence reaching a normal form; a term strongly normalizes if every of its reduction sequences reaches a normal form. However, we’ve defined our language to be deterministic, which causes weak and strong normalization to coincide.
We wish to show that all terms that have a type reduce to a value. It is insufficient to do induction on typing derivations. (Shall we try it?) What we end up needing is a (unary) relation on terms, indexed by types, and defined by induction on types, of the form , as follows:
iff and .
iff and and for all such that , .
Exercise 16. How would we extend for product and/or sum types?
Lemma (SN preserved by conversion).
Suppose that and . Then:
implies .
implies .
Proof. By induction on :
: If normalizes then normalizes by the same sequence because takes a step to , which then normalizes. We know this because our formulation of λ-st is determistic, and there is no other way to reduce the term. (We could prove this but haven’t.) Since it has type , we have
If normalizes then it does so via , so normalizes as well and by preservation it has the same type, so .
: If then we know that normalizes and when applied to a good term, that normalizes too. We need to show that does that same, that is, that implies that for arbitrary term . We know that . Since , we know that . Since is a subexpression of , we can apply the induction hypothesis at that type, yielding as desired.
If then we know that normalizes and when applied to a good term, that normalizes too. We need to know that does the same, that is, that implies that for arbitrary term . We know that . Since , we know that . Then by induction, .
QED.
Note that if a substitution satisfies a type environment, this means that it contains values that typed in the empty type environment, meaning they are closed. Thus, the order of substitution doesn’t matter, as no variable in the substitution will interfere with any other.
Now we can prove a lemma that if we apply a substitution to a term that types in an environment consistent with the substitution, then the substituted term types in the empty environment:
Lemma (Mass substitution). If and then .
Proof. By induction on the length of . If empty, then is empty, and the substitution has no effect. Otherwise, = , where = and and . Then by the substitution lemma, . Then by induction, . But that is .
Lemma (Every typed term is good). If and then .
Proof. By induction on the typing derivation:
: Appling to gets us a such that .
: Since = , and and , we have that .
: By inversion, we know that . Then by induction, we have that . By the definition of NT for , we have that types in the empty context and reduces to a natural number. Then does as well.
: By inversion, we know that and . By induction, we know that and . The former means that for any such that , we have . Let be . Then .
- : Without loss of generality, let be fresh for . So then that term equals . We need to show that . To show this, we need to show three things:
To show . It suffices to show that for some such that , by the mass substitution lemma. That is what we have.
To show . This is clear, because it is a value.
To show that for any such that , . By the definition of SN, we know that for some value . Then we can take an additional step, . Because SN is preserved by backward conversion, it suffices to show that this term is SN for .
By the lemma that SN is preserved by forward conversion, we know that . So then we can say that . Now consider inverting the judgment that . From this, we know that . Then applying the induction hypothesis, we have that . This is what we sought to show.
QED.
Strong normalization follows as a corollary.
Exercise 17. Extend the normalization proof to cover products and/or sums.
Exercise 18. Show that λ-st with the recursor still enjoys normalization.
2.6 Adding nontermination
We can add unrestricted recursion to λ-st by adding a fixed-point operator. We will also add an construct, which lets us discriminate between zero and non-zero and extracts the predecessor from a natural. (This is redundant with the recursor, but easier to use. The resulting language is equivalent to the classic PCF.)
Exercise 19. Define addition, multiplication, and factorial using and . How does it compare to using the recursor?
Exercise 20. Extend type safety for .
Exercise 21. Where does the normalization proof break down if we add ?
Exercise 22. Implement a union-find in STLC with records and vectors.