モナド変圧器をよりよく理解するために、私は1つを実装しました。 Javascriptは動的に型付けされているので、型やデータコンストラクタを模倣するのではなく、特定のモナド/トランスフォーマを形成するために対応する静的関数を保持する普通の古いJavascriptオブジェクトのみを宣言します。基本的な考え方は、これらのメソッドをコンテナ型の値/値に適用することです。タイプと容器は話すように分かれています。これはJavascriptで有効なモナド変換器ですか?
Array
には、任意の数の要素を含めることができます。モナドインタフェースを実装するようにArray
を拡張することは自明です。 Array
はまた、maybe
タイプの2つの変形を表すことができる。空のはnothing
に対応します。単一の要素を有するArray
は、just(a)
に対応する。その結果、コンテナタイプとしてArray
を使用します。これは単なる学習のための迅速かつ汚い実装であることに注意してください:
const array = {
of: x => Array.of(x),
map: f => ftor => ftor.map(f),
ap: ftor => gtor => array.flatten(array.map(f => array.map(f) (gtor)) (ftor)),
flatten: ftor => ftor.reduce((xs, y) => xs.concat(y), []),
chain: mf => ftor => array.flatten(array.map(mf) (ftor))
}
const maybe = {
of: array.of,
empty:() => [],
throw: ftor => { if (ftor.length > 1) throw Error("indeterministic value"); return ftor },
map: f => ftor => maybe.throw(ftor).map(f),
ap: ftor => gtor => maybe.flatten(maybe.map(f => maybe.map(f) (gtor)) (ftor)),
flatten: array.flatten,
chain: mf => ftor => maybe.flatten(maybe.map(mf) (ftor)),
T: M => {
return {
of: x => M.of(maybe.of(x)),
empty:() => M.of(maybe.empty()),
map: f => ftor => M.map(gtor => maybe.map(f) (gtor)) (ftor),
ap: ftor => gtor => M.flatten(M.map(htor => M.map(itor => maybe.ap(htor) (itor)) (gtor)) (ftor)),
flatten: maybe.flatten,
chain: mf => ftor => M.chain(gtor => maybe.chain(mf) (gtor)) (ftor)
};
}
};
今、私は多分maybe
秒のarray
Sを扱うことができるモナドを取得するために、モナド配列を有する変圧器結合します。
const arraym = maybe.T(array);
const add = x => y => x + y;
const addm = x => y => [x + y];
const arrayOfMaybes = [[1],[],[3]]
私は応用的ファンクタとしてarraym
を扱う場合には、すべてが期待通りに動作します。しかし
// yields: [[11],[],[13]] as expected
arraym.ap(arraym.map(add) (arrayOfMaybes)) (arraym.of(10));
、私はchain
何かがうまくいか適用するとき:
// yields: [11,13] but [[11],[13]] expected
arraym.chain(x => arraym.chain(y => addm(x) (y)) (arrayOfMaybes)) ([[10]])
は、この原因です問題
- これは有効なモナドトランスではありませんか?
- 私はチェーンを適用する方法が間違っている?
- 結果に関する私の期待は間違っていますか?
'arraym.flatten'が間違って見える – Bergi
配列が正しくない場合、誤ったネストされた配列を返す代わりにスローして型エラーが発生していると思います。 – Bergi