如何在同步上下文中使用 arrow-kt 中的 IO 组合
How to use IO compositions in arrow-kt within sync context
我有以下接口:
interface UserRepository {
fun role(codename: String): IO<Option<Role>>
fun accessRights(roleId: Long): IO<List<AccessRight>>
}
现在尝试使用它来编写有效的操作,如下所示:
private fun retrieveRole(roleCodename: String): IO<Option<RoleTo>> =
IO.fx {
val role = userRepository.role(roleCodename).bind()
role.map { r ->
val ar = userRepository.accessRights(r.id).bind()
RoleTo.of(r, ar)
}
}
代码在第二次绑定时无法编译(调用 userRepository.accessRights(r.id).bind()
,因为 bind
是挂起函数。我如何才能正确组合两个操作?我不明白为什么第一次绑定有效,但是second 没有,我不想让我的功能挂起,或者我无论如何都必须这样做?
这是一个常见问题。如果你有 Option<A>
或 Either<E, A>
并且你想对其采取行动,你的第一直觉是在块上使用它:
either.map { !someIO }
问题是 left/none 选项没有被覆盖。两边都要做,把IO提取出来再执行。
!either.fold({ ioLogError(it) }, { someIo })
目前,从 0.10 开始,因为 fold
是一个内联函数,您也可以在其中使用 !
。我不能保证将来会是这种情况,因为这是我们为方便起见而保留的意外内联行为。
我能够使用 traverse
和 IO
的应用实例解决问题:
private fun retrieveRole(roleCodename: String): IO<Option<RoleTo>> =
IO.fx {
val role = userRepository.role(roleCodename).bind()
val accessRights = role.traverse(IO.applicative()) {
userRepository.accessRights(it.id)
}.bind()
role.map2(accessRights) {
(r, ar) -> RoleTo.of(r, ar)
}
}
感谢您指出 map
需要纯函数这一事实。
我有以下接口:
interface UserRepository {
fun role(codename: String): IO<Option<Role>>
fun accessRights(roleId: Long): IO<List<AccessRight>>
}
现在尝试使用它来编写有效的操作,如下所示:
private fun retrieveRole(roleCodename: String): IO<Option<RoleTo>> =
IO.fx {
val role = userRepository.role(roleCodename).bind()
role.map { r ->
val ar = userRepository.accessRights(r.id).bind()
RoleTo.of(r, ar)
}
}
代码在第二次绑定时无法编译(调用 userRepository.accessRights(r.id).bind()
,因为 bind
是挂起函数。我如何才能正确组合两个操作?我不明白为什么第一次绑定有效,但是second 没有,我不想让我的功能挂起,或者我无论如何都必须这样做?
这是一个常见问题。如果你有 Option<A>
或 Either<E, A>
并且你想对其采取行动,你的第一直觉是在块上使用它:
either.map { !someIO }
问题是 left/none 选项没有被覆盖。两边都要做,把IO提取出来再执行。
!either.fold({ ioLogError(it) }, { someIo })
目前,从 0.10 开始,因为 fold
是一个内联函数,您也可以在其中使用 !
。我不能保证将来会是这种情况,因为这是我们为方便起见而保留的意外内联行为。
我能够使用 traverse
和 IO
的应用实例解决问题:
private fun retrieveRole(roleCodename: String): IO<Option<RoleTo>> =
IO.fx {
val role = userRepository.role(roleCodename).bind()
val accessRights = role.traverse(IO.applicative()) {
userRepository.accessRights(it.id)
}.bind()
role.map2(accessRights) {
(r, ar) -> RoleTo.of(r, ar)
}
}
感谢您指出 map
需要纯函数这一事实。