2009-01-10 42 views
21

我不認爲這是一個錯誤,但我有點困惑,爲什麼這是行不通的。一個額外的問題是爲什麼它提到變量e?沒有變量e。不明確的類型變量錯誤msg

 
    Prelude> :m +Control.Exception 
    Prelude Control.Exception> handle (\_-> return "err") undefined 

    <interactive>:1:0: 
     Ambiguous type variable `e' in the constraint: 
      `Exception e' 
      arising from a use of `handle' at <interactive>:1:0-35 
     Probable fix: add a type signature that fixes these type variable(s) 
    Prelude Control.Exception> 

顯然它工作正常ghci 6.8,我使用6.10.1。

編輯:我已經最小化了代碼。我希望有兩個6.8相同的結果和6.10

class C a                          

foo :: C a => (a -> Int)-> Int                     
foo _ = 1                          

arg :: C a => a -> Int                       
arg _ = 2                          

bar :: Int                          
bar = foo arg 

試圖編譯:

 
[1 of 1] Compiling Main    (/tmp/foo.hs, interpreted) 

/tmp/foo.hs:12:10: 
    Ambiguous type variable `a' in the constraint: 
     `C a' arising from a use of `arg' at /tmp/foo.hs:12:10-12 
    Probable fix: add a type signature that fixes these type variable(s) 
Failed, modules loaded: none. 
Prelude Control.Exception> 

回答

10

只在GHC 6.10這個問題表明了;它不能在GHC 6.8被複制,因爲handle類型是不同的:

: [email protected] 620 ; ghci 
GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help 
Loading package base ... linking ... done. 
Prelude> :m +Control.Exception 
Prelude Control.Exception> handle (\_ -> return "err") undefined 
"err" 
Prelude Control.Exception> 

OK也許我能在最後得到這個權利。我認爲問題是不是單態的限制,而是你碰到了Read/Show問題的一個實例:你提供了處理某種類型的異常,在新版本的`handle'中,有多於一種類型的異常,並且該異常的類型不會顯示在您的結果中。所以編譯器無法知道哪個你試圖處理的異常類型。一種工作方式是挑一個。下面是一些代碼,工程:

Prelude Control.Exception> let alwaysError :: SomeException -> IO String; alwaysError = \_ -> return "err" 
Prelude Control.Exception> handle alwaysError undefined 
"err" 

順便說一句,GHC庫文檔中的例子使用的handle並不6.10下編譯。我已經提交了一個錯誤報告。

+0

爲什麼編譯器還需要知道哪些異常?該函數處理來自該類的每種類型。 – luntain 2009-01-10 21:40:56

+0

由於「手柄」的類型;任何對`handle`的使用都必須應用於Exception類中的一個*特殊類型。由於您的處理程序適用於類中的所有類型,因此編譯器無法將類型分配給「句柄」。 ('e`來自'handle`類型。) – 2009-01-11 01:25:28

1

「異常e」很可能來自「句柄」的類型簽名。

The documentation 說:

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

在GHC 6.8它使用的是不同的,這可以解釋爲什麼我沒有得到這個錯誤。

handle :: (Exception -> IO a) -> IO a -> IO a 

似乎你遇到了單態限制。那個「_」 - 模式必須是單形的(它與ghc 6.8一樣)或明確地鍵入。 「解決方法」是將模式放在定義的左側,它構成Haskell報告指定的「簡單模式綁定」。

試試這個:

let f _ = return "err" 
handle f undefined 

http://www.haskell.org/haskellwiki/Monomorphism_restriction

3

一種解決方法是在GHC 6.10使用Control.OldException *而不是Control.Exception

2

嘗試給予您的處理程序類型SomeException -> IO x,其中x是具體類型,例如,

import Control.Exception 
let f _ = putStrLn "error" :: SomeException -> IO() 
in handle f undefined 
11

類型的Control.Exception.handle是:

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

你所看到的問題是,lambda表達式(\_ -> return "err")e -> IO a型,其中eException一個實例。清除泥漿?好。現在,我將提供你的情況,這實際上應該是有用的解決方案:)

它只是恰巧e應該Control.Exception.ErrorCall因爲undefined使用error會拋出ErrorCall(的Exception一個實例)。

要處理的undefined用途可以定義類似handleError

handleError :: (ErrorCall -> IO a) -> IO a -> IO a 
handleError = handle 

它本質上是一個別名Control.Exception.handlee固定爲ErrorCall這是什麼error拋出。

它看起來像這樣在運行GHCI 7.4.1時:

ghci> handleError (\_ -> return "err") undefined 
"err" 

要處理所有異常一個handleAll函數可以寫成如下:

handleAll :: (SomeException -> IO a) -> IO a -> IO a 
handleAll = handle 

捕獲所有異常是有後果描述在Control.Exception文檔的摘錄中:

捕獲所有異常

它可以捕獲所有異常,使用類型SomeException

catch f (\e -> ... (e :: SomeException) ...) 

然而,這通常不是你想要做什麼!

例如,假設您想要讀取一個文件,但是如果它不存在,則繼續,如果它包含""。您可能會試圖捕獲所有異常,並在處理程序中返回""。但是,這有各種不良後果。例如,如果用戶在恰當的時刻按下control-C,則會捕獲到異常,並且程序將繼續運行,因爲該文件包含""。同樣,如果另一個線程試圖終止讀取該文件的線程,則ThreadKilled異常將被忽略。

相反,你應該只捕獲你真正想要的例外。在這種情況下,這甚至可能比「任何IO異常」更具體。權限錯誤可能也希望以不同方式處理。相反,你可能會想是這樣的:

e <- tryJust (guard . isDoesNotExistError) (readFile f) 
let str = either (const "") id e 

還有,當你真的需要捕捉任何類型的異常occassions。但是,在大多數情況下,這只是你可以做一些清理工作;你實際上對異常本身並不感興趣。例如,如果您打開一個文件,那麼您想再次關閉它,無論處理文件是否正常執行或引發異常。但是,在這些情況下,您可以使用像bracket,finallyonException這樣的函數,它們從未真正傳遞過例外情況,只是在適當的位置調用清理函數。

但有時你確實需要捕捉任何異常,並且實際上看到異常是什麼。一個例子是在程序的最頂層,你可能希望捕獲任何異常,將其打印到日誌文件或屏幕上,然後優雅地退出。對於這些情況,可以使用catch(或其他異常捕捉函數之一)與SomeException類型。

來源:http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#g:4

相關問題