gpt4 book ai didi

kotlin - 如何使用 Kleisli 访问调用链的每个函数中的上下文?

转载 作者:行者123 更新时间:2023-12-02 13:03:26 24 4
gpt4 key购买 nike

我有一些方法的调用链,我通过 Kleisli 传递上下文。基本上我想将一个上下文传递给数据库访问层,但我想在两者之间的任何地方访问这个上下文。

以下示例完美运行。但我的问题是,我想访问 OrderService.findAll(...) 中的上下文也是。我尝试了几种方法,但我一直失败。

object OrderRepository {
fun findAll(userId: String): Kleisli<Context, ForIO, List<Order>> =
Kleisli { ctx ->
IO {
ctx.db.query("someQuery")
}
}
}

object OrderService {
fun findAll(userId: String): Kleisli<Context, ForIO, List<OrderResponse>> =
OrderRepository.findAll(userId).map(IO.monad()) { orderList ->
orderList.map {
//Create OrderResponse from Order
}
}
}

是否可以访问那里的上下文,或者这没有任何意义?谢谢您的帮助 :)

最佳答案

你需要的是一个从 D 到 D 的 Kleisli,以 D 作为上下文。这样,您也可以将 D(上下文)作为结果类型,并且您可以使用 flatMap 并访问它。这就是为什么 ask() 方法提供,可通过同伴获得的原因。

假设您的 OrderRepository也是上下文中的依赖项而不是纯函数(为了示例),因此您需要从服务的上下文中访问它。看:

interface OrderApi
interface OrderDB {
fun query(query: String): List<Order> = TODO()
}

data class Order(val id: String)
data class OrderResponse(val order: Order)
data class Context(val api: OrderApi, val repository: OrderRepository, val db: OrderDB)

class OrderRepository {
fun findAll(userId: String): Kleisli<Context, ForIO, List<Order>> =
Kleisli { ctx ->
IO {
ctx.db.query("someQuery")
}
}
}

object OrderService {
fun findAll(userId: String): Kleisli<Context, ForIO, List<OrderResponse>> {
val monad = IO.monad()
return Kleisli.ask<Context, ForIO>(monad).flatMap(monad) { ctx ->
ctx.repository.findAll(userId).map(monad) { orderList ->
orderList.map { OrderResponse(it) }
}
}
}
}

也就是说,Kleisli 是一个 Monad 转换器(也称为 ReaderT),使用起来可能有点复杂。如果您想在功能代码库上注入(inject)依赖项并保持更简单,我的建议是在上下文接收器上使用扩展函数,它已经隐式地跨所有级别传递您的依赖项,这在 on this post by Paco 中进行了描述.

关于kotlin - 如何使用 Kleisli 访问调用链的每个函数中的上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62390210/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com