我正在尝试为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#元组创建通用扩充?
答案 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#语法元组它们被视为不同的类型。这可能会在将来的编译器版本中发生变化。