Do all six problems below. There are three problems on implementing the lambda calculus and three problems on programming with Church numerals. For problems 1-3, modify the [[linterp.sml]] file. Put your answers for the Church numerals problems, 4-6, in a file called [[church.lam]].
noreduce bot = (\x.x x)(\x.x x); noreduce Y = \f.(\x.f(x x))(\x.f(x x));
A lambda term can be either a variable, a lambda abstraction, an application, or a
parenthesized lambda term. Precedence is as in ML.
A lambda abstraction is written as follows. Note that each lambda abstraction can
abstract over only one variable.
[[\name.term]]
Application of one term to another is written:
[[t1 t2]]
The lambda interpreter is very liberal about names of variables. A name is any string of characters that contains neither whitespace, nor control characters, nor any of the following characters: [[\]] [[(]] [[)]] [[.]] [[=]] [[/]]. Also, the string [[use]] is reserved and is therefore not a name. So for example, the following are all legal:
1 = \f.\x.f x; True = \x.\y.x; one = True 1;@
For these problems, define appropriate types and functions in [[linterp.sml]]. When you are done, you will have a working lambda interpreter. Some of the code we give you (Lhelp.ui and Lhelp.uo) is object code only, so you will have to build the interpreter using Moscow ML. Just typing make should do it.
1. Evaluation---Basics [15 points]. This problem has two parts:
lam : string -> term -> term (* lambda abstraction *) app : term -> term -> term (* application *) var : string -> term (* variable *) cpsLambda : (* observer *) term -> (string -> term -> 'a) -> (term -> term -> 'a) -> (string -> 'a) -> 'aThese functions should obey the following algebraic laws:
cpsLambda (lam x e) f g h = f x e cpsLambda (app e e') f g h = g e e' cpsLambda (var x) f g h = h x
Our solution to this problem is under 30 lines of ML code.
2. Evaluation---Substitution [11 points].
Implement substitution on your term representation.
Use a function subst of type string * term -> term -> term.
To compute the substitution M[x|–>N], you should call
subst (x, N) M.
Also define a function [[freeVars]] of type term -> string list which returns
a list of all the free variables in a term.
Our solution to this problem is under 40 lines of ML code.
3. Evaluation---Reductions [24 points]. In this problem, you use your substitution function to implement two different evaluation strategies.
Our solution to this problem is under 20 lines of ML code.
4. Church Numerals---predecessor [15 points]. Implement the predecessor function for the Church numerals. That is, a function [[pred]] such that [[pred(succ n)=n]], and [[pred(0)=0]]. Ultimately, you will write your function in lambda notation acceptable to the lambda interpreter, but you may find it useful to try to write your initial version in Typed uScheme (or ML or uScheme) to make it easier to debug. To get full credit, you must explain the reasoning behind your answer.
Remember,
<
Hint: Define a function [[lag]], so that [[lag(n,m) = (n+1,n)]].
Now, what is [[lag(lag(lag(lag(0,0))))]]?.
5. Church Numerals---equality [15 points].
Assume you have a predecessor function. Use it to implement an equality
function on Church numerals.
Again, turn in your answer using (untyped) lambda notation,
but feel free to start off in uScheme or Typed uScheme if that makes
it easier to debug.
(Don't expect to be able to use ML here; the
Hindley-Milner type system is not powerful enough to express the types
of all of the functions you
need to write.)
Do not use recursion or the Y-combinator in your solution.
Remember the definitions of the Booleans:
<<*>>=
true = \x.\y.x;
false = \x.\y.y;
@
Hints: Write a function to test if a Church numeral is zero.
Consider that n = m if and only if n <= m and m <= n.
Remember to use the predecessor function.
6. Church Numerals---division and modulus [20 points].
Write a function [[divmod]] such that given two Church numerals [[m]]
and [[n]], [[divmod m n]] returns a lambda-term representing the pair
(m div n, m mod n).
Again, use pure untyped lambda notation.
You may use [[pair]], [[fst]], and [[snd]] as defined in class, and
you will use the functions from the previous problems.
You may not use explicit recursion;
if you want a recursive solution, use the Y combinator.
This function should be doable in about 10 lines of ML.
Extra Credit---Normal forms galore.
Discover what Head Normal Form and Weak Head
Normal Form are and
implement reduction strategies for them.
Explain, in an organized way, the differences between the four
reduction strategies you have implemented.
Extra Credit---Typed Equality.
For extra credit, write down equality on Church numerals using Typed uScheme,
give the type of the term in algebraic notation,
and explain why this function can't be written in ML.
(By using the ``erasure'' theorem in reverse, you can take your
untyped version and just add type abstractions and type applications.)
Submit using submit-lambda from nice.
Extra Credit
Extra Credit---Normalization.
Write a higher-order function that takes as argument a reducing
strategy (e.g., reduceA or reduceN) and returns a
function that normalizes a term.
Your function should also count the number of reductions it takes to
reach a normal form.
As a tiny experiment, report the cost of computing using Church
numerals in both reduction strategies.
For example, you could report the number of reductions it takes to
reduce ``three times four''
to normal form.
What to submit
For this assignment, please submit [[church.lam]] for the parts
on Church Numerals and your modified [[linterp.sml]] for the parts on
evaluation.