Haskell Handle无法正常关闭

时间:2017-10-31 03:42:30

标签: haskell

import GHC.Conc (pseq)

import System.Directory (removeFile, renameFile)
import System.IO

main :: IO ()
main = do
    let fp = "handleCollision.txt"
    h <- openFile fp ReadMode
    l <- hGetLine h
    (hClose h) `pseq` (func fp)

func :: FilePath -> IO ()
func fp = do
    h <- openFile fp ReadMode
    cont <- hGetContents h
    chk <- openFile ('.':fp) WriteMode >>= (\h -> hPutStrLn h (unlines . map (map succ) $ lines cont) >> hClose h)
    chk `pseq` (hClose h `pseq` removeFile fp)
    renameFile ('.':fp) fp

在上面的代码中,调用main的结果是尝试删除fp引用的文件时出错。

  

***异常:DeleteFile“handleCollision.txt”:权限被拒绝(进程无法访问该文件,因为它正由另一个进程使用。)

如果我只调用'func“handleCollision.txt”',则不会发生错误。为什么main中的句柄似乎与func中fp的删除相冲突,尽管'hClose h'被视为严格而'func fp'被视为懒惰?

1 个答案:

答案 0 :(得分:5)

您应该使用Control.Parallel.pseq代替GHC.Conc.pseq来实现可移植性。但是,它没有按照你的想法做到。

pseq仅强制对WHNF进行评估。对于表达式(hClose h) :: IO (),WNHF就是 - IO动作的表示。它执行操作。

取出pseq。更好的是,使用withFile之类的方法来避免手动跟踪文件的打开和关闭。

main = do
    let fp = "handleCollision.txt"
    l <- withFile fp ReadMode hGetLine
    func fp

func fp = do
    cont <- readFile fp
    writeFile ('.':fp) $ unlines $ map (map succ) $ lines cont
    renameFile ('.':fp) fp