从 Exception 到 ExceptT 的映射
Mapping from Exception to ExceptT
我正在阅读有关异常的章节,因此我决定尝试将异常映射到 ExceptT monad 转换器。我的函数 getInt 可以从控制台读取一个整数并将异常报告为 Left "what's wrong":
getInt :: ExceptT String IO Int
getInt = ExceptT $ do
Right . read <$> getLine
`catch` \(e :: ErrorCall) -> return . Left . show $ e
我试过了,可惜没有捕获到异常,懒惰在嘲笑我。好的,让我严格使用 seq
.
getInt :: ExceptT String IO Int
getInt = ExceptT $ do
read <$> getLine >>= seq <*> return . Right
`catch` \(e :: ErrorCall) -> return . Left . show $ e
结果是:左"Prelude.read: no parse"。现在可以使用了!
我的问题是 - 这是将异常映射到 ExceptT 的正确方法吗?
正确的做法确实是强制求值read
。这可以通过按值调用应用程序 $!
更优雅地完成
getInt :: ExceptT SomeException IO Int
getInt = ExceptT $ liftIO $ try @SomeException $ do
i <- getLine
pure $! read i
通常最好将底层 monad 参数化(出于可测试性和可重用性的原因),因此我们可以这样写
getInt :: (MonadError SomeException m, MonadIO m) => m Int
getInt = liftEither =<< liftIO $ try @SomeException $ do
i <- getLine
pure $! read i
insdead 一个具体的 monad 转换器堆栈 ExceptT SomeException IO Int
我正在阅读有关异常的章节,因此我决定尝试将异常映射到 ExceptT monad 转换器。我的函数 getInt 可以从控制台读取一个整数并将异常报告为 Left "what's wrong":
getInt :: ExceptT String IO Int
getInt = ExceptT $ do
Right . read <$> getLine
`catch` \(e :: ErrorCall) -> return . Left . show $ e
我试过了,可惜没有捕获到异常,懒惰在嘲笑我。好的,让我严格使用 seq
.
getInt :: ExceptT String IO Int
getInt = ExceptT $ do
read <$> getLine >>= seq <*> return . Right
`catch` \(e :: ErrorCall) -> return . Left . show $ e
结果是:左"Prelude.read: no parse"。现在可以使用了!
我的问题是 - 这是将异常映射到 ExceptT 的正确方法吗?
正确的做法确实是强制求值read
。这可以通过按值调用应用程序 $!
getInt :: ExceptT SomeException IO Int
getInt = ExceptT $ liftIO $ try @SomeException $ do
i <- getLine
pure $! read i
通常最好将底层 monad 参数化(出于可测试性和可重用性的原因),因此我们可以这样写
getInt :: (MonadError SomeException m, MonadIO m) => m Int
getInt = liftEither =<< liftIO $ try @SomeException $ do
i <- getLine
pure $! read i
insdead 一个具体的 monad 转换器堆栈 ExceptT SomeException IO Int