gpt4 book ai didi

haskell - 如何安全地 `mapM` 超过 `System.IO.openFile`

转载 作者:行者123 更新时间:2023-12-04 11:11:33 27 4
gpt4 key购买 nike

我的应用程序需要在运行时打开多个资源。我通过映射 openFile 来实现这一点一次在应用程序的开始。

let filePaths = ["/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2"]
fileHandles <- mapM (`openFile` ReadWriteMode) filePaths
此代码不安全,因为它可能适用于前 2 个文件路径,但在打开第 3 个文件路径时会引发异常。在这种情况下,我需要关闭已经打开的前 2 个文件路径,这样我就可以退出函数而不会泄漏资源。我查看了 Control.Exception 中的功能和模式但在这种情况下没有找到任何有帮助的东西。我还没有看过 ResourceT。在这种情况下有帮助吗?
我想我正在寻找与此类似的函数签名:
safeMapM:: [a] -> (a -> IO b) -> (b -> IO()) -> [b]
在哪里 (b -> IO())是发生异常时调用的清理函数。
我能想到的解决方案可能不好:
  • 将每个元素包装在 Maybe 中.可以捕获异常并导致 Nothing . mapM总是可以完成,然后我可以检查 Nothing/Exception 然后关闭所有成功打开的文件句柄 Just Handle .
  • 使用折叠而不是 map 。当当前元素发生异常时,我可以关闭折叠的所有先前元素的文件句柄,然后重新抛出异常以阻止折叠继续。
  • 最佳答案

    如果我理解正确,问题是如何确保在发生异常时安全关闭所有句柄。
    对于单个文件,通常的保证安全的方法是 withFile .这里的复杂之处在于您要打开一系列文件。
    也许我们可以编写这个辅助函数来执行 withFile 的嵌套分配。并通过 Handle 的列表s 到最内层的回调:

    nestedWithFile :: [FilePath] -> IOMode -> ([Handle] -> IO r) -> IO r
    nestedWithFile filePaths mode callback = go [] filePaths
    where
    go acc [] =
    callback acc -- innermost invocation, protected by the withFiles
    go acc (p : ps) =
    withFile p mode (\handle -> go (acc ++ [handle]) ps)
    另一种方法是从意识到我们正在用 replicateM 做某事开始。 flavor :我们正在执行“效果” n次,并返回一个包含结果的列表。但是这里的“效果”(即 Applicative )是什么?它似乎是“使用确保释放的包装器功能保护资源的分配”。
    这种效果似乎需要对“剩余计算”进行一些控制,因为当“剩余计算”以任何方式完成时,终结器仍然必须运行。这将我们指向延续单子(monad)更改器(mutator), ContT :
    import Control.Monad
    import Control.Monad.Trans.Cont
    import System.IO

    openFile' :: FilePath -> ContT r IO Handle
    openFile' filePath = ContT (withFile filePath ReadWriteMode)

    openSameFileSeveralTimes :: Int -> FilePath -> ContT r IO [Handle]
    openSameFileSeveralTimes count filePath = replicateM count (openFile' filePath)

    -- The handles are freed when the ([Handle] -> IO r) callback exits
    useHandles :: ContT r IO [Handle] -> ([Handle] -> IO r) -> IO r
    useHandles = runContT
    对于此目的,延续转换器可能有点过于笼统。有像 managed 这样的库它们遵循相同的基 native 制,但更侧重于资源处理。

    关于haskell - 如何安全地 `mapM` 超过 `System.IO.openFile`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68844539/

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