3

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

4

2 回答 2

4

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

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

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
于 2013-02-25T03:54:28.777 回答
0

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

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"))

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

于 2017-12-10T08:36:19.090 回答