# Functor

`Functor`

is a type class that abstracts over type constructors that can be `map`

‘ed over. Examples of such
type constructors are `List`

, `Option`

, and `Future`

.

```
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
// Example implementation for Option
implicit val functorForOption: Functor[Option] = new Functor[Option] {
def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa match {
case None => None
case Some(a) => Some(f(a))
}
}
```

A `Functor`

instance must obey two laws:

- Composition: Mapping with
`f`

and then again with`g`

is the same as mapping once with the composition of`f`

and`g`

`fa.map(f).map(g) = fa.map(f.andThen(g))`

- Identity: Mapping with the identity function is a no-op
`fa.map(x => x) = fa`

## A different view

Another way of viewing a `Functor[F]`

is that `F`

allows the lifting of a pure function `A => B`

into the effectful
function `F[A] => F[B]`

. We can see this if we re-order the `map`

signature above.

```
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
def lift[A, B](f: A => B): F[A] => F[B] =
fa => map(fa)(f)
}
```

## Functors for effect management

The `F`

in `Functor`

is often referred to as an “effect” or “computational context.” Different effects will
abstract away different behaviors with respect to fundamental functions like `map`

. For instance, `Option`

’s effect
abstracts away potentially missing values, where `map`

applies the function only in the `Some`

case but
otherwise threads the `None`

through.

Taking this view, we can view `Functor`

as the ability to work with a **single** effect - we can apply a pure
function to a single effectful value without needing to “leave” the effect.

## Functors compose

If you’re ever found yourself working with nested data types such as `Option[List[A]]`

or a
`List[Either[String, Future[A]]]`

and tried to `map`

over it, you’ve most likely found yourself doing something
like `_.map(_.map(_.map(f)))`

. As it turns out, `Functor`

s compose, which means if `F`

and `G`

have
`Functor`

instances, then so does `F[G[_]]`

.

Such composition can be achieved via the `Functor#compose`

method.

```
import cats.Functor
import cats.instances.list._
import cats.instances.option._
```

```
val listOption = List(Some(1), None, Some(2))
// listOption: List[Option[Int]] = List(Some(1), None, Some(2))
// Through Functor#compose
Functor[List].compose[Option].map(listOption)(_ + 1)
// res1: List[Option[Int]] = List(Some(2), None, Some(3))
```

This approach will allow us to use composition without wrapping the value in question, but can
introduce complications in more complex use cases. For example, if we need to call another function which
requires a `Functor`

and we want to use the composed `Functor`

, we would have to explicitly pass in the
composed instance during the function call or create a local implicit.

```
def needsFunctor[F[_]: Functor, A](fa: F[A]): F[Unit] = Functor[F].map(fa)(_ => ())
def foo: List[Option[Unit]] = {
val listOptionFunctor = Functor[List].compose[Option]
type ListOption[A] = List[Option[A]]
needsFunctor[ListOption, Int](listOption)(listOptionFunctor)
}
```

We can make this nicer at the cost of boxing with the `Nested`

data type.

```
import cats.data.Nested
import cats.syntax.functor._
```

```
val nested: Nested[List, Option, Int] = Nested(listOption)
// nested: cats.data.Nested[List,Option,Int] = Nested(List(Some(1), None, Some(2)))
nested.map(_ + 1)
// res3: cats.data.Nested[List,Option,Int] = Nested(List(Some(2), None, Some(3)))
```

The `Nested`

approach, being a distinct type from its constituents, will resolve the usual way modulo
possible SI-2712 issues (which can be addressed through partial unification),
but requires syntactic and runtime overhead from wrapping and unwrapping.