javascriptfunctional-programmingmonadsterminologyfunctor

Name and existence of functor or monad to chain and terminate sequence of operations


I am looking at libraries such as Folktale and monet.js, I like being able to chain operations with map without null-checking or if statements, using e.g. Maybe, Either, Task.

I am wondering whether a similar construct exists to solve the following problem:

In other words, I'm looking for something similar to Maybe which holds a value and maps a function on Just but ignores a function mapped on Nothing, and you can extract the value. I'm looking for something that holds an input and an initial null result. When you map a function, it runs the function on the input only if result is null. If the function returns a value, that becomes the result and any other functions that are mapped are ignored. Finally, you can extract the result.

In imperative programming, this might look like:

var result1 = function1(input);
if (result1) {
  return result1;
}
var result2 = function2(input);
if (result2) {
  return result2;
}
// and so on.

Instead, I'd like to construct something along the lines of

Something(input).map(function1).map(function2).result()

or

compose(result, map(compose(function2, function1))(Something(input))

Does such a construct exist? Does it have a name? Even if this doesn't exist and I could write it myself, I'm at a loss as to what to call it.

Update

Following the solution by @Bergi I used Maybe.orElse. I wrote a little helper called ShortCircuit, which I am posting below in case anyone finds this useful.

import Maybe from "data.maybe";

const ShortCircuit = function(input, result) {
  this.input = input;
  this.result = result;
};

ShortCircuit.of = function(input, f) {
  return new ShortCircuit(input, Maybe.fromNullable(f(input)));
};

ShortCircuit.prototype.orElseMaybe = function(f) {
  return new ShortCircuit(this.input, this.result.orElse(() => Maybe.fromNullable(f(this.input))));
};

ShortCircuit.prototype.get = function() {
  return this.result.get();
};

export default ShortCircuit;

And here is how you use it:

const result = ShortCircuit.of(input, f1).orElseMaybe(f2).orElseMaybe(f3).get();

Suggestions for improvement are welcome.


Solution

  • What you are looking for is known as the Alternative type class in Haskell. I have not yet found1 a JS library implementing it, though there is support for it in PureScript and a discussion about specifying it in FantasyLand.

    Regardless, I've found a function in Folktale that does exactly what you want: Maybe's orElse. You'd use it like this:

    Something(input).orElse(function1).orElse(function2).get() // `get` throws when all failed
    

    Even better, orElse is available not only for Maybe but also on Either, Validation and Task!

    The getOrElse method, known as orElse in Monet.js, is not really helpful as it wouldn't execute your "handlers" only in the case of a fail. You can implement your own Alternative though using the cata method.

    1: Googling "JS alternative" is not really helpful either, even when you know the name :-)


    Oh, and just in case you are using promises, there's always the .catch(…) method which has broad (ES6-backed) support.