You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Arrow 1.2.0 parZipOrAccumulate绑定Nel<ApplicationError>编译失败求助

解决方案

核心问题分析

你的代码里的bind()编译失败,本质是错误类型不兼容:

  • getUser/getDepartment/save返回的是Either<ApplicationError, *>,单个错误类型
  • 外层either块的错误通道是Nel<ApplicationError>(非空列表),bind()要求抛出的错误必须和通道类型匹配

修正后的代码

override suspend fun execute(param: AddUserToDepartmentInfo): Either<Nel<ApplicationError>, Department> = either {
    // 1. parZipOrAccumulate直接接收返回Either的挂起函数,无需内部bind
    val pair: Pair<User, Department> = parZipOrAccumulate(
        errorCombiner = { e1: ApplicationError, e2: ApplicationError -> nonEmptyListOf(e1, e2) },
        fa = { getUser(param.userLegalId) },
        fb = { getDepartment(param.departmentCode) }
    ) { a, b -> Pair(a, b) }.bind()

    // 2. 单个错误转Nel后再bind,匹配外层错误类型
    saveUserDrivenPort.save(pair.first.copy(departmentId = param.departmentCode))
        .leftMap { nonEmptyListOf(it) }
        .bind()

    pair.second
}

关键修正点

  • 移除parZipOrAccumulate内部的bind:parZipOrAccumulate的设计就是接收两个返回Either<L, R>的挂起函数,自动并行执行并通过errorCombiner合并错误为Nel<ApplicationError>,内部不需要用bind提前抛出错误。
  • 单个错误转Nel:对于save这类返回单个错误的函数,用leftMap { nonEmptyListOf(it) }把ApplicationError包装成Nel<ApplicationError>,再调用bind()就符合外层either块的错误类型要求了。

额外优化(可选)

可以给Either<ApplicationError, *>加一个扩展函数,简化单个错误转Nel的操作:

fun <R> Either<ApplicationError, R>.toNelEither(): Either<Nel<ApplicationError>, R> =
    leftMap { nonEmptyListOf(it) }

之后save的调用可以简化为:

saveUserDrivenPort.save(...).toNelEither().bind()

内容的提问来源于stack exchange,提问作者codependent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 02:23:16