5

可以说我有一个像这样的歧视性工会:

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

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

4

2 回答 2

11

不像你想要的那么简洁,但你可以使用OR 模式做这样的事情:

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
于 2013-06-30T18:32:27.013 回答
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

但是如果三个案例应该以相同的方式重复处理,你应该考虑重构你的 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
于 2013-06-30T18:44:48.260 回答