Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#元组的扩展方法_F# - Fatal编程技术网

F#元组的扩展方法

F#元组的扩展方法,f#,F#,可以为F#元组编写扩展方法吗?例如,要添加实例方法.Item1和.Item2(如System.Tuple),它们相当于调用fst和snd来表示2元组?内部表示F#中(2元素)元组的System.Tuple类型实际上已经具有属性Item1和Item2,但这些属性被F#编译器隐藏。一个显而易见的向元组添加扩展成员的方法并不能奏效,所以我不希望这样做(但可能有一些我不知道的解决方法) 通常,我认为模式匹配比Item1、Item2等成员更可取(C#3.0程序员在使用元组时经常要求模式匹配支持:-) 原因

可以为F#元组编写扩展方法吗?例如,要添加实例方法.Item1和.Item2(如System.Tuple),它们相当于调用fst和snd来表示2元组?

内部表示F#中(2元素)元组的
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()