如何在 `for .. in` 中对联合构造函数进行模式匹配
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']
我可以使用一些 "trick" 来提取所有匹配特定模式的结果:
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# 中,是否有一些方便的在 list/sequence?
中提取(并匹配)与特定模式匹配的所有值的方法
我认为使用 F# 列表表达式最接近的事情是这样的:
let lefts example =
[ for e in example do
match e with Choice1Of2 l -> yield l | _ -> () ]
如果我正确理解 Haskell 代码,|
之后的部分不仅用作提取器,还用作过滤器 - 隐式跳过所有与模式不匹配的东西.
F#在列表表达式中没有同类的概念,所以你必须更加冗长。在这里,我们只是使用 for
遍历 all 项,然后我们明确地使用 yield
为源列表中的每个 Choice1Of2
生成一个新值(我们只是跳过其他任何内容)。
根据您的操作,使用 List.choose
(如 Gustavo 的回答中所述)可能更容易。但上面的内容可能最接近 Haskell 的 comprehension 语法。
在 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']
这个函数对这些情况很方便。
在 Haskell 中,如果我有一个像这样的联合类型值列表:
example :: [Either Int Char]
example = [Left 3, Right 'b', Left 6, Left 9, Right 'c']
我可以使用一些 "trick" 来提取所有匹配特定模式的结果:
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# 中,是否有一些方便的在 list/sequence?
我认为使用 F# 列表表达式最接近的事情是这样的:
let lefts example =
[ for e in example do
match e with Choice1Of2 l -> yield l | _ -> () ]
如果我正确理解 Haskell 代码,|
之后的部分不仅用作提取器,还用作过滤器 - 隐式跳过所有与模式不匹配的东西.
F#在列表表达式中没有同类的概念,所以你必须更加冗长。在这里,我们只是使用 for
遍历 all 项,然后我们明确地使用 yield
为源列表中的每个 Choice1Of2
生成一个新值(我们只是跳过其他任何内容)。
根据您的操作,使用 List.choose
(如 Gustavo 的回答中所述)可能更容易。但上面的内容可能最接近 Haskell 的 comprehension 语法。
在 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']
这个函数对这些情况很方便。