【发布时间】:2011-02-01 09:44:50
【问题描述】:
对 Haskell 来说还是很陌生..
我想读取一个文件的内容,对它做一些可能涉及 IO 的事情(现在使用 putStrLn),然后将新内容写入同一个文件。
我想出了:
doit :: String -> IO ()
doit file = do
contents <- withFile tagfile ReadMode $ \h -> hGetContents h
putStrLn contents
withFile tagfile WriteMode $ \h -> hPutStrLn h "new content"
但是由于懒惰,这不起作用。不打印文件内容。我找到了this post,它很好地解释了它。
建议的解决方案是在withFile 中包含putStrLn:
doit :: String -> IO ()
doit file = do
withFile tagfile ReadMode $ \h -> do
contents <- hGetContents h
putStrLn contents
withFile tagfile WriteMode $ \h -> hPutStrLn h "new content"
这行得通,但这不是我想做的。 I will finally replace putStrLn 中的操作可能会很长,我不想一直保持文件打开。一般来说,我只是希望能够取出文件内容,然后在处理该内容之前将其关闭。
我想出的解决方案如下:
doit :: String -> IO ()
doit file = do
c <- newIORef ""
withFile tagfile ReadMode $ \h -> do
a <- hGetContents h
writeIORef c $! a
d <- readIORef c
putStrLn d
withFile tagfile WriteMode $ \h -> hPutStrLn h "Test"
但是,我发现这很长而且有点混淆。我认为我不需要IORef 只是为了获得一个价值,但我需要“地方”来放置文件内容。此外,如果没有 writeIORef 的严格性注释 $!,它仍然无法工作。我猜IORefs 天生不严谨?
谁能推荐一种更好、更短的方法来做到这一点,同时保持我想要的语义?
谢谢!
【问题讨论】:
-
如果您发布编译代码所需的
import声明,其他人可能会帮助调试它... -
过早的优化,邪恶的根源等等。为什么你害怕保留文件描述符,只要你需要它?
-
IORef 没有您感知到的效果。 IORef 中的值可以像从块中返回的值一样懒惰。您的代码相当于也不起作用: doit file = do { d do { a
标签: haskell file-io io lazy-evaluation