kotlinarrow-kt

Can't bind when accumulating errors into a Nel<ApplicationError> using Arrow 1.2.0 parZipOrAccumulate


I'm using the new parZipOrAccumulate function from Arrow 1.2.0-RC to parallelize two calls and accumulate their errors if any:

private suspend fun getUser(legalId: UserLegalId): Either<ApplicationError, User>
private suspend fun getDepartment(departmentCode: DepartmentCode): Either<ApplicationError, Department>
        override suspend fun execute(param: AddUserToDepartmentInfo): Either<Nel<ApplicationError>, Department> = either {
            val pair: Pair<User, Department> =
                parZipOrAccumulate<ApplicationError, User, Department, Pair<User, Department>>(
                    {e1: ApplicationError, e2 : ApplicationError-> nonEmptyListOf(e1,e2)},
                    { getUser(param.userLegalId).bind() },
                    { getDepartment(param.departmentCode).bind() }
                ) { a, b -> Pair(a, b) }
            saveUserDrivenPort.save(pair.first.copy(departmentId = param.departmentCode)).bind()
            pair.second
        }

None of the three .bind() calls in the code above compile because it expects the error types to match (ApplicationError <-> Nel<ApplicationError>).

How can I accumulate errors in a Nel<ApplicationError> when I need to bind functions that may fail with an ApplicationError?


Solution

  • As answered in this related question we can get rid of the combinator function and the errors will be automatically added to a Nel.

            override suspend fun execute(param: AddUserToDepartmentInfo): Either<Nel<ApplicationError>, Department> = either {
                val pair: Pair<User, Department> =
                    parZipOrAccumulate(                   
                        { getUser(param.userLegalId).bind() },
                        { getDepartment(param.departmentCode).bind() }
                    ) { a, b -> Pair(a, b) }
                saveUserDrivenPort.save(pair.first.copy(departmentId = param.departmentCode)).mapLeft { nonEmptyListOf(it) }.bind()
                pair.second
            }