使用Arrow-Kt的mapOrAccumulate时出现类型不匹配错误
问题原因与解决方案
编译错误的核心是**mapOrAccumulate的泛型参数顺序指定错误**,导致编译器对lambda的返回值类型预期完全偏离你的代码逻辑。
错误细节
Arrow的mapOrAccumulate函数针对Iterable<A>的签名为:
fun <A, B, E> Iterable<A>.mapOrAccumulate(f: (A) -> Either<E, B>): Either<NonEmptyList<E>, List<B>>
其中:
A:集合元素的类型(这里是File,可由调用的List<File>自动推断)E:错误类型(你的代码中是Error)B:处理成功后的结果类型(你的代码中是IdocsFileInfo)
你显式指定的泛型<Error, File, IdocsFileInfo>错误地将A设为Error、B设为File、E设为IdocsFileInfo,这导致编译器要求lambda返回IdocsFileInfo,但你的file.buildDocument()返回的是Either<Error, IdocsFileInfo>,因此触发类型不匹配。
修正后的代码
方案1:移除显式泛型参数,依赖编译器自动推断(推荐)
fun mapServiceDocs(orderedFilesForPerson: List<File>): Either<NonEmptyList<Error>, List<IdocsFileInfo>> { return orderedFilesForPerson.mapOrAccumulate { file -> file.buildDocument() } }
方案2:正确指定泛型参数(仅指定E和B)
fun mapServiceDocs(orderedFilesForPerson: List<File>): Either<NonEmptyList<Error>, List<IdocsFileInfo>> { return orderedFilesForPerson.mapOrAccumulate<Error, IdocsFileInfo> { file -> file.buildDocument() } }
额外建议
java.lang.Error是JVM用于标识严重系统错误的类型,不适合用于业务错误处理。建议自定义领域错误类型,例如:
sealed class ServiceDocError(message: String) : Exception(message) { class InvalidImageCode(imageCode: String) : ServiceDocError("$imageCode is not a recognized image code.") class MissingMapping : ServiceDocError("Unable to determine mapping.") class ParseOwnerFailed(cause: String) : ServiceDocError(cause) }
然后将buildDocument的返回类型改为Either<ServiceDocError, IdocsFileInfo>,这样错误语义更清晰,也符合Arrow的错误处理最佳实践。
内容的提问来源于stack exchange,提问作者pbuchheit
相关产品推荐
相关产品推荐

