# Monad vs Monoid In Scala

This post is a sequel to Monad In Scala, Applicative vs Monad in Scala and Semigroup And Monoid In Scala.

So far we’ve made our journey through two realms of typeclasses: `Functor`

, `Applicative`

to `Monad`

and `Semigroup`

to `Monoid`

. This post won’t introduce any new typeclass but rather give some general insights over how these two realms of typeclasses connect and maybe talk a little about category theory which is an overarching mathematical field where many of these typeclasses originate.

## Realm of Monad

For the sake of illustration, we will generalize over `Functor`

, `Applicative`

and `Monad`

as simply a **Monad**.

**Monad** lets us operate on values within some **context**. Here, **context** refers to some computational context which wraps the inner value.

`Future[A]`

monad wraps value of type `A`

within the **context** of being *eventually computed in the future* and exposes a certain set of methods that defines operations on them.

`Option[A]`

monad wraps value of type `A`

within the **context** of being *optional* and exposes a certain set of methods that defines operations on them.

`List[A]`

monad wraps value of type `A`

within the **context** of being *varying number of values (non-deterministic)* and exposes a certain set of methods that defines operations on them.

Note that an actual monad instance is the type constructor itself without the type parameter, for example `Future`

is a monad instance not `Future[A]`

since it’s a concrete type. But it’s an irrelevant detail for us now.

Now, the way we **operate** these values within contexts is by passing a function to its methods. Then, internally each `Monad`

instance will **lift** these functions to the given **context** (refer to this as to what **lift**ing is). This is an important point. All that `Monad`

does is **providing a way to operate on these values within context** through methods like `map`

, `flatMap`

, `flatten`

etc. All these methods are **higher-order functions** which means they rely on passed functions to actually do some useful operations.

Again, keep in mind, `Monad`

simply exposes higher-order functions with defined semantics (whether they simply `map`

over values or `map`

and then `flatten`

over values, for example) enforced by the type signature of function that it accepts. It completely relies on the function passed in to do the real computation.

## Realm of Monoid

Again, for the sake of illustration, we generalize over `Semigroup`

and `Monoid`

as **Monoid**.

**Monoid** lets us combine values within some **context**. Again, **context** means the same thing.

`Future[A]`

monoid combine values of type `A`

within the **context** of being *eventually computed in the future*.

`Option[A]`

monoid combine values of type `A`

within the **context** of being *optional*.

`List[A]`

monoid combine values of type `A`

within the **context** of being *varying number of values (non-deterministic)*.

Note that with `Monoid`

, the actual instance is the concrete type, not type constructor unlike `Monad`

. So for example, `Future[A]`

is, in fact, the instance of `Monoid`

, but not `Future[_]`

.

Redundancy here with regards to `Monad`

is intended. The only difference between `Monad`

and `Monoid`

instances we see here is that while

`Monad`

instance simply wraps the value of type `A`

within the given **context** and expose a certain set of methods to operate on them,

`Monoid`

instance already **knows** how to **combine** these values of type `A`

within the given **context**.

## Insights

A good way to see their connection is by looking at an exmaple:

```
Future(1) |+| Future(2) // Future(3)
(Future(1) |@| Future(2)) { _ + _ } // Future(3)
```

They both produce the same result, yet the first operation relies on `Monoid[Future[A]]`

while the second operation relies `Monad[Future]`

(they are defined in `scalaz.std.Future`

).

This example makes the difference explicit. `Monoid`

is similar to `Monad`

in that they operate on values within context but `Monoid`

explicitly define the way to **combine** the values while `Monad`

simply gives a **way** to **combine** them but how it’s done needs to be explicitly passed in as a form of function.

## Redemption

I’ve made lots of generalizations and logical leaps to get the essential ideas across intuitively. So let me redeem myself a little here.

First of all, comparing `Monoid`

to `Monad`

isn’t fair since `Monad`

does a lot more than that, like enabling dependent operations etc. A more fair comparison would be between `Monoid`

and `Applicative`

since they resemble in many ways.

Both work on operations that are **independent** and thus can be run in parallel.

Both require similar set of primitive methods, that is `empty`

and `combine`

for `Monoid`

and `unit`

and `ap`

for `Applicative`

.

Both define similar operator to **combine** values. `Monoid`

has `|+|`

and `Applicative`

has `|@|`

as you can see above example (But of course `Monad`

has access to `|@|`

also since it extends `Applicative`

).

And in fact, `Monoid`

is readily convertible to `Applicative`

but not to `Monad`

. Scalaz’s `Monoid`

defines a method to do just that.

```
final def applicative: Applicative[({type λ[α]=F})#λ] = new Applicative[({type λ[α]=F})#λ] with SemigroupApply {
def point[A](a: => A) = zero
}
```

`SemigroupApply`

simply defines a mapping between `Monoid`

’s `zero`

(`empty`

) and `append`

(`combine`

) to `Applicative`

’s `point`

(`unit`

) and `ap`

.

`Monoid`

’s primitive methods map directly to `Applicative`

’s primitive methods. To quote documentation on `Monoid.applicative`

from Scalaz:

A monoidal applicative functor, that implements

`point`

and`ap`

with the operations`zero`

and`append`

respectively.

Note that the type parameter`α`

in`Applicative[({type λ[α]=F})#λ]`

is discarded; it is a phantom type.

As such, the functor cannot support scalaz.Bind.

## Takeaway

Use `Monoid`

when all you need is to **combine** **indepedent** operations (values within context) and how the **combine** works is fixed and thus **can** be pre-defined.

Use `Applicative`

when you need to **combine** **indepedent** operations (values within context) and how the **combine** works **cannot** be pre-defined and thus needs to pass function to do so.

Use `Monad`

when you need to **combine** **possibly dependent** operations (values within context) and how the **combine** works **cannot** be pre-defined and moreover it can **depend** on the result of the previous operation and thus need to pass function to do so.

We can see here that as we gain more **flexibility**, we also gain more **complexity** and **verbosity**:

```
Future(1) |+| Future(2) // Monoid
(Future(1) |@| Future(2)) { _ + _ } // Applicative
Future(1).flatMap(one => Future(one + 2)) // Monad
```