2013-02-15 62 views
1

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

回答

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

+0

太棒了!任何想法为什么编译器不满意我的版本? – vlad 2013-02-15 20:58:46

+2

是的。显式成员约束需要'inline'。 – Daniel 2013-02-15 20:59:45

+0

无论我是否声明函数“inline”,我都会得到相同的错误 – vlad 2013-02-15 21:00:31