A while ago, I really wanted to have the Maybe Monad in my JS projects. I ended up trying to use Promises as a stand-in solution (using Promise.resolve as my unit, then chaining from there), but using resolve and reject for nullable types made it unwieldy and difficult to parse.

I've seen some cool implementations of the Maybe Monad in JS online, but many use classes and seem to mutate state. I wanted to make an immutable and purely functional version (if not only as a proof of concept).

You will see that I also added a last formal parameter to Maybe and Just. This is so that, when a chain falls through, debugging can be made easier by seeing the last value that was valid.

I'm looking for more ways to make this usable and perhaps more abstract. I originally created a symbol for Nothing, but found that null works pretty well too. What are your thoughts and criticisms?

const MType = Symbol("Maybe");
const isMaybe = x => (x instanceof Object && MType in x);
const isNone = x => x === null || x === undefined;

const Just = (x, last) => ({
  valueOr : alternative => isNone(x) ? alternative : x,
  then : f => Maybe(isNone(x) ? x : f(x), x),
  catch : f => Maybe(isNone(x) ? f(last) : x, x),
  type : MType

const Maybe = (x, last = null) => isMaybe(x, last) ? x : Just(x, last);

const nested = {
  a : {
    b : {
      c : {
        e : 6

    .then(({ a }) => a)
    .then(({ b }) => b)
    .then(({ c }) => c)
    .then(({ d }) => d)
    .catch(last => `Last value: ${JSON.stringify(last)}`)

// Output: Last value: {"e":6}

  • \$\begingroup\$ I believe it would be much more interesting to review a concrete application of your code. I fear this will be closed as off-topic because of the example code you used. \$\endgroup\$ – IEatBagels Jun 26 '18 at 19:41
  • 1
    \$\begingroup\$ I suppose the example I have at the end of this code is not extremely concrete, but it is the intended use case. My desire is to create a Monad for controlling flow of logic in a chain that could have nullable types in the pipe. If null is ever encountered, logic should fall through to a catch statement that can handle that event. \$\endgroup\$ – Kyle Hovey Jun 27 '18 at 16:59