Skip to content

Modus-Logo-Long-BlackCreated with Sketch.

  • Services
  • Work
  • Blog
  • Resources

    OUR RESOURCES

    Innovation Podcast

    Explore transformative innovation with industry leaders.

    Guides & Playbooks

    Implement leading digital innovation with our strategic guides.

    Practical guide to building an effective AI strategy
  • Who we are

    Our story

    Learn about our values, vision, and commitment to client success.

    Open Source

    Discover how we contribute to and benefit from the global open source ecosystem.

    Careers

    Join our dynamic team and shape the future of digital transformation.

    How we built our unique culture
  • Let's talk
  • EN
  • FR

A Curious JavaScripter’s Guide to Monad Pattern

There are times when, on the journey to enlightenment, one comes across a programming concept so mind-bending, and yet so simplistically elegant that they weep with inner joy. I mean sure, loops are great. But recursion is another beast entirely; allowing you to express yourself so tersely both in code and on paper that life without it seems dull, if not handicapped. Yet I, along with probably many others, struggled to apply recursion intuitively to solve problems when the concept was first introduced to me.

The Monad pattern is a similarly invigorating concept. One that requires a good bit of work to grok, but also adds a sophisticated construct to your arsenal. It can also help reduce moving parts in program, resulting in code that’s potentially easier to read. So let’s explore a bit to see what it’s about.

Programming with context

To really understand what monads are and why they’re useful, we need to take a short detour to first explore contexts. Think of context as special powers attached to a variable which can be used in subtle ways as its value changes.

For example, imagine if our functions accept a value, knowing that there may not be a value at all. This is not exactly a new thing. We’ve been checking for null inputs since before dinosaurs.

However, what we’ve generally been doing was sprinkling if-else at random places to make sure nulls and invalid values are handled. This example is about abstracting this type of check to a higher level so that we may express our logic more clearly. In other words, providing a home for most boilerplate if-else checking.

Observe the following snippet:

class Maybe {
    constructor (type, value) {
        Object.extend(this, {type, value})
    }

    static just (val) {
        return new Maybe('just', val);
    }

    static nothing () {
        return new Maybe('nothing', null);
    }
}

Maybe.just('Hello'); // Represents a concrete value
Maybe.nothing() // Represents an invalid

So Maybe is a class, while just and nothing are its two constructors. All concrete values can be thought of as wrapped inside a just while nothing represents nothing (literally!). We’ve used type to differentiate between the two. However, type is not the context. It’s just a representation of the idea that an object of Maybe can represent a value or absence of it. Take a moment to re-read the previous sentence again. When we write our code to deal with objects of Maybe, we’ll know that the object may actually be nothing.

If you found the above text hard to grok, just think of nothing as a glorified null for now. One which we define ourselves instead of (sometimes) incorrectly assuming null to always be invalid. just, therefore, is everything that’s not nothing. i.e. an actual value.

So, with our custom wrappers to represent valid and invalid values, let’s see how our lives have been made a little easier.

Say hello to chain a.k.a. the life-blood of the monad pattern

Chain is a method which, wait for it, allows a chain of operations in sequence. What’s the rub? It also takes care of handling invalid or nothing values while it’s at it to make sure our code doesn’t crash and burn if users start sending nyan-cats through an email field.

We edit our Maybe class and add a chain method thus:

class Maybe {

    // ... original definition of Maybe

    chain (fn) {
        if (this.type === 'nothing') {
            return Maybe.nothing();
        } else {
            return fn(this.value);
        }
    }
}

Example Time!

We have a series of string manipulation methods, all of which need to check for certain invalid conditions to be a little robust.

const titleize = input => {
    if (typeof input !== 'string' || input.length === 0) {
        return '';
    }

    return input[0].toUpperCase() + input.slice(1);
}

const exclaim = input => {
    if (typeof input !== 'string' || input.length === 0) {
        return '';
    }

    return input + '!';
}

const someString = 'kent is superman';
exclaim(titleize(someString)); // 'Kent is superman!'

const someInvalid = 123;
exclaim(titleize(someInvalid)); // ''

Even for this small example, notice how adding type safety led to seemingly repetitive code. Let’s lift that up in chain method. Here’s the finished chain method with our custom logic ready for primetime.

class Maybe {
    // ... original definition of Maybe

    chain (fn) {
        if (this.type === 'nothing') {
            return Maybe.nothing();
        } else if (typeof this.value !== 'string' || this.value.length === 0) {
            return Maybe.nothing();
        } else {
            return fn(this.value);
        }
    }
}

const titleize = input => {
    return Maybe.just(input[0].toUpperCase() + input.slice(1));
};

const exclaim = input => {
    return Maybe.just(input + '!');
};

const someString = Maybe.just('kent is superman');
someString
    .chain(titleize)
    .chain(exclaim); // just 'Kent is superman!';

const someInvalid = Maybe.just(123);
someInvalid
    .chain(titleize);
    .chain(exclaim); // nothing

const someNothing = Maybe.nothing();
someNothing
    .chain(titleize)
    .chain(exclaim); // nothing

Observe how we removed the type and length checking and instead made the return value a Maybe object. Also, notice the pattern of execution went from function1(function2(input)) to input.chain(function1).chain(function2) which follows an arguably more natural flow. This might seem familiar to those who use promises to serialize async operations. They follow the monad pattern too, btw. If only javascript supported custom definitions for operators, our final code could’ve looked like input |> function1 |> function2. Nice, eh?

Wrap-Up

Note that the monad pattern is an abstraction like most other patterns, not a defined block of code. Case in point, what we saw above isn’t the high and low of it. It was a single example of how the monad pattern can be applied to deal with invalids. There’s lots more ways to exploit monads for a ridiculous variety of tasks. Feel free to google Either Monad, Logger Monad or Parser Monad to explore a few more.

Hopefully this post gave you insight to leverage the Monad pattern. I’d be happy to read about you using it in your work or personal projects. Share your thoughts in the comments below. Use it to direct any hate, praises, WTFs too 🙂

Note:

  • The chain is actually called bind in monadic nomenclature. But since the word is already in javascript’s dictionary for an entirely different purpose than what we used chain for, it was rechristened.
  • What we saw above is monad the pattern. A Monad (the thing) is a functional typeclass which lists a few other helper methods in addition to bind (or chain from our code). It works similarly though.
  • Posted in Application Development
    Share this

    Akash Agrawal

    Akash Agrawal is a Software Engineer with Modus Create. He is an experienced JavaScript and Ruby programmer with chops in front and backend development along with database architecture. Akash has a deep interest in pure functional languages and is a padwan haskell hacker. He enjoys exploring surrounding areas on his bike when not working.
    Follow

    Related Posts

    • Quick practical guide for ES6 Featured Image
      Quick Practical Guide for ES6

      In this post we are going to examine what new features arrived in ES6 and…

    • Quick practical guide for ES6 Featured Image
      Quick Practical Guide for ES6

      In this post we are going to examine what new features arrived in ES6 and…

    Want more insights to fuel your innovation efforts?

    Sign up to receive our monthly newsletter and exclusive content about digital transformation and product development.

    What we do

    Our services
    AI and data
    Product development
    Design and UX
    IT modernization
    Platform and MLOps
    Developer experience
    Security

    Our partners
    Atlassian
    AWS
    GitHub
    Other partners

    Who we are

    Our story
    Careers
    Open source

    Our work

    Our case studies

    Our resources

    Blog
    Innovation podcast
    Guides & playbooks

    Connect with us

    Get monthly insights on AI adoption

    © 2025 Modus Create, LLC

    Privacy PolicySitemap
    Scroll To Top
    • Services
    • Work
    • Blog
    • Resources
      • Innovation Podcast
      • Guides & Playbooks
    • Who we are
      • Our story
      • Careers
    • Let’s talk
    • EN
    • FR