是否可以爲F#元組編寫擴展方法?例如,添加實例方法.Item1和.Item2(如System.Tuple)相當於爲2元組調用fst和snd?F#元組的擴展方法
回答
不完美,但我用這個。 (我從http://www.fssnip.net/6V借原代碼,增加了小的修改。)
[<AutoOpen>]
module TupleExtensions =
type System.Tuple with
static member Item1(t) = let (x,_) = t in x
static member Item1(t) = let (x,_,_) = t in x
static member Item1(t) = let (x,_,_,_) = t in x
static member Item1(t) = let (x,_,_,_,_) = t in x
static member Item1(t) = let (x,_,_,_,_,_) = t in x
static member Item1(t) = let (x,_,_,_,_,_,_) = t in x
static member Item2(t) = let (_,x) = t in x
static member Item2(t) = let (_,x,_) = t in x
static member Item2(t) = let (_,x,_,_) = t in x
static member Item2(t) = let (_,x,_,_,_) = t in x
static member Item2(t) = let (_,x,_,_,_,_) = t in x
static member Item2(t) = let (_,x,_,_,_,_,_) = t in x
static member Item3(t) = let (_,_,x) = t in x
static member Item3(t) = let (_,_,x,_) = t in x
static member Item3(t) = let (_,_,x,_,_) = t in x
static member Item3(t) = let (_,_,x,_,_,_) = t in x
static member Item3(t) = let (_,_,x,_,_,_,_) = t in x
static member Item4(t) = let (_,_,_,x) = t in x
static member Item4(t) = let (_,_,_,x,_) = t in x
static member Item4(t) = let (_,_,_,x,_,_) = t in x
static member Item4(t) = let (_,_,_,x,_,_,_) = t in x
static member Item5(t) = let (_,_,_,_,x) = t in x
static member Item5(t) = let (_,_,_,_,x,_) = t in x
static member Item5(t) = let (_,_,_,_,x,_,_) = t in x
static member Item6(t) = let (_,_,_,_,_,x) = t in x
static member Item6(t) = let (_,_,_,_,_,x,_) = t in x
static member Item7(t) = let (_,_,_,_,_,_,x) = t in x
如何使用它:
let t = (1, 2, 3)
let item1 = Tuple.Item1(t)
Tuple.Item1這裏定義有超過FST的優勢:它是多態的項目數。一旦我們使用這些擴展方法編寫使用n元組的函數,我們可以在不修改函數體的情況下將其擴展爲n + 1元組。相反,我們必須修改參數類型聲明。這是更輕鬆。
在F#中內部表示(2元素)元組的System.Tuple<'T1, 'T2>
類型實際上已經具有屬性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"
由於@Tomas Petricek指出,因爲他們在System.Tuple<'T1, 'T2>
已經存在,所以無法命名的屬性Item1
和Item2
。試圖這樣做將導致一個錯誤:
error FS2014: A problem occurred writing the binary [filename]: Error in pass2 for type [...], error: Error in pass2 for type MyTuple`2, error: duplicate entry 'Item1' in property table
您也可以使用fst
和snd
功能得到你想要的值(顯然寫自己的第三,第四,等等。如果你真的想) 。
解決方法是使用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()
但我同意,這不是一個好主意,通過方法來訪問一個元組的元素,模式匹配是最好的方式。
- 1. F#和PLINQ擴展方法
- 2. 是否有可能爲F#元組創建擴展方法
- 3. 擴展方法定義/調用在F#
- 4. 如何創建擴展方法(F#)?
- 5. 組織擴展方法
- 6. 分組擴展方法
- 7. F#模塊擴展與類型擴展
- 8. 擴展方法
- 9. 擴展方法
- 10. 的擴展方法
- 11. F#將活動模式與擴展元組匹配
- 12. f的反應式擴展#
- 13. 可擴展枚舉的擴展方法
- 14. 擴展類成員的擴展方法?
- 15. 使用擴展方法的擴展類
- 16. 使用擴展方法覆蓋F#中的靜態屬性
- 17. 使用F#函數類型的擴展方法
- 18. 是否存在與此C#擴展方法等效的F#?
- 19. F#的一種擴展方法,參考另一
- 20. 無法在F#中擴展運算符?
- 21. 單元測試UrlHelper擴展方法
- 22. AutoMapper展開擴展方法
- 23. 如何分組擴展方法?
- 24. TypeScript - 數組排序擴展方法
- 25. 如何組織Kotlin擴展方法
- 26. 擴展方法擴展靜態類
- 27. NativeScript擴展方法
- 28. 擴展方法ConvertAll
- 29. C#擴展方法
- 30. XElement.Elements()擴展方法?
感謝Tomas。我同意,但是如果有解決方法,我仍然對此感興趣(而不是像下面的bytebuster建議的那樣採用新的類型)? – mpeac