繁体   English   中英

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使用静态成员约束。 静态成员约束不会查看扩展方法,因此不是一个选项。

包装整个复杂类型是一个选项,但它太过分了,如果它只是一个特定的调用,你有很多方法用几个键击计算总和,你可以使用fold ,如另一个答案所示。 或者,如果您确定列表始终至少包含一个元素,则可以使用List.reduce (+)

这可能可以在F#的未来版本中修复,但问题是静态成员约束不适用于字段,除非它们具有getter。 但是在F#lib中,它们可以“模拟”现有类型的那些成员, 它们通常使用原始类型,否则它不适用于intfloat ,因为它们也没有该成员。

我不确定Complex是否在System.Numerics中定义的事实是不以这种方式实现它的原因,或者可能是他们只是忘了它。 在任何情况下,您都可以打开问题或提交拉取请求以解决问题。

最后,如果您仍希望以通用方式使用它,则另一个选项是重新定义sum函数。 例如,来自最新的F#+版本的sum函数(这里是源代码 )可以正常工作(它有相同的问题,但很容易修复,实际上它是一个bug)几乎所有的数字类型,包括Complex和大多数派对数字类型,因为它具有后备机制,当该类型没有get_Zero成员时,它依赖于某些转换。

List.sum无法识别定义为扩展名的Zero 它必须是该类型的一部分。

请改用List.fold

let sum = [c 1.0; c 2.0] |> List.fold (+) Complex.Zero

BTW System.Numerics.Complex实际上有一个静态Zero ,但它是一个字段,而不是一个属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM