Homework #6
Due: Tue, Nov 24
How to Submit
Submit a single file named
HW6.hs
through Canvas.Read the Homework Policy! This describes what to do if you cannot solve a problem.
Description
Template and supporting files: HW6.hs, DeBruijn.hs
Download both files and put them in the same directory. You should only modify and submit the HW6.hs
file.
In this assignment, you will be working with the implementation of nameless lambda calculus defined in DeBruijn.hs, which we discussed in class. The file also contains implementations of all of the Church encodings that we’ve covered, encoded in nameless lambda calculus.
Part 1: Nameless lambda calculus warm-up
The first part of the assignment is a warm-up to help you get familiar with nameless lambda calculus and the Haskell implementation.
For each of the three example expressions (in the comments above
ex1
,ex2
, andex3
), translate the expression into a corresponding nameless lambda calculus expression, then encode that expression as a value of typeExp
. You only need to provide the Haskell encoding in your solution. Note that for the tests to pass, you should choose the lowest possible De Bruijn index for any free variables.Define the Haskell function
closed :: Exp -> Bool
that takes a nameless lambda calculus function and returns a boolean value indicating whether the expression is closed (i.e. does not contain any free variables).
Part 2: Church pair update functions
In the second part of the assignment, you will define lambda calculus functions for updating each element of a Church-encoded pair.
Note that it is much easier to solve these problems if you reuse the existing definitions for Church pairs in your solution (i.e. pair
, fst
, and snd
) rather than try to develop a corresponding lambda calculus expression from scratch.
Define the value
setFst
, a lambda calculus function that updates the first element of a Church-encoded pair.Define the value
setSnd
, a lambda calculus function that updates the second element of a Church-encoded pair.
Part 3: Church encoding a Haskell program
In the third part of the assignment, you will be encoding a small Haskell program in lambda calculus. The template defines a data type Shape
and a few functions that operate on shapes. Your task is to determine how to encode the Shape
data type and each of these functions in lambda calculus.
Define the values
circleExp
andrectangleExp
that correspond to theCircle
andRectangle
data constructors in the Haskell program. Note that you should not change the types of these values. The providedencodeShape
function uses these values to transform a value of typeShape
into the corresponding encoding in lambda calculus.Define the values
squareExp
,areaExp
, andperimeterExp
that correspond to the Haskell functionssquare
,area
, andperimeter
, respectively. How these functions are implemented will depend on how you encode theShape
data type.
The file contains several unit tests to check your encodings.
Extra practice
For additional practice beyond this assignment, here are some tasks you might also try to implement, ranked roughly from easier to harder:
Add Church encodings for 4-tuples and 4-sums.
Add more kinds of shapes to the Haskell program in Part 3, then revise your lambda calculus encoding to include these new kinds of shapes.
Implement some simple recursive functions, such as the Fibonacci function. You can use the implementation of the factorial function in
DeBruijn.hs
as a guide.Implement another recursive data type, such as a binary tree of natural numbers, and functions that operate on that data type. You can use the implementation of lists in
DeBruijn.hs
as a guide.Implement a function to convert from nameless lambda calculus to named lambda calculus, and/or vice versa. Note that because I used the same constructor and function names in each module, you’ll have to import one of them qualified.