Haskell の putStr は文字を出力しない。

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 アクションを返す関数である。