|

# Programming in System F

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
```

## Introduction

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.f
```
This executes filename.f and then enters the REPL.

## Requirements

Submit a file named solution.f with the following:

1. 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``````
2. We discussed how to encode the either type in class:
``````type ('a, 'b) either =
| Left of 'a
| Right of 'b``````
Booleans are even simpler:
``````type bool =
| True
| False``````
And they are even simpler to encode:
```/* 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.
3. 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``````
4. 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.
5. 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;;```
6. Implement binary search trees for integers. You should support two operations: insert and find.