## What is a Functor?

Chances are you’ve already used a Functor. You probably use it everyday irrespective of the language you use. Paraphrasing Typeclassopedia: “A Functor represent a container of some sort with the ability to apply a function uniformly to every element of that container”.

Say we had a List of words and we wanted to find out the lengths of each of those words. We would use a List[String], find the length of each String and get a List[Int] in return.

In scala we could do something like:

``````List("one", "two", "three") map (_.length)
res12: List[Int] = List(3, 3, 5)``````

We applied the length function to each element of the List “container”. What has also happened is that a List[String] has been converted to a List[Int]. We started with a List of words and we end up with a List of word-lengths.

Functors operate on type constructors - which are types that need additional types parameters to be constructed. List[T], Map[K, V], Option[T] and Either[L,R] etc are all type constructors as they need one or more types to be constructed.

For example:

``````List -> is a type constructor
List[Long] -> is a type``````

A functor can be defined as:

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

Assuming the F type constructor was List, the above trait could be implemented as:

``````class ListFunctor extends Functor[List] {
def fmap[A,B](f: A => B, fa:List[A]): List[B] = fa match {
case Nil => Nil
case x::xs => f(x) :: fmap(f, xs)
}
}``````

All Functor implementations traverse over the type supplied and apply the function f, to each element within that type. In the case of List, f is applied to each element of the List.

We could use the ListFunctor as:

``new ListFunctor().fmap((_:String).length, List("one", "two", "three"))``

This gives us the same results as before, but we’ve abstracted over the List type constructor and we can covert from List[A] -> List[B] where A and B are any types.

Import points to note are:

1. The container remains the same (F or in the above case List)
2. The supplied function f, works on the value contained within the container.

As per Typeclassopedia: “fmap applies a function to each element of the container without altering the structure of the container”

## Some Examples

Let’s create our own type constructor to hold a single value. Let’s call it Holder:

``case class Holder[T](value:T)``

Now let’s define a Functor for Holder:

``````class HolderFunctor extends Functor[Holder] {
def fmap[A,B](f: A => B, fa:Holder[A]): Holder[B] = Holder(f(fa.value))
}``````

Here’s how we use it:

``````new HolderFunctor().fmap("Give me " + (_:Int).toString, Holder(5))
res0: Holder[String] = Holder(Give me 5)``````

We converted a Holder [Int] -> Holder [String] by mapping across the value in the Holder.

## Functor Laws

There are 2 Functor laws:

1. mapping with identity over every item in a container has no effect
``fmap(identity, F[A]) == F[A]``
1. mapping a composition of two functions over any item in a container is the same as mapping the first function and then mapping the second.
``fmap(g compose f, F[A]) ==  fmap(g, fmap(f, F[A]))``

Let’s see if HolderFunctor obeys these 2 laws:

``````new HolderFunctor().fmap(identity(_:Int), Holder(5)) == Holder(5)
res11: Boolean = true

def giveMe: Int => String = n => "Give me " + n.toString
def strLength: String => Int = str => str.length

new HolderFunctor().fmap(strLength compose giveMe, Holder(5)) ==
new HolderFunctor().fmap(strLength, new HolderFunctor().fmap(giveMe, Holder(5)))
res13: Boolean = true``````

Looks like it does obey both laws. :)

## Why use Functors?

So here’s the real question: Why use Functors? By defining Functors for each container you are interested in, you could define a single function that fmaps across any container containing any type:

``def fmap[F[_], A, B](f: A => B, fa: F[A])(implicit functor:Functor[F]): F[B] = functor.fmap(f, fa)``

Let’s try and call it with Holder:

``````case class Person(name:String)
fmap((_:Person).name, Holder(Person("Harry Potter")))
11: error: could not find implicit value for parameter functor: Functor[Holder]``````

Let’s create an implicit Functor[Holder]:

``````implicit def holderFunctor: Functor[Holder] = new HolderFunctor()
fmap((_:Person).name, Holder(Person("Harry Potter")))
res23: Holder[String] = Holder(Harry Potter)``````

Let’s try and use it with Functor[List]:

``````fmap("|" + (_:Int).toString + "|", List(1,2,3,4))
12: error: could not find implicit value for parameter functor: Functor[List]``````

Let’s create an implicit Functor[List]:

``````implicit def listFunctor: Functor[List] = new ListFunctor()
fmap("|" + (_:Int).toString + "|", List(1,2,3,4))
res28: List[java.lang.String] = List(|1|, |2|, |3|, |4|)``````

What if we want to use it with Option? We simply create an implicit Functor[Option]:

``````implicit def optionFunctor: Functor[Option] = new Functor[Option] {
def fmap[A,B](f: A => B, fa:Option[A]): Option[B] = fa map (f)
}``````

We can now call fmap with Option:

``````fmap((_:Int).toString + " optional", Some(123):Option[Int])
res37: Option[java.lang.String] = Some(123 optional)``````

Verifying the laws for Functor[Option]:

``````optionFunctor.fmap(identity(_:Int), Some(6)) == Some(6)
res17: Boolean = true

optionFunctor.fmap(identity(_:Int), None) == None
res18: Boolean = true

optionFunctor.fmap(strLength compose giveMe, Some(6)) == optionFunctor.fmap(strLength, optionFunctor.fmap(giveMe, Some(6)))
res19: Boolean = true

optionFunctor.fmap(strLength compose giveMe, None) == optionFunctor.fmap(strLength, optionFunctor.fmap(giveMe, None))
res20: Boolean = true``````

We could further simplify fmap as:

``def fmap[F[_] : Functor, A, B](f: A => B, fa: F[A]): F[B] = implicitly[Functor[F]].fmap(f, fa)``

Functor has allowed us to define a single fmap function to map across any container for any value type! :)

Here’s a listing of the snippets:

``````List("one", "two", "three") map (_.length)

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

class ListFunctor extends Functor[List] {
def fmap[A,B](f: A => B, fa:List[A]): List[B] = fa match {
case Nil => Nil
case x::xs => f(x) :: fmap(f, xs)
}
}

new ListFunctor().fmap((_:String).length, List("one", "two", "three"))

case class Holder[T](value:T)

class HolderFunctor extends Functor[Holder] {
def fmap[A,B](f: A => B, fa:Holder[A]): Holder[B] = Holder(f(fa.value))
}

new HolderFunctor().fmap("Give me " + (_:Int).toString, Holder(5))
new HolderFunctor().fmap(identity(_:Int), Holder(5)) == Holder(5)

def giveMe: Int => String = n => "Give me " + n.toString
def strLength: String => Int = str => str.length

new HolderFunctor().fmap(strLength compose giveMe, Holder(5)) ==
new HolderFunctor().fmap(strLength, new HolderFunctor().fmap(giveMe, Holder(5)))

def fmap[F[_], A, B](f: A => B, fa: F[A])(implicit functor:Functor[F]): F[B] = functor.fmap(f, fa)

case class Person(name:String)

implicit def holderFunctor: Functor[Holder] = new HolderFunctor()
fmap((_:Person).name, Holder(Person("Harry Potter")))

implicit def listFunctor: Functor[List] = new ListFunctor()
fmap("|" + (_:Int).toString + "|", List(1,2,3,4))

implicit def optionFunctor: Functor[Option] = new Functor[Option] {
def fmap[A,B](f: A => B, fa:Option[A]): Option[B] = fa map (f)
}

fmap((_:Int).toString + " optional", Some(123):Option[Int])

optionFunctor.fmap(identity(_:Int), Some(6)) == Some(6)
optionFunctor.fmap(identity(_:Int), None) == None

optionFunctor.fmap(strLength compose giveMe, Some(6)) == optionFunctor.fmap(strLength, optionFunctor.fmap(giveMe, Some(6)))
optionFunctor.fmap(strLength compose giveMe, None) == optionFunctor.fmap(strLength, optionFunctor.fmap(giveMe, None))

def fmap2[F[_] : Functor, A, B](f: A => B, fa: F[A]): F[B] = implicitly[Functor[F]].fmap(f, fa)``````