2008/09/12

IO型は、使うだけなら簡単に思える。たとえば String -> IO () という型の putStr に文字列を渡せば、それが画面に印字される。
Main >putStr "abcdef\n"
abcdef
putStr の出力は IO () 型なので、結果として印字された「abcdef」は文字列ではない。じゃあ、IO () 型の出力はどこにいったんだろう? Show クラスのインスタンスがないということ? でも、だとしたらGHCがエラーを出力するんじゃなかったっけ?

とにかく絶対に IO () な何かが関数の結果として返ってきているはずなので、IO () -> String な関数を定義してそれに putStr をつないでみた。
vacant :: IO () -> String
vacant o = "munashii"
Main >vacant $ putStr "subarashii\n"
"munashii"
どうして「subarashii」が印字されないん?

結局、これはやっぱり副作用じゃないってことなんだろうな。Scheme でも同じことをすると、
gosh> (define (vacant o) "munashii")
vacant
gosh> (vacant (print "subarashii"))
subarashii
"munashii"
これが本物の副作用ということなのか!

3 件のコメント:

  1. GHCiの挙動はユーザが入力した式の型によって少し違うことに注意!
    式が IO a の場合にはそのアクションを「実行」する
    式が IO a 以外の場合には、print〈入力した式〉 を「実行」する

    返信削除
  2. putStrLn "hoge" `seq` putStrLn "HOGE"
    とするとどうなると思いますか?

    返信削除
  3. IOは処理系の挙動が変わるんですね。

    > putStrLn "hoge" `seq` putStrLn "HOGE"

    まんまと、hogeHOGE だと思ってしまいました。

    返信削除