I am going to talk about a little library I created in Swift to be used either standlone or with Swiftz lib. It is called Swiftz-Validation.
It’s a data structure that typically models form validations, and other scenarios where you want to aggregate all failures, rather than short-circuit if an error happens (for which Swiftx’s Either is better suited). A Validation may either be a Success(value), which contains a successful value, or a Failure(value), which contains an error.
A Validation is a data structure that implements the Applicative interface (.ap
), and does so in a way that if a failure is applied to another failure, then it results in a new validation that contains the failures of both validations. In other words, Validation is a data structure made for errors that can be aggregated, and it makes sense in the contexts of things like form validations, where you want to display to the user all of the fields that failed the validation rather than just stopping at the first failure.
Validations can’t be as easily used for sequencing operations because the.ap
method takes two validations, so the operations that create them must have been executed already. While it is possible to use Validations in a sequential manner, it's better to leave the job to Either, a data structure made for that.
In the following example we are going to validate a password: it should contain more than 8 characters, it should contain an especial character and it has to be different from the user name.
Things like form and schema validation are pretty common in programming, but we end up either using branching or designing very specific solutions for each case.
With branching, I mean using if-else conditions, things get quickly out of hand, it doesn’t scale because it’s difficult to abstract over it and it’s hard to reason about each rule. Let’s see an example of the same validation as before, using branching:
Because this function uses if
conditions and modifies a local variable it's not very modular. This means it's not possible to split these checks in smaller pieces that can be entirely understood by themselves — they modify something, and so you have to understand how they modify that thing, in which context, etc. For very simple things it's not too bad, but as complexity grows it becomes unmanageable.
The main advantages of Swiftz-Validation is that:
In the following example, you can see how the Validation structure gives you a tool for basing validation libraris and functions on in a way that’s reusable (DRY) and composable:
The Validation lib is implemented as an enum with two cases:
Validation functions just return one of these two cases instead of throwing errors or mutating other variables. The keys of working with Validations are:
Now, we are going to see some examples:
Combining validations
Transforming validation values
Reacting to validation results
I wrote this lib as an personal experiment since the core SwiftZ library doesn’t include a similar data structure and I think it is a very important one, because validation is pretty common in every sowftware program. The lib is still work in progress but it can be used with SwiftZ or standalone. I would add more operations like liftA3 and similar.
Feel free to pull request the repo and improve it, thanks!.
The lib it’s inspired by the Validation Package for Haskell: https://hackage.haskell.org/package/Validation
Acknowledgements