5

モナドに飛び込んだ後、モナドは何らかのコンテキスト (失敗、非決定論、状態など) 内で計算を連鎖できるようにするための一般的な概念であり、その背後に魔法がないことを理解しました。

それでも IO モナドは魔法ではなく特別な感じがします。

  • 他のモナドのように IO モナドをエスケープすることはできません
  • mainIO アクションは関数によってのみ実行できます
  • IO は常にモナド トランスフォーマー チェーンの一番下にあります
  • IOモナドの実装は不明確で、ソースコードはいくつかのHaskellの内部を示しています

上記の理由は何ですか?IO が特別な理由は何ですか?

更新:純粋なコードの評価順序は関係ありません。しかし、IO を実行するときは問題になります (それを読む前に顧客を保存したい)。私が理解していることから、IOモナドはそのような順序保証を提供してくれます。それは一般的なモナドの特性ですか、それとも IO モナドに固有のものですか?

4

2 に答える 2

7

他のモナドのように IO モナドをエスケープすることはできません

「逃げる」という言葉の意味がわかりません。つまり、どうにかしてモナド値の内部表現をアンラップします (例: リスト -> コンスセルのシーケンス)。これは実装の詳細です。実際、純粋な HaskellIO エミュレーションを定義できます。基本的にはState、グローバルに利用可能なデータが大量にあるだけです。それは のすべてのセマンティクスを持ちますがIO、現実世界と実際にやり取りすることなく、そのシミュレーションのみを行います。

つまり、モナド内から「値を抽出」することができます – いや、ほとんどの純粋な Haskell モナドでさえ、それは一般的に可能ではありません。たとえば、Maybe a(could be Nothing) またはReader b a(what if bis uninhabited?)から値を抽出することはできません。

IOmainアクションは関数によってのみ実行できます

まあ、ある意味では、すべては関数によってのみ実行できmainます。何らかの方法で呼び出されないコードはそこにあるだけで、何も変更せずにmain置き換えることができます。undefined

IO は常にモナド トランスフォーマー チェーンの一番下にあります

本当ですが、それは例えばの場合にも当てはまりSTます。

IOモナドの実装は不明確で、ソースコードには Haskell の内部構造がいくつか示されています

繰り返しますが、実装は実装の詳細です。実装の複雑さはIO、実際には高度に最適化されていることに大きく関係しています。特殊化された純粋なモナド (たとえばattoparsec )についても同じことが言えます。

すでに述べたように)、より単純な実装が可能ですが、それらは完全に最適化された現実世界のIO型ほど有用ではありません。

幸いなことに、実装はそれほど気にする必要はありません。の内部IO不明確かもしれませんが、実際のモナド インターフェイスである外部は非常に単純です。

純粋なコードの評価順序は関係ありません

まず第一に、純粋なコードでは評価順序が重要になる可能性があります!

Prelude> take 10 $ foldr (\h t -> h `seq` (h:t)) [] [0..]
[0,1,2,3,4,5,6,7,8,9]
Prelude> take 10 $ foldr (\h t -> t `seq` (h:t)) [] [0..]
^CInterrupted.

しかし実際には、純粋なコードの評価の順序が間違っているために、 ⊥ 以外の誤った結果が得られることは決してありません。ただし、実際にはモナド アクションの並べ替え (またはその他) には適用されません。IOシーケンスの順序を変更すると、ランタイムがこの構造を構築するために使用する評価順序だけでなく、結果のアクションの実際の構造も変更されるためです。

例 (リストモナド):

Prelude> [1,2,3] >>= \e -> [10,20,30] >>= \z -> [e+z]
[11,21,31,12,22,32,13,23,33]
Prelude> [10,20,30] >>= \z -> [1,2,3] >>= \e -> [e+z]
[11,12,13,21,22,23,31,32,33]

そうは言っても、確かに非常に特別です。実際、モナドと呼ぶのをためらう人もいると思います(モナドの法則を満たすためIOに実際に何を意味するのかは少し不明です)。IO特に、レイジー IOは大きなトラブルメーカーの 1 つです (常に避けるのが最善です)。

于 2016-04-13T12:01:02.943 に答える
2

STモナド、またはほぼ間違いなくモナドについても同様のステートメントを作成できますSTM(ただし、実際には の上にモナドを実装できますIO)。

基本的に、Reader モナド、Error モナド、Writer モナドなどはすべて純粋なコードです。およびモナドはSTIO実際に不純なこと (状態の突然変異など) を行う唯一のものであるため、純粋な Haskell では定義できません。それらはコンパイラのどこかに「組み込まれている」必要があります。

于 2016-04-13T11:31:28.893 に答える