0

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

    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'

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

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

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

instance Exception ParseError

这是异常处理程序的类型:

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

这也是 ghc 的 7.4.1 版本。

任何想法为什么?

4

2 回答 2

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
于 2013-05-28T04:11:24.383 回答
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.

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

于 2013-05-28T03:52:41.037 回答