2014-01-18 29 views
3

我想一個簡單的處理程序添加到readFile功能:異常處理「READFILE」

readHandler :: IOError -> IO() 
readHandler e 
    | isDoesNotExistError e = putStrLn "The file does not exist" 
    | otherwise = putStrLn "Something went wrong" 

main = do 
    // stop executing if there is no file 
    contents <- (readFile "path.xml") `catch` readHandler 
    // generates [(x,y),(x,y)] 
    coordinates = parseXML contents 
    // I want to do something with the coordinates 
    nextFunction coordinates 

當我嘗試編譯此我得到的錯誤:

Couldn't match type `()' with `[Char]' 
Expected type: IOError -> IO String 
    Actual type: IOError -> IO() 
In the second argument of `catch', namely `readHandler' 
In a stmt of a 'do' block: 
    contents <- (readFile "path") `catch` readHandler 
In the expression: 
    do { contents <- (readFile "path") `catch` readHandler; 
     putStrLn contents } 

因此readHandler :: IOError -> IO()應該是readHandler :: IOError -> IO String

但是這樣我就不能打印錯誤信息。

我應該如何解決這個問題?

回答

5

catch (readFile "path") readHandler應該是什麼類型?

顯然,如果該文件存在,我們就希望它是一個Stringcatch不應該改變它的類型,所以在某種程度上我們不得不產生String不管。因爲如果一個異常被拋出,readHandler運行時,它也必須產生一個字符串。

這樣catch被表現得像一個非常複雜的if表情:)然而,這是不理想的,因爲我們不希望保持與一些隨機String沒有來從文件上運行我們的函數。

相反,我們可以做類似

main = handle readHandler $ do 
    ... 

因爲現在我們只需要產生IO(),微不足道。

如果您不喜歡不管是什麼原因船,另一個理智的選擇是到刺激性例外改造,以更加愉快Either

main = do 
    strOrExc <- try $ readFile "foo" 
    case strOrExc of 
    Left except -> print except 
    Right contents -> putStrLn contents 

,當然你可以處理這個Exception e => Either e a以任何方式帶來你的幸福。

當然還有最後一種選擇,使整個程序來個急剎車,然後有。我們可以僅僅通過改變readHandler

import System.Exit 

readHandler :: IOError -> IO a 
readHandler = putStrLn "Buckle your seatbelts" >> exitFailure 
+0

我編輯我的代碼更清晰。有沒有辦法與我的處理程序一起使用第二個解決方案,如果找到該文件,繼續執行我的執行鏈? –

+0

@格特 - 揚肯定,而不是隻打印字符串,把任何你打算在這種情況下,分公司使用的字符串。這當然是醜陋的。一種不合理的方法是「單一」單元。 – jozefg

+0

現在的問題是,「strOrExc」的類型爲「無論是A0字符串」,而不是‘字符串’。我認爲我對Haskell的知識還不足以解決這個問題。謝謝你的幫助! :) –

2

抓做到這一點的類型是

catch :: Exception e => IO a -> (e -> IO a) -> IO a 

因此,如果抓的第一個參數是IO String,那麼第二個參數(這是一個功能),具有返回無論是。 你可以改變你readHandler像這樣:

readHandler :: IOError -> IO String 
readHandler e 
    | isDoesNotExistError e = do putStrLn "The file does not exist" ; return "" 
    | otherwise = do putStrLn "Something went wrong" ; return "" 

但我不知道,這是否是通緝「副作用」(返回一個空字符串)。

+0

這可行,但我需要程序停止並且不返回空字符串。我認爲必須有更好的方式。 –