【发布时间】:2011-01-14 14:52:28
【问题描述】:
F# 是否存在与 C# 相同的问题,即不能直接将算术运算符用于泛型 T 类型?
你能写一个通用的 Sum 函数来返回任何支持算术加法的值的总和吗?
【问题讨论】:
F# 是否存在与 C# 相同的问题,即不能直接将算术运算符用于泛型 T 类型?
你能写一个通用的 Sum 函数来返回任何支持算术加法的值的总和吗?
【问题讨论】:
正如 brian 所提到的,有一些对泛型算术的内置支持,您可以使用“静态约束”来自己定义一些泛型函数(尽管这有点受限)。
除此之外,您还可以使用动态“数字关联”,在函数中使用时会有点慢,但它可以很好地用于定义自己的向量或矩阵类型。这是一个例子:
#r "FSharp.PowerPack.dll"
open Microsoft.FSharp.Math
let twoTimesLarger (n:'a) (m:'a) =
let ops = GlobalAssociations.GetNumericAssociation<'a>()
let sel = if ops.Compare(n, m) > 0 then n else m
ops.Multiply(sel, ops.Add(ops.One, ops.One))
我们首先需要引用包含该功能的 F# PowerPack 库。然后我们定义一个带有签名'a -> 'a -> 'a 的泛型函数。第一行动态获取使用类型'a 的数字操作(它本质上使用一些以类型为键的查找表)。然后,您可以使用数值运算对象的方法来执行乘法、加法(Multiply、Add)和许多其他操作。该函数适用于任何数字:
twoTimesLarger 3 4
twoTimesLarger 2.3 2.4
twoTimesLarger "a" "b" // Throws an exception!
当您定义自己的数值类型时,您可以定义其数值运算并使用GlobalAssociations.RegisterNumericAssociation 注册它们。相信这也意味着注册操作后你就可以使用内置的F#Matrix<YourType>和Vector<YourType>了。
【讨论】:
F# 对此有一些有限的支持。一个好的通用解决方案可能涉及类型类,CLR 通常不支持,特别是 F#。
F# 使用“静态成员约束”和“内联”函数重载算术运算符。这是使例如+ 操作符在 ints 和 floats 上工作。您可以编写 inline 函数,其实现基于内置的数学运算符并取得一些进展,但一般来说这并非易事。您可以查看例如F# 源代码分发中Array.sum(在 FSharp.Core 中的 array.fs 中)的源代码,与 CTP 一起来感受一下。
另请参阅此答案的“静态成员约束”和“模拟类型类”部分:
Functions with generic parameter types
以及图书馆的各个部分,如
http://msdn.microsoft.com/en-us/library/ee370581(VS.100).aspx
http://msdn.microsoft.com/en-us/library/ee340262(VS.100).aspx
【讨论】:
你可以这样做。
let inline sum<'a when 'a : (static member (+) : 'a -> 'a -> 'a)> a b =
a + b
let result = sum<int> 3 4
但是,如果我尝试let result = sum 3 4,则会收到错误"type ambiguity inherent in the use of the operator '( + )'"
【讨论】:
^a 而不是 'a,但我可能错了...
let inline sum a b = a + b
我所知道的用于执行泛型算术的最佳机制是类型类,遗憾的是 C#、F# 和 .Net 运行时均不支持它。但是,您可以手动模拟它们,如本博文所述:
Type Classes Are The Secret Sauce
该技术应该适用于 C# 2.0 或更高版本(使用匿名委托/lambda)。
人们经常转向界面,但会遇到一些问题
接口声明,对于所有实现,该接口上的所有方法都采用相同的隐式“this”参数类型。如果 Foo 实现了某个接口,那么显然 'this' 参数必须是该实现的 Foo 类型。但是没有办法要求其他方法参数也是Foo类型。
Type classes 允许您(除其他外)对所有方法参数执行这种约束,而不仅仅是第一个参数。
如前面引用的文章中所述,您可以通过将函数表作为显式参数传递来模拟类型类。
(社区 wiki:将在此处发布该文章中翻译成 C# 的示例,但由于冗长的解释而没有时间)
【讨论】: