2016-07-01 54 views
0

什麼是執行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" 
+0

所以,你正在尋找的東西像一個'allM'功能,'all'一個單子相同呢? –

+2

我的推薦:不要打擾。只要做你想做的事情與文件,並捕捉異常,如果他們不存在。畢竟,在執行此檢查和下一步之間它們可能會停止存在,所以如果您想要一個強大的程序,則必須處理該異常! –

+1

我們不知道OP的應用程序,但有時可能需要在開始昂貴或耗時的操作之前執行「飛行前檢查」,以確保它不會因「明顯」原因而失敗。 – ErikR

回答

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" 
+0

我的'check'函數返回一個'IO Bool',這就是我所遇到的問題..我實際上希望'check'打印一些內容來控制每個文件,然後最後我要做一個最終輸出依賴於所有文件傳遞。 – matthias

+0

答覆已更新。 – ErikR

+0

這實際上完美適合我需要的東西。另外,你阻止了我用'allM'掙扎。很好的回答,並感謝您的時間! #note讓自己更容易達到摺疊和掃描! – matthias

1

我建議使用allMControl.Monad.Loops包。如果它看到任何值是錯誤的,那麼它會退出,如果您的檢查涉及一些昂貴的計算,那麼它很有用。

下面是一個簡單的例子:

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"