关闭文件句柄会导致 Haskell 出现问题

Closing file handle causes troubles in Haskell

我有以下代码用于加载文件内容并使用 aeson 将其解析为对象:

  loadFromFile filename = do
    fileHandle <- openFile ( dataDir ++ "/" ++ filename ) ReadMode
    contents <- B.hGetContents fileHandle
    let result = fromMaybe initial $! JSON.decode contents in do
      hClose fileHandle
      return $! result 

此代码的问题在于它会导致以下错误:

filename.json: hGetBufSome: illegal operation (handle is closed)
filename.json: hGetBufSome: illegal operation (handle is closed)

我不太明白为什么它认为文件句柄已关闭。毕竟我在关闭手柄之前正在阅读它。还是延迟评估会影响执行顺序?我尝试添加相应的 $! 运算符以使其更快地评估,但它没有帮助。如果我删除 hClose fileHandle 行,那么我会开始出现以下类型的零星错误:

filename.json: openFile: resource busy (file is locked)

如果有人知道如何修复这个 catch22,我将不胜感激。谢谢!

与其在关闭句柄后强制执行结果,不如在关闭句柄之前强制执行结果,以下是使用 BangPatterns 执行此操作的方法:

  loadFromFile filename = do
    fileHandle <- openFile ( dataDir ++ "/" ++ filename ) ReadMode
    contents <- B.hGetContents fileHandle
    let !result = fromMaybe initial $! JSON.decode contents
    hClose fileHandle
    return result

在这种情况下不需要 deepseq,因为(我相信)decode 函数会在决定是 return Nothing 还是 [=15= 之前处理整个输入], 所以只强制一级就够了。

而且,如果可能的话,最好完全避免句柄:

  loadFromFile filename = do
    contents <- B.readFile ( dataDir ++ "/" ++ filename )
    return $! fromMaybe initial $! JSON.decode contents