问题描述
当给定由 分隔的文本输入文件时,该程序产生我期望的输出:
This program produces the output I expect when given an input file of text delimited by :
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
用 withFile 替换 openFile 并稍微重新排列
By substituting withFile for openFile and rearranging slightly
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
我根本没有得到任何输出.我被难住了.
I manage to get no output at all. I'm stumped.
不再难倒了:感谢所有人的深思熟虑和发人深省的答案.我在文档中多读了一点,了解到withFile 可以理解为括号 的部分应用.
Not stumped anymore: thanks to one and all for the thoughtful and thought-provoking answers. I did a little more reading in the documentation and learned that withFile can be understood as a partial application of bracket.
这就是我的结局:
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
推荐答案
文件过早关闭.来自 文档:
The file is being closed too early. From the documentation:
句柄将在退出 withFile 时关闭
这意味着该文件将在 withFile
函数返回后立即关闭.
This means the file will be closed as soon as the withFile
function returns.
因为hGetContents
和朋友们比较懒,所以它不会尝试读取文件,直到它被putStrLn
强制,但到那时,withFile
应该已经关闭了文件.
Because hGetContents
and friends are lazy, it won't try to read the file until it is forced with putStrLn
, but by then, withFile
would have closed the file already.
为了解决问题,把整个事情传递给withFile
:
To solve the problem, pass the whole thing to withFile
:
main = withFile "test.txt" ReadMode $ handle -> do
xs <- getlines handle
sequence_ $ map putStrLn xs
这是有效的,因为当 withFile
开始关闭文件时,您已经打印了它.
This works because by the time withFile
gets around to closing the file, you would have already printed it.
这篇关于withFile 与 openFile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!