*Due date: Friday, October 18th, 11:59PM*

You must update the course software to get the support code for this assignment. From the terminal:

$ opam update $ opam install cs691f.1.3.2

In this assignment, you will write several little programs in System F. The support code includes a System F implementation which has several convenient features (e.g., top-level let bindings and the ability to give names to types). You don't need to implement System F yourself, though you're welcome read or change the code if you like.

Once you update the course software, you should have another executable
called `systemf`

alongside the `cs691f`

executable
that you used in previous assignments. Running it starts a System F
REPL. You can also store REPL commands to a file and do:

$ systemf filename.fThis executes filename.f and then enters the REPL.

Submit a file named *solution.f* with the following:

- Implement triples in System F, in a manner analogous to pairs.
You should implement a triple constructor and projection functions
that are isomorphic to the following OCaml code:
`type ('a, 'b, 'c) triple = Triple of a * b * c let triple_proj1 (t : ('a, 'b, 'c) triple) : 'a = match x with | Triple (a, b, c) -> a let triple_proj2 (t : ('a, 'b, 'c) triple) : 'b = match x with | Triple (a, b, c) -> b let triple_proj3 (t : ('a, 'b, 'c) triple) : 'c = match x with | Triple (a, b, c) -> c`

- We discussed how to encode the
*either*type in class:Booleans are even simpler:`type ('a, 'b) either = | Left of 'a | Right of 'b`

And they are even simpler to encode:`type bool = | True | False`

/* Booleans */ type [[Bool]] = forall R . R -> R -> R;; let true = typfun R -> fun (x : R) -> fun (y : R) -> x;; let false = typfun R -> fun (x : R) -> fun (y : R) -> y;; let if = typfun R -> fun (cond : [[Bool]]) -> fun (true_branch : R) -> fun (false_branch : R) -> cond<R> true_branch false_branch;; let and = fun (e1 : [[Bool]]) -> fun (e2 : [[Bool]]) -> typfun R -> fun (x : R) -> fun (y : R) -> e1 <R> (e2 <R> x y) y;; let or = fun (e1 : [[Bool]]) -> fun (e2 : [[Bool]]) -> typfun R -> fun (x : R) -> fun (y : R) -> e1 <R> x (e2 <R> x y);;

Implement the*not*,*nand*, and*xor*operators for booleans. - Encode a constructor for the following type and an expression to project
its components and discriminate its variants:
`type 'a foo = | Bar of 'a * 'a | Baz`

- We discussed lists and option types in class:
/* Lists and options */ type [[Option T]] = forall R . (T -> R) -> R -> R;; let some = typfun T -> fun (x : T) -> typfun R -> fun (some : T -> R) -> fun (none : R) -> some x;; let none = typfun T -> typfun R -> fun (some : T -> R) -> fun (none : R) -> none;; let option_case = typfun T -> typfun R -> fun (v : [[Option T]]) -> fun (some_case : T -> R) -> fun (none_case : R) -> v <R> some_case none_case;; type [[List T]] = forall R . (T -> R -> R) -> R -> R;; let cons = typfun T -> fun (hd : T) -> fun (tl : [[List T]]) -> typfun R -> fun (c : T -> R -> R) -> fun (n : R) -> c hd (tl <R> c n);; let empty = typfun T -> typfun R -> fun (c : T -> R -> R) -> fun (n : R) -> n;; /* An example list */ let example_list = cons<int> 100 (cons<int> 200 (cons<int> 300 (empty<int>)));;

Implement the*reverse*function.**Hint:**First, write a function to add an element to the end of a list. This function is commonly called*snoc*. - Implement insertion sort for lists of integers. It is possible to
Church-encode integers yourself, but they are quite difficult to read.
Instead, you should use the support code which has primitive integers
and comparison functions that return Church booleans:
/* Integer comparisons */ 10 = 10;; 50 = 1;; 10 < 5;; 10 > 5;;

- Implement binary search trees for integers. You should support two
operations:
*insert*and*find*.