gpt4 book ai didi

haskell - 通过示例了解 `withFile`

转载 作者:行者123 更新时间:2023-12-01 08:29:17 25 4
gpt4 key购买 nike

我在 Haskell 中实现了 withFile:

withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a  
withFile' path iomode f = do
handle <- openFile path iomode
result <- f handle
hClose handle
return result

当我运行 Learn You a Haskell 提供的 main 时,它按预期打印出“girlfriend.txt”的内容:

import System.IO

main = do
withFile' "girlfriend.txt" ReadMode (\handle -> do
contents <- hGetContents handle
putStr contents)

我不确定我的 withFile' 是否可以处理最后两行:(1) 关闭句柄和 (2) 将结果作为 IO a

为什么没有发生以下情况?

  1. result 被懒惰地绑定(bind)到 f 句柄
  2. hClose 句柄 关闭文件句柄
  3. result 得到 return,这导致 f 句柄 的实际评估。由于 handle 已关闭,因此会引发错误。

最佳答案

Lazy IO 俗称令人困惑。

取决于 putStr 是否在 hClose 之前执行。

注意第一次和第二次使用之间的区别(括号是不必要的,但在第二个示例中会澄清)。

ghci> withFile' "temp.hs" ReadMode (hGetContents >=> putStr) -- putStr 
import System.IO
import Control.Monad
withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a
withFile' path iomode f = do
handle <- openFile path iomode
result <- f handle
hClose handle
return result
ghci> (withFile' "temp.hs" ReadMode hGetContents) >>= putStr
ghci>

在这两种情况下,传入的 f 都有机会在句柄关闭之前运行。由于延迟评估,hGetContents 仅在需要时读取文件,即被迫为某些其他函数生成输出。

在第一个示例中,由于 f(hGetContents >=> putStr),因此必须读取文件的完整内容才能执行 putStr .

在第二个示例中,hGetContents 之后不需要计算任何内容以 返回结果,这是一个惰性列表。 (我可以很高兴 return (show [1..]) 如果我选择使用整个输出,它只会无法终止。)这被视为惰性 IO 的问题,已修复通过严格的 IO、管道或导管等替代方案。

当句柄过早关闭时返回文件的空字符串可能是一个错误,但在关闭之前运行整个 f 肯定不是。

关于haskell - 通过示例了解 `withFile`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24234517/

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