# Explore “herding cats”: Semigroupal, Apply, Applicative

### Semigroupal

```
trait Semigroupal[F[_]] extends Serializable {
def product[A, B](fa: F[A], fb: F[B]): F[(A, B)]
}
```

Here we’re dealing with cartesian product.

```
Semigroupal[Option].product(1.some, 2.some) === (1,2).some
Semigroupal[Option].product(1.some, none[Int]) === none[(Int, Int)]
Semigroupal[List].product(List(1, 2, 3), List("foo", "bar")) === List((1, "foo"), (1, "bar"), (2, "foo"), (2, "bar"), (3, "foo"), (3, "bar"))
```

### Apply

Apply is quite tricky.

There are plenty of explanations that aren’t bringing much sense to me.

Docs describe main function `def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]`

as “Given a value and a function in the Apply context, applies the function to the value.”

That still far away from motivation since our usual friends like `List`

or `Option`

typically shouldn’t handle function inside.

More or less good wording sounds like “apply lifts function `A => B`

to container F[_]”.

It’s easy to construct such kind of composition where we build `Option[A => B]`

and pass values there but that’s not a tooling for everyday anyway.

What is ap provides another one example.

```
val applyOption: Apply[Option] = Apply[Option]
val optionOfStringToUpperCase: Option[String] => Option[String] = applyOption.ap[String, String](((s: String) => s.toUpperCase).some)
val upper1 = optionOfStringToUpperCase("string".some)
upper1 === "STRING".some
optionOfStringToUpperCase(none[String]) === none
val toUpper: String => String = _.toUpperCase
val upper2 = toUpper.some <*> "string".some
upper2 === "STRING".some
```

`ap2`

and `map2`

are introduced here too.

```
Apply[Option].map2("hello ".some, "world".some)(_ + _) === "hello world".some
Apply[Option].map2(none[String], "world".some)(_ + _) === none[String]
val composeTwoOptions: (Option[String], Option[Int]) => Option[String] = Apply[Option].ap2(((s: String, i: Int) => s + i).some)
composeTwoOptions.apply("hi".some, 1.some) === "hi1".some
composeTwoOptions.apply("hi".some, none[Int]) === none[String]
```

Product left/right are important tools, and they’re declared at Apply.

The allows to omit result of computations on the left/right side.

```
"hello".some *> "world".some === "world".some
"hello".some <* "world".some === "hello".some
none[String] *> "world".some === none[String]
none[String] <* "world".some === none[String]
```

#### mapN magic

`cats.ApplyArityFunctions`

is responsible for bringing `map3`

, `map4`

, etc.

```
Apply[Option].map3(2.some, 2.some, 1.some)(_ + _ + _) === 5.some
```

`cats.syntax.TupleSemigroupalSyntax`

brings some magic with `mapN`

:

```
(1.some, 2.some).mapN { case (a, b) => a + b } === 3.some
```

Magic is multiplied by zero under the hood:

```
private[syntax] final class Tuple3SemigroupalOps[F[_], A0, A1, A2](private val t3: Tuple3[F[A0], F[A1], F[A2]]) {
def mapN[Z](f: (A0, A1, A2) => Z)(implicit functor: Functor[F], semigroupal: Semigroupal[F]): F[Z] = Semigroupal.map3(t3._1, t3._2, t3._3)(f)
```

So, there are just dozens of implementations.

### Applicative

Typically `Applicative`

is described as applicative functor where `map`

, `ap`

, and `pure`

are equally important.

We already considered `Apply`

and `Functor`

, hence we’re interested in `pure`

method responsible for initialization of specified container: `def pure[A](a: A): F[A]`

For Either it is going to be `Right(a)`

, Option has `Some(a)`

, and so on.

Even while it seems extremely natural when we work with particular implementations it is vital to have abstraction to describe such a thing.

There are good definitions for `pure`

and `product`

: (Applicative Typeclass)[https://typelevel.org/cats/typeclasses/applicative.html#applicative]

```
Applicative[Option].pure(1) === 1.some
Applicative[Vector].pure(1) === Vector(1)
```

You can “replicate” values inside F:

```
Applicative[Option].replicateA(3, 1.some) === List(1, 1, 1).some
```

Applicative is composable:

```
Applicative[List].compose[Vector].compose[Option].pure(3) === List(Vector(3.some))
```

Some unit-functions that could be used when you need to preserve F-context but content doesn’t matter or should be hidden:

```
Applicative[Option].unit === ().some
Applicative[List].whenA(true)(List(1, 2, 3)) === List((), (), ())
```