# The I-Combinator in Practice

This is my second post on an on-going series on my experiments investigating the practical use of Combinators. As a recap, Combinators are functional patterns that glue (AKA compose) together functions. These patterns promote single responsibility and decoupling.

The I-Combinator is more commonly known as the Identity function. You've probably seen it before. The Identity function can be defined as such in C#:

```
Func<T, T> Identity<T>() => x => x;
```

It's a function that returns its own input. Simple as that, but how useful is that? Well, it turns out that in order to write code that is *algebraic* in nature, the structures should have *algebraic* properties. Algebraic code abide by the laws of mathematics making it easier to prove and are less error prone.

The Identity function is the Identity of a function and this allows it to be composable. If this trips you up, then these examples might make more sense:

- 0 is the identity for sums
- 1 is the identity for multiplication.

## Reducing functions

When working with a list of integers, we can calculate the total as follows:

```
var numbers = {1, 2, 3, 4, 5};
var total = number.Aggregate(0, (a, b) => a + b);
```

Notice how 0 or the identity is passed into Aggregate (AKA reduce). Well, if we were to compose functions together, we could implement it as such:

```
var functions = { f, g, h, i }
var composed = functions.Aggregate(Identity, (a, b) => a(b));
```

For users of `Redux`

, you'll notice that in most implementations of the `Reducer`

, that if the `Action`

is not recognized, then return the current state. This is an example of the Identity in action.

## Conditional Pipeline Stages

Another use case is for functional pipelines. Given a pipeline, we can easily skip certain stages in the pipeline by returning the Identity function. In this case, the Identity function acts like a no-operation (noop), but allows the caller to still compose the pipeline without having to perform the conditional check.

```
public Func<T, T> DoSomething<T>(T input) {
if (input.IsValid()) {
return MyNewBehavior();
} else {
return Identity();
}
}
```

So the I-Combinator is pretty straightforward, but it's real power comes when combined with other Combinators. In fact, the most minimal turing complete language can be made with 3 Combinators and one of them is the I-Combinator.