Skip to content

Instantly share code, notes, and snippets.

@briancavalier
Created December 31, 2013 16:55
Show Gist options
  • Save briancavalier/8199502 to your computer and use it in GitHub Desktop.
Save briancavalier/8199502 to your computer and use it in GitHub Desktop.
JavaScript Maybe monad
module.exports = Maybe;
function Maybe(x) {
this._value = x;
}
Maybe.of = of;
Maybe.empty = empty;
var nothingValue = void 0;
var nothing = Maybe.nothing = new Maybe(nothingValue);
function of(x) {
return new Maybe(x);
}
function empty() {
// For Semigroup/Monoid
return nothing;
}
Maybe.catMaybes = function(list) {
return list.reduce(function(justs, maybe) {
if(maybe.isJust()) {
justs.push(maybe);
}
return justs;
}, []);
};
Maybe.mapMaybes = function(f, list) {
return list.reduce(function(justs, maybe) {
var mappedMaybe = maybe.map(f);
if(mappedMaybe.isJust()) {
justs.push(mappedMaybe);
}
return justs;
}, []);
};
Maybe.prototype.isNothing = function() {
return this._value === nothingValue;
};
Maybe.prototype.isJust = function() {
return !this.isNothing();
};
Maybe.prototype.map = function(f) {
return this.isNothing() ? this : of(f(this._value));
};
Maybe.prototype.ap = function(maybe) {
return this.flatMap(function(f) {
return maybe.map(f);
});
};
Maybe.prototype.flatMap = function(f) {
return this.isNothing() ? this : f(this._value);
};
Maybe.prototype.concat = function(maybe) {
// Semigroup/Monoid
// See http://en.wikibooks.org/wiki/Haskell/MonadPlus#Definition
return this.isNothing() ? maybe : this;
};
Maybe.prototype.filter = function(predicate) {
return this.isJust() && predicate(this._value) ? this : nothing;
};
Maybe.prototype.maybe = function(f, defaultValue) {
return this.isNothing() ? defaultValue : f(this._value);
};
Maybe.prototype.fromMaybe = function(defaultValue) {
return this.isNothing() ? defaultValue : this._value;
};
Maybe.prototype.fromJust = function() {
if(this.isNothing()) {
throw new TypeError('fromJust: Maybe is nothing');
}
return this._value;
};
Maybe.prototype.foldl = Maybe.prototype.foldr = function(f, initial) {
return this.isNothing() ? initial : f(initial, this._value);
};
Maybe.prototype.foldl1 = Maybe.prototype.foldr1 = function(f) {
return this.fromJust();
}
Maybe.prototype.reduce = function(f) {
return arguments.length < 2 ? this.foldl1(f) : this.foldl(f, arguments[1]);
};
Maybe.prototype.reduceRight = function(f) {
return arguments.length < 2 ? this.foldr1(f) : this.foldr(f, arguments[1]);
};
Maybe.prototype.listToMaybe = function(list) {
return list.length === 0 ? nothing : of(list[0]);
};
Maybe.prototype.maybeToList = function() {
return this.isNothing() ? [] : [this._value];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment