generics - F#中的泛型函数

标签 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

在这里,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

When writing simple generic code that has some type parameter 'T, we don’t know anything about the type parameter and there is no way to restrict it to a numeric type that provides all the operators that we may need to use in our code. This is a limitation of the .NET runtime and F# provides two ways for overcoming it.



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

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

If the type is a named type, then the type definition does not have, and is not inferred to have, the NoComparison attribute, and the type definition implements System.IComparable or is an array type or is System.IntPtr or is System.UIntPtr.


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

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

关于generics - F#中的泛型函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10589729/

相关文章:

templates - websharper - 使用具有两种方式绑定(bind)的 html 模板

f# - f# 中的缩进错误?

f# - 如何在一个简单的函数中实现自动泛化

generics - 从具有 null 的静态函数返回 Template<T?> 时如何获取正确的类型

java - 迁移 Java 类以使用泛型

c# - 为什么我不能将对象转换为受约束的泛型?

java - 为什么这个赋值在 Java 泛型中是非法的?

wpf - 使用 Gjallarhorn 处理多个命令(来自按钮)的正确方法