F# fanbois often talk about how F# supposedly makes “composition” easier than C# (or indeed any OO-first langage). If you come from a C# background, you might not really think about what people mean by “composition”, because to be honest functional composition in the OO world is pretty difficult to achieve. You achieve it normally through inheritiance, which is a bit of a cop-out, or you start looking at things like like the Strategy pattern to achieve it in a more decoupled manner, typically through interfaces. But I tended to think of composition as something abstract before I started looking at F#.
One simpler way to achieve composition in the OO world is to use a (somewhat underused and misunderstood) feature common to IoC containers – to apply interceptors & policies to implement composition and pipelining (e.g. Decorator and Chain of Responsibility patterns). This is commonly known as Aspect Oriented Programming (AOP); common aspects include cross cutting concerns like logging and caching. Well, here’s an implementation of a fairly simple interception framework in F# that can chain up arbritrary decorators on a target function quickly and easily.
Composition through Aspects in F#
The goal would be to have a function – let’s say one that adds two numbers together – and be able to apply validation or logging to it in a decoupled manner.
First thing we do is define the signature of any “aspect”: –
Very simple – every aspect takes in a value of the same type as the “real” function, and returns a message that says either “fine, carry on, “something is wrong, here’s an exception”, or “return prematurely with this value”. Easy. Let’s take our usual friendly calculator add function and a set of sample aspects: –
How do we chain these aspects up together with the raw add function? Quite easily as it turns out, with two simple functions, plus F#’s built-in compose operator (>>). The first one “bolts” one aspect to another, and returns a function with the same signature. The second function closes the chain and bolts the final aspect to the “real” function: –
Now that we’ve done that, we can chain up our aspects together using the following syntax: –
Nice, but we can make it better by defining a couple of custom operators which allows us to write code much more succinctly: –
This sort of compositional frameworkl is relatively easy on the eye, and thanks to F#’s ability to generalise functions automatically, aspects are generic enough to achieve decent reuse without the need for reflection or codegen. Whilst this isn’t a replacement for everything that you can do with a framework like Unity, Ninject or Postsharp, this very simple example illustrates how you can rapidly compose functions together in a succinct manner. If you’re interested in more of this sort of thing, have a look at Railway Oriented Programming on the excellent F# for Fun and Profit website.