![](/img/trans.png)
[英]How do I Pattern Match on the actual container of Discriminated Union cases?
[英]How to pattern match on union constructors in `for .. in`
在Haskell中,如果我有一个联合类型值的列表,如下所示:
example :: [Either Int Char]
example = [Left 3, Right 'b', Left 6, Left 9, Right 'c']
我可以使用一些“技巧”来提取匹配某些特定模式的所有结果:
lefts :: [Int]
lefts = [l | Left l <- example]
但是,如果我尝试将其转换为F#,我会收到错误:
let lefts = [for Choice1Of2 l in example -> l]
~~~~~~~~~~~~
Incomplete pattern matches on this expression. (...)
这很有意义(甚至可能比默默地忽略像Haskell那样的Right
值更好!)但是在F#中,是否有一些方便的方法来提取(和匹配)匹配列表中某个模式的所有值/顺序 ?
在F#中如果你不匹配所有情况,你会在所有情况下得到警告。
所以你可以在表达式中写出两个案例的匹配,但是对于你的例子而不是理解我会使用函数List.choose
:
let example = [Choice2Of2 3; Choice1Of2 'b'; Choice2Of2 6; Choice2Of2 9; Choice1Of2 'c']
List.choose (function (Choice1Of2 x) -> Some x | _ -> None) example
// val it : char list = ['b'; 'c']
这个功能对于这些情况很方便。
我认为使用F#list表达式最接近的事情是这样的:
let lefts example =
[ for e in example do
match e with Choice1Of2 l -> yield l | _ -> () ]
如果我正确理解Haskell代码,那么|
之后的部分 不仅用作提取器,还用作过滤器 - 隐含地跳过与模式不匹配的所有事物。
F#在列表表达式中没有相同的概念,因此您必须更加详细。 在这里,我们只使用for
迭代所有项目,然后我们显式使用yield
为源列表中的每个Choice1Of2
生成一个新值(我们只是跳过其他任何内容)。
根据你正在做的事情,使用List.choose
(如Gustavo的回答中提到的)可能会更容易。 但上面可能是最接近Haskell的理解语法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.