gpt4 book ai didi

Haskell 从文件 IO 返回惰性字符串

转载 作者:行者123 更新时间:2023-12-02 18:30:45 24 4
gpt4 key购买 nike

我又回来了,带着我最新杰作的(对我来说)非常奇怪的行为......

此代码应该读取文件,但它没有:

readCsvContents :: String -> IO ( String )
readCsvContents fileName = do
withFile fileName ReadMode (\handle -> do
contents <- hGetContents handle
return contents
)

main = do
contents <- readCsvContents "src\\EURUSD60.csv"
putStrLn ("Read " ++ show (length contents) ++ " Bytes input data.")

结果是

Read 0 Bytes input data.

现在我更改了第一个函数并添加了一个 putStrLn:

readCsvContents :: String -> IO ( String )
readCsvContents fileName = do
withFile fileName ReadMode (\handle -> do
contents <- hGetContents handle
putStrLn ("hGetContents gave " ++ show (length contents) ++ " Bytes of input data.")
return contents
)

结果是

hGetContents gave 3479360 Bytes of input data.
Read 3479360 Bytes input data.

什么鬼???嗯,我知道,Haskell 很懒。但我不知道我必须像这样踢它的屁股。

最佳答案

你说得对,这很痛苦。出于这个原因,请避免使用旧的标准文件 IO 模块 - 除非像您一样简单地读取不会更改的整个文件;这可以通过 readFile 来完成。

readCsvContents :: Filepath -> IO String
readCsvContents fileName = do
contents <- readFile fileName
return contents

请注意,根据单子(monad)定律,这与1完全相同

readCsvContents = readFile

您尝试的问题是,当 monad 退出 withFile 时,句柄被无条件关闭,而不检查 contents 的惰性评估是否实际上强制了文件读取。这当然是可怕的;我自己永远不会费心去使用 handle 。 readFile 通过将句柄的关闭与原始结果 thunk 的垃圾收集联系起来来避免该问题;这也不完全是好事,但通常效果很好。

为了正确使用文件 IO,请查看 conduitpipes图书馆。前者更注重性能,后者更注重优雅(但实际上,区别并没有那么大)。

<小时/>

1您的第一次尝试与 readCsvContents fn = withFile fn ReadMode hGetContents 相同。

关于Haskell 从文件 IO 返回惰性字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30864903/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com