and last name must not be empty. Age must be over 18. Document ID must be 8 digits followed by a letter. Phone number must have 9 digits. Email must contain an @ symbol. @tomasruizlopez | #AltConfMadrid | @bow_swift
case userTooYoung(Date) case invalidDocumentId(String) case invalidPhoneNumber(String) case invalidEmail(String) } @tomasruizlopez | #AltConfMadrid | @bow_swift
case let (.failure(error), _) case let (_, .failure(error)) } API not available (firstNameResult, lastNameResult).map { firstName, lastName in } @tomasruizlopez | #AltConfMadrid | @bow_swift
Fail-fast: return the first error found. 2. Error accumulation: provide a list of all errors found. @tomasruizlopez | #AltConfMadrid | @bow_swift
at least one: Validated<NonEmptyArray<ValidationError>, Form> Or alternatively: Validated<NEA<ValidationError>, Form> Even more succint, with the ValidatedNEA typealias: ValidatedNEA<ValidationError, Form> @tomasruizlopez | #AltConfMadrid | @bow_swift
are combined and reported: errorAccummulation(firstName: "", lastName: "", birthday: Date(), documentId: "1B", phoneNumber: "AABBCC", email: "myemail") Invalid(NonEmptyArray([User's email is invalid: "myemail", User's phone number is invalid: "AABBCC", User's document id is invalid: "1B", User is too young: 2019-05-27 13 46 31 +0000, Last name is empty: "", First name is empty: ""])) @tomasruizlopez | #AltConfMadrid | @bow_swift
fa, fb, fc) { a, b, c in } Validated<ValidationError, Form>.map( fa, fb, fc) { a, b, c in } In general, working with any type F F<Form>.map( fa, fb, fc) { a, b, c in } @tomasruizlopez | #AltConfMadrid | @bow_swift
Result is nice, but needs a more powerful API. Bow provides Either (fail-fast) and Validated (error accumulation). Make illegal states impossible to represent. Use abstractions based on type classes. @tomasruizlopez | #AltConfMadrid | @bow_swift
ValidationError: Error { case emptyFirstName(String) case emptyLastName(String) case userTooYoung(Date) case invalidDocumentId(String) case invalidPhoneNumber(String) case invalidEmail(String) indirect case multiple(first: ValidationError, rest: [ValidationError]) } @tomasruizlopez | #AltConfMadrid | @bow_swift