# FunctionK

API Documentation: FunctionK

A `FunctionK`

transforms values from one first-order-kinded type (a type that takes a single type
parameter, such as `List`

or `Option`

) into another first-order-kinded type. This transformation is
universal, meaning that a `FunctionK[List, Option]`

will translate all `List[A]`

values into an
`Option[A]`

value for all possible types of `A`

. This explanation may be easier to understand if we
first step back and talk about ordinary functions.

## Ordinary Functions**

Consider the following scala method:

`def first(l: List[Int]): Option[Int] = l.headOption`

This isn't a particularly helpful method, but it will work as an example. Instead of writing this as a
method, we could have written this as a function *value*:

`val first: List[Int] => Option[Int] = l => l.headOption`

And here, `=>`

is really just some syntactic sugar for `Function1`

, so we could also write that as:

`val first: Function1[List[Int], Option[Int]] = l => l.headOption`

Let's cut through the syntactic sugar even a little bit further. `Function1`

isn't really a special type.
It's just a trait that looks something like this:

```
// we are calling this `MyFunction1` so we don't collide with the actual `Function1`
trait MyFunction1[A, B] {
def apply(a: A): B
}
```

So if we didn't mind being a bit verbose, we could have written our function as:

```
val first: Function1[List[Int], Option[Int]] = new Function1[List[Int], Option[Int]] {
def apply(l: List[Int]): Option[Int] = l.headOption
}
```

## Abstracting via Generics**

Recall our `first`

method:

`def first(l: List[Int]): Option[Int] = l.headOption`

The astute reader may have noticed that there's really no reason that this method needs to be tied directly to `Int`

. We could use generics to make this a bit more general:

`def first[A](l: List[A]): Option[A] = l.headOption`

But how would we represent this new `first`

method as a `=>`

/`Function1`

value? We are looking for something like a type of `List[A] => Option[A] forAll A`

, but this isn't valid scala syntax. `Function1`

isn't quite the right fit, because its `apply`

method doesn't take a generic type parameter.

## Higher Kinds to the Rescue**

It turns out that we can represent our universal `List`

to `Option`

transformation with something that looks a bit like `Function1`

but
that adds a type parameter to the `apply`

method and utilizes higher kinds:

```
trait MyFunctionK[F[_], G[_]] {
def apply[A](fa: F[A]): G[A]
}
```

Cats provides this type as `FunctionK`

(we used `MyFunctionK`

for our example type to avoid confusion). So now we can write `first`

as a `FunctionK[List, Option]`

value:

```
import cats.arrow.FunctionK
val first: FunctionK[List, Option] = new FunctionK[List, Option] {
def apply[A](l: List[A]): Option[A] = l.headOption
}
```

## Syntactic Sugar**

If the example above looks a bit too verbose for you, the kind-projector
compiler plugin provides a more concise syntax.
After adding the plugin to your project, you could write the `first`

example as:

`val first: FunctionK[List, Option] = λ[FunctionK[List, Option]](_.headOption)`

Cats also provides a `~>`

type alias for `FunctionK`

, so an even more concise version would be:

```
import cats.~>
val first: List ~> Option = λ[List ~> Option](_.headOption)
```

Being able to use `~>`

as an alias for `FunctionK`

parallels being able to use `=>`

as an alias for `Function1`

.

## Use-cases**

`FunctionK`

tends to show up when there is abstraction over higher-kinds. For example, interpreters for free monads and free applicatives are represented as `FunctionK`

instances.

## Types with more than one type parameter**

Earlier it was mentioned that `FunctionK`

operates on first-order-kinded types (types that take a single type parameter such as `List`

or `Option`

). It's still possible to use `FunctionK`

with types that would normally take more than one type parameter (such as `Either`

) if we fix all of the type parameters except for one. For example:

```
type ErrorOr[A] = Either[String, A]
val errorOrFirst: FunctionK[List, ErrorOr] =
λ[FunctionK[List, ErrorOr]](_.headOption.toRight("ERROR: the list was empty!"))
```

## Natural Transformation**

In category theory, a natural transformation provides a morphism between Functors while preserving the internal structure. It's one of the most fundamental notions of category theory.

If we have two Functors `F`

and `G`

, `FunctionK[F, G]`

is a natural transformation via parametricity. That is, given `fk: FunctionK[F, G]`

, for all functions `A => B`

and all `fa: F[A]`

the following are equivalent:

`fk(F.map(fa)(f)) <-> G.map(fk(fa))(f)`

We don't need to write a law to test the implementation of the `fk`

for the above to be true. It's automatically given by parametricity.

Thus natural transformation can be implemented in terms of `FunctionK`

. This is why a parametric polymorphic function `FunctionK[F, G]`

is sometimes referred as a natural transformation. However, they are two different concepts that are not isomorphic.

For more details, Bartosz Milewski has written a great blog post titled "Parametricity: Money for Nothing and Theorems for Free".