ここに考えるべき食べ物があります。
モナドコードを書くとき、モナドは実行された操作に順序を課します。たとえば、IOモナドに書き込む場合:
do a <- doSomething
b <- doSomethingElse
return (a + b)
私はdoSomething
前に実行されることを知っていますdoSomethingElse
。
ここで、Cのような言語の同等のコードを考えてみましょう。
return (doSomething() + doSomethingElse());
Cのセマンティクスは、これら2つの関数呼び出しが評価される順序を実際には指定しないため、コンパイラーは自由に物事を自由に移動できます。
私の質問はこれです:この評価順序も未定義のままにするHaskellでモナディックコードをどのように書くのですか?理想的には、コンパイラのオプティマイザがコードを調べて動き始めたときに、いくつかのメリットを享受できます。
仕事を成し遂げることができないが、正しい「精神」にあるいくつかの可能なテクニックはここにあります:
- 機能的なスタイルでコードを記述します。つまり、モナディック呼び出しを記述
plus doSomething doSomethingElse
してplus
スケジュールします。欠点:モナディックアクションの結果の共有を失い、plus
それでも物事がいつ評価されるかについて決定を下します。 - 遅延IOを使用します。つまり
unsafeInterleaveIO
、評価の遅延を要求するようにスケジューリングを延期します。しかし、怠惰は、順序が定義されていない厳密なものとは異なります。特に、すべてのモナディックアクションを実行する必要があります。 - レイジーIO、すべての引数をすぐにシーケンスすることと組み合わせる。特に、
seq
順序の制約を課しません。
この意味で、私は単調な順序付けよりも柔軟性がありますが、完全な怠惰よりも柔軟性が低いものが必要です。