你會更好刪除文件,如果不存在,它只是恢復:
import Prelude hiding (catch)
import System.Directory
import Control.Exception
import System.IO.Error hiding (catch)
removeIfExists :: FilePath -> IO()
removeIfExists fileName = removeFile fileName `catch` handleExists
where handleExists e
| isDoesNotExistError e = return()
| otherwise = throwIO e
這就避免了有人刪除的文件中的競爭條件的代碼檢查它是否存在並刪除它。無論如何,這可能無關緊要,但無論如何,這都是不錯的做法。
請注意import Prelude hiding (catch)
行 - 這是因爲Prelude包含異常處理中的舊功能,現在不贊成使用Control.Exception,它也有一個名爲catch
的函數;進口產品線只是隱藏了Prelude的catch
而非Control.Exception。
但是,這仍然留下您更基本的基本問題:您如何在IO
中編寫條件?
那麼,在這種情況下,就足夠了簡單地做
when fileExists $ removeFile filename
(使用Control.Monad.when)。但是這裏通常在Haskell中查看類型是很有幫助的。
條件的兩個分支必須具有相同的類型。所以填寫
if fileExists
then removeFile filename
else ???
我們應該看看removeFile filename
的類型;無論???
是什麼,它必須具有相同的類型。
System.Directory.removeFile的類型爲FilePath -> IO()
,所以removeFile filename
的類型爲IO()
。所以我們想要的是一個IO行爲,其結果類型爲()
,它什麼都不做。
嗯,return
目的是構造一個沒有效果的行爲,並且僅返回恆定值,並return()
具有用於此的權利類型:IO()
(或更一般地,(Monad m) => m()
)。所以???
是return()
(你可以看到我在上面改進的代碼片段中使用,當removeFile
因文件不存在而失敗時不做任何事情)。
(順便說一句,你現在應該能夠實現when
與return()
的幫助,這是非常簡單的:))
,如果你發現很難進入的東西Haskell的方式不要擔心起初 - 它會自然而然地出現,而當它發生時,這是非常有益的。 :)
`doesFileExist`函數實際上是一個競爭條件的邀請。它不應該存在。 – augustss 2011-12-14 12:20:27
@augustss:我們如何將它重命名爲`didFileExistLastTimeIChecked`? – 2011-12-14 18:11:21
我建議`didFileNotNeverExist`。 – ehird 2011-12-14 18:34:24