如何组合两个具有zio效果和不同类型环境的Http4s路由
How to compose two Http4s routes with zio effect and different types of environment
我有两条 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
有解决办法吗?
让我们处理一下:
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
的所有路由。
我有两条 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
有解决办法吗?
让我们处理一下:
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
的所有路由。