问题
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. Suggestions?
type A =
{AData:string}
member this.SharedMethod (x:float) : int= ...
type B =
{BData:float}
member this.SharedMethod (x:float) : int= ...
type AB =
| A of A
| B of B
let CallSharedMethod (ab:AB) x =
match ab with
| AB.A(a') -> a'.SharedMethod x
| AB.B(b') -> b'.SharedMethod x
回答1:
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
).
回答2:
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.
来源:https://stackoverflow.com/questions/27136056/discriminated-union-member-methods