"尝试"没有抓住例外情况

Imp*_*ive 7 haskell exception

我正在使用hedis并试图处理服务器死机的情况.根据文件:

与服务器的连接丢失:如果连接丢失,命令函数将抛出ConnectionLostException.它只能在runRedis之外捕获.

所以我假设我想捕获ConnectionLostException.然而,虽然我似乎能正确地抓住它,但它似乎也冒出了顶部,我不知道为什么.这是一些代码(只在GHCI中运行):

:set -XOverloadedStrings
import Database.Redis
import Control.Exception

conn <- connect defaultConnectInfo
runRedis conn $ ping
Run Code Online (Sandbox Code Playgroud)

现在,如果我在建立连接和运行命令之间杀死redis服务器,我会得到我期望的结果:

⟨interactive⟩:ConnectionLost***例外:ConnectionLost

所以相反我尝试做以下(我添加>>= evaluate以试图强制评估错误,但它没有区别):

let tryR = try :: IO a -> IO (Either ConnectionLostException a)
tryR . (>>= evaluate) . runRedis conn $ ping
Run Code Online (Sandbox Code Playgroud)

这给了我:

左Con:ConnectionLost nectionLost

所以我得到了Left预期的结果,但是异常的中途也可能被GHCI捕获和显示.对于未被评估的事情,这是一个问题吗?

nh2*_*nh2 2

就像约翰暗示的那样,似乎有东西将这条消息打印到stderr

考虑这个例子:

{-# LANGUAGE OverloadedStrings #-}

import Control.Concurrent (threadDelay)
import Control.Exception
import Control.Monad
import Database.Redis
import System.Mem

tryR :: IO a -> IO (Either ConnectionLostException a)
tryR = try


main :: IO ()
main = do
  conn <- connect defaultConnectInfo
  loop conn
  putStrLn $ "exiting gracefully after counting up some numbers"
  performGC
  forM_ [1..10] $ \i -> do
    print i
    threadDelay 10000 -- 0.05 seconds
  where
    loop conn = do

      e <- tryR . (>>= evaluate) . runRedis conn $ ping

      case e of
        Right x  -> do print x
                       threadDelay 1000000
                       loop conn
        Left err -> do putStrLn $ "tryR caught exception: " ++ show err
Run Code Online (Sandbox Code Playgroud)

它打印:

Right Pong
Right Pong  <-------------- after this I Ctrl-C the redis server
tryR caught exception: ConnectionLost
exiting gracefully after counting up some numbers
1
test: ConnectionLost
2
3
4
5
6
7
8
9
10
Run Code Online (Sandbox Code Playgroud)

这看起来像是堆栈中的某些内容正在异步test: ConnectionLost打印此内容(或者test.hs: ConnectionLost如果您使用 GHCI/runghc)。

如果那是 GHC,那可能是一个错误,但它很可能是由hedis它的依赖项之一完成的(我还没有发现它本身hedis)。