Learn You a Haskell for Great Good!を写経して学習しています。
以下のソースは Learn You a Haskell for Great Good! / 9 Input and Output / Exceptions を基に入力したファイルが存在しなかった場合はリトライするように書いたつもでした。
import System.Environment import System.IO import System.IO.Error -- この場合は File name: が表示される。 -- main = toTry main = toTry `catch` (\e -> toTry `catch` (\e -> toTry `catch` handler)) toTry :: IO () toTry = do putStr "File name:" fileName <- getLine contents <- readFile fileName putStrLn $ "The file has " ++ show (length (lines contents)) ++ " lines!" handler :: IOError -> IO () handler e | isDoesNotExistError e = putStrLn "The file doesn't exist!" | otherwise = ioError e
- 1回で存在するファイル名が入力された場合。
$ runghc exception.hs exception.hs -- getLine に対する入力 File name:The file has 19 lines!
- 3回ともで存在するファイル名が入力されなかった場合。
$ runghc exception.hs abc -- getLine に対する入力 hoge -- getLine に対する入力 nnn -- getLine に対する入力 File name:File name:File name:The file doesn't exist!
最後に File name: が出力されました。catchの中で出力するのではなく、これを出力してね、という手続きを返すからなのでしょう。
- 追記 2011/06/18:hFlush stdout を入れて解決しました。
import System.Environment import System.IO import System.IO.Error main = toTry `catch` (\e -> toTry `catch` (\e -> toTry `catch` handler)) toTry :: IO () toTry = do putStr "File name:" hFlush stdout -- ※これを入れることで解決。 fileName <- getLine contents <- readFile fileName putStrLn $ "The file has " ++ show (length (lines contents)) ++ " lines!" handler :: IOError -> IO () handler e | isDoesNotExistError e = putStrLn "The file doesn't exist!" | otherwise = ioError e
$ runghc exception.hs File name:hoge File name:huga File name:exception.hs The file has 21 lines!