# Quick notes on functors

## Functors

A functor is a design pattern that allows us to apply a function to a contextualized (wrapped) type. This is accomplished by implementing the `map`

function:

```
fmap :: (a -> b) -> f a -> f b
```

The function definition receives two parameters:

- a function that takes an instance of
*A*and returns an instance of*B*and - a contextualized (wrapped) instance of A (
*F[A]*in scala or*f a*in haskell), and returns a contextualized instance of B.

Laws:

- If we map the
`id`

function over a functor, the functor that we get back should be the same as the original functor. For example:

```
ghci> fmap id [1..5]
[1,2,3,4,5]
ghci> fmap id (Just 3)
Just 3
ghci> fmap id []
[]
ghci> fmap id Nothing
Nothing
```

- Composing two functions and then mapping the result function over a functor should be the same as first mapping one function over the functor and then mapping the other one. That is
`fmap (f . g) F = fmap f (fmap g F)`

.

## Applicative functors

Functors are useful when mapping over functions that take one parameter. For mapping over functions with two or more we use Applicative functors. There are two functions to implement:

```
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
```

The `<*>`

function looks very similar to fmap, but the first parameter takes a functor that has a function in it and the second one has another functor. `<*>`

extracts the function from the first one and applies it to the second one. The `Applicative`

instance implementation for `Maybe`

looks like this:

```
instance Applicative Maybe where
pure = Just
Nothing <*> _ = Nothing
(Just f) <*> something = fmap f something
```

Notice that we are calling `fmap`

inside the implementation of `<*>`

. Remember that an Applicative functor is a Functor too, therefore we need to implement `fmap`

.

Applicative examples:

```
ghci> Just (+3) <*> Just 9
Just 12
ghci> pure (+3) <*> Just 10
Just 13
ghci> Just (++"hahah") <*> Nothing
Nothing
ghci> Nothing <*> Just "woot"
Nothing
ghci> pure (+) <*> Just 3 <*> Just 5
Just 8
ghci> pure (+) <*> Just 3 <*> Nothing
Nothing
ghci> pure (+) <*> Nothing <*> Just 5
Nothing
```

A similar example can be created using Scala and Cats. We first need to add the following libraries to `build.sbt`

:

```
libraryDependencies += "org.typelevel" %% "cats-effect" % "2.5.4"
libraryDependencies += "org.typelevel" %% "cats-core" % "2.3.0"
```

Applicative functor example:

```
import cats.Functor
trait Applicative[F[_]] extends Functor[F] {
def pure[A](a: => A): F[A]
def <*>[A,B](fa: => F[A])(f: => F[A => B]): F[B]
}
implicit val listApplicative: Applicative[List] =
new Applicative[List] {
def pure[A](a: => A): List[A] = List(a)
def <*>[A,B](fa: => List[A])(f: => List[A => B]): List[B] = for {
elem <- fa
func <- f
} yield func(elem)
def map[A,B](fa: List[A])(f: A => B): List[B] =
<*>(fa)(pure(f))
}
object Applicative {
def apply[F[_]](implicit a: Applicative[F]) = a
}
val add = (x: Int, y: Int) => x + y
val list1 = List(1, 2, 3)
val list2 = List(4, 5, 6)
val x = Applicative[List].<*>(list2)(Functor[List].map(list1)(add.curried))
```

where the result is the sum of each of the elements of `list1`

plus `list2`

:

```
res0: List[Int] = List(5, 6, 7, 6, 7, 8, 7, 8, 9)
```

## References

- Lipovača, Miran. “Functors, Applicative Functors and Monoids”. Learn You a Haskell for Great Good!, learnyouahaskell.com/functors-applicative-functors-and-monoids