8. The Lambda Calculus

1. Consider the following datatype which encodes λ-expressions:

data LExpr = Var Char | Lambda Char LExpr | App LExpr LExpr 

Enroll LExpr in class Show.

2. Write a function vars which returns a list of variables used in a λ-expression:

vars :: LExpr -> [Char]

3. Write a function reducible which tests if an expression can be reduced to another. Write tests first! What are the cases when an expression is reducible?

reducible :: LExpr -> Bool

4. Write a function which renames all occurrences of a variable with another, in a λ-expression:

rename :: Char -> Char -> LExpr -> LExpr

5. Write a function which replaces all occurrences of a variable with a λ-expression, in a λ-expression:

replace :: Char -> LExpr -> LExpr -> LExpr

6. Write a function which takes a λ-expression of the form (λx.<body> <arg>) and reduces it in a SINGLE step.

  1. What should (λx.(x x) y) produce?
  2. What should (λx.λx.(x x) y) produce?

7. Add two data constructors to the type LExpr so that we can also model functions and applications in uncurry form. Examples: (λx y z.<body>), (f x y z).

8. Write a proper display function for these new constructors.

9. Write a function luncurry which takes an uncurries λ-expression and transforms it in curry form.

lcurry :: LExpr -> LExpr

10. Write a function lcurry which takes a curried λ-expression and transforms it in uncurry form.

(((f x) y) z)   becomes    (f x y z)
(((f ((g a) b)) y) ((h u) v))  becomes  (f (g a b) y (h u v))

11. Write the function fv which computes the list of all free variables of a λ-expression.

fv :: LExpr -> [Char]

12. Write a function bv which computes the list of all bound variables of a λ-expression.

bv :: LExpr -> [Char]

13. Write a function subst which computes the textual substitution of all free occurrences of some variable x by e in e', according to the lecture definition:

subst :: Char -> LExpr -> LExpr -> LExpr

14. Implement a function which reduces a reducible λ-expression to an irreducible one. (According to the lecture definition, what happens with λx.(λx.x x) ?

reduce :: LExpr -> LExpr

15. Implement normal-order evaluation.

16. Implement applicative (strict) evaluation.