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.
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.
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 definition written in 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 are some additional remarks and suggestions.
Hints: Read the Unification section on pages 272–273.
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 on page 276 of 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 -output ml ml.sml.
Type soundness (very difficult).
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 definitions 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.
NIL
and one case
for PAIR
.
There are also some common assumptions which are mistaken:
begin
is never empty.
For your work with a partner, run submit105-ml-inf-pair to submit these files:
In the README, please tell us what parts of the assignment you have completed, including any extra-credit parts. If you want to show us additional evidence that your code works, put it in file transcript.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.