F# - 如何使用 get_Zero 扩展类型以便我可以通用地使用现有类型?
F# - How do I extend a type with get_Zero so I can use an existing type generically?
我尝试以下操作:
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
创建自己的包装器类型并覆盖所有运算符(如果我希望它执行复数执行的其他操作)?
List.sum
无法识别定义为扩展名的 Zero
。它必须是类型的一部分。
改用List.fold
:
let sum = [c 1.0; c 2.0] |> List.fold (+) Complex.Zero
顺便说一句 System.Numerics.Complex
实际上有一个静态 Zero
,但它是一个字段,而不是 属性。
List.sum
使用静态成员约束。静态成员约束不考虑扩展方法,因此这不是一个选项。
包装整个复杂类型是一个选项,但它太过分了,如果它只是一个特定的调用,你有很多方法可以通过更多的击键来计算总和,你可以使用 fold
,如上所示另一个答案。或者,如果您确定列表将始终包含至少一个元素,则可以使用 List.reduce (+)
。
这可能会在 F# 的未来版本中得到修复,但问题是静态成员约束不适用于字段,除非它们具有 getter。但是在 F# lib 中,他们可以 "emulate" 那些现有类型的成员,they do it normally with primitive types 否则它不会与 int
、float
一起工作,因为他们没有那个成员要么。
我不确定 Complex
是在 System.Numerics
中定义的事实是否是不以这种方式实现它的原因,或者他们可能只是忘记了它。在任何情况下,您都可以打开一个问题或提交一个拉取请求来修复它。
最后,如果您仍想以通用方式使用它,另一种选择是重新定义 sum
函数。例如 sum
函数(这里的 source) from the latest F#+ 版本可以正常工作(它有同样的问题但很容易修复,实际上它是一个错误)几乎所有数字类型,包括 Complex
和大多数第三方数字类型,因为它有一个回退机制,当类型没有 get_Zero
成员时依赖于某些转换。
我尝试以下操作:
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
创建自己的包装器类型并覆盖所有运算符(如果我希望它执行复数执行的其他操作)?
List.sum
无法识别定义为扩展名的 Zero
。它必须是类型的一部分。
改用List.fold
:
let sum = [c 1.0; c 2.0] |> List.fold (+) Complex.Zero
顺便说一句 System.Numerics.Complex
实际上有一个静态 Zero
,但它是一个字段,而不是 属性。
List.sum
使用静态成员约束。静态成员约束不考虑扩展方法,因此这不是一个选项。
包装整个复杂类型是一个选项,但它太过分了,如果它只是一个特定的调用,你有很多方法可以通过更多的击键来计算总和,你可以使用 fold
,如上所示另一个答案。或者,如果您确定列表将始终包含至少一个元素,则可以使用 List.reduce (+)
。
这可能会在 F# 的未来版本中得到修复,但问题是静态成员约束不适用于字段,除非它们具有 getter。但是在 F# lib 中,他们可以 "emulate" 那些现有类型的成员,they do it normally with primitive types 否则它不会与 int
、float
一起工作,因为他们没有那个成员要么。
我不确定 Complex
是在 System.Numerics
中定义的事实是否是不以这种方式实现它的原因,或者他们可能只是忘记了它。在任何情况下,您都可以打开一个问题或提交一个拉取请求来修复它。
最后,如果您仍想以通用方式使用它,另一种选择是重新定义 sum
函数。例如 sum
函数(这里的 source) from the latest F#+ 版本可以正常工作(它有同样的问题但很容易修复,实际上它是一个错误)几乎所有数字类型,包括 Complex
和大多数第三方数字类型,因为它有一个回退机制,当类型没有 get_Zero
成员时依赖于某些转换。