簡體   English   中英

F#成員對元組的約束

[英]F# member constraints on tuples

當我意識到我需要一個額外的價值時,我通常會寫一個“哦耶”的時刻寫F#。 這通常可以通過向傳遞的元組添加另一個值來輕松完成。 但是,這意味着各種地圖/排序/收集/等。 需要更新,特別是函數fst / snd只適用於長度為2的元組。

這不是一個大問題,但在探索性開發過程中它很煩人,但我會寫一個助手來減輕煩惱:

let inline get2 (t:^a) = (^a : (member get_Item2 : unit -> string) (t, ()))
let inline get2a (t:^a) = (^a : (member Item2 : string) t)

但是,這兩個版本都不起作用。 第一個, get2 ,將無法編譯,“預期的1個表達式,得到2”。 第二個, get2a ,將編譯,但隨后不能在元組上使用:“類型'(int * string)'不支持任何名為'get_Item2'的運算符”。

有沒有辦法做到這一點,不涉及大量的重載? 帶有嘈雜的 OverloadID注釋 (F#2.0中不需要注釋)

對F#元組的ItemX靜態約束不起作用的原因是因為System.Tuple<_,...,_>只是元組的編碼形式,而不是編譯器使用的靜態表示。 請參閱規范中的6.3.2元組表達式

但是,通過一些工作,您可以獲得給定元組的運行時編碼,如下所示:

open System
//like get2a but generic return type
let inline get2b (t:^a) = (^a : (member Item2 : 'b) t)

let x = (1,2)
let y = (1,2,3)

get2b (box x :?> Tuple<int,int>)
get2b (box y :?> Tuple<int,int,int>)

你可以使用反射來做到這一點:

let inline get (t:^a) = t.GetType().GetProperty("Item2").GetValue(t,null) :?> string

另外,我建議元組實際上並不是一個很好的數據結構來傳遞數據,它們在小型操作的函數中可能很有用,但是如果結構經常發生變化,那么元組可能真的很痛苦。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM