Tutorial Week 6 (Solutions)
Task 1. Develop type-checking algorithms for the following language constructs, along the lines of the type-checking algorithm we developed in the lectures.
• Here is pseudo-code for typechecking P+Q: case class Plus ( lhs : Prog, rhs : Prog ) extends Prog
•
• def check ( env : SymbolTable, p : Prog ) : Type = {
• …
• case Plus ( l : Prog, r : Prog ) => {
• if ( check ( env, l ) != Int_T () || check ( env, r ) != Int_T () )
• throw new Exception ( “…” )
• else
• Int_T () } }
•
• while P do Q case class While ( cond : Prog, body : Prog ) extends Prog
•
• case While ( cond, body ) => {
• val t_cond = check ( env, cond )
• if ( t_cond != Bool_T ) throw new Exception ( “…” )
• val t_body = check ( env, body )
• if ( t_body != Unit_T ) throw new Exception ( “…” )
• Unit_T () }
•
• repeat P until Q case class RepeatUntil ( body : Prog, cond : Prog ) extends Prog
•
• case RepeatUntil ( body, cond ) => {
• val t_body = check ( env, body )
• if ( t_body != Unit_T ) throw new Exception ( “…” )
• val t_cond = check ( env, cond )
• if ( t_cond != Bool_T ) throw new Exception ( “…” )
• Unit_T () }
•
Task 2. Some languages have features like exceptions (which can be raised using a construct like throw), or Java’s System.exit ( … ) that immediately aborts the calling program. Discuss how to type-check such program constructs.
Answer: The trick is to realise that these constructs can have any type whatsoever as return type, since they never return. For example if e has type integer, then System.exit ( … ) has type t for any type t.
This is also true for throw, but we must have a type of exceptions in our sets of types. Then whatever is being thrown must have be an exception.
Task 3. Consider a function/procedure/method as follows:
def f( x : ??? ) : ??? = { return x }
Discuss what kind of types you would give to f.
Answer: There are many approaches to this problem. But all involve in some form or shap a new form of type called universal type. Some programming languages write it like this:
def [T] f( x : T ) : T = { return x }
This means: for any type T, the procedure f has type
def f( x : T ) : T = { return x }
For example f has type
def f( x : Int ) : Int = { return x }
and
def f( x : Bool ) : Bool = { return x }
A lot more could be said about this topic. If you are interested, please contact me, or read the excellent book Types and programming languages by B. Pierce — it’s in the library.