sgtz
sgtz

Reputation: 9009

how to do recursive discriminated unions by value?

In F# is it possible to have a discriminated union based on both a type and a value?

Here's an attempt at expressing this without knowing what the syntax should look like.

type Foo =
    | A of int * Foo
    | B of string where B.name = "1" * Foo
    | C of string where C.name = "2" * Foo
    | Empty

Upvotes: 0

Views: 340

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243041

I'm not entirely sure what you're trying to achieve. But, if you want to create a type that will have a name property when which is "1" when the type is B and "2" when it is C, then you can add a member:

type Foo =
  | A of int * Foo
  | B of Foo
  | C of Foo
  | Empty
  member x.Name = 
    match x with
    | B _ -> "1"
    | C _ -> "2"
    | _ -> failwith "Name is not available!"

If you were hoping to use the numbers in pattern matching, then you can define an active pattern. Say you have a type with just A or B (which has a name):

type Foo = 
  | A of int
  | B of string * Foo

Now you can write an active pattern that lets you distinguish between A, B with name "1" and B with name "2":

let (|A|B1|B2|) x = 
  match x with
  | A n -> A n
  | B("1", foo) -> B1 foo
  | B("2", foo) -> B1 foo
  | _ -> failwith "Invalid B"

If you now have a value foo, you can pattern match against these three cases:

match foo with
| A n -> ...
| B1 subfoo -> ...
| B2 subfoo -> ...

Upvotes: 5

Related Questions