F# – Extending Discriminated Unions using marker interfaces

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

In most cas­es, hav­ing to spec­i­fy all your union cas­es 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­ev­er, some­times I do find myself wish­ing for some exten­si­bil­i­ty so that I can keep using DU types instead of hav­ing to revert back to a com­plex class hier­ar­chy.

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:


How­ev­er, 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 bloat­ed and to keep the spe­cial­ized mes­sage types clos­er to code that actu­al­ly 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.

Anoth­er approach to this prob­lem is to use mark­er inter­faces, so the above code becomes:


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­i­ty to your DU types.

Notice how the func­tion f is changed from pat­tern match­ing the union cas­es 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­cif­ic type.


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