Support Validation using Applicative Functor
See original GitHub issueHey there, that’s a great library! But I see an issue, similar to the same issue that affects validation via annotations. It is not that simple to define a reusable Value Object class, that is itself composed by other Value Object classes.
Example in Kotlin:
data class Email private constructor(val value: String){
companion object {
fun of(value: String): Either<ConstraintViolations, Email> = ValidatorBuilder.of<Email>()
.konstraint(Email::value) {
email()
}.build()
.validateToEither(Email(emailValue))
}
}
data class Phone private constructor(val value: String){
... similar factory method here
}
data class ContactsInfo(val email: Email, val phone: PhoneNumber){
companion object {
fun of(emailValue: String, phoneValue: String): Either<ConstraintViolations, ContactsInfo>{
val email: Either<ConstraintViolations, Email> = Email.of(emailValue)
val phone: Either<ConstraintViolations, PhoneNumber> = PhoneNumber.of(phoneValue)
... How to compose email and phone here to build a ContactsInfo()? ...
}
}
}
Build a ConcactsInfo
like in the example is not possible as Either
lacks of a flatMap
method. But also if flatMap
was there, it would short-circuit on email
, and then we would miss an eventual error on phone
, in the list of ConstraintViolations.
I see only two ways out, in the current version of Yavi:
- making public the constructors of
Email
andPhoneNumber
and having theof
factory method return theConstraintValidations
, by callingvalidate
instead ofvalidateToEither
. Then, every time check the value of theisValid
property ofConstraintValidations
. This solution is not explicit, neither type-safe, and drives to duplication. - Use exceptions.
My solution proposal is: let’s discuss a way of integrating Yavi with the Validation Monad of Konad in order to have an extension method like
fun <T> Validator<T>.validateToKonad(target: T): Validation<ConstraintViolations, T> =
validate(target).run {
if(isValid) target.success()
else fail()
}
With the Validation
from Konad the example above would become
data class ContactsInfo(val email: Email, val phone: PhoneNumber){
companion object {
fun of(emailValue: String, phoneValue: String): Validation<ConstraintViolations, ContactsInfo> =
::ContactsInfo + Email.of(emailValue) + PhoneNumber.of(phoneValue)
}
}
Issue Analytics
- State:
- Created 2 years ago
- Comments:14 (10 by maintainers)
Top GitHub Comments
BTW, I think YAVI’s Arguments Validator can achieve the same outcome though it’s more verbose:
YAVI 0.6.0 has been released though it’s not yet synced with Maven Central https://github.com/making/yavi/releases/tag/0.6.0
Final form looks like