尝试不会处理任何异常

时间:2013-05-28 03:23:44

标签: haskell exception-handling

这是基于我之前的问题here的建议:

    go bs = do
       r <- try $ parseRequest reader bs secure
       case r of
         Left ex -> do
            putStrLn "got exception"
            exceptionHandler writer ex
            go empty
         Right (request, bs') -> do
            sendResponse writer =<< app request
            go bs'

当没有异常时,右边部分没有问题。但是,当抛出异常时,异常会一直冒泡到顶部,而Left则不会运行。它似乎并不是什么样的例外。

以下是它应该捕获的异常(虽然它也不会捕获error):

data ParseError                                                                 
    = Unexpected                                                                
    | MalformedRequestLine ByteString                                           
    | MalformedHeader      ByteString                                           
    | MissingHeader        ByteString Headers                                   
    | UnknownSIPVersion    ByteString                                           
      deriving (Typeable, Show, Eq)    

instance Exception ParseError

以下是exceptionHandler的类型:

exceptionHandler :: (ByteString -> IO ())                                         
             -> ParseError                                                    
             -> IO ()

这也是ghc的7.4.1版本。

任何想法为什么?

2 个答案:

答案 0 :(得分:5)

我怀疑问题是您使用的throw未在try的范围内进行评估。在这种情况下,当您尝试使用结果时,您将在try之后获得异常。如果可以,请改用throwIO以确保在正确的时间抛出异常。

注意区别:

> :set -XDeriveDataTypeable
> :m + Control.Exception Data.Typeable
> data Boom = Boom deriving (Show, Typeable)
> instance Exception Boom
> try $ return (throw Boom) :: IO (Either Boom Int)
Right *** Exception: Boom
> try $ throwIO Boom :: IO (Either Boom Int)
Left Boom

答案 1 :(得分:1)

你的问题让我感到痛苦,因为如果你使用正确的try它应该有效,但你没有提供最低限度的例子。相反,我将提供一个功能示例,并让您确定代码中的不同之处。

{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables #-}

我只需要ScopedTypeVariables,因为我没有使用显式类型的函数。

import Control.Exception as X
import Data.ByteString as B
import Data.Typeable
import Data.Data

注意我正在使用Control.Exception模块和try函数。我怀疑你的try来自其他地方。

data ParseError
    = Unexpected
    | MalformedRequestLine ByteString
    | MalformedHeader      ByteString
    | MissingHeader        ByteString ()
    | UnknownSIPVersion    ByteString
      deriving (Typeable, Show, Eq)

instance Exception ParseError

parseRequest :: IO Int
parseRequest = throw Unexpected

为了测试,我的parseResult只会抛出一些东西。

exceptionHandler :: (ByteString -> IO ())
                 -> ParseError
                 -> IO ()
exceptionHandler f p = print p

main = do
  r <- X.try parseRequest
  case r of
    Right i -> print i
    Left (e :: ParseError) -> print ("Caught",e)

主要程序非常无聊 - 只是对日常工作重要部分的总结。它运行良好:

$ ghc so.hs
[1 of 1] Compiling Main             ( so.hs, so.o )
Linking so ...
$ ./so
("Caught",Unexpected)

如果将异常修改为其他类型,您将看到未捕获异常:

parseRequest :: IO Int
parseRequest = error "This is a different type, and won't be caught by 'ParseError' handlers."

结果:

$ ./so
so: This is a different type, thus not caught by 'ParseError' handlers.

如果您希望捕获所有异常,那么您需要一个足以完成该任务的类型。