One of the prob­lems with using F#’s Dis­crim­i­nated Unions is that they are not exten­si­ble, in that all your union cases must be spec­i­fied inside one Dis­crim­i­nated Union (abbre­vi­ated to DU from this point) type and you can’t inherit from an exist­ing DU type to add addi­tional union cases.

In most cases, hav­ing to spec­ify all your union cases inside one DU type makes per­fect sense and I’m sure there is a very good rea­son for the lan­guage design­ers to not allow inher­i­tance with DU types.

How­ever, some­times I do find myself wish­ing for some exten­si­bil­ity so that I can keep using DU types instead of hav­ing to revert back to a com­plex class hierarchy.

Sup­pose you have a mes­sag­ing appli­ca­tion, you can define the dif­fer­ent types of mes­sages your sys­tem under­stands as a DU:

image

How­ever, as the appli­ca­tion grows you might want to add more spe­cial­ized types of mes­sages, and you don’t want to add them to Mes­sageTypes to stop it from becom­ing bloated and to keep the spe­cial­ized mes­sage types closer to code that actu­ally under­stand them.

So what do you do in that case? Go back to using a class hier­ar­chy? Sure, that’s one approach.

Another approach to this prob­lem is to use marker inter­faces, so the above code becomes:

image

The fact that DU types can imple­ment inter­faces is often over­looked but you can make good use of it here to enable some exten­si­bil­ity to your DU types.

Notice how the func­tion f is changed from pat­tern match­ing the union cases to pat­tern match­ing against the type of the mes­sage (sim­i­lar to how you can use pat­tern match­ing in a try-with block) before pass­ing the mas­sage to the appro­pri­ate han­dler func­tion that under­stands that spe­cific type.

 

Well, thank you for read­ing and hope this post proves to be help­ful to you Smile

Share

3 Responses to “F# – Extending Discriminated Unions using marker interfaces”

  1. This is a cool way to go about it.

    I was think­ing though, if you had the inter­face imple­ment the match­ing func­tion you’d never need to worry about invent­ing a mech­a­nism for replac­ing g with f. Even bet­ter, you’d never need to write f, only h.

  2. Carsten says:

    This is a known prob­lem (exten­si­bil­ity or types = more or less what OO pro­vides) VS (exten­si­bil­ity of func­tions = more or less FP with DU)

    There is a lec­ture on Channel9 nicely explain­ing the prob­lem and the solu­tion Haskell pro­vides: http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Dr-Ralf-Laemmel-Advanced-Functional-Programming-The-Expression-Problem
    enjoy.

  3. theburningmonk says:

    @Carsten — excel­lent video, very edu­ca­tional! Thanks for the link.

Leave a Reply