Thinking Functionally: Function composition

We've mentioned function composition a number of times in passing now, but what does it actually mean? It can seem quite intimidating at first, but it is actually quite simple.

Say that you have a function `f` that maps from type `T1` to type `T2`, and say that you also have a function `g` that maps from type `T2` to type `T3`. Then you can connect the output of `f` to the input of `g`, creating a new function that maps from type `T1` to type `T3`.

Here's an example:

```static float f(int x)  => x * 3.0f;  // f is int->float
static bool g(float x) => x > 4.0f;  // g is float->bool```

We can create a new function `h` that takes the output of `f` and uses it as the input for `g`.

```static bool h(int x)
{
var y = f(x);
return g(y);
}```

A much more compact way is this:

```static bool h(int x) => g(f(x));    // h is int->bool

//test
var x = h(1);   // x == false
var y = h(2);   // y == true```

So far, so straightforward. What is interesting is that we can define a new function called `compose` that, given functions `f` and `g`, combines them in this way without even knowing their signatures.

```static Func<A, C> compose<A, B, C>(Func<A, B> a, Func<B, C> b) =>
v => b(a(v));```

`compose` is part of `LanguageExt.Prelude` and can be used to compose up to 7 functions.

Now we compose `f` and `g` from before into a combined function of `h`:

```Func<int, bool> h = compose(f, g);

//test
var x = h(1);   // x == false
var y = h(2);   // y == true```

You can also call the `Compose` extension method on `Func<A, B>` if you prefer the more fluent style.

```Func<int, bool> h = f.Compose(g);

//test
var x = h(1);   // x == false
var y = h(2);   // y == true```

The `backCompose` Prelude function and the `BackCompose` extension methods can be used to flip the composition of the functions.

Limitations

Because of a limitation in how C# treats 'method groups', you will have to provide the generic arguments if you're working with static methods:

`var h = compose<int, float, bool>(f, g);`

One way around that is to declare your static methods as readonly static fields:

```static readonly Func<int, float> f =
x => x * 3.0f;

static readonly Func<float, bool> g =
x => x > 4.0f;```

This is a really frustrating limitation of C# and has been raised as an issue. The readonly static field approach isn't too bad, although there may be performance considerations in regular use. It does however make all uses of the first-class functions very easy to parse:

This

`var h = compose(f, g);`

Is clearer than this:

`var h = compose<int, float, bool>(f, g);`

NEXT: Combinators

Clone this wiki locally
You can’t perform that action at this time.
Press h to open a hovercard with more details.