使用不完整模式匹配作为过滤器

Ale*_*sti 5 f# list-comprehension pattern-matching

假设我有以下代码:

type Vehicle =
| Car  of string * int
| Bike of string

let xs = [ Car("family", 8); Bike("racing"); Car("sports", 2); Bike("chopper") ]
Run Code Online (Sandbox Code Playgroud)

我可以使用不完整的模式匹配过滤上面的列表,如下所示:

> for Car(kind, _) in xs do
>    printfn "found %s" kind;;

found family
found sports
val it : unit = ()
Run Code Online (Sandbox Code Playgroud)

但它会导致:warning FS0025: Incomplete pattern matches on this expression. For example, the value 'Bike (_)' may indicate a case not covered by the pattern(s). Unmatched elements will be ignored.

由于忽略了无与伦比的元素是我的意图,是否有可能摆脱这种警告?

是否有一种方法可以使列表推导工作,而不会导致MatchFailureException?例如:

> [for Car(_, seats) in xs -> seats] |> List.sum;;
val it : int = 10
Run Code Online (Sandbox Code Playgroud)

Lau*_*ent 10

两年前,您的代码是有效的,这是标准的方法.然后,语言已被清理,设计决策是支持显式语法.出于这个原因,我认为忽略警告并不是一个好主意.

代码的标准替换是:

for x in xs do
    match x with
    | Car(kind, _) -> printfn "found %s" kind
    | _ -> ()
Run Code Online (Sandbox Code Playgroud)

(你也可以在pad样本中使用高阶函数)

对于另一个,List.sumBy很适合:

xs |> List.sumBy (function Car(_, seats) -> seats | _ -> 0)
Run Code Online (Sandbox Code Playgroud)

如果您更喜欢坚持理解,这是明确的语法:

[for x in xs do
    match x with
    | Car(_, seats) -> yield seats
    | _ -> ()
] |> List.sum
Run Code Online (Sandbox Code Playgroud)

  • @gasche:我的计算机上有旧的编译器,我可以告诉你版本1.9.3.14和1.9.6.16之间发生的变化.我无法找到适当的参考,但这些发行说明提到了语法简化:[link](http://blogs.msdn.com/b/dsyme/archive/2008/08/29/detailed-release-票据换了-F-月-2008-CTP-release.aspx).这里还有一个讨论:[link](http://cs.hubfs.net/forums/thread/12072.aspx). (4认同)

Bri*_*ian 5

您可以通过#nowarn指令或--nowarn:编译器选项使任何警告静音(传递警告编号,此处25如下FS0025).

但更一般地说,不,最好的事情就是明确过滤,就像在另一个答案中一样(例如choose).


pad*_*pad 5

要明确声明要忽略不匹配的大小写,可以使用List.choose并返回None那些不匹配的元素.您的代码可以用更加独特的方式编写,如下所示:

let _ = xs |> List.choose (function | Car(kind, _) -> Some kind
                                    | _ -> None)
           |> List.iter (printfn "found %s")

let sum = xs |> List.choose (function | Car(_, seats)-> Some seats
                                      | _ -> None) 
             |> List.sum
Run Code Online (Sandbox Code Playgroud)

  • 您可以使这更简洁,如`xs |> List.choose(函数Car(kind,_) - > Some(kind)| _ - > None)` (5认同)