






Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Material Type: Exam; Class: PROGRAMMING LANGUAGES; Subject: Computer Science; University: Rice University; Term: Fall 2008;
Typology: Exams
1 / 12
This page cannot be seen from the preview
Don't miss anything!







Name:
Id #:
Pledge:
The syntax of (Implicitly) Polymorphic Jam is a restriction of the syntax of untyped Jam. Every legal Polymorphic Jam program is also a legal untyped Jam Program. But the converse is false, because there may not be a valid typing for a given untyped Jam program.
The following grammar describes the abstract syntax of Polymorphic Jam. Each clause in the grammar corresponds directly to a node in the abstract syntax tree. The let construction has been limited to a single binding for the sake of notational simplicity. It is straightforward to generalize the rule to multiple bindings (with mutual recursion). Note that let is recursive.
M ::= M (M · · · M ) | P (M · · · M ) | if M then M else M | let x := M in M | V V ::= map x · · · x to M | x | n | true | false | null n ::= 1 | 2 |... P ::= cons | first | rest | null? | cons? | + | - | / | * | = | < | <= | <- | + | - | ~ | ref |! x ::= variable names
In the preceding grammar, unary and binary operators are treated exactly like primitive functions. Monomorphic types in the language are defined by τ , below. Polymorphic types are defined by σ. The → corresponds to a function type, whose inputs are to the left of the arrow and whose output is to the right of the arrow.
σ ::= ∀α 1 · · · αn. τ τ ::= int | bool | unit | τ 1 × · · · × τn → τ | α | list τ | ref τ α ::= type variable names
In the following rules, the notation Γ[x 1 : τ 1 ,... , xn : τn] means the Γ ∪ {x 1 : τ 1 ,... , xn : τn}.
Γ true : bool Γ false : bool Γ ` n : int
Γ[x 1 : τ 1 ,... , xn : τn] M : τ Γ map x 1... xn to M : τ 1 × · · · × τn → τ
[abs]
Γ M : τ 1 × · · · × τn → τ Γ M 1 : τ 1 · · · Γ Mn : τn Γ M (M 1 · · · Mn) : τ
[app]
The following table gives types for all of the primitive functions and operators and the polymorphic constant null. Programs are type checked starting with a primitive type environment consisting of this table.
null ∀α. list α cons ∀α. α × list α → list α first ∀α. list α → α rest ∀α. list α → list α cons? ∀α. list α → bool null? ∀α. list α → bool = ∀α. α × α → bool
< int × int → bool <= int × int → bool
(unary) - int → int (unary) + int → int (unary) ˜ bool → bool <- ∀α. ref α × α → unit ref ∀α. α → ref α ! ∀α. ref α → α
The Typed Jam language used in Assignment 5 (absent the explicit type infor- mation embedded in program text) can be formalized as a subset of Polymorphic Jam. For the purposes of this test, Typed Jam is simply Polymorphic Jam less the letpoly inference rule which prevents it from inferring polymorphic types for program-defined functions.
Problem 1. [15 points]
(i) [5 points] Give a simple example of an untyped Jam expression (which is not a value) that is not typable in Polymorphic Jam, yet does not generate a run-time error when executed. Briefly but convincingly explain why.
The program (map x to x(x)) (map x to x(x)), commonly called Omega, is not typable in Polymorphic Jam yet does not generate a run-time error. It is not typable because the body of the function (map x to x(x)) con- tains the self-application x(x) which is not typable. x(x) is not typable because x has a function type α → β with an input type α that equals the function type α → β. But these two type are not unifiable because α → β contains α. Circular bindings of type variables are not allowed in Polymorphic Jam. The program does not generate a run-time error because (map x to x(x)) (map x to x(x)) is not a value but directly (“in one step”) reduces to itself generating a divergent computation.
(ii) [5 points] Give a simple example of an untyped Jam expression that is not typable in Typed Jam, but is typable in Polymorphic Jam. Briefly but convincingly explain why.
The program let id = map x to x; in (id(id))(17) is typable in Poly- morphic Jam but not in Typed Jam because the id function is polymor- phic. It is used with two different typings in the body of the let. Tbe inner occurrence of id has type int → int while the outer occurrence has type (int → int) → (int → int).
(iii) [5 points] Assume that we extend Polymorphic Jam by dropping the “value restriction” on the right hand side of bindings in letpoly rule and add the block construct (definable as an expansion into map application) and the corresponding typing rule. Give a simple example of a program that is typable in extended Polymorphic Jam but generates a run-time type error (misinterpreting one type of data as another) when it is executed.
let fn := ref(map x to x); in { fn <- map x to x+1; (!fn)(true); } The preceding program uses fn polymorphically: once as type ref(int → int)), so the assigment to fn is type correct, and once as type ref(bool → bool, so the application of !fn to true is type correct. But the assign- ment places a function of type int → int in the cell fn, which fails when it is applied to true because !fn tries to add 1 to its argument x. There are no polymorphic values in Polymorphic Jam (or in ML/OCaml for that matter) only amibiguous ones (like null and map x to x) with types that are determined by context.
(ii) [15 points] Is the same program
let foldr := map f,e,l to if null?(l) then e else f(first(l), foldr(f, e, rest(l))); in foldr(cons, null, cons(foldr(map x,y to x+y, 0, cons(1,null)), null))
typable in Polymorphic Jam? Justify your answer in same way as in part (i).
Yes. The detailed proof derivation is elided, but the subproof generating a type for the right-hand-side of the foldr binding generates the type (α × β → β) × β × α − list → β where α and β are fresh type variables (not in Γ for the typing of the entire program). In the subproof assigning a type to the body of the let, foldr has the polymorphic type (a type scheme) ∀α, β[(α × β → β) × β × α − list → β] which enables foldr to have the two distinct typings described in the solution to part (i).
Problem 3. [25 points] Convert the following untyped Jam program to CPS. Use the identity func- tion as your top level continuation and do not CPS either nested lets or applica- tions of primitive operations (primitive functions or operators). Note that let is recursive.
let foldr := map f,e,l to if null?(l) then e else f(first(l), foldr(f, e, rest(l))); in foldr(map x,y to x+y, 0, cons(1,null))
Your CPS translation simply has to put all calls on program defined functions in tail position.
let foldrK := map fK,m,l,k to if null?(l) then k(e) else foldrK(f, e, rest(l), map v to fK(first(l), v, k)); in foldrK(map x,y,k to k(x+y), 0, cons(1,null), map v to v)