### Haskell composition operator fun: (.).(.)

I've been learning Haskell over the summer, and have definitely had my fair share of head-scratching moments!

Having seen this reddit thread, I attempted to figure out the type of the expression `(.).(.)` which is the infix representation of `(.)(.)(.)` (the function composition operator, applied to itself twice).

This was not an easy task for a novice Haskeller such as myself, so hopefully others may benefit from my notes that follow.

The type of the operator `(.)` is:

``````(.) :: (b -> c) -> (a -> b) -> a -> c
``````

The first step of figuring out the type of `(.)(.)(.)` is to calculate the type of `(.)(.)`

Since we are applying the (.) section (a section is a partially applied operator) to itself, we shall rename the parameter types to avoid confusion. The first argument, `(.)` (we shall call it `(.)1`) therefore has the following type:

``````(.)1 :: (b1 -> c1) -> (a1 -> b1) -> a1 -> c1
``````

When applying `(.)` to the single argument `(.)1` we are 'substituting'

``````(b -> c)
``````

for

``````(b1 -> c1) -> (a1 -> b1) -> a1 -> c1
``````

taking a three-parameter function and passing it to something that expects a one-parameter function. Therefore, the result is a two-parameter function. This is as if the original function took a a two-parameter function as a parameter.

Matching the types gives us the following 'mappings':

``````b :: (b1 -> c1)
``````

and

``````c :: (a1 -> b1) -> a1 -> c1
``````

In `(.)`'s signature, the result of providing a single argument is of type: `(a -> b) -> a -> c`

but using the type 'mappings', we obtain a result that looks like:

``````(.)(.) :: (a -> (b1 -> c1)) -> a -> (a1 -> b1) -> a1 -> c1
``````

Notice how we've replaced the original single parameter with two new parameters.

We can then repeat for the second argument of `(.)`, which we shall name `(.)2` and has type:

``````(b2 -> c2) -> (a2 -> b2) -> a2 -> c2
``````

N.B. `(.)(.)` takes 4 parameters, the first being a function of type ```a -> (b1 -> c1)```.

When we apply `(.)(.)` to `(.)` we are providing its first parameter, which gives us type mappings of:

``````a :: (b2 -> c2)
``````

and

``````(b1 -> c1) :: (a2 -> b2) -> a2 -> c2
``````

therefore:

``````b1 :: (a2 -> b2)
``````

and

``````c1 :: a2 -> c2
``````

The result of applying `(.)(.)` to a single argument is ```a -> (a1 -> b1) -> a1 -> c1``` But using our mappings we see that the type is:

``````(.)(.)(.) :: (b2 -> c2) -> (a1 -> a2 -> b2) -> a1 -> a2 -> c2
``````

We can rename some types to simplify to the result given by GHCi:

``````(.)(.)(.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
``````

Which is a function that takes a single-parameter function, a two-parameter function, and two values. The result is obtained by applying the two-parameter function to the two values and passing the result to the single-parameter function.

...and with that we've solved the puzzle!