Skip to content

Instantly share code, notes, and snippets.

@nakamura-to
Created July 31, 2013 12:59
Show Gist options
  • Save nakamura-to/6121758 to your computer and use it in GitHub Desktop.
Save nakamura-to/6121758 to your computer and use it in GitHub Desktop.
JavaScriptでMaybeモナド - Douglas Crockfordの実装とECMA Script 6のgeneratorを使った実装の比較
// Douglas CrockfordのMaybeモナド
//
// http://www.youtube.com/watch?v=b0EF0VTs9Dc
// 上記のyoutubeより(時間にして21:50, 26:50, 27:15のコード)
function MONAD(modifier) {
var prototype = Object.create(null);
return function unit(value) {
var monad = Object.create(prototype);
monad.bind = function (func, args) {
return func.apply(undefined, [value].concat(Array.prototype.slice.apply(args || [])));
};
if (typeof modifier === 'function') {
modifier(monad, value);
}
return monad;
};
}
var maybe = MONAD(function (monad, value) {
if (value === null || value === undefined) {
monad.is_null = true;
monad.bind = function () {
return monad;
};
}
});
// example 1
var monad = maybe(1);
monad.bind(function (value) {
monad = maybe(value + 2);
monad.bind(function (value) {
console.log(value); // 3
});
});
// example 2
monad = maybe(null);
monad.bind(function (value) {
monad = maybe(value + 2);
monad.bind(function (value) {
console.log(value); // unreachable
});
});
// ECMA Script 6 のgeneratorを使ったMaybeモナド
//
// 実装は https://github.com/nakamura-to/mflow より
// node v0.11.4で --harmony-generators オプションをつけて稼動確認
function maybe(fn) {
var gen = fn();
var ret = gen.next();
while (!ret.done) {
if (ret.value == null) return null;
ret = gen.next(ret.value);
}
return ret.value;
}
// example 1
maybe(function * () {
var value = yield 1;
value = yield value + 2;
console.log(value); // 3
});
// example 2
maybe(function * () {
var value = yield null;
value = yield value + 2;
console.log(value); // unreachable
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment