[英]match by value in a discriminated union, in F#
with this union:与这个联盟:
type T =
| A
| B
| C
and a T list和一个T列表
I would like to implement something like this pseudo code:我想实现类似这个伪代码的东西:
let countOfType (t: Type) (l: T list) =
l
|> List.filter (fun x -> x.GetType() = t)
|> List.length
when I would pass if I want to count the 'A', 'B', etc.. but A.GetType() and B.GetType() return the T type, so this doesn't work.如果我想计算 'A'、'B' 等,我什么时候会通过。但是 A.GetType() 和 B.GetType() 返回 T 类型,所以这不起作用。
Is there a way where I could check the type by passing it as a parameter?有没有办法通过将类型作为参数传递来检查类型?
The practical case here is that I have a Map that gets updated every few seconds and its values are part of the same DU.这里的实际情况是我有一个每隔几秒更新一次的 Map 并且它的值是同一个 DU 的一部分。 I need to be able to see how many of each type, without having to update the code (like a match block) each time an entry gets added.
我需要能够查看每种类型的数量,而不必在每次添加条目时更新代码(如匹配块)。
Addendum: I simplified the original question too much and realized it after seeing Fyodor's answer.附录:我把原来的问题简化了太多,看到Fyodor的回答后才明白。
So I would like to add the additional part: how could this also be done for cases like these:所以我想添加额外的部分:对于这样的情况,如何也能做到这一点:
type T =
| A of int
| B of string
| C of SomeOtherType
For such enum type T
as you specified, you can just use regular comparison:对于您指定的枚举类型
T
,您可以只使用常规比较:
let countOfType t (l: T list) =
l
|> List.filter (fun x -> x = t)
|> List.length
Usage:用法:
> countOfType A [A; A; B; C; A]
3
> countOfType B [A; A; B; C; A]
1
Try List.choose: ('a -> 'b option) -> 'a list -> 'b list
, it filters list based on 'a -> 'b option
selector.尝试
List.choose: ('a -> 'b option) -> 'a list -> 'b list
,它根据'a -> 'b option
选择器过滤列表。 If selectors evaluates to Some
, then value will be included, if selector evaluates to None
, then value will be skipped.如果选择器评估为
Some
,则将包含 value ,如果选择器评估为None
,则 value 将被跳过。 If you worry about allocations caused by instantiation of Some
, then you'll have to implement version that will use ValueOption
如果您担心由
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"
You can pattern match, and throw away the data, to create a function for the filter.您可以进行模式匹配,然后丢弃数据,为过滤器创建一个函数。
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
But in general i would asume, that you create a predicate function in your modul.但总的来说,我会假设您在模块中创建了一个谓词函数。
let isA x =
match x with
| A _ -> true
| _ -> false
if you have those functions you can just write如果你有这些功能,你可以写
[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.