In this assignment you will implement Hindley-Milner type inference, which represents the current ``best practice'' for flexible static typing. The assignment has two purposes:
U. Test cases for unification. [6 points]
Submit three test cases for unification. At least two of these test
cases should be for types that have no unifier.
Assuming that we provide a function
unifyTest : ty * ty -> answer,
put your test cases in file utest.sml as three successive
calls to unifyTest.
Do not define unifyTest yourself.
Here is a sample utest.sml file:
val _ = unifyTest (TYVAR "a", TYVAR "b") val _ = unifyTest (CONAPP (TYCON "list", [TYVAR "a"]), TYCON "int") val _ = unifyTest (TYCON "bool", TYCON "int")Naturally, you will supply your own test cases.
T. Test cases for type inference. [6 points]
Submit three test cases for type inference. At least two of these test
cases should be for terms that fail to type check.
Each test case should be a top-level item for uML.
Put your test cases in a file ttest.uml.
Here is a sample ttest.uml file:
(val weird (lambda (x y z) (cons x y z))) (+ 1 #t) (lambda (x) (cons x x))Naturally, you will supply your own test cases.
For the remaining problems, here is a point breakdown with some additional remarks and suggestions.
Hints: Read the Unification section on pages 268–269.
Be careful when you unify a list that you use all the
information you compute, and that you use it as soon as possible.
You'll be passing subsitutions like mad.
It may be easiest to unify the tails first, then the heads.
For ideas, you might want to look at the typesof
function in Ramsey and Kamin.
This is one assignment where it pays to run a lot of tests, of both good and bad definitions. The most effective test of your algorithm is not that it properly assign types to correct terms, but that it reject ill-typed terms. This assignment is your best chance to earn the large bonuses available by finding bugs in the instructor's code. I have posted a functional topological sort that makes an interesting test case.
Incidentally, if you call your interpreter ml.sml, you can build a standalone version in a.out by running mosmlc ml.sml or a faster version in ml by running mlton-compiler ml.sml.
Type soundness (very difficult). Available only to students who have not taken CS 256:
Prove that the uML interpreter never raises BugInTypeInference
.
That is, prove that well-typed uML programs don't go wrong.
I'll accept such a proof at any time during the term, not just in time
for this homework.
Doing this extra credit correctly will almost certainly make a
difference to your final course grade (unless you're already on track
for an A).
The real test of your interpreter is that it should reject incorrect definitions. You should prepare a dozen or so top-level items that should not type check, and make sure they don't. For example:
(val bad (lambda (x) (cons x x))) (val bad (lambda (x) (cdr (pair x x))))Pick your toughest three test cases to submit for problem T.
Your solutions are going to be evaluated automatically. We must be able to compile your solution in Moscow ML by typing, e.g.,
mosmlc ml.sml
If there are errors in this step, we will not grade your solution.
Also, if you have defined any new exceptions, make sure they are
handled. It's not acceptable for your interpreter to crash with an
unhandled exception just because some code didn't type-check.