17

私は Haskell と IO モナドを学んでいます。これにより、プログラムが「こんにちは」と「さようなら」を出力するように強制されないのはなぜだろうかと思います。

second a b = b
main = print ((second $! ((print "hi") >>= (\r -> return ()))) "bye")

私が理解している限り、$!オペレーターは の最初の引数を強制的secondに評価し、その値から値を取得して に渡すために>>=オペレーターを実行する必要があります。これにより、「hi」が画面に出力されます。print "hi"\r -> return ()

私の推論の何が問題になっていますか?

また、Haskell が「安全な」コード内で IO 操作を実行するように (安全でない関数を使用する以外に) だまされないことを証明する方法はありますか?

4

2 に答える 2

34

強制している((print "hi") >>= (\r -> return ()))式は で、タイプはIO ()です。そのため、IO アクションを表します。しかし、そのようなものを評価することは、それを実行することとはまったく異なります!

値を評価するということは、それを弱頭正規形と呼ばれるものに変えるのに十分なステップを実行することを意味します。は抽象的であるためIO、この場合、それが何を意味するかを理解するのは少し難しいですが、 として考えることができIO aます。RealWorld -> (a, RealWorld)RealWorld

RealWorld実行は評価を意味しますが、引数としても渡します。したがって、IO効果が発生します。

これはすべて に固有のものではありませんIO。あなたの混乱と概念は にも等しく当てはまりますa -> b。2 番目の引数が関数の場合の動作を理解すれば$!、それが IO アクションの場合に何が起こるかを理解できます。

于 2014-07-16T08:25:40.950 に答える
21

評価実行を混同しています。のような式を強制すると、print "hi"何も出力されません。IO()何かを出力するアクションを表す値 (この場合は type の値) を生成するだけです。print "hi"の値は、「hi」を印刷するためのレシピと考えることができます。

于 2014-07-16T08:26:28.513 に答える