kota's memex

Some years ago I read this great article https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/ which explains the idea of "type-driven development" by using an example in which you can either validate user input over and over again or parse it one time and use the type system to prove that it has already been validated.

Rust's type system is much weaker than haskell, but is still good enough to implement many of the ideas coming from the functional programming world.

Say you get some user input and need to ensure it's not blank, is under a certain length, and doesn't include certain characters. You could write a function that takes your string and returns a boolean. In dynamically typed languages this is not only standard, but is often the only option. In languages with a good type system you could instead write a function that takes a string and returns a custom Username type. If the only way to create a username type is your Parse constructor then you now have a string which is proven to be validated.

pub struct SubscriberName(String);

impl SubscriberName {
	pub fn parse(s: String) -> SubscriberName {
		let is_empty_or_whitespace = s.trim().is_empty();
		let is_too_long = s.graphemes(true).count() > 256;

		let forbidden_characters =
			['/', '(', ')', '"', '<', '>', '\\', '{', '}'];

		let contains_forbidden_characters =
			s.chars().any(|g| forbidden_characters.contains(&g));

		if is_empty_or_whitespace
			|| is_too_long
			|| contains_forbidden_characters
		{
			panic!("{} is not a valid subscriber name.", s)
		} else {
			Self(s)
		}
	}
}

impl AsRef<str> for SubscriberName {
	fn as_ref(&self) -> &str {
		&self.0
	}
}

This code has the ability to parse a string into a new SubscriberName type which proves the input has been validated. We've also implemented AsRef<str> so that SubscriberName can be elegantly converted to a immutable reference to the string it contains when it needs to be used as a string.