如果编译器推断出输入参数的类型,为什么编译器不会选择正确版本的重载方法.
在这个例子中,为什么当类型在被比较的元素上正确推断时,它不能选择正确的Math.Max:
let listMax =
List.map2 (fun l r -> Math.Max(l,r)) [2;4] [5;3] //compile error
let listMax2 =
List.map2 (fun (l:int) r -> Math.Max(l,r)) [2;4] [5;3] //no compile error
Run Code Online (Sandbox Code Playgroud)
当然,在这种情况下你可以使用max函数,但是还有很多其他方法没有本机等价.
正如@Gos正确指出的那样,在这种情况下使用管道运算符会有所帮助.原因是类型推断从左到右工作 - 因此,如果你使用管道运算符,它知道其中一个输入是一个整数列表,并且基于此,它选择正确的重载Math.Max.
编译器通常需要在重载解析时或者想要调用对象上的成员时知道类型(例如,如果你想l.Foo()在map函数中做) - 因为在这种情况下,它需要知道究竟是什么类型是.
F#还定义了自己的基本数学函数版本,它们更适合于类型推断.所以你可以Math.Max用max函数替换(你也可以很好地直接传递给它map2):
List.map2 max [2;4] [5;3]
Run Code Online (Sandbox Code Playgroud)
这样做效果更好,因为F#不需要执行重载解析(函数不会重载).它只是跟踪一个满足并在以后解决的特殊通用约束.