Binding more than one variable at a time
----------------------------------------
1. Jacobson's reader monad only allows for establishing a single binding
relationship at a time. It requires considerable cleverness to deploy
her combinators in a way that establishes multiple binding
relationships, as in
John_x thinks Mary_y said he_x likes her_y.
See her 1999 paper for details.
Here is [[code for the simple arithmetic reader monad discussed in the
lecture notes|code/arith1.ml]]. It computes
`\x. (+ 1 (* (/ 6 x) 4))`. Your task is to modify it to compute
`\x\y.(+ 1 (* (/ 6 x) y))`. You will need to modify five lines.
The first one is the type of a boxed int. Instead of `type num = int
-> int`, you'll need
type num = int -> int -> int
The second and third are the definitions of mid and map2. The fourth
is the one that encodes the variable x, the line that begins `(Leaf
(Num (fun x -> ...`. The fifth line you need to modify is the one
that replaces "4" with "y". When you have these lines modified,
you should be able to execute the following expression:
# match eval t2 with Leaf (Num f) -> f 2 4;;
- : int = 13
2. Based on the evaluator code from the assignment from week 7,
enhance the code to handle an arbitrary set of free variables.
Return to the original code (before executing the modifications
required by exercise 1).
Start like this:
type env = string -> int
type num = env -> int
let g = fun var -> match var with "x" -> 2 | "y" -> 4 | _ -> 0;;
When you have it working, try
# match eval t2 with Leaf (Num f) -> f g;;
- : int = 13
3. Add in the maybe monad. Start here:
type num = env -> int option
Show that your code handles division by zero gracefully.