对于某些文件操作,我需要检查文件是否存在,是否已被修改,然后才对其执行一些操作。我的新手Haskell代码如下所示(简化):
someFileOp ::FileContents -> FilePath -> IO (FileOpResult)
someFileOp contents absFilePath = do
fileExists <- DIR.doesFileExist absFilePath
if fileExists
then do
isMod <- isModified contents absFilePath
if isMod
then return FileModified
else return $ doSomethingWithFile
else return FileNotFound
确实有效。但是,嵌套的if表达式在我看来错误-不像FP。在IO中检查几个布尔条件然后根据其结果采取某些措施的惯用方式是什么?
您发布的代码对我来说很好。另一种可能性是像ExceptT Err IO
这样的短路单子。
data Err = FileNotFound | FileModified
getFileContents :: FilePath -> ExceptT Err IO FileContents
getFileContents fp = do
exists <- doesFileExist fp
if exists then {- ... -} else throwError FileNotFound
someFileOp :: FileContents -> FilePath -> ExceptT Err IO FileOpResult
someFileOp fc fp = do
fc' <- getFileContents fp
when (fc /= fc') (throwError FileModified)
doSomethingWithFile
忽略丹尼尔(Daniel)在比赛中的要点,以及为什么通常不做检查文件的原因,更多的Haskell解决方案通常是monad转换器。这是ExceptT变压器有意义的典型情况。我还包括对ContT的(误用)用法,以防您好奇并想探索:
我将使用whenM :: Monad m => m Bool -> m () -> m()
或ifM :: Monad m => m Bool -> m a -> m a -> m a
,例如在extra
中可用: