使用'Ex.catch'产生的模糊类型变量'a0'

Lia*_*m M 2 haskell exception-handling

我一直在摆弄Haskell,试图理解错误处理.在这样做的同时,我试图了解如何阅读和理解GHC的输出,以便我可以更好地调试类型错误.

我写了以下测试:

import System.Environment
import qualified Control.Exception as Ex

getNum :: Int -> Int
getNum i = (!!) [1,2,3,4] i

outNum :: Int -> IO()
outNum i = Ex.catch (putStrLn(show (getNum i))) (\err -> putStrLn (show err))

main = do
   args <- getArgs
   outNum 3
Run Code Online (Sandbox Code Playgroud)

这会引发以下错误:

使用'Ex.catch'产生的模糊类型变量'a0'可以防止约束'(Ex.Exception a0)'被解决.

查看所涉及的功能的定义:

catch :: IO a -> (IOError -> IO a) -> IO a
putStrLn :: String -> IO ()
show :: Show a => a -> String
error :: [Char] -> a
Run Code Online (Sandbox Code Playgroud)

我正在考虑这个并思考,类型a必须是()(单位类型).我误解了什么,应该如何管理我的示例以便它捕获异常并显示错误?

Eri*_*ikR 8

GHC不知道为什么要捕获的异常类型.

例如,这个版本的outNum将捕获任何IOException:

outNum :: Int -> IO()
outNum i = Ex.catch (putStrLn(show (getNum i)))
           (\err -> putStrLn (show (err :: Ex.IOException)))
Run Code Online (Sandbox Code Playgroud)

您可以使用捕获所有异常Ex.SomeException.但是,请参阅有关在Control.Exception文档中执行此操作的注释

要捕获几种不同的异常,请参阅该catches函数

更新

指示您感兴趣的异常类型的另一种方法是将处理程序定义为命名函数并提供"普通"类型签名:

outNum i = Ex.catch (putStrLn (show (getNum i))
            handler
  where handler :: Ex.IOException -> IO ()
        handler err = putStrLn $ "caught: " ++ show err
Run Code Online (Sandbox Code Playgroud)

通常你会看到catch写为中缀运算符:

outNum i = putStrLn (show (getNum i)) `catch` handler
Run Code Online (Sandbox Code Playgroud)

最后,使用ScopedTypeVariables,您可以将类型注释放在lambda的参数上:

{-# LANGUAGE ScopedTypeVariables #-}

outNum i = putStrLn ...
             `catch` (\(err :: Ex.SomeException) -> putStrLn ("caught: " ++ show err))
Run Code Online (Sandbox Code Playgroud)