Maybe Monad, IO Monad and State Monad are some examples of widely used Monads.
In this article, we will learn how to use them, why they are useful, and how we can build them in Typescript.
Monad, What are We Talking About?
A Monad is a concept from the world of functional programming and category theory.
Monads can help us structure our programs in a functional and composable way.
They can also help manage state and side effects—yes, they can do a lot!
Time to get to know them.
Thinking Inside the Box — Maybe Monad
We can think of a Monad as a box, meaning we can take a value and insert it inside a box known as Just.
In a case where there is no value, it is represented by an empty Box known as Nothing.
We can then create a Maybe that can take the form of either Just or Nothing.
Now that we have Maybe as a tool, the question is: what can we do with it?
One of the outstanding features of Monads is their composability, and we can achieve it by using a special function known as bind (which might also be referred to as flatMap or chain).
bind enables us to take a function, apply it to the Monad, and receive a new Monad in return.
In the example below, the Monad contains no value. After using bind we will stay with no value:
We will just stay with nothing (pun intended).
We can continue binding with more and more functions without worrying about the absence of values.
That is what makes this tool so useful. Monads enables us to write a cleaner code, with fewer conditional checks for the existence of a value.
Okay, time to write some code!
Writing Our Own Maybe Monad
First, we will define the Maybe class:
We are defining an abstract class with a single method- bind.
bind takes a function that, in turn, operates on the current value within the Box to create a new Maybe Monad.
Now, we need to implement the class with Just and Nothing classes:
The Just class holds a private property- value.
The bind function receives a function as an input and applies it on the private value, resulting in a new Maybe.
On the other hand, implementing Nothing is straightforward; it always returns Nothing!
What we need is a function as an input to bind.
We will create a prop function, which accesses a property in an object:
The definition may seem a bit complex, primarily due to the types involved. However, this function essentially returns Just if the object has the specified property and Nothing otherwise.
Below we can see an example of using prop with the Maybe Monad:
Notice how prop returns a function that accesses the value within the Monad and generates a new Monad.
If we were to modify the input slightly, we would obtain Nothing.
We have created a safe way to access any Object!!
In addition, if you look closely, it might look very similar to something else.
Yes, yes, it’s similar to optional chaining, and we’ve effectively created our own version using the Maybe Monad. This is quite exciting, at least for me!
Get Out of the Box
While we can keep binding more and more functions with the Maybe Monad, there are cases when we need to extract the value from the Monad. For example, printing or saving data to a database.
In order to get the value out of the Monad, we can use a function called match (In Haskell, they simply use pattern matching).
If the Monad is a Just, the isJust function will be executed, and if it’s a Nothing (you guessed it folks), the ifNothing function will run.
Here’s the definition of the match function:
The ifJust function retrieves the value that was inside the Monad while ifNothing operates without a value.
The return value is determined by what ifJust or ifNothing returns.
In many cases, the value returned will be void, since the Monad will hold the value until a side effect is performed.
In the example below, if there is a value, we print it; otherwise, we log “Oh no, no value.”
While extracting values from the Monad is important, it is safer for our code to postpone the extraction until absolutely necessary.
You can play with the full example here:
TS Playground – An online editor for exploring TypeScript and JavaScript
Other Monads and What Are They Good For
Now that we’ve explored the Maybe Monad, we can apply this knowledge to a variety of other “Boxes.”
State Monad
The State Monad is used to manage and manipulate state. It’s a way to encapsulate stateful computations without resorting to mutable variables or global state.
IO Monad
IO Monad is used to manage side effects. Examples of side effects include reading from or writing to files, interacting with the network, or performing other impure actions.
Either Monad
The Either Monad provides a way to propagate and handle errors through a series of computations without the need for explicit error-checking and branching in your code.
These Monads share similar concepts with the Maybe Monad, so now you have the ability to explore them on your own.
The exciting part is, there are many more Monads to discover!
Sum Up
Our journey began with an exploration of the Box metaphor, helping us grasp how the Maybe Monad can be viewed as putting a value in a Box.
We learned about bind, a tool that empowers us to compose various computations in a pure and seamless manner.
We then proceeded to build our own complete version of the Maybe Monad in TypeScript and applied it to implement optional chaining ourselves.
We had a quick overview of other Monads out there and discussed their respective use cases.
I hope that after reading this article, you no longer fear the “M word” and feel inspired to explore and write more pure, composable, beautiful code.
Happy learning!
Resources:
Hardcore Functional Programming in JS
Illustrations was drawn with:https://whimsical.com/
Editing Credit: Keren Haham.
Monads in TypeScript was originally published in Better Programming on Medium, where people are continuing the conversation by highlighting and responding to this story.