Validation — collecting errors
If you’ve ever fixed a validation error on a form, resubmitted, and been told about a different error — you’ve felt the frustration of validation that stops at the first failure. Validation<E, A> runs all checks and collects every failure in one pass. Users see everything wrong at once, not one problem at a time.
The problem with short-circuiting
Section titled “The problem with short-circuiting”When validating a form, Result’s behavior is unhelpful:
If validateName fails, the pipeline stops. The user sees one error, fixes it, submits again, and sees the next one. You want to show all three errors at once.
The Validation approach
Section titled “The Validation approach”Validation accumulates errors across independent checks. When you combine two invalid validations, both error lists are merged:
Running both checks with ap collects all failures:
If both pass, you get the assembled value:
Creating Validations
Section titled “Creating Validations”fail is the most common way to create failures — it wraps a single error in a list. toInvalid lets you provide multiple errors directly when you already have them.
How ap accumulates errors
Section titled “How ap accumulates errors”ap is what sets Validation apart from Result. The pattern is: start with your constructor function wrapped in Validation.of, then apply each validated argument with ap:
Each ap step:
- If both sides are valid, applies the function to the value
- If either side is invalid, merges both error lists into a single
Invalid
The key property: all ap steps run regardless of prior failures. This is what allows all errors to be collected.
chain vs ap — dependent vs independent
Section titled “chain vs ap — dependent vs independent”chain in Validation still short-circuits on the first error, just like Result.chain. Use it when later checks depend on earlier ones succeeding:
Use ap for independent checks that can all run in parallel:
Combining validations
Section titled “Combining validations”combine merges two validations, accumulating errors if either is invalid:
For three or more validations, combineAll folds over an array:
combineAll is most useful when you only need to know whether the whole set passes — the individual values are less important than the error list.
Transforming values with map
Section titled “Transforming values with map”map transforms the valid value, leaving Invalid untouched:
Extracting the value
Section titled “Extracting the value”getOrElse — provide a fallback:
match — handle each case explicitly. The invalid handler receives the full error list:
fold — same as match with positional arguments (invalid handler first):
When to use Validation vs Result
Section titled “When to use Validation vs Result”Use Validation when:
- You’re validating multiple independent fields and want all errors at once
- The consumer of your output (e.g., a form UI) needs the complete list of what went wrong
Use Result when:
- Each step depends on the previous one succeeding
- You want to fail fast and stop processing as soon as something goes wrong
- The operation isn’t about validation — it’s about control flow
In practice, many real-world scenarios mix both: use Validation to check individual fields, then use Result to sequence the side effects once the data is known to be valid.