Andrew M
Andrew M

Reputation: 157

In F# is it possible to create a pattern that will match multiple cases of a discriminate union?

Lets say I have a discriminated union like this:

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

Is there any concise way to complete the following function without specifying all the remaining cases

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

Such that the pattern will generically handle the remaining similarly structured union cases the same way. In the example code, it would mean a single case statement for Bar,Baz, and Qux that would behave like the following.

    | Bar(i) -> i

I didn't see anything in the language reference that would allow this type of matching but I'm curious if it's possible.

Upvotes: 5

Views: 1554

Answers (2)

N_A
N_A

Reputation: 19897

Not quite as concise as you want, but you can do something like this using the OR pattern:

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

It does, however, eliminate the duplication of all of the (possibly) complex portion of that case.

For the sake of further illustration, you can also do this even if your cases don't match exactly like so:

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

Upvotes: 11

pad
pad

Reputation: 41290

You can also change the view of discriminated unions using 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

But if three cases should be handled in the same way repetitively, you should consider to refactor your 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

Upvotes: 11

Related Questions