2012-08-06 40 views
15

在C#中,我可以爲T類型的通用陣列像這樣定義一個擴展方法:如何在F#中定義T []的類型擴展?

,但對我的生活我無法弄清楚如何做到在F#一樣!我試過type 'a array with,type array<'a> withtype 'a[] with,編譯器對其中的任何一個都不滿意。

任何人都可以告訴我什麼是在F#中這樣做的權利?

當然,我可以通過掩蓋Array模塊來做到這一點,並很容易地添加一個功能,但我真的想知道如何做到這一點,作爲擴展方法!

+0

什麼是「爲我的生活」意味着:)? – Omu 2012-08-06 21:35:21

+0

擴展'System.Array'是我的第一個想法,但需要一個類型參數和強制轉換,除非你可以使用'obj'。 – Daniel 2012-08-06 21:39:37

+1

@Chuck Norris - 意思是'我不能...甚至在我非常努力地嘗試' – theburningmonk 2012-08-06 21:42:54

回答

27

你必須使用「反引號標記」寫數組類型 - 這樣的:

type 'a ``[]`` with 
    member x.GetOrDefault(n) = 
    if x.Length > n then x.[n] 
    else Unchecked.defaultof<'a> 

let arr = [|1; 2; 3|] 
arr.GetOrDefault(1) //2 
arr.GetOrDefault(4) //0 

編輯:語法type ``[]``<'a> with ...似乎也被允許。在F#源文件(prim-types-prelude.fs)中,你可以找到如下定義:

type ``[]``<'T> = (# "!0[]" #) 
+0

+1好找!這是在規格/文檔? – Daniel 2012-08-07 16:47:17

+0

@Daniel:試驗。我試圖找到規範/文檔中的任何內容,但沒有成功。 – 2012-08-07 16:49:12

+0

對不起,我編輯了我的問題。謝謝。 – Daniel 2012-08-07 16:49:50

10

好問題。我無法弄清楚如何延長'T[]但你可以採取的事實,即陣列實現IList<_>做:

type System.Collections.Generic.IList<'T> with 
    member x.GetOrDefault(n) = 
    if x.Count > n then x.[n] 
    else Unchecked.defaultof<'T> 

let arr = [|1; 2; 3|] 
arr.GetOrDefault(1) //2 
arr.GetOrDefault(4) //0 
+1

我很確定F#中沒有合法的語法來向數組類型添加擴展成員,所以這可能是最好的選擇我不能想到任何缺點,除了這種方法也出現在任何其他IList類型中)。 – Brian 2012-08-06 21:36:47

+0

@丹尼爾 - 聖潔的廢話,你是對的! 'T []確實實施IList <'T>!我不知道!不知道這對我來說是否合理,但是一個數組需要連續的內存塊,對嗎?因此每次添加操作都必須重新分配給整個新陣列,這在我看來應該是你應該勸阻並鼓勵使用List (它有一個內部緩衝區來管理)的東西。 – theburningmonk 2012-08-06 21:40:11

+3

'IList <_>'的變異成員,'Add' /'Remove'等,拋出'NotSupportedException'。嘗試:'([| 1 |]:> System.Collections.Generic.IList <_>).Add(2)' – Daniel 2012-08-06 21:44:33