F#元组的扩展方法
可以为F#元组编写扩展方法吗?例如,要添加实例方法.Item1和.Item2(如System.Tuple),它们相当于调用fst和snd来表示2元组?内部表示F#中(2元素)元组的F#元组的扩展方法,f#,F#,可以为F#元组编写扩展方法吗?例如,要添加实例方法.Item1和.Item2(如System.Tuple),它们相当于调用fst和snd来表示2元组?内部表示F#中(2元素)元组的System.Tuple类型实际上已经具有属性Item1和Item2,但这些属性被F#编译器隐藏。一个显而易见的向元组添加扩展成员的方法并不能奏效,所以我不希望这样做(但可能有一些我不知道的解决方法) 通常,我认为模式匹配比Item1、Item2等成员更可取(C#3.0程序员在使用元组时经常要求模式匹配支持:-) 原因
System.Tuple
类型实际上已经具有属性Item1
和Item2
,但这些属性被F#编译器隐藏。一个显而易见的向元组添加扩展成员的方法并不能奏效,所以我不希望这样做(但可能有一些我不知道的解决方法)
通常,我认为模式匹配比Item1
、Item2
等成员更可取(C#3.0程序员在使用元组时经常要求模式匹配支持:-)
原因是模式匹配迫使您命名事物。比较这两个代码段:
let (width, height) = tuple
width * height
以及使用属性的版本:
tuple.Item1 * tuple.Item2
第二个略短,但可读性肯定较差。我认为,你所问的不是很实用的方式。您可以使用实例方法创建自己的类型,但同时会丢失函数编程的许多方面,例如模式匹配 除此之外,DU似乎是一种方式:
type MyTuple<'T, 'U> =
| MyTuple of 'T * 'U
with
member this.MyItem1 = match this with | MyTuple(x,y) -> x
member this.MyItem2 = match this with | MyTuple(x,y) -> y
let x = MyTuple(42, "foo")
let y1 = x.MyItem1 // 42
let y2 = x.MyItem2 // "foo"
键入MyTuple=
|“T*”U的MyTuple
具有
member this.MyItem1=将其与| MyTuple(x,y)->x匹配
member this.MyItem2=将其与| MyTuple(x,y)->y匹配
设x=MyTuple(42,“foo”)
设y1=x.MyItem1//42
设y2=x.MyItem2/“foo”
正如@Tomas Petricek所指出的,您无法命名属性Item1
和Item2
,因为它们已经存在于System.Tuple
中。尝试这样做将导致错误:
错误FS2014:写入二进制文件[filename]时出现问题:类型[…]的pass2中出现错误,类型MyTuple`2的pass2中出现错误,属性表中出现重复条目'Item1'
您还可以使用
fst
和snd
函数来获取您想要的值(如果您真的想要,可以为第三、第四等编写自己的值)。不完美,但我正在使用它。(我从中借用了原始代码并添加了一些小的修改。)
这里定义的Tuple.Item1比fst有优势:它在项目数量上是多态的。一旦我们使用这些扩展方法编写了使用n个元组的函数,我们就可以在不修改函数体的情况下将其扩展为n+1个元组。相反,我们必须修改参数类型声明。更轻松。解决方法是使用C风格的扩展定义
这将很好地工作:
open System.Runtime.CompilerServices
[<Extension>]
type TupleExtensions () =
[<Extension>] static member First((a,b)) = a
[<Extension>] static member First((a,b,c)) = a
let x = (1,2).First()
let y = (1,2,3).First()
open System.Runtime.CompilerServices
[]
类型TupleExtensions()=
[]静态成员第一((a,b))=a
[]静态成员第一((a,b,c))=a
设x=(1,2).First()
设y=(1,2,3).First()
但是我同意通过方法访问元组的元素不是一个好主意,模式匹配是最好的方法。多亏了Tomas。我同意,但我仍然有兴趣,如果有一个解决办法(不诉诸一个新的类型,如下面由bytebuster建议)?
let t = (1, 2, 3)
let item1 = Tuple.Item1(t)
open System.Runtime.CompilerServices
[<Extension>]
type TupleExtensions () =
[<Extension>] static member First((a,b)) = a
[<Extension>] static member First((a,b,c)) = a
let x = (1,2).First()
let y = (1,2,3).First()