Functor

In category theory, a functor is a mapping between categories. Practically speaking, this allows a function of type A => B to be lifted to a function of type F[A] => F[B], for some type constructor F.

.--------------.         .-------------------.
|  Category _  |         |   Category F[_]   |
|--------------|         |-------------------|
| A            |         |   F[A]            |
| B            |         |   F[B]            |
| A => B   ~~~~~~~ map ~~~~> F[A] => F[B]    |
'--------------'         '-------------------'

This can be read as:

  1. The category _ contains objects of type A and B, and a morphism from A to B.
  2. The category F[_] contains objects of type F[A] and F[B], and a morphism from F[A] to F[B].
  3. A functor for F[_] maps morphisms from _, for example converting A => B into F[A] => F[B].

This is useful when you have a value of type F[A] and you want to apply a function of type A => B to it, resulting in a value of type F[B].

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

object Functor {
  implicit class FunctorOps[A, F[_]: Functor](fa: F[A]) {
    def map[B](f: A => B): F[B] =
      implicitly[Functor[F]].map(fa)(f)
  }
}