Discriminated union member methods

后端 未结 2 1362
孤独总比滥情好
孤独总比滥情好 2021-02-13 16:28

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.

相关标签:
2条回答
  • 2021-02-13 16:41

    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.

    0 讨论(0)
  • 2021-02-13 16:55

    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).

    0 讨论(0)
提交回复
热议问题