这是基于我之前的问题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版本。
任何想法为什么?
答案 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.
如果您希望捕获所有异常,那么您需要一个足以完成该任务的类型。