# Exploring properties of function composition in Kotlin

Function composition is a technique where you create a new function by applying the result of one function to another. I've sometimes heard this described as "chaining" multiple functions together.

Assuming two functions \(f(x)\) and \(g(x)\), we can compose a new function \(h(x)\) by passing the result of \(g(x)\) to \(f(x)\)

\[h(x)=f(g(x))\]

Another notation for \( f(g(x)) \) is \(f \circ g(x) )\) ( or \(f \circ g\) omitting the parameter), read as \(f\) of \(g\) of \(x\), or \(f\) after \(g\) of \(x\).

We can begin to describe this as code by declaring `f`

and `g`

functions. Here `f`

is a function that accepts a Double an returns a String, while `g`

is a function that accepts an Integer and returns a Double.

```
val f: (Double) -> String = { x ->
"$x"
}
val g: (Int) -> Double = { x ->
x * 1.0
}
```

We can compose these functions by declaring a new function `h`

that applies the result of `f`

and then `g`

. This creates a new function that accepts an Integer and returns a String.

```
val h: (Int) -> String = { x -> f(g(x)) }
```

By composing the functions we've created a new function that's a direct mapping from Integer to String.

We can create a higher order function to generify the process of composing functions easier. Note that the order of the parameters is resolved right to left to match the mathematical notation.

```
fun <T, U, V> compose(fn2: (U) -> V, fn1: (T) -> U): (T) -> V {
return { fn2(fn1(it)) }
}
```

and refactor the previous example to use `compose`

to create `h`

```
val h: (Int) -> String = compose(f, g)
```

Category Theory for Programmers^{[1]} describes two properties that composition in any category must satisfy.

- "Composition is associative" - Regardless of how they are grouped by parenthesis, the result should always be the same
^{[2]}.

\[ f \circ (g \circ h) = (f \circ g) \circ h = f \circ g \circ h \]

Let's update our example to demonstrate this

```
val f: (Double) -> String = { x ->
"$x"
}
val g: (Int) -> Double = { x ->
x * 1.0
}
val h: (List<Int>) -> Int = {
it.size
}
```

We now have 3 functions `f`

, `g`

, and `h`

which have their corresponding implementations. Composing the functions in any pair gives us the same result.

```
val `f o g o h`: (List<Int>) -> String = {
f(g(h(x)))
}
val `(f o g) o h`: (List<Int>) -> String = compose(compose(f, g), h)
val `f o (g o h)`: (List<Int>) -> String = compose(f, compose(g, h))
```

- "For every object A there is an arrow which is a unit of composition. This arrow loops from the object to itself" - This describes an identity function.

\[ f \circ \text{id}_A = f\]

or

\[ \text{id}_B \circ f = f\]

We can describe an identity \( \text{id}_A \), read identity on A as a mapping to itself.

In code, it's a function that returns the value that is passed to it

```
fun <T> id(x: T): T {
return x
}
```

When composed with another function, we can see that the result is the function it was composed with as expected.

```
val `f o id`: (Double) -> String = compose(f, ::id)
val `id o f`: (Double) -> String = compose(::id, f)
```

Category: The essence of composition (2014) Bartosz Milewski’s Programming Cafe. Available at: https://bartoszmilewski.com/2014/11/04/category-the-essence-of-composition/ (Accessed: January 22, 2024). ↩︎

If you are interested in proofs, this Stackoverflow thread breaks it down in a couple of different ways. ↩︎