2012-09-07 48 views
4

爲什麼這個代碼工作,異常警告在Haskell,但與OldException

import qualified Control.OldException as E 

但與

import qualified Control.Exception as E 

下面是代碼:

fileContents <- (readFile "shpm.txt") `E.catch` (\_ -> return "") 

這裏是錯誤我得到「新」異常

Ambiguous type variable `e0' in the constraint: 
    (E.Exception e0) arising from a use of `E.catch' 
Probable fix: add a type signature that fixes these type variable(s) 
In a stmt of a 'do' block: 
    fileContents <- (readFile "shpm.txt") 
        `E.catch` (\ _ -> return "No Tasks") 

回答

9

因爲類型已更改。具體做法是:

  • OldException:catch :: IO a -> (Exception -> IO a) -> IO a
  • 例外:catch :: Exception e => IO a -> (e -> IO a) -> IO a

新的模式需要知道什麼e值是爲Exception e類型。這實際上意味着你需要告訴編譯器你正在捕獲哪個異常。您使用OldException的示例會捕獲所有內容,現在不鼓勵(有關更多信息,請參閱Catching All Exceptions)。

一個簡單的修正你的函數將是這樣的:

foo = (readFile "foo") `E.catch` (\e -> const (return "") (e :: E.IOException)) 

或者拉姆達少版本:

bar = (readFile "foo") `E.catch` myHandler 

myHandler :: E.IOException -> IO String 
myHandler _ = return "" 
+0

這工作得很好,我明白除了「const」之外的所有東西,那是幹什麼的? –

+1

@hatboysam'const'只需要兩個參數並返回第一個(「拋棄」第二個參數)。這只是給了我一種提供'e'類型的內聯聲明的方法(實際上並未使用'e'的值)。我首先想到了這一點,因爲它是對你的例子的直接修改,但第二個例子更清晰,可能是你應該使用的。 –

+0

謝謝!很好的解釋。 –

1

您需要爲被捕獲的異常提供一個explict類型。例如:

fileContents <- (readFile "shpm.txt") `E.catch` ((\_ -> return "") :: E.SomeException -> IO String) 
+0

我認爲你有一個流浪''::那裏。 – huon

+0

因爲我的編輯12秒前沒有! –