When you con­sider the age old prob­lem of rep­re­sent­ing dif­fer­ent shapes (cir­cle, tri­an­gle, square, rec­tan­gle, etc.) my OO fed devel­oper brain nat­u­rally jumps to a class hier­ar­chy along the line of:

image

This is per­fectly fine and legit, but it’s not the only way to approach things. Since I’ve been on a more var­ied diet of pro­gram­ming par­a­digms I’m much more open to the idea of using F#’s dis­crim­i­nated unions to rep­re­sent hier­ar­chi­cal data.

Dis­crim­i­nated union is a fun­da­men­tal type in func­tion pro­gram­ming, and for C# devel­op­ers, think of it as an Enum with strongly typed names where the names don’t have to be of the same type. Using dis­crim­i­nated unions, you can rewrite the above code as:

image

And to test it, let’s cre­ate some shapes and work­out their respec­tive areas:

image

Was that more dif­fi­cult than its C# coun­ter­part? Not at all, in fact, I’ve lit­tered the F# code with com­ments and still ended up with near half as much code! Check out my solu­tion for project euler prob­lem 54, a work­ing poker hand eval­u­a­tor in 100 lines of code , pretty sweetSmile

Clos­ing thoughts…

That said, class hier­ar­chies are great at mod­el­ling real world enti­ties and they allow you to cap­ture com­mon­al­i­ties and shared behav­iours, if done cor­rectly they can remove dupli­cated code and reduce defects.

Dis­crim­i­nated unions on the other hand, are a great fit for hier­ar­chi­cal data struc­tures such as binary tree, and for small hier­ar­chies it requires lit­tle over­head in set­ting them up so it can give you a nice pro­duc­tiv­ity boost.

Whilst I’m not sug­gest­ing that you should start con­vert­ing all your class hier­ar­chies to dis­crim­i­nated unions, I think there is a lot of value in hav­ing it in your tool­box nonethe­less. The more tools you have at your dis­posal the bet­ter, being able to use the right tool for the right task beats ham­mer­ing a screw in my opinion!

Share

3 Responses to “F# — Use Discriminated Unions instead of class hierarchies”

  1. Johann says:

    I think the key to choos­ing cor­rectly between class hier­ar­chies and unions is extend­abil­ity by out­siders. If you want to allow that with­out forc­ing them to mod­ify your code, then class hier­ar­chies are the way to go.

    Unions are attrac­tive when used in con­junc­tion with pat­tern match­ing, as the com­piler tells you if all cases are handled.

    It’s also easy to add new cases to a union, no cer­e­mony involved. With classes, one often finds one­self shoe-horning new sub­classes into inter­faces that are sel­dom exactly what you would like them to be.

  2. […] my pre­vi­ous post on dis­crim­i­nated unions, I pre­sented dis­crim­i­nated unions as an alter­na­tive to […]

  3. […] Union types, they work nicely with pat­tern match­ing inside your F# code and can often alle­vi­ate some of the cer­e­mony involved around cre­at­ing and using a com­plex object […]

Leave a Reply