node.jsがECMAScript Harmony ジェネレーターをサポートするようになったので、Haskell で単項コードを簡潔に alaブロックを記述できます。do
function monad(unit, bind) {
return function (f) {
return function () {
var g = f.apply(this, arguments);
return typeOf(g) === "Generator" ? send() : unit(g);
function send(value) {
var result = g.next(value);
if (result.done) return unit(result.value);
else return bind(result.value, send);
}
};
};
}
function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
上記のコードには、次のような決定論的モナドmonad
を作成するために使用できる関数があります。
var maybe = monad(function (a) {
return {just: a};
}, function (m, f) {
return m === null ? null : f(m.just);
});
maybe
次のように使用できるようになりました。
var readZip = maybe(function * (a, b) {
var a = yield readList(a);
var b = yield readList(b);
return _.zip(a, b);
});
上記の関数readZip
は 2 つの文字列を取り、それらをリストに変換してから圧縮します。エラーが発生した場合は、すぐに を返しますnull
。次の関数に依存します。
function readList(string) {
try {
var value = JSON.parse(string);
return value instanceof Array ? {just: value} : null;
} catch (error) {
return null;
}
}
テストして、期待どおりに機能するかどうかを確認します。
console.log(readZip('[1,2,3,4]', '["a","b"]')); // [[1,"a"],[2,"b"],[3,"c"]]
console.log(readZip('hello', '["a","b"]')); // null
console.log(readZip('[1,2,3,4]', 'world')); // null
同様に、他の決定論的モナドを作成することもできます。たとえば、私のお気に入りのcont
モナドは次のとおりです。
var cont = monad(function (a) {
return function (k) {
return k(a);
};
}, function (m, k) {
return function (c) {
return m(function (a) {
return k(a)(c);
});
};
});
cont
これで、継続渡しスタイルの関数を簡潔に作成するために使用できます。
var fib = cont(function * (n) {
switch (n) {
case 0: return 0;
case 1: return 1;
default:
var x = yield fib(n - 1);
var y = yield fib(n - 2);
return x + y;
}
});
fib
この機能は次のように使用できます。
fib(10)(function (a) { console.log(a); }); // 55
残念ながらmonad
、決定論的モナドに対してのみ機能します。list
特定の位置から一度しかジェネレーターを再開できないため、モナドのような非決定論的なモナドでは機能しません。
私の質問はこれです: モナドのような非決定論的モナドlist
を JavaScript で簡潔に実装する方法は他にありますか?