是否可以为F#元组创建扩展方法

时间:2013-02-24 05:24:45

标签: generics f# extension-methods tuples

我正在尝试为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#元组创建通用扩充?

2 个答案:

答案 0 :(得分:4)

您的问题的答案与我对类似问题here给出的答案几乎相同。也就是说,你的类型扩展不起作用的原因是因为“System.Tuple<_,...,_>只是元组的编码形式,而不是编译器使用的静态表示。请参阅规范中的6.3.2 Tuple Expressions。” / p>

要使用您的类型扩展名,您必须首先打包然后转换元组值:

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

答案 1 :(得分:0)

您可以使用C#样式扩展方法,但请注意您在ToParameter的定义中有错误,参数应该是curry:

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#语法元组它们被视为不同的类型。这可能会在将来的编译器版本中发生变化。