If you were ever exposed to functional programming or went through a programming language course, you surely must have heard this dreadful word: **Monad**. It's usually followed by other words like complicated, confusing, difficult to understand, lots of theory, etc.

I was more than once in that position, trying to understand what a monad is by reading lengthy articles only to find myself more confused than before.

But in all fairness, *monad* is a pretty easy concept to grasp, at least if you are looking for a practical explanation and don't care about the theory behind it so much.

After all...

## So, what is a Monad?

Well, a monad is a concept that comes from *category theory*. It does have a lot of theory behind it, which I have to admit, it can be quite overwhelming and complicated. If you are interested in that, there are multiple resources online to learn more about it (a good one is this series of lectures on category theory).

But in practice, a *monad* is basically a **type wrapper** which represents **a specific form of computation**.

In other words, you use it to *wrap other types* in order to give them some *additional context*.

Let's write some code and try to expand on it as we go along.

Let's try and create a new *monad* called `Container`

which can represent the result of an operation that can either return a value (in this case it will be `NonEmpty`

) or return nothing (`Empty`

).

```
sealed trait Container[+A] {
def isEmpty: Boolean
}
case class NonEmpty[+A](value: A) extends Container[A] {
override val isEmpty: Boolean = false
}
case object Empty extends Container[Nothing] {
override val isEmpty: Boolean = true
}
```

Is that all? Wow, that was simple.

Err, not exactly…in order for a type wrapper to be considered a *monad*, it needs to provide two operations.

### Pure

*Monads* need to provide a way to wrap a pure value of a type into the monad itself (in other words, to yield a **monadic value**).

This function can be found with different names, depending on the language/library you might be using, but the most common ones are: **identity**, **pure** or **unit** (in Scala), **return** (in Haskel).

So, we can extend our example above to include this method.

```
trait Container[+A] {
def isEmpty: Boolean
}
object Container {
def pure[A](value: A): Container[A] =
if (value == null) Empty
else NonEmpty(value)
}
case class NonEmpty[+A](value: A) extends Container[A] {
override val isEmpty: Boolean = false
}
```

It is sort of a *monad constructor* if you will. This is the reason why in the above example I defined it in the companion object instead of the trait itself.

### FlatMap

The second thing that a *monad* needs to provide is a way to compose functions that output monadic values (called **monadic functions**).

Well, this is what I'm talking about:

`def flatMap[B](f: A => M[B]): M[B]`

Basically, it needs to provide a function that receives another function `f`

as a parameter which is applied in the wrapped type `A`

and returns a monad of another type `B`

.

This function is commonly named **flatMap**, but again, you will find it with different names, depending on the language and/or library you're using, e.g. **bind**, **>>=** (in Haskel).

```
trait Container[+A] {
def isEmpty: Boolean
def flatMap[B](f: A => Container[B]): Container[B] = this match {
case NonEmpty(value) => f(value)
case Empty => Empty
}
}
object Container {
def pure[A](value: A): Container[A] =
if (value == null) Empty
else NonEmpty(value)
}
```

Hmmm, so as long as I have a type wrapper that provides two functions with the above signatures, I have a *monad*?

Not exactly. We talked about naming and signatures…but we never talked about the laws these functions should obey.

## Monad Laws

In order for a type wrapper to be considered a proper *monad*, in addition to providing the **pure** and **flatMap** functions, it needs to obey certain laws as well, called **monad laws**.

In particular, there are 3 laws:

**Left Identity**: If we create a*monad*out of a value and then*flatMap*the monad using a function`f`

, it should give us the same result as applying the function`f`

in the initial value.

```
def onlyPositives(value: Int): Container[Int] =
if (value >= 0) NonEmpty(value) else Empty
val value: Int = 1337
Container.pure(value).flatMap(onlyPositives) == onlyPositives(value)
```

**Right Identity**: If we have a m*onadic value*and we*flatMap*using the*pure*operation, we should get back the initial*monadic value*.

```
val monadicValue: Container[Int] = Container.pure(42)
monadicValue.flatMap(Container.pure) == monadicValue
```

**Associativity**: When we have a chain of**monadic function**applications, it shouldn't matter how they are nested.

```
val monadicValue: Container[String] = NonEmpty("monads rule")
def size(value: String): Container[Int] = Container.pure(value.length)
def isEven(value: Int): Container[Boolean] = NonEmpty(value % 2 == 0)
monadicValue.flatMap(size).flatMap(isEven) == monadicValue.flatMap(str => size(str).flatMap(isEven))
```

## Conclusion

All the above could be summarised in the following:

- A
*monad*is a type wrapper that provides some computation context to the wrapped values - It needs to provide a way of wrapping values of any basic type within the
*monad*(i.e. create**monadic values**) - It needs to provide a way to compose functions that output monadic values (i.e.
**monadic functions**) - It needs to obey the three monad laws:
**left identity**,**right identity**and**associativity**

Of course, in reality, monads will most likely have much more methods than the two I described above. But all these methods, can be composed in one way or another from the two listed here.

I hope, at this point, monad is a less scaring concept for you.

But, why do we even care about monads? Why all these laws and rules? And what are these *free monads*, *comonads* and *additive monads* you've been hearing about?

Well, let's talk about this and also give some concrete examples of monads that you can find in most functional programming languages in another post.