无法使用 `fromException` 转换通过 `throwTo` 抛出的异常

Unable to cast exceptions thrown via `throwTo` using `fromException`

在处理 Haskell 项目时我遇到了问题,通过 throwTo 抛出到线程的任何异常都会导致 NothingSomeException 投射时使用 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,则需要为 Type1Type2 提供两种不同的类型。

但一般来说,我建议不要直接使用异步异常,而是使用 async 包中的实用程序,例如 race.