# Monad In Scala

During last few months, I’ve learned a bit of functional programming in Scala. To document what I’ve learned so far, there will be a few posts regarding various functional concepts mostly around typeclasses and scalaz library. These posts are purely for self-documenting purposes and it lacks proper explanation on various concepts. Unlike other posts, this post won’t be very useful to anyone since trying to explain even just the basics of these typeclasses can easily get out of hand so I didn’t bother. Also I put more emphasis on the practicality rather than theoretical correctness.

To understand `Monad`

, we start our journey with what typeclass is.

## Typeclass

Typeclass, which originates from Haskell, is nothing like `class`

. It is an `interface`

where a type can conform to. It is implemented with `trait`

in scala.

Typeclass requires you to define a certain **primitive methods** from which it **derives** other useful methods which you can use.

All that sounds very abstract because they are. It is an abstraction over types that share common patterns. Some of the examples of typeclass are `Functor`

, `Applicative`

, `Monad`

etc.

Typeclass exists for one primary reason. To enable better code reuse through abstraction.

Any type that *implements* primitive methods required by a given typeclass, becomes an **instance** of that typeclass (or more mathematically correct way to say is that *the given type forms a given typeclass*).

Like learning any abstract concept, iterating definitions lead nowhere. We need concrete examples to understand these, otherwise, abstract nonsense.

We start with `Functor`

.

## Functor

`Functor`

is a typeclass which requires primitive method `map`

, which should be familiar to most if not all.

`Functor`

is hardly useful by itself since it doesn’t do much. However, it forms the base class from which the other many useful typeclasses extend from.

`Functor`

lets you operate on values within a **context**.

By **context**, we mean something that adds additional meanings to the type by wrapping the type within it.

Think how `Option`

, which is an instance of `Functor`

(i.e it implements `map`

method) gives an additional meaning (context) to the type it wraps. `Option[Int]`

is an `Int`

that **may** or **may not** be present. It gives a context (of its existentiality) over the type that it wraps within.

## Apply

`Apply`

is a typeclass which requires primitive method `ap`

. It extends `Functor`

and therefore has access to all the methods in `Functor`

. This is where things start getting interesting.

Here is the signature of `ap`

.

```
def ap[A, B](fa: F[A])(f: F[A => B]): F[B]
```

`ap`

isn’t much different from `map`

other than the fact that its function is wrapped in the same context as the values it operate on where `F`

is the context.

So using `Option`

example, our function can be wrapped inside an `Option`

context.

Why is this useful? Using `ap`

method, we can achieve something like this.

```
def map2[A, B, Z](fa: F[A], fb: F[B])(f: F[(A, B) => Z]): F[Z] =
ap(fb)(ap(fa)(map(f)(f => (a: A) => (b:B) => f(a, b))))
```

This is `map2`

implementation from Scalaz. It looks very scary but all that we need to understand is that `ap`

allows our operations on values within context to be nested. This is possible because as said, `ap`

takes in a function that is within the context.

Most commonly, you will use `|@|`

operator in place of `ap`

method, which is one of the derived methods from `ap`

.

You can do things like:

```
(Option(1) |@| Option(2) |@| Option(3)) { (one, two, three) one + two + three } // 6
```

It allows to operate values within the same context all at the same time. `Apply`

shines particularly when the context is `Future`

where it enables the concurrent execution of all `Future`

context-bound values.

## Applicative

`Applicative`

is a typeclass which requires primitive method `pure`

. It extends `Apply`

(therefore, also `Functor`

).

`pure`

is also known as `unit`

, `point`

, etc. What it does is simple. It wraps a given value within its context.

```
def pure[A](x: A): F[A]
```

`Applicative`

doesn’t do much that `Apply`

can’t, other than providing `pure`

method, which is useful whenever you need to wrap some value within the context like:

```
Apply[Option].pure(1) // Option[Int] // which is equivalent to
Option(1)
```

To me, `Applicative`

is significant not because of what it provides but rather how it bridges us to a realm of `Monad`

by providing `pure`

method.

As with, `Apply`

, `Applicative`

is useful when you operate on values within the same context, which are **independent** to each other, therefore allowing us to operate on all of them concurrently.

## Monad

`Monad`

is a typeclass which requires primitive method `flatMap`

(or sometimes, instead, `flatten`

). It extends `Applicative`

(therefore also, `Apply`

and `Functor`

).

`Monad`

is a very useful concept. It allows us to operate on values within the context that are possibly **dependent** on the results of each other.

Note how operations in `Monad`

can **depend** on the previous operation’s result unlike `Applicative`

where all operations must be independently executed.

To understand how this is achieved, let’s look at the type signature of primitive method that it requires, `flatMap`

:

```
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
```

`flatMap`

takes a function that takes `A`

and returns `B`

with context `F`

and returns `B`

with context `F`

.

Unlike `map`

where with function `A => F[B]`

would inevitably return `F[F[B]]`

, `flatMap`

instead returns `F[B]`

. Its nested contexts `F[F[_]]`

is **flatten**ed to a single context `F[_]`

, therefore the name `flatMap`

where it `map`

the function to the value within context and then `flatten`

s the results `F[F[B]] => F[B]`

.

This is immensely useful since now it means we can do nest one `Monad`

ic operation within another `Monad`

ic operation, which lets the nested operation to access its previous operation’s result through `A`

.

Here is an example with `Option`

:

```
Option(1).flatMap(one => if (one == 1) Option(10) else Option.empty[Int] ) // Option(10)
```

It’s a stupid example but it illustrates the point nicely. Our operation of returning either `Option(10)`

or `Option.empty[Int]`

**depend** on the previous result of operation (which is really just the value of a value in the context since `Option()`

simply wraps the value within `Option`

context).

**Monad allows us to chain together operations in a monadic context**.

Here is less stupid example using `Future`

, which is yet another `Monad`

instance:

```
def fetchId: Future[Int] = ???
def fetchName(id: Int): Future[String] = ???
def fetchAddress(id: Int, name: String): Future[Address] = ???
fetchId.flatMap(id =>
fetchName(id).flatMap(name =>
fetchAddress(id, name)
)
) // Future[Address]
```

Note how each operation is nested to depend on the result of previous operations all within the context of `Future`

, without having to **unwrap** that context.

That’s Monad.

Let’s see how all these things connect.

`Functor`

allows us to operate on values within **context** with function that produces another value.

`Applicative`

allows us to operate on values within **context** with function within **context** that produces another value. (Often `Apply`

is merged into `Applicative`

as a single concept.)

`Monad`

allows us to operate on values within **context** with function that produces another value within **context**.

**context** seems to be a recurring word. What is **context**?

**context** is a type that wraps another type (and thus give the value an additional context / meaning).

A type that can wrap another type is called a **type constructor** or **higher-kinded type**. As for what **kind** is, refer to [wiki](https://en.wikipedia.org/wiki/Kind_(type_theory)). It is basically a type for a type.

So **context** is a **type constructor** and what we mean when we say type `A`

is an instance `Monad`

, what we really mean is that type constructor `A`

defines primitive methods required by typeclass `Monad`

.

Why do we bother making our type `A`

making an instance of `Monad`

when we can still use method like `flatMap`

without explicitly making it an instance?

Because `Monad`

typeclass provides myriads of other methods that derive from our primitive method `flatMap`

. We get all of these methods for free without ever implementing them just by making our type `A`

conform to `Monad`

. This facilitates DRY principle and leads to better code reuse.

For example, by simply implementing a single method `flatMap`

on `A`

, we get all primitive methods and its derived methods from `Functor`

, `Apply`

, and `Applicative`

plus the derived methods directly from `flatMap`

.

## Takeaway

`Monad`

lets us operate on values within context and chain such monadic operations in a dependent way without unwrapping the context.