Control.Exception.handle
türüdür:
handle :: Exception e => (e -> IO a) -> IO a -> IO a
Gördüğünüz sorun lambda ifadesi (\_ -> return "err")
değil e
Exception
bir örneği olan tip e -> IO a
ait olmasıdır. Çamur kadar temiz? İyi. Şimdi ben aslında yararlı olması gereken bir çözüm :)
Sadece çok olur sizin durumunuzda ErrorCall
(Exception
bir örneği) atar error
kullanan Control.Exception.ErrorCall
undefined
beri e
olması gerektiğini vereceğiz.
handleError :: (ErrorCall -> IO a) -> IO a -> IO a
handleError = handle
Esasen e
ile Control.Exception.handle
error
atar ne ErrorCall
olarak sabit bir takma ad:
Eğer
handleError
gibi bir şey tanımlayabilir
undefined
kullanımlarını işlemek için.
yılında GHCi 7.4.1 çalıştırdığınızda
Bu şuna benzer:
ghci> handleError (\_ -> return "err") undefined
"err"
şöyle bir handleAll
fonksiyonu yazılabilir tüm istisnalar işlemek için:
handleAll :: (SomeException -> IO a) -> IO a -> IO a
handleAll = handle
sonuçları vardır tüm istisnaları yakalamak Control.Exception
belgelerinin şu alıntılarında iyi tanımlanmıştır:
yakalamak tüm istisnalar
O SomeException
türünü kullanarak, tüm özel durumları yakalamak mümkündür:
catch f (\e -> ... (e :: SomeException) ...)
ANCAK, bu yapmak istediğim normalde değil! Örneğin, bir dosyayı okumak istediğinizi varsayalım, ancak varsa, ""
içeriyormuş gibi devam edin. Tüm özel durumları yakalamak ve işleyicide ""
'u döndürmek isteyebilirsiniz. Bununla birlikte, bunun her türlü istenmeyen sonuçları vardır. Örneğin, kullanıcı yalnızca C-Control'de C tuşuna basarsa, UserInterrupt
istisnası yakalanır ve program, dosyanın ""
içerdiği inancıyla çalışmaya devam eder. Benzer şekilde, başka bir iş parçacığı dosyayı okuma iş parçacığı öldürmeye çalışırsa, ThreadKilled
istisnası göz ardı edilir.
Bunun yerine, yalnızca gerçekten istediğiniz özel durumları yakalamanız gerekir. Bu durumda, bu muhtemelen "herhangi bir IO istisnası" ndan daha spesifik olacaktır; Bir izin hatası büyük olasılıkla farklı ele alınmak isteyecektir. Bunun yerine, muhtemelen böyle bir şey isteyeyim:
e <- tryJust (guard . isDoesNotExistError) (readFile f)
let str = either (const "") id e
gerçekten istisna her türlü yakalamak gerekiyor özel günler vardır. Ancak, çoğu durumda, bu sadece bazı temizlik yapabilmeniz içindir; aslında istisnanın kendisi ile ilgilenmiyorsunuz.Örneğin, bir dosyayı açarsanız, dosyayı tekrar işleyip işlemeyeceğinizi, dosyanın normal şekilde işleyip işlemeyeceğini veya bir istisna atar. Bununla birlikte, bu gibi durumlarda, aslında size özel bir durum iletmeyen bracket
, finally
ve onException
gibi işlevleri kullanabilirsiniz, ancak temizleme işlevlerini uygun noktalarda aramanız yeterlidir.
Ancak bazen gerçekten bir istisna yakalamanız ve aslında istisnanın ne olduğunu görmeniz gerekir. Bir örnek, bir programın en üst düzeyindedir, herhangi bir istisnayı yakalamak, bir log dosyasına veya ekrana yazdırmak ve sonra incelikle çıkmak isteyebilirsiniz. Bu durumlarda, SomeException
türüyle catch
(veya diğer istisna yakalama işlevlerinden biri) kullanabilirsiniz.
Kaynak: http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#g:4
Neden derleyici hangi istisna bilmek gerekir? İşlev, sınıftaki her türünü işler. – luntain
'handle' türünden dolayı; "handle" kullanımı, Exception sınıfından * bir * özel türe uygulanmalıdır. İşleyiciniz sınıftaki tüm türler için çalıştığından, derleyicinin 'handle' türüne bir ataması için bir yol yoktur. ('' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'Döndürür.) –
Eğer ScopedTypeVariables uzantısını kullanırsanız, '' unrule '' komutunu '' ('\' _ExException) '-' 'err' 'döndürün' 'yapabilirsiniz. – porges