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?
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.
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() .
To access the private members of the superclass you need to use setter and getter methods and call them using the subclass object.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With