在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#中,是否有一些方便的方法来提取(和匹配)所有与列表/序列中的特定模式匹配的值?
答案 0 :(得分:16)
在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']
此功能对于这些情况非常方便。
答案 1 :(得分:12)
我认为使用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的理解语法。