Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Are you familiar with the idea of "making illegal states unrepresentable", and "parse, don't validate"?

https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va...

You brought up the examples of doing the wrong thing with booleans. With a good type system you can cut down on needing to use booleans in the first place for a lot of things. Your isSomething(x) example is a good one: presumably some code after this is implicitly relying on this predicate being true about x. If you forget to do the check, or you invert the check, then that's a bug.

But another way to do this is to encode the predicate into the type system, so the compiler makes you get it right. Concretely, supposing x is a string, and you need to check if x is a valid username before invoking username-related code on x. Then you can have a function like:

    fn as_username(x: String) -> Optional[Username]
A Username is just a type alias for a String, i.e. the runtime representation is the exact same, with no overhead. You put the parsing/validation logic inside that function. Then code expecting a username will take a value of type Username rather than String. If as_username is the only function with Username in the return type, then having a value of type Username is proof that the as_username function was already called at some point previously, and gave its blessing to the underlying string so that the Optional could be unpacked.

    match as_username(raw_string) {
    // compiler forces us to handle both cases, ie we can't forget
    // to check validity
        case Some(username: Username) {
            // code in here can assume we have a proper username
        }
        case None {
            // handle what to do otherwise
        }
    }
Sure, you have to write the as_username function correctly, there's no getting around that. But you only have to get it right once.


> Are you familiar with the idea of "making illegal states unrepresentable", and "parse, don't validate"?

I haven't heard of those concepts/ideas before. Thanks for linking the article to define those concepts. With your example, and the article mentioning that "parsing should take place at the boundaries" (paraphrase), I can see how types (a la ML families) can be defined and composed give internal coherence once an external input has been parsed and hence validated.

Really interesting approach which I haven't considered before!


Glad I could help!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: