缺少类型约束的泛型数组的总和

时间:2013-02-15 20:54:28

标签: generics f#

我正在尝试编写一个简单的数组添加函数。唯一的复杂性来自于我试图使其成为通用的。我知道在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:是否有不同/更简单的方法来做到这一点,或者这是使它运作的正确方法?

1 个答案:

答案 0 :(得分:6)

标记函数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类型是使用此成员隐式扩充的。如果您尝试从自己的代码中调用成员约束,这可能会导致运行时失败。