当我尝试运行此代码时...
module Main where
import qualified Data.Text.Lazy.IO as LTIO
import qualified Data.Text.Lazy as LT
import System.IO (IOMode(..), withFile)
getFirstLine :: FilePath -> IO String
getFirstLine path =
withFile path ReadMode (\f -> do
contents <- LTIO.hGetContents f
return ("-- "++(LT.unpack . head $ LT.lines contents)++" --"))
main::IO()
main = do
firstLine <- getFirstLine "/tmp/foo.csv"
print firstLine
我得到
"-- *** Exception: Prelude.head: empty list
...我希望它打印“/tmp/foo.csv”的第一行。你能解释一下为什么吗?最终,我试图弄清楚如何从文件输入创建一个懒惰的文本列表。
最佳答案
正如 Daniel Lyons 在评论中提到的,这是由于 IO 和懒惰的交互造成的。
想象一下,如果你愿意:
withFile
打开文件,到文件句柄 f
。 f
内容的 Thunk。 withFile
关闭文件。 HaskellWiki / Maintaining laziness 页面上提到了这个陷阱。
要修复,您可以读取
withFile
中的整个文件内容(可能通过使用 seq
强制它)或延迟关闭文件而不是使用 withFile
。关于Haskell:为什么这段代码会失败?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12012907/