【问题标题】:In F# is it possible to create a pattern that will match multiple cases of a discriminate union?在 F# 中,是否可以创建一个匹配多个判别联合的模式?
【发布时间】:2013-06-27 22:16:20
【问题描述】:

假设我有一个像这样的歧视性工会:

type Example = 
   |Foo of string
   |Bar of int
   |Baz of int
   |Qux of int
   |NoValue

有没有什么简洁的方法可以在不指定其余所有情况的情况下完成以下功能

let doIt (ex:Example) = 
    match ex with
    | Foo(_) -> 0
    | NoValue -> -1

这样,该模式通常会以相同的方式处理剩余的类似结构的联合案例。在示例代码中,这意味着 Bar、Baz 和 Qux 的单个 case 语句的行为如下。

    | Bar(i) -> i

我在语言参考中没有看到任何允许这种类型匹配的内容,但我很好奇它是否可能。

【问题讨论】:

    标签: .net f# pattern-matching


    【解决方案1】:

    没有你想要的那么简洁,但你可以使用OR pattern

    let doIt (ex:Example) =
        match ex with
        | Foo(_) -> 0
        | NoValue -> -1
        | Bar(i) | Baz(i) | Qux(i) -> i;;
    

    但是,它确实消除了该案例中所有(可能)复杂部分的重复。

    为了进一步说明,即使您的案例不完全匹配,您也可以这样做:

    type Example =
      | Foo of string
      | Bar of int * int
      | Baz of int
      | Qux of int
      | NoValue
    
    let doIt (ex:Example) =
        match ex with
        | Foo _ -> 0
        | NoValue -> -1
        | Bar(i,_) | Baz i | Qux i -> i
    

    【讨论】:

      【解决方案2】:

      您还可以使用Active Patterns 更改区分联合的视图:

      let (|SingleInt|_|) = function
         | Foo _ -> None
         | NoValue -> None
         | Bar i | Baz i | Qux i -> Some i
      
      let doIt ex = 
          match ex with
          | SingleInt i -> i
          | Foo _ -> 0
          | NoValue -> -1
      

      但是如果三个案例应该以相同的方式重复处理,你应该考虑重构你的 DU:

      type IntCase = | Bar | Baz | Qux
      
      type Example = 
         | Foo of string
         | SingleInt of int * IntCase
         | NoValue
      
      let doIt ex = 
          match ex with
          | SingleInt(i, _) -> i
          | Foo _ -> 0
          | NoValue -> -1
      

      【讨论】:

      • 如果 int 案例通常以重复方式使用,我大体上同意您的重构。我接受了另一个,因为在这个特定的用例中,Bar、Baz、Qux 通常是离散使用的,但在一个特定的情况下,需要通用处理。
      • 公平点。如果您想知道,这种特殊情况称为OR pattern
      • 将这些答案结合起来会非常好,它们都非常有用。
      猜你喜欢
      • 2018-02-03
      • 1970-01-01
      • 2018-11-24
      • 1970-01-01
      • 2016-03-24
      • 2010-10-18
      • 2014-10-08
      • 1970-01-01
      • 2019-01-10
      相关资源
      最近更新 更多