F# - 如何扩展型与get_Zero这样我就可以使用现有的类型一般?我就、可以使用、类型、get_Zero

2023-09-04 12:54:12 作者:梨涡少年

我尝试了以下内容:

let c x = System.Numerics.Complex(x, 0.0)
let sum = [c 1.0; c 2.0] |> List.sum

不过,我得到这个错误:

But I get this error:

不支持运营商的get_Zero'类型'System.Numerics.Complex

我读类型扩展名的规则,从 https://msdn.microsoft .COM / EN-US /库/ dd233211.aspx ,并尽量做到以下几点:

I read the rules on type extensions, from https://msdn.microsoft.com/en-us/library/dd233211.aspx, and try to do the following:

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

我仍然得到这个错误。

I still get that error.

是否有可能扩展型与get_Zero运营商?还是我必须创建自己的包装类型各地 System.Numerics.Complex 并覆盖所有的运营商,如果我想要它做其他的事情,复数呢?

Is it possible to extend a type with the get_Zero operator? Or do I have to create my own wrapper type around System.Numerics.Complex and override all the operators if I want it to do the other things that complex numbers do?

推荐答案

List.sum 使用静态成员的约束。静态成员约束并不考虑扩展方法,所以这不是一个选项。

List.sum uses static member constraints. Static member constraints don't look into extensions methods so that's not an option.

结束语整个复杂类型是一种选择,但它是矫枉过正,如果它仅仅是一个特定的电话,你有很多方法来计算的总和多带几个按键,你可以使用作为显示在对方的回答。或者您可以使用 List.reduce(+)如果您确信名单将始终至少有一个元素。

Wrapping the whole complex type is an option but it's overkill, if it is just a specific call you have many ways to compute the sum with a few more keystrokes, you can use a fold as shown on the other answer. Alternatively you can use List.reduce (+) if you are sure that the list will always have at least one element.

这也许可以得到固定在F#的未来版本,但问题是,静态成员的约束不下地干活了,除非他们有一个getter。然而,在F#的lib他们可以模仿的成员为现有类型,的他们这样做通常与原始类型的,否则不会与 INT ,浮动,因为他们没有那个名成员。

This might be possible to get fixed in a future version of F# but the problem is that static member constraints don't work with fields, unless they have a getter. However in the F# lib they can "emulate" those members for existing types, they do it normally with primitive types otherwise it wouldn't work with int, float, since they don't have that member either.

我不知道一个事实,即复合 System.Numerics 定义不给理由实现这种方式,也可能是他们只是忘了。在任何情况下,你可以打开一个问题或提交给把它固定拉请求。

I'm not sure if the fact that Complex is defined in System.Numerics was the reason not to implement it this way, or may be they just forgot it. In any case you can open an issue or submit a pull request to get it fixed.

最后,如果你仍然想使用它在一个通用的方式另一种选择是重新定义功能。例如在函数(这里的的来源)从最新的 F#+ 版本将正常工作(它有同​​样的问题,但很容易解决,其实这是一个错误),与几乎所有的数字类型,包括复合和大多数第三方党的数字类型,因为它依赖于一些转换时的类型不具有 get_Zero 构件的应变机制。

Finally another option if you still want to use it in a generic way is to redefine the sum function. For instance the sum function (here's the source) from the latest F#+ version will work fine (it had the same problem but was very easy to fix, actually it was a bug) with practically all numeric types, including Complex and most third party numeric types because it has a fallback mechanism which relies in some conversions when the type doesn't have a get_Zero member.