CS 3520 Homework 9   - Due November 21

This homework is due November 21, 8:00 AM.

Submit your work using DrScheme's Handin button, even if it's OCaml/F# code. The handin server will not run any tests.

See Using Typed Languages for information on downloading PLAI Typed, OCaml, or F#.

Exercise 9.1, True, False, equals, and if

Start with tfae.ml or tfae-t.scm. The implementation already includes a boolean type, but no expressions of boolean type.

Add support for true, false, {= ... ...}, and {if ... ... ...} expressions, where = produces a boolean given two numbers, and if requires a boolean expression for the test.

The examples below use suggested constructor names. If you use different names, then adjust the tests. You don't need to write a parser; just test directly on abstract syntax.

Examples (PLAI Typed):

  (test (interp (eq (num 13)
                    (ifthenelse (eq (num 1) (add (num -1) (num 2)))
                                (num 12)
                                (num 13)))
                (mtSub))
         (boolV false))

  (test (typecheck (eq (num 13)
                       (ifthenelse (eq (num 1) (add (num -1) (num 2)))
                                   (num 12)
                                   (num 13)))
                   (mtEnv))
         (boolT))

  (test/exn (lambda ()
              (typecheck (add (num 1)
                              (ifthenelse (bool true)
                                          (bool true)
                                          (bool false)))
                         (mtEnv)))
            "no type")

Examples (Ocaml/F#):

  test(interp(Eq(Num(13),
                 If(Eq(Num(1),Add(Num(-1), Num(2))),
                    Num(12),
                    Num(13))),
               MTSub),
       BoolV(false));;

  test(typecheck(Eq(Num(13),
                    If(Eq(Num(1),Add(Num(-1), Num(2))),
                       Num(12),
                       Num(13))),
                 MTEnv),
      BoolT);;

  testExn(fun () -> typecheck(Add(Num(1), If(True, True, False)), MTEnv));;

Exercise 9.2, Pairs

Implement {pair ... ...}, {fst ...}, and {snd ...} expressions as shown in lecture for TPRCFAE (but not implemented in lecture).

Examples (PLAI Typed):

  (test (interp (fst (pair (num 10) (num 8)))
                (mtSub))
        (numV 10))
  (test (interp (snd (pair (num 10) (num 8)))
                (mtSub))
        (numV 8))

  (test (typecheck (pair (num 10) (num 8))
                   (mtEnv))
        (crossT (numT) (numT)))
  (test (typecheck (add (num 1) (snd (pair (num 10) (num 8))))
                   (mtEnv))
        (numT))

  (test (typecheck (fun 'x (crossTE (numTE) (boolTE))
                    (ifthenelse (snd (id 'x)) (num 0) (fst (id 'x))))
                   (mtEnv))
       (arrowT (crossT (numT) (boolT)) (numT)))

  (test/exn (lambda ()
              (typecheck (fst (num 10)) (mtEnv)))
            "no type")
  (test/exn (lambda ()
              (typecheck (add (num 1) (fst (pair (bool false) (num 8))))
                         (mtEnv)))
            "no type")
  (test/exn (lambda ()
              (typecheck (fun 'x (crossTE (numTE) (boolTE))
                               (ifthenelse (fst (id 'x)) (num 0) (fst (id 'x))))
                         (mtEnv)))
            "no type")

Examples (OCaml/F#):

  test(interp(Fst(Pair(Num(10), Num(8))), MTSub),
       NumV(10));;
  test(interp(Snd(Pair(Num(10), Num(8))), MTSub),
       NumV(8));;

  test(typecheck(Pair(Num(10), Num(8)), MTEnv),
       CrossT(NumT, NumT));;
  test(typecheck(Add(Num(1), Snd(Pair(False, Num(8)))), MTEnv),
       NumT);;
  test(typecheck(Fun("x", CrossTE(NumTE, BoolTE),
                    If(Snd(Id("x")), Num(0), Fst(Id("x")))),
                MTEnv),
       ArrowT(CrossT(NumT, BoolT), NumT));;

  testExn(fun () -> typecheck(Fst(Num(10)), MTEnv));;
  testExn(fun () -> typecheck(Add(Num(1), Fst(Pair(False, Num(8)))), MTEnv);;
  testExn(fun () -> typecheck(Fun("x", CrossTE(NumTE, BoolTE),
                                  If(Fst(Id("x")), Num(0), Fst(Id("x")))),
                              MTEnv));;

Exercise 9.3, Functions that Accept Multiple Arguments, Yet Again

With pairs, functions can accept multiple arguments by accepting paired values, but we can also add direct support for multiple arguments.

Change the interpreter to allow multiple function arguments and multiple arguments at function calls. The grammar of the language is now as follows:

  <TMFAE> = <number>
          | true
          | false
          | {+ <TMFAE> <TMFAE>}
          | {- <TMFAE> <TMFAE>}
          | {= <TMFAE> <TMFAE>}
          | <id>
          | {if <TMFAE> <TMFAE> <TMFAE>}
          | {fun {[<id> : <tyexp>]*} <TMFAE>}
          | {<TMFAE> <TMFAE>*}
          | {pair <TMFAE> <TMFAE>}
          | {fst <TMFAE>}
          | {snd <TMFAE>}

To support this grammar, change the fun/Fun and app/App constructors in FAE/fae, and the arrowTE/ArrowTE constructor in TE/te (plus other constructors that do not represent the input program):

  (define-type FAE
    ...
    [fun (params : (listof symbol))
         (argty : TE)
         (body : FAE)]
    [app (fun-expr : FAE)
         (arg-exprs : (listof FAE))]
    ...)

  (define-type TE
    ...
    [arrowTE (args : (listof TE))
             (result : TE)]
    ...)
  

or

  type fae = 
      ...
    | Fun of string list * te list * fae
    | App of fae * fae list
      ...

  type te =
      ...
    | ArrowTE of te list * te
      ...

In OCaml/F#, the map function is List.map:

  List.map (fun x -> x+1) [1;2;3];; (* produces [2;3;4] *)

Examples (Typed Scheme):

  (test (interp (app (fun (list) (list) (num 10)) (list))
               (mtSub))
        (numV 10))
  (test (interp (app (fun (list 'x 'y) (list (numTE) (numTE))
                          (sub (id 'x) (id 'y)))
                     (list (num 10) (num 20)))
                (mtSub))
        (numV -10))

  (test (typecheck (app (fun (list 'x 'y) (list (numTE) (boolTE))
                             (id 'y))
                        (list (num 10) (bool false)))
                   (mtEnv))
        (boolT))
  (test/exn (lambda ()
              (typecheck (app (fun (list 'x 'y) (list (numTE) (boolTE))
                               (id 'y))
                          (list (num 10) (num 10)))
                         (mtEnv)))
            "no type")

Examples (OCaml/F#):

  test(interp(App(Fun([], [], Num(10)), []), MTSub),
       NumV(10));;
  test(interp(App(Fun(["x"; "y"], [NumTE; NumTE], Sub(Id("x"), Id("y"))), 
                  [Num(10); Num(20)]), 
              MTSub),
       NumV(-10));;

  test(typecheck(App(Fun(["x"; "y"], [NumTE; BoolTE], Id("y")), 
                     [Num(10); False]), 
                 MTEnv),
       BoolT);;
  testExn(fun () -> typecheck(App(Fun(["x"; "y"], [NumTE; BoolTE], Id("y")), 
                                  [Num(10)]), 
                              MTEnv));;


Last update: Thursday, November 15th, 2007
mflatt@cs.utah.edu