F#中的通用函数

Asi*_*sik 9 generics f# automatic-generalization

我仍然试图围绕F#如何概括(或不是)函数和类型,并且有一个案例让我烦恼:

let min(a, b) = if a < b then a else b

let add(a, b) = a + b

let minInt = min(3, 4)
let minFloat = min(3.0, 4.0) // works!

let addInt = add(3, 5)
let addFloat = add(3.0, 5.0) // error: This expression was expected to have type
                             // int but here has type float
Run Code Online (Sandbox Code Playgroud)

这里min具有泛型类型,'a * 'a -> 'a (requires comparison)而add具有一种具体类型int * int -> int,显然是从它在程序中的第一次使用推断出来的.两者都以相同的方式声明和使用,那为什么泛化的区别呢?

我理解在add的情况下,问题可以通过声明函数内联来进行,因为它会导致它获得泛型类型定义,即'a * 'b -> 'c (requires member (+)),但这并不能解释为什么在这种情况下需要它而不是其他.

yam*_*men 7

@TomasP在这个问题上有一篇很好的文章:http://tomasp.net/blog/fsharp-generic-numeric.aspx

在编写具有某个类型参数'T的简单通用代码时,我们对类型参数一无所知,并且无法将其限制为提供我们可能需要在代码中使用的所有运算符的数字类型.这是.NET运行时的限制,F#提供了两种克服它的方法.

但是为什么<>(和扩展=,<=>=)好吗?

在F#编译器将equalitycomparison不同(见第5.2.10平等和比较约束的规范,感谢@Daniel).您获得了特殊 comparison约束,这是允许的(简单地,请参阅规范以获取更多详细信息):

如果类型是命名类型,那么类型定义没有,也没有推断出具有NoComparison属性,并且类型定义实现System.IComparable或者是数组类型或者是System.IntPtr或者是System.UIntPtr .

+操作员没有这种特殊处理.为什么不能有这样的约束numeric

那不是那个也为字符串定义的运算符吗?在某些语言中列表和集合?当然这将是一个addable约束,而不是numeric.然后可以在具有不同语义含义的程序中找到许多这样的重载运算符.所以F#提供了一个带有静态成员约束和inline关键字的'catch-all'方法.只有equality而且comparison很特别.

  • @yamen:`comparison`约束不会在C#中产生类似`where T:IComparable`的东西.它仅在编译时存在,并且限制较少.请参阅[规范的相关部分](http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc321997037). (2认同)