Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access DU member's named fields

How can I access the named fields of a discriminated union's member?

Example:

type Point = | Point of x : int * y : int
let p = Point(3, 1)
// how to access x-value or y-value of p here?
like image 561
Tobi Holy Avatar asked Mar 08 '17 22:03

Tobi Holy


People also ask

How do you display the field list for all relationships in access?

On the Database Tools tab, in the Relationships group, click Relationships. On the Design tab, in the Relationships group, click All Relationships. All tables that have relationships are displayed, showing relationship lines.

How do you access the members of a class?

Accessing data members and member functions: The data members and member functions of class can be accessed using the dot('.') operator with the object. For example if the name of object is obj and you want to access the member function with the name printName() then you will have to write obj.printName() .

How do you access private members in subclass?

To access the private members of the superclass you need to use setter and getter methods and call them using the subclass object.

How do we access class members in Java?

To access the members of a class from other class. First of all, import the class. Create an object of that class. Using this object access, the members of that class.


1 Answers

In general, unions with named fields work just like any other union type: You would access the fields via match:

let x, y = 
    match p with 
    | Point (x1, y1) -> x1, y1

The F# documentation also mentions a way of matching only some named parameters. In your case, this means you can write:

let xOnly = 
    match p with 
    | Point (x = x1) -> x1

If all you have is a single case, see the answer by @p.s.w.g. The code in that answer is general for all discriminated unions. For singleton unions with named fields, you can use the special syntax shown above and write:

let Point(x = myX) = p

This binds the value of field x to myX.

PS as per the comments: Why can you not read out the fields right away, by doing p.x? You can think of a discriminated union as a small object hierarchy (and use it such, see the discriminated union documentation: "You can often use a discriminated union as a simpler alternative to a small object hierarchy"). Consider the following DU:

type Shape = | Circle of r: float | Square of float

You can view Shape as the superclass. Circle and Square are two derived classes, each with a single float property. Each instance of Circle or Square that you create will be upcast to be a Shape.

With that, it becomes clear why you can't read out the fields immediately: you first need to establish which of the derived classes you are looking at, only after the cast to the right subclass you can read out the fields.

This object hierarchy view matches very closely to how DUs are handled internally by F#: If you look at the DU type in reflection, you will see two nested types that have the same name as your union cases:

> typeof<Shape>.GetNestedTypes()
|> Seq.iter (fun t -> 
    let p = t.GetProperties() 
    let s = 
        p
        |> Array.map (fun p -> sprintf "%s: %s" p.Name p.PropertyType.Name) 
        |> String.concat "; "
    printfn "Nested type %s: %i Properties %s" t.Name p.Length s
);;
Nested type Tags: 0 Properties 
Nested type Circle: 4 Properties r: Double; Tag: Int32; IsCircle: Boolean; IsSquare: Boolean
Nested type Square: 4 Properties Item: Double; Tag: Int32; IsCircle: Boolean; IsSquare: Boolean

The actual data lives in properties of the subclass. For Circle, we used named fields, you see the property r. For Square, we have data in the Item property (or Item1, Item2 if there were multiple arguments). The rest are compiler generated: the numeric Tag field that will be used to quickly distinguish between the subclasses, and two bool properties for subclass checks.

The superclass itself only has compiler-generated properties:

>     typeof<Shape>.GetProperties()
    |> Seq.iter (fun p -> printfn "Property %s" p.Name);;
Property Tag
Property IsCircle
Property IsSquare
like image 166
Anton Schwaighofer Avatar answered Sep 28 '22 03:09

Anton Schwaighofer