我有一个通过处理错误的函数Either
:
funErrViaEither :: a -> Either SomeException b
我想在另一个应该更灵活并返回的函数中使用这个函数MonadThrow m
:
funErrViaThrow :: MonadThrow m => a -> m b
funErrViaThrow x =
if x = someCondition
then funErrViaEither
else throwM (SomeException MyCustomException)
这不能编译;类型检查器抱怨返回类型funErrViaEither
与预期类型不匹配m b
。我不明白为什么-Either
有一个实例MonadThrow
with SomeException
作为类型Left
.
我哪里出错了?转换通过信号发出的错误的正确方法是什么Either
进入一个通过信号发出的MonadThrow
?
虽然你不能使用funErrViaEither x :: Either SomeException b
直接当将军MonadThrow m => m b
,您可以处理Either
使用模式匹配,适当地抛出或返回:
case funErrViaEither x of
Left err -> throwM err
Right y -> return y
但是,我认为您可能已经用以下内容过度包装了您的例外情况SomeException
。当您从Either SomeException
to MonadThrow m
,因此完整的类型检查示例如下所示:
import Control.Monad.Catch
data MyCustomException = NoNegatives | NoOdds deriving (Show)
instance Exception MyCustomException
funErrViaEither :: Int -> Either SomeException Int
funErrViaEither n | n < 0 = throwM NoNegatives -- or Left (SomeException NoNegatives)
| otherwise = Right $ n `div` 2
funErrViaThrow :: MonadThrow m => Int -> m Int
funErrViaThrow x =
if even x
then case funErrViaEither x of
Left (SomeException err) -> throwM err -- peel off SomeException
Right y -> return y
else throwM NoOdds
main = do
print =<< funErrViaThrow 6
(print =<< funErrViaThrow 5)
`catch` (\err -> putStrLn $ "caught: " ++ show (err :: MyCustomException))
print =<< funErrViaThrow (-2)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)