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

vla*_*lad 1 generics f#

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

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

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

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

我确定这只是一个语法问题,有人能指出我在正确的地方吗?

ps:有没有不同/更简单的方法来做到这一点,或者这是使它工作的正确方法?

Dan*_*iel 6

标记功能inline.然后推断出约束.

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

您的功能也可以这样写:

let inline add a b = Array.map2 (+) a b
Run Code Online (Sandbox Code Playgroud)

编辑

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

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])))
Run Code Online (Sandbox Code Playgroud)

但它会生成警告:

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

  • 是.显式成员约束需要`inline`. (2认同)