如何将 Either 转换为 MonadThrow
How to convert Either to MonadThrow
我有一个通过 Either
处理错误的函数:
funErrViaEither :: a -> Either SomeException b
我想在另一个应该更灵活的函数中使用这个函数 return MonadThrow m
:
funErrViaThrow :: MonadThrow m => a -> m b
funErrViaThrow x =
if x = someCondition
then funErrViaEither
else throwM (SomeException MyCustomException)
这不编译;类型检查器抱怨 funErrViaEither
的 return 类型与预期类型 m b
不匹配。我不明白为什么 - Either
有一个 MonadThrow
的实例,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
切换到 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)
我有一个通过 Either
处理错误的函数:
funErrViaEither :: a -> Either SomeException b
我想在另一个应该更灵活的函数中使用这个函数 return MonadThrow m
:
funErrViaThrow :: MonadThrow m => a -> m b
funErrViaThrow x =
if x = someCondition
then funErrViaEither
else throwM (SomeException MyCustomException)
这不编译;类型检查器抱怨 funErrViaEither
的 return 类型与预期类型 m b
不匹配。我不明白为什么 - Either
有一个 MonadThrow
的实例,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
切换到 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)