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

Generics 是否可以为F#元组创建扩展方法,generics,f#,extension-methods,tuples,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) 我收到一个错误,提示“未定义此字段、构造函数或成员'TopParameter'。在解释器中,以下表达式

我正在尝试为F#元组创建一个类型扩充方法。这段代码编译得很好:

type System.Tuple<'a, 'b> with
    member this.ToParameter name =
        match this with
        | this -> sprintf "%s=%O,%O" name (this.Item1, this.Item2)
我收到一个错误,提示“未定义此字段、构造函数或成员'TopParameter'。在解释器中,以下表达式将其类型报告为某种形式的System.Tuple'2:

typedefof<'a * 'b>.FullName
(1, 2).GetType().FullName
它报告一个int*int类型。当我尝试扩充这个类型,或者它的泛型等价物“a*”b时,我会得到一个错误


有没有可能为F#元组创建一个通用增广

您的问题的答案将与我对类似问题的答案几乎相同。也就是说,类型扩展不起作用的原因是“
System.Tuple
只是元组的编码形式,而不是编译器使用的静态表示形式。请参见规范中的。”

要使用类型扩展,您必须先选择框,然后强制转换元组值:

let tuple = box ("cat", 2) :?> System.Tuple<string,int>
printfn "%s" (tuple.ToParameter("test"))
let tuple=box(“cat”,2):?>System.tuple
printfn“%s”(元组TopParameter(“测试”))
旁白:还要注意,您的类型扩展中有一个轻微的语法错误,应该是:

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
使用
成员名称:this.ToParameter name=
与此匹配
|此->sprintf“%s=%O,%O”将this.Item1命名为this.Item2//删除了Item1和Item2周围的参数
您可以使用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"))
open System.Runtime.CompilerServices
[]
类型TupleExtensions()=
[]静态成员ToParameter((a,b),name)=sprintf“%s=%O,%O”name a b
printfn“%s”(“cat”,2).t参数(“测试”))

之所以使用
System.Tuple
不起作用,是因为在编译时.NET元组和F#语法元组被视为不同的类型。这可能会在未来版本的编译器中发生变化。

将其作为扩展方法(而不是函数)有什么特殊原因吗?我希望能够在各种类型上调用TopParameter。我有一个用于IEnumerablew的扩展,为什么不只是用重载方法创建一个类型,那么您只需要使用
utils.ToParameter(t)
而不是
t.ToParameter()
,这看起来还可以
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
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"))