我尝试以下方法:
let c x = System.Numerics.Complex(x, 0.0)
let sum = [c 1.0; c 2.0] |> List.sum
但是我收到了这个错误:
The type 'System.Numerics.Complex' does not support the operator 'get_Zero'
我从https://msdn.microsoft.com/en-us/library/dd233211.aspx阅读了有关类型扩展的规则,并尝试执行以下操作:
module ComplexExtension =
let c x = System.Numerics.Complex(x, 0.0)
type System.Numerics.Complex with
// I also tried a bunch of other ways of writing these
// as static or instance members, but nothing worked
static member Zero = c 0.0
static member One = c 1.0
open ComplexExtension
let sum = [c 1.0; c 2.0] |> List.sum
我仍然遇到了这个错误。
是否可以使用get_Zero运算符扩展类型?或者我是否必须在System.Numerics.Complex
周围创建自己的包装器类型并覆盖所有操作符,如果我希望它执行复杂数字的其他操作?
答案 0 :(得分:4)
List.sum
使用静态成员约束。静态成员约束不会查看扩展方法,因此不是一个选项。
包装整个复杂类型是一个选项,但是它太过分了,如果它只是一个特定的调用,你可以用很多方法通过几次击键来计算总和,你可以使用fold
,如另一个所示回答。或者,如果您确定列表中始终至少包含一个元素,则可以使用List.reduce (+)
。
这可能可以在F#的未来版本中修复,但问题是静态成员约束不适用于字段,除非它们有getter。但是在F#lib中,他们可以“模拟”现有类型的成员they do it normally with primitive types,否则它不适用于int
,float
,因为他们也没有该成员。
我不确定在Complex
中定义System.Numerics
的事实是不是以这种方式实现它的原因,或者可能是他们忘了它。在任何情况下,您都可以打开问题或提交拉取请求以解决问题。
如果您仍希望以通用方式使用它,最后另一个选项是重新定义sum
函数。例如,来自最新source版本的sum
函数(这里是F#+)将正常工作(它有相同的问题,但很容易修复,实际上它是一个错误)几乎所有数字类型,包括Complex
和大多数第三方数字类型,因为它有一个回退机制,当该类型没有get_Zero
成员时,它依赖于某些转换。
答案 1 :(得分:1)
List.sum
无法识别定义为Zero
的扩展程序。它必须是该类型的一部分。
改为使用List.fold
:
let sum = [c 1.0; c 2.0] |> List.fold (+) Complex.Zero
BTW System.Numerics.Complex
实际上有静态Zero
,但它是一个字段,而不是属性。