Haskell:在一次故障后执行操作

时间:2016-07-01 23:57:32

标签: haskell

如果IO Bool中的任何一个Bool

,那么执行False测试列表然后在最后执行操作的最佳方式是什么?

如果我有功能检查目录中是否存在给定文件

check :: FilePath -> IO ()
check s = do 
          r <- doesFileExist s
          putStrLn s ++ if r then " exists" else " does not exist"

我希望能够检查文件列表,然后在最后执行另一个功能,具体取决于是否所有测试都通过了?

目前我只能考虑用

之类的东西再次进行检查
allPassed = do 
            l <- mapM doesFileExist [`list of files`]
            if all (==True) l then "all ok" else "meh"

2 个答案:

答案 0 :(得分:1)

我会像这样使用foldM

import Control.Monad

check :: FilePath -> IO Bool
check = undefined

process files = do
  allok <- foldM (\b f -> fmap (b &&) (check f)) True files
  if allok then putStrLn "All OK" else putStrLn "Oops"

请注意,这将始终执行所有测试。

docs for allM表示它是短路的,所以

do allok <- allM check files
   if allok then ... else ...

将在第一次失败后停止执行检查。

<强>更新

以下是一些演示代码:

import Control.Monad

check :: Int -> IO Bool
check x =  do putStrLn ("x = " ++ show x)
              return $ even x

process files = do
  allok <- foldM (\b f -> fmap (b &&) (check f)) True files
  if allok then putStrLn "All OK" else putStrLn "Oops"

main = do process [1..5]   -- will print "Oops"
          process [2,4,6]  -- will print "All OK"

答案 1 :(得分:1)

我建议使用allM包中的Control.Monad.Loops。如果它看到任何值为false,它会提前退出,如果您的检查涉及一些昂贵的计算,这将非常有用。

这是一个简单的例子:

import Control.Monad.Loops

doesFileExist :: FilePath -> IO Bool
doesFileExist path
    | path == "holiday.jpg" = return True
    | path == "me.jpg" = return True
    | path == "pop song.mp3" = return True
    | otherwise = return False

check :: FilePath -> IO Bool
check s = do
    r <- doesFileExist s

    putStrLn $ s ++ if r
                        then " exists"
                        else " does not exist"

    return r

main :: IO ()
main = do
    allPassed <- allM check ["holiday.jpg", "cat.mp4", "me.jpg"]

    if allPassed
        then putStrLn "Yes"
        else putStrLn "No"