Ecole Polytechnique Fédérale de Lausanne
Exercise 3 Simply typed Lambda-Calculus
English only

Exercise 4 Buffer Session

This exercise session can be used to complete the exercises of the previous weeks.

For those who have already finished, here is an optional task to deepen your understanding on the use of type systems in compilers.

Symbols instead of Indices

We have used de Bruijn indices to avoid name clashes. Another way that is closer to what actually happens in compilers is to use Symbols.

A symbol is an object that is generated for each name definition (in our languages, that would be lambda abstraction). Name references are then resolved to symbol references by name analysis.

Since objects can easily be distinguished from each other, name clashes cannot happen - symbols are not compared based on their name, but on their memory location.

There will be no solutions for these exercises.

Optional Task 4.1

Change the implementation of the untyped lambda evaluator to use symbols.

  • Write a class Symbol to represent symbols. It must not be a case class.
  • add mutable fields var sym:Symbol to Lam and Var
  • change the Context so that it is a subclass of scala.collection.immutable.ListMap[Symbol,Binding]
  • Replace the DeBruijnPhase with a NameAnalysis phase that generate and sets symbols. Change the Main class so that it calls NameAnalysis instead of DeBruijnPhase
  • Change the substitution in the evaluator, so that it works on symbols instead of integer indices. Test your program.

Optional Task 4.2

  • Adapt your changes to the simply typed evaluator.
  • Do you still need the class Context after name analysis?

Optional Task 4.3 (only for the lambda addicted)

A more elegant way to formulate the lambda calculus is to fix a set of constants, for our language C = {true,false,succ,pred,iszero,if} and define the set of terms as E ::= x | E E | \x.E | c where c is a constant. Constants are typed.

In addition to beta reduction, there is a set C_rules that defines how to apply reductions on applications built up from constants.

Write up the formal definitions, for an arbitrary set C_rules.

Based on this definition, write scala functions for the constructors succ,zero,true,false which represent Num as Int, Bool as Boolean. Write Scala functions for the predefined functions that compute the desired value. These are your C_rules (you need to create an initial context so that names that look like free variables are bound to the constants).

Write a fast interpreter for our language (which does not output single reductions) using the functions.