このプログラムは、\n で区切られたテキストの入力ファイルを与えられた場合に、期待どおりの出力を生成します。
import System.IO
main :: IO ()
main = do h <- openFile "test.txt" ReadMode
xs <- getlines h
sequence_ $ map putStrLn xs
getlines :: Handle -> IO [String]
getlines h = hGetContents h >>= return . lines
openFileをwithFileに置き換えて少し並べ替えると
import System.IO
main :: IO ()
main = do xs <- withFile "test.txt" ReadMode getlines
sequence_ $ map putStrLn xs
getlines :: Handle -> IO [String]
getlines h = hGetContents h >>= return . lines
まったく出力が得られません。困惑しています。
追記:もう困惑していません。思慮深く考えさせられる回答をくださった皆様に感謝します。ドキュメントをもう少し読んで、次のことを知りました。ファイル付きの部分的な応用として理解できるブラケット。
最終的にこうなりました:
import System.IO
main :: IO ()
main = withFile "test.txt" ReadMode $ \h -> getlines h >>= mapM_ putStrLn
getlines :: Handle -> IO [String]
getlines h = lines `fmap` hGetContents h
ベストアンサー1
ファイルが閉じられるのが早すぎます。ドキュメンテーション:
ハンドルはwithFile の終了時に閉じられます
これは、関数が返されるとすぐにファイルが閉じられることを意味しますwithFile
。
および の仲間は怠惰なのでhGetContents
、 で強制されるまでファイルを読み取ろうとはしませんputStrLn
が、その時点では、withFile
すでにファイルが閉じられているでしょう。
問題を解決するには、全体を に渡しますwithFile
:
main = withFile "test.txt" ReadMode $ \handle -> do
xs <- getlines handle
sequence_ $ map putStrLn xs
これが機能するのは、withFile
ファイルを閉じるまでに、すでに印刷が完了しているからです。