问题
I made function that's name is maptree
. And below is my code:
datatype 'a tree = LEAF of 'a | NODE of 'a tree * 'a tree;
fun maptree(f, NODE(X, Y)) = NODE(maptree(f, X), maptree(f, Y))
| maptree(f, LEAF(X)) = LEAF(f X);
I expected maptree to have the type
('a -> 'a) -> 'a tree -> 'a tree
but the type inferred by the compiler is
('a -> 'b) * 'a tree -> 'b tree
Why is this happening?
回答1:
The Hindley-Milner type-inference algorithm allows you to get more general type than you expected.
When the algorithm tries to infer the type for maptree
, it assumes that f: 'a -> 'b
(from the fact you're using f
as a function). And nothing restricts the type of f
further.
If you, for example, defined the maptree
function as follows (I used f
twice in the LEAF
case):
fun maptree(f, NODE(X, Y)) = NODE(maptree(f, X), maptree(f, Y))
| maptree(f, LEAF(X)) = LEAF(f (f X))
Then the type-inference mechanism would have to restrict the type of f
to 'a -> 'a
(since we feed the output of the function to its input).
The output of SML/NJ for the modified case:
val maptree = fn : ('a -> 'a) * 'a tree -> 'a tree
来源:https://stackoverflow.com/questions/36998218/why-is-the-type-inferred-for-my-ml-function-different-than-i-expect