英文:
How can we use context receivers and Arrow 1.2.0 parZipOrAccumulate? No required context receiver found: Cxt
问题
以下是代码的中文翻译部分:
给定以下函数:
```kotlin
context(Raise<ApplicationError>)
suspend fun getUser(legalId: UserLegalId): User
context(Raise<ApplicationError>)
suspend fun getDepartment(departmentCode: DepartmentCode): Department
context(Raise<ApplicationError>)
suspend fun save(user: User): User
我想并行调用它们并累积它们的错误:
context(Raise<Nel<ApplicationError>>)
override suspend fun execute(param: AddUserToDepartmentInfo): Department {
val pair: Pair<User, Department> =
parZipOrAccumulate(
{ e1, e2 -> e1 + e2 },
{ getUser(param.userLegalId) },
{ getDepartment(param.departmentCode) }
) { a, b -> Pair(a, b) }
saveUserDrivenPort.save(pair.first.copy(departmentId = param.departmentCode))
return pair.second
}
然而,在parZipOrAccumulate内部的getUser()
和getDepartment()
调用不会编译:
未找到所需的上下文接收器:Cxt { context(arrow.core.raise.Raise<xxx.ApplicationError>) private open suspend fun getUser(...)}
英文:
Given the following functions:
context(Raise<ApplicationError>)
suspend fun getUser(legalId: UserLegalId): User
context(Raise<ApplicationError>)
suspend fun getDepartment(departmentCode: DepartmentCode): Department
context(Raise<ApplicationError>)
suspend fun save(user: User): User
I want to invoke them in parallel and accumulate their errors:
context(Raise<Nel<ApplicationError>>)
override suspend fun execute(param: AddUserToDepartmentInfo): Department {
val pair: Pair<User, Department> =
parZipOrAccumulate(
{e1, e2 -> e1 + e2},
{ getUser(param.userLegalId) },
{ getDepartment(param.departmentCode) }
) { a, b -> Pair(a, b) }
saveUserDrivenPort.save(pair.first.copy(departmentId = param.departmentCode))
return pair.second
}
However, the getUser()
and getDepartment()
invocations inside parZipOrAccumulate don't compile:
No required context receiver found: Cxt { context(arrow.core.raise.Raise<xxx.ApplicationError>) private open suspend fun getUser(...)
答案1
得分: 0
你可以尝试省略{e1, e2 -> e1 + e2}
参数吗?在这种情况下不需要,因为外部Nel<ApplicationError>
已经被推断出Nel
累加器。
context(Raise<ApplicationError>)
suspend fun getUser(legalId: UserLegalId): User
context(Raise<ApplicationError>)
suspend fun getDepartment(departmentCode: DepartmentCode): Department
context(Raise<ApplicationError>)
suspend fun save(user: User): User
context(Raise<Nel<ApplicationError>>)
suspend fun execute(param: AddUserToDepartmentInfo): Department {
val pair: Pair<User, Department> =
parZipOrAccumulate(
{ getUser(param.userLegalId) },
{ getDepartment(param.departmentCode) }
) { a, b -> Pair(a, b) }
// 将`Raise<ApplicationError>`转换为`ScopedRaiseAccumulate<ApplicationError>`
recover({
saveUserDrivenPort.save(pair.first.copy(departmentId = param.departmentCode))
}) { raise(nonEmptyListOf(it)) }
return pair.second
}
英文:
Can you try omitting the {e1, e2 -> e1 + e2}
argument? That is not needed in this case because the Nel
accumulator is inferred by the outer Nel<ApplicationError>
.
context(Raise<ApplicationError>)
suspend fun getUser(legalId: UserLegalId): User
context(Raise<ApplicationError>)
suspend fun getDepartment(departmentCode: DepartmentCode): Department
context(Raise<ApplicationError>)
suspend fun save(user: User): User
context(Raise<Nel<ApplicationError>>)
suspend fun execute(param: AddUserToDepartmentInfo): Department {
val pair: Pair<User, Department> =
parZipOrAccumulate(
{ getUser(param.userLegalId) },
{ getDepartment(param.departmentCode) }
) { a, b -> Pair(a, b) }
// Turn `Raise<ApplicationError>` into `Raise<Nel<ApplicationError>>`
recover({
saveUserDrivenPort.save(pair.first.copy(departmentId = param.departmentCode))
}) { raise(nonEmptyListOf(it)) }
return pair.second
}
I tried this locally, and it works for me. The Raise<ApplicationError>
is exposed as ScopedRaiseAccumulate<ApplicationError>
in the lambda of parZipOrAccumulate
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论