4
\$\begingroup\$

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
      }
    }
  }
}

console.log(
  Maybe(nested)
    .then(({ a }) => a)
    .then(({ b }) => b)
    .then(({ c }) => c)
    .then(({ d }) => d)
    .catch(last => `Last value: ${JSON.stringify(last)}`)
    .valueOr()
);

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

\$\endgroup\$

closed as off-topic by πάντα ῥεῖ, Stephen Rauch, Raystafarian, Billal Begueradj, Incomputable Jun 28 '18 at 19:40

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Lacks concrete context: Code Review requires concrete code from a project, with sufficient context for reviewers to understand how that code is used. Pseudocode, stub code, hypothetical code, obfuscated code, and generic best practices are outside the scope of this site." – πάντα ῥεῖ, Raystafarian, Billal Begueradj, Incomputable
If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\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