[英]match by value in a discriminated union, in F#
與這個聯盟:
type T =
| A
| B
| C
和一個T列表
我想實現類似這個偽代碼的東西:
let countOfType (t: Type) (l: T list) =
l
|> List.filter (fun x -> x.GetType() = t)
|> List.length
如果我想計算 'A'、'B' 等,我什么時候會通過。但是 A.GetType() 和 B.GetType() 返回 T 類型,所以這不起作用。
有沒有辦法通過將類型作為參數傳遞來檢查類型?
這里的實際情況是我有一個每隔幾秒更新一次的 Map 並且它的值是同一個 DU 的一部分。 我需要能夠查看每種類型的數量,而不必在每次添加條目時更新代碼(如匹配塊)。
附錄:我把原來的問題簡化了太多,看到Fyodor的回答后才明白。
所以我想添加額外的部分:對於這樣的情況,如何也能做到這一點:
type T =
| A of int
| B of string
| C of SomeOtherType
對於您指定的枚舉類型T
,您可以只使用常規比較:
let countOfType t (l: T list) =
l
|> List.filter (fun x -> x = t)
|> List.length
用法:
> countOfType A [A; A; B; C; A]
3
> countOfType B [A; A; B; C; A]
1
嘗試List.choose: ('a -> 'b option) -> 'a list -> 'b list
,它根據'a -> 'b option
選擇器過濾列表。 如果選擇器評估為Some
,則將包含 value ,如果選擇器評估為None
,則 value 將被跳過。 如果您擔心由Some
實例化引起的分配,那么您必須實現將使用ValueOption
版本
let onlyA lis =
lis |> List.choose (function
| (A _) as a -> Some a
| _ -> None)
let onlyB lis =
lis |> List.choose (function
| (B _) as b -> Some b
| _ -> None)
let lis = [
A 1
A 22
A 333
B ""
B "123"
]
lis |> onlyA |> List.length |> printfn "%d"
您可以進行模式匹配,然后丟棄數據,為過濾器創建一個函數。
type T =
| A of int
| B of string
| C of float
[A 3;A 1;B "foo";B "bar";C 3.1; C 4.6]
|> List.filter (fun x ->
match x with
| A _ -> true
| B _ -> false
| C _ -> false
)
|> List.length
但總的來說,我會假設您在模塊中創建了一個謂詞函數。
let isA x =
match x with
| A _ -> true
| _ -> false
如果你有這些功能,你可以寫
[A 3;A 1;B "foo";B "bar";C 3.1; C 4.6]
|> List.filter isA
|> List.length
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.