I want to define a method shared by all members of a discriminated union. Currently I\'ve implemented it like this, but it seems really inelegant- surely there is a better way.
In your example, you have augmented the record types A
and B
each with an instance member. However, you can not only augment record types, you can also augment union types (as shown in @Rodrick's answer). If you do this, the union's augmentation will be "shared" by each DU case, which is what you have asked for. To make this more explicit, I have renamed some parts of your example:
type A = { AData:string }
type B = { BData:float }
type AB =
| ACase of A
| BCase of B
member __.SharedMethod x = 0
let callSharedMethod (ab:AB) x = ab.SharedMethod x
If you look at the compiled code in the object browser (or a decompiler like ILSpy), you will see that AB
is compiled as the base class of two subclasses AB.ACase
and AB.BCase
, and SharedMethod
belongs to the base class AB
.
See also section 8.5.1 of the F# 3.0 specification: Members in Union Types.
What about something like this?
type AB =
| A of string
| B of float
member self.SharedMethod (x : float) =
match self with
| A s -> x
| B f -> f + x
This assumes that you want each variant of your sum type (aka discriminated union) to do something different with the float parameter.
For the case of A
, I just return the original value since there's not much else I can do (since there is no generally useful relationship between string
and float
that yields a float
).