簡體   English   中英

如何編寫F#聯合類型選擇器?

[英]How to write an F# union type chooser?

如果使用F#,還有更好的方法嗎?

type T =
    | A of int
    | B of string
    static member chooseA x = match x with A i -> Some i | _ -> None
    static member chooseB x = match x with B s -> Some s | _ -> None

用例如下:

let collection = [A 10; B "abc"]
let aItems = collection |> Seq.choose T.chooseA
let bItems = collection |> Seq.choose T.chooseB

謝謝!

使用List.partition拆分源元素:

type T =
    | A of int
    | B of string

let collection = [A 10; B "abc"; A 40; B "120"]

let result = List.partition (function | A _ -> true | _ -> false) collection

val result : T list * T list = ([A 10; A 40], [B "abc"; B "120"])

然后,您可以使用fst和snd選擇相關列表。

這很尷尬,但是我可以理解為什么它不是F#設計的重要案例。 通常,有一種解決方案允許完整的模式匹配,而不是多個(有些不完整)的模式匹配。 例如,可以這樣構造兩個具體的項目序列:

let aItems, bItems =
    let accA, accB = ResizeArray(), ResizeArray()
    collection |> Seq.iter (function A i -> accA.Add i | B s -> accB.Add s)
    seq accA, seq accB

如果您不喜歡,可以采用類似的無突變解決方案,但是我幾乎沒有理由擔心封裝突變。 請注意,結果強制轉換為seq

這將按照其設計方式使用模式匹配:

  • 如果將另一個大小寫添加到T ,則處理功能中將顯示一條警告,這正是繼續編輯的地方:確定如何處理新輸入的大小寫。
  • 該程序不必為每種輸入重復多次輸入,而只需遍歷一次並在初次遇到時處理每個項目。

如果上述方法不合適,您仍然可以通過使用function關鍵字並將聲明選擇器函數聲明為lambda來稍微縮短問題的代碼。 例如:

let aItems = collection |> Seq.choose (function A i -> Some i | _ -> None)

請注意,這是惰性的,就像問題中的建議一樣:在這里,對aItems每次迭代aItems將不必要地遍歷輸入中的所有B例。

我可以提供以下變體:

open System.Reflection

type T =
    | A of int
    | B of string

let collection = [A 10; B "abc"; A 40; B "120"]

let sp (col: T list) (str:string) = 
      if col=[] then []
      else  
        let names = "Is" + str
        col |> List.filter(fun x-> let t = x.GetType()
                                   if t.GetProperty(names) = null then false
                                   else 
                                   t.InvokeMember(names, BindingFlags.GetProperty, null, x, null) :?> bool)
            |> List.map(fun y ->
                y.GetType().InvokeMember("get_Item", BindingFlags.InvokeMethod, null, y, null))

sp collection "A" |> printfn "%A\n"
sp collection "B" |> printfn "%A\n"   
sp collection "C" |> printfn "%A\n"

打印:

[10; 40]

["abc"; "120"]

[]

http://ideone.com/yAytQk

我是F#的新手,所以我認為這可以輕松完成

暫無
暫無

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

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