validity

Compile-time enforcement of arbitrary invariants

In general, it is a good idea to make invalid states unrepresentable. This can often be achieved using the type system, but there is a limit to the type system's power.

For example, imagine you're trying to represent a user's email address. You might write a struct like this: rust struct Email(pub String); But you don't want any old string to be allowed, you might want to validate that it is actually a valid email address. So your code might look like: ```rust fn validate_email(email: &Email) -> bool { // ... }

fn handleemail(email: Email) { if !validateemail(&email) { panic!("invalid email"); // or return Err(...) }

dostuffwithvalidemail(email: Email); }

fn dostuffwithvalidemail(email: Email) { println!("definitely a valid email: {}", email.0); } `` This works, but we're "hiding" a particular invariant from the compiler:dostuffwithemailcannot be called with anEmailthat might returnfalsewhen passed tovalidateemail`.

However, with validity, we can make a few small changes to tell the compiler about this invariant:

Great! We now can't forget to validate emails, since there is no other way to create a Valid<T>.

Warning - determinism

Note, this implementation assumes that is_valid is deterministic (i.e. it gives the same result every time it's called). For example, the following implementation can allow an invalid value to exist inside a Valid<T>: rust impl Valid for MyType { type Error = (); fn is_valid(&self) -> Result<(), ()> { match rand::random() { true => Ok(()), false => Err(()), } } }