首页 > 解决方案 > Kotlin 箭头组合已验证列表

问题描述

我有以下课程:

class Person(id: Long, name: String)

sealed class PersonError {
    data class InvalidId(val field: String) : PersonError()
    data class InvalidName(val field: String) : PersonError()
}

当我循环并通过多人进行验证时,我得到:

List<ValidatedNel<Error, Person>>

或者:

List<Validated<Error, Person>>

如何将上面的列表转换为:

Validated<Nel<MappingError>, List<Person>>

我想累积与所有人验证相关的所有错误。这是必需的,因为我想做以下事情:

val vId : ValidatedNel<Error, Long> = validateId(id).toValidatedNel()
val vPersons : List<ValidatedNel<Error, Person>> = validatePersons(persons).toValidatedNel()

ValidatedNel.applicative<Nel<PersonError>>(Nel.semigroup<PersonError>())
    .map(vId, vPersons) {
        val id = it.a
        val persons = it.b
        Group(id, persons)
    }.fix()

当前的“地图”不接受List<ValidatedNel<Error>, Person>>

标签: kotlinkotlin-coroutinesarrow-kt

解决方案


左侧Validated需要一个Semigroup来收集所有错误;您的右侧Validated需要一个product(因为Group(a, b)是产品类型);并且在特定人中累积错误需要sequence(或traverse具有身份功能)来收集给定人的所有错误,因此以下应该起作用:

        val SE = Nel.semigroup<PersonError>()

        val validatedGroup: ValidatedNel<PersonError, Group> = vId.product(
                SE,
                vPersons.sequence(ValidatedNel.applicative(SE)).fix().map { it.fix() }
        ).map(::Group.tupled2())

我认为在即将发布的 Arrow 版本中,对 fix() 的调用将被最小化或消除,因此希望.fix().map { it.fix() }可以很快被删除。


推荐阅读