У меня есть следующие классы:
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>>
В левой части 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() }
скоро можно будет удалить.