5 ms·
>This would allow validations to build on each other, as well as validating arbitrary combinations of fields. Validations "building on each other" is a common
by ivanbakel 5y ago
>This would allow validations to build on each other, as well as validating arbitrary combinations of fields.
Validations "building on each other" is a common requirement, but in this style of code is often deliberately left out.
The trouble is that the goals of "collecting all the errors possible" and "allowing nested validation" are incompatible, in general - the system would have to be aware of dependencies between pieces of data in order to do it correctly (i.e. capture as many errors as possible). It's typically much better to have the programmer direct the nested validation, so that they can opt in to discarding error messages.
There's an interesting case of this in Haskell code, in the `Validation` type [0]. It's not identical to the OP, since that type is a functor rather than a cofunctor - but the idea is the same. Importantly, `Validation` is not a `Monad`, because that would let you write dependent rules which discarded errors (and therefore broke the typeclass laws).
[0]: https://hackage.haskell.org/package/validation-1.1.1/docs/Data-Validation.html#t:Validation https://hackage.haskell.org/package/validation-1.1.1/docs/Da...
- shepmaster 5y ago> the system would have to be aware of dependencies between pieces of data in order to do it correctly Yep, which is why I expect that a graph is needed to model the validations that I picture in my mind. > so that they can opt in to discarding error messages Do you have any small examples of when you'd want to discard error messages?
- catlifeonmars 5y agoAgree, graph makes sense. Ideally, with a finite set of rules, you can traverse the entire graph, generating all possible error messages, and then filter error messages by some heuristic (such as shortest path); displaying only the filtered subset to the end user.
- ivanbakel 5y ago>Do you have any small examples of when you'd want to discard error messages? My point is more that error messages risk being discarded wherever there are nested validations (when talking about Haskell). Consider the following crude example: validate = do x <- foo -- `x` is the result of some validation bar x -- and here, it is fed into a dependent validation where bar y = do z <- baz -- `baz` is a validation, but independent of the argument foobaz y z -- `foobaz` is a validation dependent on the argument return () No part of `bar` will run if `foo` fails to validate and yield the data required to run `bar`. But running the `bar` validation involves a sub-validation `baz` that is independent of the argument passed to `bar` - so in reality, it should be possible to always run `baz` and capture any error messages from it. But the way the code is structured means that the `baz` errors are silently dropped some of the time, even when they could be captured. It's up to the programmer to decide if the extra complexity of floating `baz` to the top-level is worthwhile - and the programmer has to keep these kinds of decisions in mind constantly while writing the validation code. Reordering validations is also a possibility, and it might be available in a graph-based rules engine. But you have to take care to not introduce side-effects into any part of the validation process, otherwise you would get surprising behaviour whenever there was a re-ordering. When writing Haskell code, re-ordering is not really an option for that reason.
- anchpop 5y agoMy bet is that you could represent that with Arrow. Too bad nobody uses them. They’re kind of monads except they represent graphs instead of sequences