【问题标题】:Sum of generic arrays missing type constraint缺少类型约束的泛型数组的总和
【发布时间】:2013-02-15 20:54:27
【问题描述】:

我正在尝试编写一个简单的数组添加函数。唯一的复杂性来自我试图使其通用的尝试。我知道在 C# 中值类型没有类型约束,但我的理解是 F# 可以使它与 explicit member constraint 一起工作。这是我的尝试:

let Add<'T when 'T : (member (+) : 'T -> 'T -> 'T)> (A : 'T[]) (B : 'T[]) =
    Array.init A.Length (fun i -> A.[i] + B.[i])

编译器列出了三个错误:一个在 A.[i] 上,一个在 + 号上,一个在 B.[i] 上,但我猜它们都是一样的:

A type parameter is missing a constraint 
'when  ^T : (static member ( + ) :  ^T *  ^T ->  ^?6069)'

我确定这只是语法问题,谁能指出我正确的地方?

p.s.:有没有不同的/更简单的方法可以做到这一点,或者这是让它工作的正确方法?

【问题讨论】:

    标签: generics f#


    【解决方案1】:

    标记函数inline。然后将推断约束。

    let inline Add (A : 'T[]) (B : 'T[]) =
      Array.init A.Length (fun i -> A.[i] + B.[i])
    

    你的函数也可以这样写:

    let inline add a b = Array.map2 (+) a b
    

    编辑

    要明确约束,您可以这样做(看起来很糟糕)

    let inline Add< ^T when ^T : (static member (+) : ^T * ^T -> ^T) > (A : ^T[]) (B : ^T[]) =
        Array.init A.Length (fun i -> (^T : (static member (+) : ^T * ^T -> ^T) (A.[i], B.[i])))
    

    但它会产生警告:

    名称为“op_Addition”的成员约束由 F# 编译器赋予特殊状态,因为某些 .NET 类型隐式地使用此成员进行扩充。如果您尝试从自己的代码中调用成员约束,这可能会导致运行时失败。

    【讨论】:

    • 太棒了!知道为什么编译器对我的版本不满意吗?
    • 是的。显式成员约束需要inline
    • 无论我是否声明函数inline,我都会遇到同样的错误
    • 你的语法有点不对劲。但是,(+) 上的约束对编译器具有特殊意义并会生成警告。
    • 糟糕是轻描淡写。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 1970-01-01
    • 2020-05-30
    • 1970-01-01
    • 2022-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多