我正在尝试在使用 Doobie 将用户插入数据库的同一事务中发送电子邮件。
我知道我可以举起IO
into ConnectionIO
通过使用Async[ConnectionIO].liftIO(catsIO)
where catsIO: IO[String]
但在我的代码中我不进行操作IO
, I use F
有约束条件,例如F[_]: Async
那么我可以替换F
用我自己的 monad 进行测试。
是否有可能以某种方式举起F[String]
into ConnectionIO[String]
不使用IO
直接输入?
这是我找到的 IO 类型的答案:1 个事务内的 Doobie 和 DB 访问组合 https://stackoverflow.com/questions/50472904/doobie-and-db-access-composition-within-1-transaction
Cats 有一个叫做 FunctionK 的东西,这是一种自然的转换。
我这样做了:
在世界之巅,一切都已建成,你将需要这个
val liftToConnIO: FunctionK[IO, ConnectionIO] = LiftIO.liftK[ConnectionIO]
在需要从 F[String] 转换为 G[String] 的类中(当您构造所有内容时,F 将是 IO,G 将是 ConnectionIO),您可以通过liftToConnIO
并在需要时使用它将 F[A] 转换为 G[A]。
不想抽象 IO 和 ConnectionIO 的类可以通过 FunctionK 来完成提升:
class Stuff[F[_], G[_]](emailer: Emailer[F], store: Store[G], liftToG: FunctionK[F, G]) {
def sendEmail: G[Unit] =
for {
_ <- doDatabaseThingsReturnStuffInG
_ <- liftToG(emailer.sendEmail)
_ <- doMoreDatabaseThingsReturnStuffInG
} yield ()
}
(您可能需要 F 和 G 上的上下文边界(同步?))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)