**Monads** in **Functional Programming** play an important role but they mostly confuse the beginners. One of the reasons for the confusion is that they mostly have a knowledge of imperative style programming, where they have no idea about function composition and its importance. In the terms of functional programming, the composition is the root where we have a set(Z) and we compose the elements of the set with the help of functions. For the basic idea of function composition, you can have a walk through my last blog on functors.

Today our focus will be on **Monads**. So, the first question that comes to our mind “Why Monads?”

The **one-liner answer** to this question is, when we have **side effects** in our program, then the monads come into the picture.

Now the next question is “**What type of side effects can we have?**”

- We are using the database for performing some operations like
**CRUD**. Every operation can return a different result. - We are updating the UI as per our requirements, like adding a button to the frame on the basis of some condition but the problem is that the method might return a unit.
- Accessing files, read data from network and more…

The one truth of application development is: **Without side-effects, there is no possibility of building any applications**.

Let’s take an example for performing some pure and **side-effects** operations. Our requirements are like, we need to perform operations like insert, update, find and send the data to the network one after another. So, in the imperative style we need to perform the below steps:

addRecordInDatabase(record: Record): Unit = { .... } updateUI(): Unit = { .... } val record = findTheLastRecord(): Record = { .... } sendRecordToTheNetwork(record: Record): Unit = { .... }

In the above example, every method returns a different value and it is also possible that every method might behave differently in the case of failures. In that case, we need to handle the exceptions according to the method. This makes our code **bulky** and **dirty**.

So, “**How can we handle these situations in the scenario of functional programming?**”

As we know, functional programming means to design or write pure functions without any side-effects. But the one bitter truth of functional programming is that there is no way for designing a side-effected function so that it can be pure. We just create an illusion of pure functional using a wrapper or monads and the output of those functions are a monad of a type. We will explore this in later examples.

Like in the example discussed earlier, where we interacted with the database and the network layer, in that case, we need to wrap the output of all the methods in **SomeIO** monad of some type like** SomeIO[T]** which will help us to compose the methods easily. So, let’s convert the earlier code into our **SomeIO[T]** monad.

addRecordInDatabase(record: Record): SomeIO[Unit] = { .... } updateUI(): Some[Unit] = { .... } val record = findTheLastRecord(): SomeIO[Record] = { .... } sendRecordToTheNetwork(record: Record):SomeIO[Unit] = { .... }

So, the next questions that pop up in our mind are “**How monad help us with above workflow? What are the benefits we get for changing the return types?**”

First, let’s take the quick brief of the compositions again. There are two types of compositions :

**First**, the output of one function is the input of another, which was mentioned in my last blog.**Second**, the intermediate result of one function passes to the next inner function initially completing the inner function first and then moving to the outer one which we will use in our Monads.

Now we have an idea, Monad has a structure which contains some methods. But before moving to the structure, we need to remember one thing “**Monad is a Functor**“. Let’s take the example and structure of the monad.

trait Monad[F[_]] extends Functor { def pure[A](a: A): F[A] def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] }

In the above structure, we have a trait named **Monad** but the **F** can be any monad which can contain any type and two methods **pure** and **flatMap**, which we will elaborate later but it also extends a **Functor** trait, meaning that the Monad also contains the **map** method. In the meantime, the only thing we need to remember for the monads is “**If the class contains method map, flatMap and pure, it is called a Monad**“.

In our Scala core library, we have existing monads like **Option[T]**, **List[T]**, **Future[T]** and more. All these monads have the **pure** method but with the different name. For eg, using the **apply** method, we convert the normal int value to **Option[Int]** or **List[Int]** etc. With **Future.successfull(1)**, we can create **Future[Int]**. So, this means that every library which contains a **map**, **flatMap** and **pure**(this method name depends on class) can be called a **Monad**.

Now, we have an idea about the **map** method from the last blog and the **pure** method which we saw earlier in this blog. Now let’s have a look at **flatMap**.

- As we discussed monads are helping us to pass the intermediate result to our next function if required and perform whatever operation we want to perform. This is only possible because the monads contain
**flatMap**method. **flatMap**is used, when we have a container within another container like**Option[Option[T]]**or**List[List[T]]**. So, it pulls out the elements from inner container and merges it into the outer container and then returns a container of the specific type like**Option[T]**or**List[T]**.

Now we have a brief idea about monad structure and its methods like **pure**, **map** and **flatMap**. let’s look into our earlier examples where monads can help us with method composition.

As we know, we have a **SomeIO** monad which means that the structure of monads is something like this:

case class SomeIO[T](value: A) { def pure(a: A): SomeIO = { ... } def map[A, B](f: A => B): SomeIO[B] = { ... } def flatMap[A, B](f: A => SomeIO[B]): SomeIO[B] = { ... } }

Now, we have our custom monad with all methods required in monads creation. If you want to explore more about method implementations, look at this video. We have an idea, about the **map** and **flatMap** method and if we look into the **flatMap** method, it accepts HOF function which takes **A** and returns **SomeIO[B]** and **flatMap** will return **SomeIO[B]** as well. That means we can write our example like this:

addRecordInDatabase(record).flatMap { _ => // perform operation after insert record into database updateUI().flatMap { _ => // perform operation after update ui findTheLastRecord().flatMap { record => // perform operation after fetching the last record sendRecordToTheNetwork(record).map { _ => // perform operation after passes the data to network } } } }

In this example, we are performing operation one after another as per our requirements with the help of **flatMap** and **map** method. With the help of **flatMap** method, we are achieving this operation because every method returns monad of some type like **SomeIO[T]** and **flatMap** is the only method where we can pass HOF with A input and return monad of some type and function itself with the same monad value.

We can also write above solution with the **monadic operator ( <- )** or Scala** for comprehension** which makes our code more concise and readable as below:

for { _ <- addRecordInDatabase(record) _ <- updateUI() record <- findTheLastRecord() _ <- sendRecordToTheNetwork(record) } yield ()

So, in this way, we can compose multiple functions easily with the help of monads which may contain side effects but we can compose them easily. Scala contains a lot of inbuilt monads but sometimes as per our requirements, we might require to create our custom monad or **scala-cats** and the **scalaz** libraries provide us with a bunch of most useful monads for writing compositional code. We will be discussing them along with the examples in our future blogs.

Reblogged this on Harmeet Singh(Taara).