我仍在努力探索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

在这里,min具有通用类型'a * 'a -> 'a (requires comparison),而add具有具体类型int * int -> int,显然是从其在程序中的首次使用推断出来的。两者都以相同的方式声明和使用,那么为什么泛化有所不同?

我知道在add的情况下,可以通过声明内联函数来避免问题,这使它获得了通用类型定义,即'a * 'b -> 'c (requires member (+)),但这并不能解释为什么在这种情况下需要这样做,而不是另一个。

最佳答案

@TomasP在这里就此问题撰写了出色的文章:http://tomasp.net/blog/fsharp-generic-numeric.aspx



但是,为什么<>(以及扩展名=<=>=)可以吗?

F#编译器对equalitycomparison的处理方式有所不同(请参阅specs中的5.2.10相等性和比较约束,感谢@Daniel)。您将获得特殊 comparison约束,该约束在以下情况下才允许使用(请参见规范以获取更多详细信息):


+运算符没有这种特殊处理。为什么没有numeric这样的约束?

难道不是也为字符串定义了该运算符吗?在某些语言中用于列表和集合?当然,这将是addable约束,而不是numeric。然后,可以在具有不同语义含义的程序中找到许多这样的重载运算符。因此,F#提供了具有静态成员约束和inline关键字的“包罗万象”方法。仅equalitycomparison是特殊的。

10-06 05:13