Skip to content

Instantly share code, notes, and snippets.

@DeTeam
Last active August 29, 2015 13:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DeTeam/9854451 to your computer and use it in GitHub Desktop.
Save DeTeam/9854451 to your computer and use it in GitHub Desktop.
Full of fun Maybe ap functor in JS.
// The Type
function Maybe(){};
// `Nothing` Type Constructor
function Nothing() {
this.value = null;
};
// `Just` Type Constructor
function Just(value) {
this.value = value;
};
// Make those two share prototype
Nothing.prototype = Object.create(Maybe);
Just.prototype = Object.create(Maybe);
Maybe.pure = function(value) {
return new Just(value);
};
Maybe.map = function(f) {
return this.value ? this.pure(f.call(this.prototype, this.value)) : this;
};
function nothing() { return new Nothing(); }
function just(value) { return new Just(value); }
function fromMaybe(m, defaultValue) {
if (m instanceof Just) {
return m.value;
} else {
return defaultValue;
}
}
Nothing.prototype.ap = function() { return this; }
Just.prototype.ap = function(m) {
return m.map(function(value) {
if(typeof this.value !== 'function') {
throw new Error('YOU SHALL NOT PASS!');
}
if (this.value.length > 1) {
return this.value.bind(this, value);
} else {
return this.value(value);
}
}.bind(this));
};
// TEST
(function() {
function sum(a, b) { return a + b; }
function getItem(hash, key) {
return hash.hasOwnProperty(key) ? just(hash[key]) : nothing();
}
console.assert( just(sum).ap(just(3)).ap(just(4)).value === 7 );
console.assert( just(sum).ap(nothing()).ap(just(4)).value === null );
console.assert( just(sum).ap(just(4)).ap(nothing()).value === null );
var hash = {
a: 5,
b: 10
};
var getFromHash = getItem.bind(null, hash);
var result = just(sum).ap(getFromHash('a')).ap(getFromHash('b')).map(function(v) { return v * v; });
console.log(fromMaybe(result, 'NOTHING'));
var wrongResult = just(sum).ap(getFromHash('__unknown_key__')).ap(getFromHash('b'));
console.log(fromMaybe(wrongResult, 'NOTHING'));
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment