# 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.

Apply examples

### 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((), (), ())
``````

Tags:

Categories:

Updated: