2013-02-24 56 views
3

我正在嘗試爲F#元組創建一個類型擴充方法。此代碼編譯就好:是否有可能爲F#元組創建擴展方法

type System.Tuple<'a, 'b> with 
    member this.ToParameter name = 
     match this with 
     | this -> sprintf "%s=%O,%O" name (this.Item1, this.Item2) 

然而,當我嘗試調用這個方法:

printfn "%s" (("cat", 2).ToParameter("test")) 

我得到一個錯誤說「該字段,構造函數或成員‘ToParameter’沒有定義」。在解釋,下列詞語報告其類型爲某種形式的System.Tuple'2的:

typedefof<'a * 'b>.FullName 
(1, 2).GetType().FullName 

在Visual Studio中,如果我將鼠標懸停在表達:

let a = 1, 2 

它報告int * int類型。當我嘗試增加這種類型或者它的通用等價物時,'a *'b,我得到一個錯誤。

是否有可能爲F#元組創建通用擴充?

+1

使此擴展方法(而不是函數)的任何特定原因? – pblasucci 2013-02-24 11:55:12

+0

我想能夠在可能的類型上調用ToParameter。我有擴充工作IEnumerable <'a>,字符串和其他。要創建一個可以處理所有這些類型的函數,我將不得不求助於拳擊和反射。我可以爲每種類型創建一個不同的方法,但是這會使API不易讀。 – 2013-02-24 19:04:30

+1

爲什麼不只是用重載的方法創建一個類型 - 那麼你只需要'utils.ToParameter(t)'而不是't.ToParameter()'這看起來沒問題 – 2013-02-24 21:04:01

回答

4

您的問題的答案將幾乎與我給類似問題here的答案相同。也就是說,類型擴展名不起作用的原因是因爲「System.Tuple<_,...,_>只是元組的編碼形式,而不是編譯器使用的靜態表示法,請參閱規範中的6.3.2 Tuple Expressions

要使用你的類型的擴展名,你就必須先框,然後投你的元組值:

let tuple = box ("cat", 2) :?> System.Tuple<string,int> 
printfn "%s" (tuple.ToParameter("test")) 

旁白:也請注意,你必須在你的類型的擴展名有輕微語法錯誤,應該是:

type System.Tuple<'a, 'b> with 
    member this.ToParameter name = 
     match this with 
     | this -> sprintf "%s=%O,%O" name this.Item1 this.Item2 //removed parens around Item1 and Item2 
0

您可以使用C#風格的擴展方法,但要注意你在你的ToParameter定義錯誤,論據要令行禁止:

open System.Runtime.CompilerServices 

[<Extension>] 
type TupleExtensions() = 
    [<Extension>] static member ToParameter((a, b), name) = sprintf "%s=%O,%O" name a b 

printfn "%s" (("cat", 2).ToParameter("test")) 

使用System.Tuple不起作用的原因是因爲在編譯時.NET元組和F#語法元組被視爲不同的類型。這可能會在編譯器的未來版本中發生變化。

相關問題