+ let b = bool in
+ let y = yes in
+ let n = no in
+ match b with true -> y | false -> n
+
+ This almost works. For instance,
+
+ if true then 1 else 2;;
+
+ evaluates to 1, and
+
+ let b = true in let y = 1 in let n = 2 in
+ match b with true -> y | false -> n;;
+
+ also evaluates to 1. Likewise,
+
+ if false then 1 else 2;;
+
+ and
+
+ let b = false in let y = 1 in let n = 2 in
+ match b with true -> y | false -> n;;
+
+ both evaluate to 2.
+
+ However,
+
+ let rec blackhole x = blackhole x in
+ if true then blackhole else blackhole ();;
+
+ terminates, but
+
+ let rec blackhole x = blackhole x in
+ let b = true in
+ let y = blackhole in
+ let n = blackhole () in
+ match b with true -> y | false -> n;;
+
+ does not terminate. Incidentally, `match bool with true -> yes |
+ false -> no;;` works as desired, but your assignment is to solve it
+ without using the magical evaluation order properties of either `if`
+ or of `match`. That is, you must keep the `let` statements, though
+ you're allowed to adjust what `b`, `y`, and `n` get assigned to.
+
+ [[hints/assignment 5 hint 1]]
+
+Booleans, Church numerals, and v3 lists in OCaml
+------------------------------------------------
+
+(These questions adapted from web materials by Umut Acar. See
+<http://www.mpi-sws.org/~umut/>.)
+
+Let's think about the encodings of booleans, numerals and lists in System F,
+and get data-structures with the same form working in OCaml. (Of course, OCaml
+has *native* versions of these datas-structures: its `true`, `1`, and `[1;2;3]`.
+But the point of our exercise requires that we ignore those.)
+
+Recall from class System F, or the polymorphic λ-calculus.
+
+ types τ ::= c | 'a | τ1 → τ2 | ∀'a. τ
+ expressions e ::= x | λx:τ. e | e1 e2 | Λ'a. e | e [τ]
+
+The boolean type, and its two values, may be encoded as follows:
+
+ bool := ∀'a. 'a → 'a → 'a
+ true := Λ'a. λt:'a. λf :'a. t
+ false := Λ'a. λt:'a. λf :'a. f
+
+It's used like this:
+
+ b [τ] e1 e2
+
+where b is a boolean value, and τ is the shared type of e1 and e2.
+
+**Exercise**. How should we implement the following terms. Note that the result
+of applying them to the appropriate arguments should also give us a term of
+type bool.
+
+(a) the term not that takes an argument of type bool and computes its negation;
+(b) the term and that takes two arguments of type bool and computes their conjunction;
+(c) the term or that takes two arguments of type bool and computes their disjunction.
+
+
+The type nat (for "natural number") may be encoded as follows:
+
+ nat := ∀'a. 'a → ('a → 'a) → 'a
+ zero := Λ'a. λz:'a. λs:'a → 'a. z
+ succ := λn:nat. Λ'a. λz:'a. λs:'a → 'a. s (n ['a] z s)
+
+A nat n is defined by what it can do, which is to compute a function iterated n
+times. In the polymorphic encoding above, the result of that iteration can be
+any type 'a, as long as you have a base element z : 'a and a function s : 'a → 'a.
+
+**Exercise**: get booleans and Church numbers working in OCaml,
+including OCaml versions of bool, true, false, zero, iszero, succ, and pred.
+It's especially useful to do a version of pred, starting with one
+of the (untyped) versions available in the lambda library
+accessible from the main wiki page. The point of the excercise
+is to do these things on your own, so avoid using the built-in
+OCaml booleans and integers.
+
+Consider the following list type:
+
+ type 'a list = Nil | Cons of 'a * 'a list
+
+We can encode τ lists, lists of elements of type τ as follows:
+
+ τ list := ∀'a. 'a → (τ → 'a → 'a) → 'a
+ nil τ := Λ'a. λn:'a. λc:τ → 'a → 'a. n
+ make_list τ := λh:τ. λt:τ list. Λ'a. λn:'a. λc:τ → 'a → 'a. c h (t ['a] n c)
+
+More generally, the polymorphic list type is:
+
+ list := ∀'b. ∀'a. 'a → ('b → 'a → 'a) → 'a
+
+As with nats, recursion is built into the datatype.
+
+We can write functions like map:
+
+ map : (σ → τ ) → σ list → τ list
+
+<!--
+ = λf :σ → τ. λl:σ list. l [τ list] nil τ (λx:σ. λy:τ list. make_list τ (f x) y
+-->
+
+**Excercise** convert this function to OCaml. We've given you the type; you
+only need to give the term.