我正在尝试编写一个简单的数组添加函数。唯一的复杂性来自于我试图使其成为通用的。我知道在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:是否有不同/更简单的方法来做到这一点,或者这是使它运作的正确方法?
答案 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类型是使用此成员隐式扩充的。如果您尝试从自己的代码中调用成员约束,这可能会导致运行时失败。