みどりねこ日記

よくわからないけど、頑張りますよ。

Haskellのdo記法(4)

do記法の最後の式はdoブロックの結果となります。今までの例では、結果の型はIO ()、つまりIOモナドの空の値でした。

前回の例を、受け取った名前を結果として返す関数、つまり型としてはIO Stringである関数として書き換えます。することといえば、最後にreturn式をつけるだけです。

nameReturn :: IO String
nameReturn = do putStr "What is your first name? "
	first <- getLine
	putStr "And your last name? "
	last <- getLine
	let full = first ++ " " ++ last
	putStrLn ("Pleased to meet you, " ++ full ++ "!")
	return full

この例のコードは、IOモナドに包んだ状態でStringであるフルネームを”返す”関数(IO String型)です。おそらく、こういったコードはreturnの機能について誤解を招く理由です。Cなどのreturnと名前が一緒なだけでなく、その働きも同じようなものに”見えて”しまいます。
しかし、以下のコードを見て下さい。

nameReturn' = do putStr "What is your first name? "
	first <- getLine
	putStr "And your last name? "
	last <- getLine
	let full = first ++ " " ++ last
	putStrLn ("Pleased to meet you, " ++ full ++ "!")
	return full
	putStrLn "I am not finished yet!"

最後の"I am not finished yet!"という文字列出力処理は”実行されます”。つまり、HaskellのreturnはCのそれのように制御の流れを止めてしまう最後の処理ではありません。nameReturn'の型はIO ()です。これはつまり、returnによって作られたIO String型のものは完全に捨てられてしまったことを表しています。doブロックの最後の結果はputStrLnアクション、つまりIO ()であり、これがdoブロック全体の結果となるわけです。