无法使用 `fromException` 转换通过 `throwTo` 抛出的异常
Unable to cast exceptions thrown via `throwTo` using `fromException`
在处理 Haskell 项目时我遇到了问题,通过 throwTo
抛出到线程的任何异常都会导致 Nothing
从 SomeException
投射时使用 fromException
键入我自己的异常类型。作为演示,请考虑以下代码片段:
{-# LANGUAGE LambdaCase #-}
import Control.Concurrent (threadDelay)
import UnliftIO.Async (async, asyncThreadId, waitCatch)
import UnliftIO.Exception (Exception, SomeAsyncException (..), SomeException (..),
asyncExceptionToException, catch, fromException, throwIO,
throwTo, toException)
data MyException = Type1 | Type2
deriving (Show)
instance Exception MyException
toMyException :: SomeException -> Maybe MyException
toMyException = fromException
sleepAndThrow :: (Exception e) => Int -> e -> IO ()
sleepAndThrow i e = do
threadDelay (i * 1000000)
print e
throwIO e
main :: IO ()
main = do
t1 <- async $ sleepAndThrow 1 Type1 -- Throw Type1 in 1 second
t2 <- async $ threadDelay 500000 >> throwTo (asyncThreadId t1) Type2 -- Cancel t1 in 0.5
-- seconds with Type2
waitCatch t1 >>= \case
Left e -> putStr "Exception: " >> print (toMyException e)
Right () -> error "this should not happen"
看看这个,我希望控制台输出如下:
Exception: Just Type2
而我得到一个:
Exception: Nothing
你们谁能告诉我,我做错了什么吗?
提前致谢。
如果要异步抛出异常,请将异常设置为异步异常。
instance Exception MyException where
toException = asyncExceptionToException
fromException = asyncExceptionFromException
这意味着如果要同步抛出 Type1
和异步抛出 Type2
,则需要为 Type1
和 Type2
提供两种不同的类型。
但一般来说,我建议不要直接使用异步异常,而是使用 async
包中的实用程序,例如 race
.
在处理 Haskell 项目时我遇到了问题,通过 throwTo
抛出到线程的任何异常都会导致 Nothing
从 SomeException
投射时使用 fromException
键入我自己的异常类型。作为演示,请考虑以下代码片段:
{-# LANGUAGE LambdaCase #-}
import Control.Concurrent (threadDelay)
import UnliftIO.Async (async, asyncThreadId, waitCatch)
import UnliftIO.Exception (Exception, SomeAsyncException (..), SomeException (..),
asyncExceptionToException, catch, fromException, throwIO,
throwTo, toException)
data MyException = Type1 | Type2
deriving (Show)
instance Exception MyException
toMyException :: SomeException -> Maybe MyException
toMyException = fromException
sleepAndThrow :: (Exception e) => Int -> e -> IO ()
sleepAndThrow i e = do
threadDelay (i * 1000000)
print e
throwIO e
main :: IO ()
main = do
t1 <- async $ sleepAndThrow 1 Type1 -- Throw Type1 in 1 second
t2 <- async $ threadDelay 500000 >> throwTo (asyncThreadId t1) Type2 -- Cancel t1 in 0.5
-- seconds with Type2
waitCatch t1 >>= \case
Left e -> putStr "Exception: " >> print (toMyException e)
Right () -> error "this should not happen"
看看这个,我希望控制台输出如下:
Exception: Just Type2
而我得到一个:
Exception: Nothing
你们谁能告诉我,我做错了什么吗?
提前致谢。
如果要异步抛出异常,请将异常设置为异步异常。
instance Exception MyException where
toException = asyncExceptionToException
fromException = asyncExceptionFromException
这意味着如果要同步抛出 Type1
和异步抛出 Type2
,则需要为 Type1
和 Type2
提供两种不同的类型。
但一般来说,我建议不要直接使用异步异常,而是使用 async
包中的实用程序,例如 race
.