1

我有两条Http4s路线:

val routes1:HttpRoutes[Task] = ???
val routes2:HttpRoutes[RTask] = ???

哪里RTask只是Task/RIO一个自定义环境:

type RTask[A] = RIO[Env,A]

可以通过导入“zio-cats-interop”库并做常规来完成具有相同类型参数的两条路由的组合routes1<+>routes1,但是由于类型参数HttpRoutes是不变的,我不能对不同的类型做同样的事情:

routes1<+>routes2 /// error here

有什么解决办法吗?

4

1 回答 1

2

让我们对事物进行处理:

type HttpRoutes[F[_]] = Http[OptionT[F, *], F]
type Http[F[_], G[_]] = Kleisli[F, Request[G], Response[G]]

所以你HttpRoutes[RTask]实际上是Kleisli[OptionT[RTask, *], Request[RTask], Response[RTask]]

假设您有applyR: RTask ~> Task(应用 R)和requireR: Task ~> RTask(添加不会使用的 R)。

val applyR: RTask ~> Task = new (RTask ~> Task) {
  def apply[A](rtask: RTask[A]): Task[A] = ... // apply Env here
}
val requireR: Task ~> RTask = new (Task ~> RTask) {
  def apply[A](task: Task[A]): RTask[A] = ... // require Env here
}

您可以调整 Kleisli 的每一个:输入、输出、使用它们的效果,尽管这将是一件苦差事:

val routesRTask: HttpRoutes[RTask]

val routesTask: HttpRoutes[Task] =
  Kleisli { (reqTask: Request[Task]) =>
    val reqRTask: Request[RTask] = req.mapK(requireR)
    val responseRTask: OptionT[RTask, Response[RTask]] = routesRTask(reqTask)
    responseRTask.mapK(applyR) // OptionT[Task, Response[RTask]]
                 .map(_.mapK(applyR)) // OptionT[Task, Response[Task]]
  }

您可以将上面的逻辑提取到某个函数并将其应用于应该从转换为的所有RTask路由Task

于 2021-01-30T18:53:47.397 回答