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 件のコメント:

匿名 さんのコメント...

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

匿名 さんのコメント...

putStrLn "hoge" `seq` putStrLn "HOGE"
とするとどうなると思いますか?

k16 さんのコメント...

IOは処理系の挙動が変わるんですね。

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

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