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.


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.

  1. For each of the three example expressions (in the comments above ex1, ex2, and ex3), translate the expression into a corresponding nameless lambda calculus expression, then encode that expression as a value of type Exp. 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.

  2. 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.

  1. Define the value setFst, a lambda calculus function that updates the first element of a Church-encoded pair.

  2. 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.

  1. Define the values circleExp and rectangleExp that correspond to the Circle and Rectangle data constructors in the Haskell program. Note that you should not change the types of these values. The provided encodeShape function uses these values to transform a value of type Shape into the corresponding encoding in lambda calculus.

  2. Define the values squareExp, areaExp, and perimeterExp that correspond to the Haskell functions square, area, and perimeter, respectively. How these functions are implemented will depend on how you encode the Shape 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.

Back to course home page