Haskellの練習として、catコマンドを実装してみる。
getConentsを使う
もっとも簡潔な実装。
-- cat1.hs main = getContents >>= putStr
do記法を使って書くと次のようになる。
main = do
x <- getContents
putStr x
上のコードは下と同値である。
main = getContents >>= (\x -> putStr x)
ここで、>>=はいわゆるbind演算である。
(\x -> putStr x)はputStrそのものなので、より簡潔な形に直すことで最初のコードになる。
実行結果。
$ runghc cat1.hs hoge hoge fuga fuga [Ctrl+D]
getLineを使う
getLineで1行ずつ読む場合は、EOFErrorのハンドルが必要になる。
-- cat2.hs
import System.IO.Error
main = catchIOError catLoop handleError
where catLoop = getLine >>= putStrLn >> catLoop
handleError e
| isEOFError e = return ()
| otherwise = ioError e
putStrLnの戻り値(IO型)はcatLoopに必要ないので、>>=の代わりに戻り値を捨てる>>を使う。
handleErrorはEOFErrorのときのみ()(unit、空の値を表す)を値に持つモナドを返し、それ以外のときはIOErrorを値に持つモナドを作って返す。
実行結果。
$ runghc cat2.hs hoge hoge fuga fuga [Ctrl+D]