Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous record type inside discriminated union

The F# tutorial includes the following snippet:

/// A record for a person's first and last name
type Person = {     
    First : string
    Last  : string
}

/// define a discriminated union of 3 different kinds of employees
type Employee = 
    | Engineer  of Person
    | Manager   of Person * list<Employee>            // manager has list of reports
    | Executive of Person * list<Employee> * Employee // executive also has an assistant

The fact that Manager and Executive are described as tuples offends my sensibilities (I'm easily offended). It strikes me as not terribly expressive. I tried to modify them as follows:

/// define a discriminated union of 3 different kinds of employees
type Employee = 
    | Engineer  of Person
    | Manager   of { Name: Person; Reports: Employee list }            // manager has list of reports
    | Executive of { Name: Person; Reports: Employee list; Assistant: Employee}   // executive also has an assistant

Sadly, the definitions of Manager and Executive now give an error: "This construct is deprecated; consider using a separate record type instead." Ok, seems fair, let's call it ManagerType. But wait ... ManagerType refers to Employee (for the Reports part), and Employee refers to ManagerType (for the Manager option).

Is there a solution here? Is it not possible for two data structures to be defined in terms of each other?

like image 671
CSJ Avatar asked Feb 05 '14 21:02

CSJ


People also ask

How is a discriminated union defined?

A discriminated union is a union data structure that holds various objects, with one of the objects identified directly by a discriminant. The discriminant is the first item to be serialized or deserialized. A discriminated union includes both a discriminant and a component.

When to use Discriminated union?

Discriminated unions are useful for heterogeneous data; data that can have special cases, including valid and error cases; data that varies in type from one instance to another; and as an alternative for small object hierarchies.


1 Answers

You can define mutually dependent types using and:

    type Employee = 
    | Engineer  of Person
    | Manager   of Manager            // manager has list of reports
    | Executive of Executive
    and Manager = { Name: Person; Reports: Employee list }
    and Executive = { Name: Person; Reports: Employee list; Assistant: Employee }
like image 159
Lee Avatar answered Oct 14 '22 03:10

Lee