简体   繁体   English

在Math.Max上进行F#类型推断

[英]F# Type inference on Math.Max

Why won't the compiler pick the correct version of an overloaded method if it has inferred the types of the input parameters. 如果编译器已经推断出输入参数的类型,为什么不选择正确版本的重载方法。

In this example why can't it pick the correct Math.Max to use when the type has correctly inferred on the elements being compared: 在此示例中,当类型已正确推断出要比较的元素时,为什么不能选择要使用的正确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    

Of course you can just use the max function in this case, but there are plenty of other methods that don't have a native equivalent. 当然,在这种情况下,您可以只使用max函数,但是还有许多其他方法没有本机等效方法。

As @Gos correctly points out, using the pipeline operator helps in this case. 正如@Gos正确指出的那样,在这种情况下,使用管道运算符会有所帮助。 The reason is that the type inference works from left to right - so, if you use the pipeline operator, it knows that one of the inputs is a list of integers and, based on that, it picks the right overload of Math.Max . 原因是类型推断从左到右起作用-因此,如果使用管道运算符,它将知道输入之一是一个整数列表,并在此基础上选择Math.Max的正确重载。

The compiler generally needs to know the type when it does overload resolution or when you want to invoke a member on a object (eg if you wanted to do l.Foo() inside the map function) - because in this case, it needs to know what exactly the type is. 编译器执行重载解析或要在对象上调用成员时(例如,如果要在map函数中执行l.Foo()通常需要知道类型-因为在这种情况下,它需要知道确切的类型是什么。

F# also defines its own versions of basic math functions which work better with type inference. F#还定义了自己的基本数学函数版本,可以更好地进行类型推断。 So you can replace Math.Max with the max functions (which you can also nicely pass directly to map2 ): 因此,您可以用max函数替换Math.Max (也可以将其直接传递给map2 ):

List.map2 max [2;4] [5;3] 

This works better, because F# does not need to perform overload resolution (the function is not overloaded). 这样效果更好,因为F#不需要执行重载解析(该函数不会重载)。 It just keeps track of a special generic constraint that is satisfied and resolved later. 它只是跟踪一个特殊的通用约束 ,该约束在以后得到满足和解决。

I can't tell you why but I found that the pipeline operator often helps type inference: 我无法告诉您原因,但是我发现管道运算符通常有助于键入推断:

let listMax = 
    [5;3] |> List.map2 (fun l r -> Math.Max(l,r)) [2;4]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM