# Functor

A non-mathematical introduction to functors.

`Option` and `List` are two well-known classes, both of which have the function `map` that takes a function that is applied to the values contained by the `List` or `Option`.

Here are two functions that take `List[Int]` and `Option[Int]` and increments the values:

``````def inc(o: Option[Int]): Option[Int] = o.map(i => i + 1)

def inc(l: List[Int]): List[Int] = l.map(i => i + 1)
``````

The `inc` functions do not care about `Option` or `List` particularly, they need a way to work on the values they contain, but sadly `inc` is duplicated. It doesn’t have to be.

One way to fix this is to use a `Functor` that supplies a `map` function for any `F[_]`.

``````// scala 3
trait Functor[F[_]] {
extension [A, B](x: F[A])
def map(f: A => B): F[B]
}
``````

Given `x: F[A]`, `Functor[F]` provides a `map` method. Here is `inc` written using `Functor[F]`:

``````def inc[F[_]: Functor](a: F[Int]): F[Int] = a.map(i => i + 1)
``````

`F[_]: Functor` means that it requires an instance of `Functor[F]`. Scala finds that instance by looking in lots of places for it, one being the companion object of the `F[_]`.

For `Option` and `List` those instances are:

``````given Functor[Option] with {
extension [A, B](m: Option[A])
override def map(f: A => B): Option[B] = m.map(f)
}

given Functor[List] with {
extension [A, B](m: List[A])
override def map(f: A => B): List[B] = m.map(f)
}
``````

Your own classes can play too:

``````final case class Blub[A](v: A)

object Blub {
given Functor[Blub] with {
extension [A, B](blub: Blub[A])
override def map(f: A => B): Blub[B]
= Blub(f(blub.v))
}
}

inc(Blub(1)) gives Blub(2)
``````

Note that this is an example of the typeclass pattern, read more here.

## Laws

A proper functor must obey two laws:

1. Identity: Mapping with the identity function is a no-op
2. Composition: `fa.map(f).map(g) = fa.map(f.andThen(g)`