3

モナド変圧器をよりよく理解するために、私は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]]) 

は、この原因です問題

  • これは有効なモナドトランスではありませんか?
  • 私はチェーンを適用する方法が間違っている?
  • 結果に関する私の期待は間違っていますか?
+0

'arraym.flatten'が間違って見える – Bergi

+1

配列が正しくない場合、誤ったネストされた配列を返す代わりにスローして型エラーが発生していると思います。 – Bergi

答えて

2

チェーンの適用方法がこの問題の原因ですか?

はい。 mfを渡す必要があります。arraymを返し、のようにarrayを返しません。あなたがこれを支援するために

const addmm = x => y => array.map(maybe.of)(addm(x)(y)) 
arraym.chain(x => arraym.chain(addmm(x))(arrayOfMaybes))([[10]]) 

を使用することができ、あなたはまた、すべてのモナド変換子のためにliftの実装を検討することがあります。

+0

これは良いヒントです。私はこれを詳しく見ていきます。私はすべての変圧器が特定のリフト機能を必要とすると思う。ありがとう! – ftor

+0

誤って持ち上げられた 'addm'関数が実際に原因でした。外側モナドと内側モナドの両方の計算が正しく適用されたようですが、結果として得られるモナドは多分型を失いました。したがって、私は 'Number'の' Array'を取得しました。これがバグか機能なのかなと思います。 – ftor

+0

@ftorそれは別のリストと多分型の代わりに配列だけを使うことから生じるバグです。もちろん、あなたはそれをフィーチャーと呼ぶことができます:-) – Bergi

関連する問題