【发布时间】:2021-11-18 11:49:38
【问题描述】:
我有一个连接到数据库的函数,然后运行查询。每个步骤都会产生IO (Either SomeErrorType SomeResultType)。
我真正喜欢在学习 Haskell 时使用 Either 和类似的 monad 的一件事是能够使用像 >>= 这样的单子函数和像 mapLeft 这样的组合子来简化很多预期的处理错误状态。
我在这里阅读博客文章、Control.Monad.Trans 文档和其他关于 SO 的答案的期望是,我必须以某种方式使用转换器/升降机从 IO 上下文移动到 Either 上下文。
This answer 特别好,但我很难将它应用到我自己的案例中。
我的代码的一个更简单的例子:
simpleVersion :: Integer -> Config -> IO ()
simpleVersion id c =
connect c >>= \case
(Left e) -> printErrorAndExit e
(Right conn) -> (run . query id $ conn)
>>= \case
(Left e) -> printErrorAndExit e
(Right r) -> print r
>> release conn
我的问题是 (a) 我并不真正了解 ExceptT 如何将我带到与 mapLeft handleErrors $ eitherErrorOrResult >>= someOtherErrorOrResult >>= print 世界相似的地方的机制; (b) 我不确定如何确保始终以最好的方式释放连接(即使在我上面的简单示例中),尽管我想我会使用bracket pattern。
我确信每个(相对)新的 Haskeller 都这么说,但我仍然真的不了解 monad 转换器,而且我读到的所有内容(除了前面链接的 SO 答案)对我来说都太不透明了(还)。
我怎样才能将上面的代码转换成可以消除所有这些嵌套和错误处理的东西?
【问题讨论】:
-
相关question
-
也相关,但是关于
MaybeT而不是ExceptT: stackoverflow.com/questions/32579133/… 来自基地的关于bracket的一个注释:它适用于普通的IO动作而不是IO动作“装饰” “与变压器。一种可能的方法是使用ExceptT来避免嵌套的cases,然后使用runExceptT回到IO操作,并使用bracket包装该结果操作。
标签: haskell error-handling monads monad-transformers