Last active
August 29, 2015 13:57
-
-
Save DeTeam/9854451 to your computer and use it in GitHub Desktop.
Full of fun Maybe ap functor in JS.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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