I'm reading Robert Harper's Programming in Standard ML (Version 1.2 of 11.02.11).
On solving the ambiguity of type inference. Robert Harper says that:
The important question is how much context is considered before the situation is considered ambiguous? The rule of thumb is that context is considered up to the nearest enclosing function declaration.
And because of that, the following code will be rejected:
let
val double = fn x => x + x
in
(double 3.0, double 4.0)
end
I think the reason for the rejection is that the compiler can't decide whether double is int->int or real->real. The code snippet doesn't provide enough context to resolve the ambiguity. And some compilers set it to int->int by default which makes the code snippet ill-typed.
My questions are:
What does "nearest enclosing function declaration" mean?
How to make the compiler infer the function double's type is real -> real by the "nearest enclosing function declaration" without specifying the type explicitly?
I think the reason for the rejection is that the compiler can't decide whether
doubleisint->intorreal->real. The code snippet doesn't provide enough context to resolve the ambiguity. And some compilers set it toint->intby default which makes the code snippet ill-typed.
This is mostly correct, except that the code snippet actually does provide enough context to resolve the ambiguity (at least to the point of ruling out int -> int); it's just that some compilers will only consider the smallest enclosing declaration (in this case val double = fn x => x + x), or even less, in deciding the type of +. That's actually what this passage is about — the compiler has to decide how much context to consider, and some compilers consider less than others.
That + defaults to int * int -> int, in the absence of sufficient context to resolve the ambiguity in a different way, is actually mandated by Appendix E of the Definition.
- What does "nearest enclosing function declaration" mean?
It means the smallest function declaration that contains the overloaded operator or constant. In this case the overloaded operator is +, and its nearest enclosing function declaration is val double = fn x => x + x.
- How to make the compiler infer the function
double's type isreal -> realby the "nearest enclosing function declaration" without specifying the type explicitly?
If you mean only that you don't want to have to specify the whole of real -> real, then you could write:
val double = fn x => x + (x : real)
If you mean that you don't want any explicit type annotation at all, then I think the only option is to write something a bit hackish, such as:
val double = fn x => x + x + 0.0
Or you could go with:
val double = fn x => 2.0 * x
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With