2013-02-15 23 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