[ANN] `validated` crate: The cumulative sibling of `Result`

Hey folks, we're proud to announce the initial release of the validated (GIthub) crate. This provides the Validated type, the "cumulative sibling" of Result or Either.

Error Weaving

You may be familiar with using collect to short-circuit a sequence of operations that return Result:

let v: Vec<u32> = vec![1, 2, 3];
let r: Result<Vec<u32>, &str> = v
    .map(|n| if n % 2 == 0 { Err("Oh no!") } else { Ok(n * 2) })
assert_eq!(Err("Oh no!"), r);

Note that here, the potentially expensive operation (usually IO, but here is just n * 2) is skipped for 3, since the closure failed on 2. But what if you didn't want to short-circuit, but collect all errors that occurred?

Enter Validated:

use validated::Validated::{self, Good, Fail};
use nonempty::NonEmpty;

let v = vec![Good(1), Validated::fail("No!"), Good(3), Validated::fail("Ack!")];
let r: Validated<Vec<u32>, &str> = Fail(NonEmpty::from(("No!", vec!["Ack!"])));
assert_eq!(r, v.into_iter().collect());

This is very useful for cases where you want to know all failed cases as once, say when validating user input on a form, or when running concurrent operations with rayon. In fact, validated supports rayon, allowing you to collect all potential errors across spawned threads.

We're also not limited to collecting into an inner Vec: you can fold that inner value into anything that implements FromIterator!

Mapping Composite Results

This crate also provides various mapN methods (currently up to 4), which will only succeed if all subcases succeeded. And here there is still no short-circuiting; all errors are concatinated in the final result.

use validated::Validated::{self, Good, Fail};

let v: Validated<u32, &str> = Good(1).map3(Good(2), Good(3), |a, b, c| a + b + c);
assert_eq!(v, Good(6));

Such methods would be useful for Option and Result too, but they are strangely missing. FP folks will recognize such methods.

Thanks everyone, and let us know if you have any issues! Also it's my birthday. Cheers!


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.