1

我正在尝试编写一个简单的数组添加函数。唯一的复杂性来自我试图使其通用的尝试。我知道在 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])

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

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

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

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

4

1 回答 1

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

于 2013-02-15T20:56:20.927 回答