←back to thread

Parse, don't validate (2019)

(lexi-lambda.github.io)
398 points declanhaigh | 4 comments | | HN request time: 0.313s | source
Show context
bruce343434 ◴[] No.35053912[source]
Note that this basically requires your language to have ergonomic support for sum types, immutable "data classes", pattern matching.

The point is to parse the input into a structure which always upholds the predicates you care about so you don't end up continuously defensively programming in ifs and asserts.

replies(12): >>35054046 #>>35054070 #>>35054386 #>>35054514 #>>35054901 #>>35054993 #>>35055124 #>>35055230 #>>35056047 #>>35057866 #>>35058185 #>>35059271 #
Thaxll ◴[] No.35054901[source]
You're describing deserialization in a strong typing language, sometimes it's not enough, ok your email went to an empty string which is useless.
replies(2): >>35054943 #>>35055012 #
Kinrany ◴[] No.35054943[source]
You can have a ValidEmail type that performs all the checks on construction.
replies(1): >>35055657 #
1. Thaxll ◴[] No.35055657[source]
OP said to not validate.
replies(3): >>35055815 #>>35056190 #>>35060605 #
2. lkitching ◴[] No.35055815[source]
The OP is contrasting between a 'validation' function with type e.g.

    validateEmail :: String -> IO ()
and a 'parsing' function

    validateEmail :: String -> Either EmailError ValidEmail
The property encoded by the ValidEmail type is available throughout the rest of the program, which is not the case if you only validate.
3. mrkeen ◴[] No.35056190[source]
That's fine.

Validation would be:

   Email email = new Email(anyString);
   email.validate();
Parsing (in OP's context) would be:

   Either<Error, ValidEmail> eEmail = Email.from(anyString);
4. gnulinux ◴[] No.35060605[source]
You're misunderstanding. Validation looks like

  validateEmail : String -> String -- post-condition: String contains valid email
whereas parse looks like:

  parseEmail : String -> Either EmailError ValidEmail
There is no problem using `ValidEmail` abstraction. The problem is type stability, when your program enters a stronger state at runtime (i.e. certain validations are performed at runtime) it's best to enter a strong state at compile time (stronger types) so that compiler can verify these conditions. If you remain at String, these validations (that a string is valid email) have no compile-time counterpart so there is no way for compiler to verify. So use `ValidEmail` instead.