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 のタイプです。

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

また、これは ghc のバージョン 7.4.1 です。

理由はありますか?

4

2 に答える 2

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 に答える