0

純粋なコードと純粋でないコードを分離するために IO が使用されていることを理解しています。また、IO が参照透過性を可能にしていることも承知しています。

ただし、IO に関する 1 つのことは、まだ少しわかりにくい点です。つまり、呼び出されたときにすべてが一度に実行されるため、IO に含まれるアクション間で悪いことが起こらないことが保証されます (遅延構成にすぎないため)。そのため、この遅延構成が最終的に呼び出されると、他の並行コードはそれを歪めることはできません (この遅延構成)。

それで、それは本当ですか?(このコンテキストでは) IO は、このようなコードよりも優れているでしょうか?

var x = 1; //shared resource

//some other code access and changes x to 2

const y = multiplyBy100(x);
const z = add1000(y);

log(z); // 1200 instead of desired 1100

IO がそのような問題の解決策であることを理解しています。

IO(function () {return x;}).map(multiplyBy100).map(add1000).map(log); //1100 no matter what

私の推論は大丈夫ですか?

4

1 に答える 1

0

IOモナドが不純なアクションと純粋なアクションの分離を可能にするのは事実であるため、あなたの考えは正しい方向に始まります。あなたがそれについて言及するとき、あなたは何かが欠けていると思います

また、IO が参照透過性を可能にしていることも承知しています。

IO 自体のセマンティクスと、それ以外のコードに提供される利点を混同している可能性があります。IO はそれ自体で参照透過性をあまり考慮していませんが、その代わりに、参照透過性 (純粋) である関数が、参照透過性を失うことなく IO 内に含まれる不純なアクションとやり取りできるようにしています。

IO アクションを作成して実行すると、結果が参照透過性であるとは限りません。これがまさにポイントです。これは、IO が不純なアクションの投棄場であるという理解で武装していれば、驚くべきことではありません。

そのため、この遅延構成が最終的に呼び出されると、他の並行コードはそれを歪めることはできません (この遅延構成)。

残念ながら、それほど単純ではありません。コードが怠惰であっても、参照透過性にはなりません。IO の遅延 (レイジー) などの一連の関数の評価は、操作対象の値とは関係ありません。

JavaScript のコンテキストでは、すべての値が参照です。スコープ内に参照があるスタック上の関数は、その参照の値を変更できます。何があっても 1100 の値を返す IO を示す独自のコード例で、これが何を意味するかをお見せしましょう。x をラップする IO を宣言する前または後に x の値を変更すると、IO によって返される値はそのような変更を反映します。したがって、このコードは戻りません//1100 no matter whatが、実際には戻り1200ます。

function switcharoo() {
  x = 2;
}

var x = 1;

var IOdoMaths = IO(() => x).map(x => x * 100).map(x => x + 1000);

// Some concurrent proccess calls this
switcharoo();

var result = IOdoMaths.runIO();

console.log(result); // 1200

IO アクションの結果は になると予想していました1100が、代わりに が得られまし1200た。IO を作成したときに、値ではなく参照をラップしたことを思い出してください。これは、Javascript のあらゆる種類のクロージャに当てはまります。クロージャーを宣言した後に IO に詰め込んでも問題ありません。同じルールが適用されます。

于 2016-07-27T20:35:32.637 に答える