Haskell には文字列を表示するための関数 putStr があります。
Main> :t putStr putStr :: String -> IO ()
putStr は文字列を引数として IO アクションを返します。
putStr は出力する手続きを返すのであって、putStr が呼ばれたときに関数の中で出力するのではありません。
IO()型の関数が複数呼ばれると、IO アクションは合成されます。
そのことを Debug.Trace で確認してみます。
module Main where import Debug.Trace main :: IO() main = do hello world hello :: IO() hello = trace "hello," ( putStr "Hello,") world :: IO() world = trace "wrold!" ( putStr "world!\n")
Hello, → hello, → world! → wrold! と表示されそうですが、そうはなりません。
> :main hello, wrold! Hello,world!
- hello関数の()の中の putStr "Hello," では"Hello," を出力するIO アクションが返され、trace は
"hello," と表示して、putStr で作られた IO アクションを返します。
- world関数も同様に動作し、 IO アクション返します。
- main では hello 関数の返した IO アクションと world 関数の返したIO アクションが合成されて返され、Haskell
の環境がそれを出力する。
> :m Debug.Trace > let out = trace "hello" $ putStrLn "Hello" -- 出力の必要はない > out -- この時点で必要になったので実行される。 hello Hello > out -- trace は実行されず、確定したIOアクションだけ。 Hello > out Hello > let hello = trace "hello," ( putStr "Hello,") > let world = trace "wrold!" ( putStr "world!\n") > let out = hello >> world > out hello, wrold! Hello,world! > hello >> world -- > Hello,world! > out -- > Hello,world!
putStr は IO アクションを返す関数である。