Doobie - 将任意效果提升到 ConnectionIO 中

Leo*_*nti 5 scala scala-cats doobie cats-effect

我正在尝试在使用 Doobie 将用户插入数据库的同一事务中发送电子邮件。
我知道我可以举IOConnectionIO通过使用Async[ConnectionIO].liftIO(catsIO)其中catsIO: IO[String]
但在我的代码,我不上工作IO,我使用F与约束,例如F[_]: Async 于是我可以代替F我自己的单子进行测试。

是否可以在不直接使用类型的情况下以某种方式提升F[String]进入? ConnectionIO[String]IO

这是我为 IO 类型找到的答案:Doobie and DB access composition within 1 transaction

Cha*_*ton 7

Cats 有一种叫做 FunctionK 的东西,它是一种自然转换。

我这样做了:

在世界之巅,一切都在这里建造,你将需要这个

val liftToConnIO: FunctionK[IO, ConnectionIO] = LiftIO.liftK[ConnectionIO]
Run Code Online (Sandbox Code Playgroud)

在需要从 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 ()

}
Run Code Online (Sandbox Code Playgroud)

(您可能需要 F 和 G 上的上下文边界(同步?))