在F#中是否可以创建一个匹配歧视联合的多个案例的模式?

时间:2013-06-30 18:28:20

标签: .net f# pattern-matching

假设我有一个像这样的歧视联盟:

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

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

2 个答案:

答案 0 :(得分:11)

不像你想要的那么简洁,但你可以使用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

答案 1 :(得分:10)

您还可以使用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

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

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