CS691F Programming Languages

| Introduction | Schedule | Software | OCaml Standard Library | Course Libraries |

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.