-
source :: Parse, don’t validate
Notes
When it comes to type-driven development the right approach should be [[file:../20210516164014-parse_don_t_validate.org][parse, don't validate]].
Static type systemsallow for figuring out what's possible to implement.
Given the Haskelltype signature:
head :: [a] -> a
You can reason that this would yield a partial function because it cannot be
implemented for []
.
However, since we can't implement that type signature fully, we can adjust the signature to be:
head :: [a] -> Maybe a
indicating that the function may return nothing in certain cases. This may be
suitable, but down the road it causes problems, as it forces the rest of the
program to deal with a Maybe
value.
The better solution would be to return a new type, NonEmpty
, that constrains
the type of data the function can work with.
data NonEmpty a = a :| [a] head :: NonEmpty a -> a head (x:|_) = x
Through this process we have strengthened our type.
Consider: what is a parser Really, a parser is just a function that consumes less-structured input and produces more-structured output. By its very nature, a parser is a partial function—some values in the domain do not correspond to any value in the range—so all parsers must have some notion of failure. Often, the input to a parser is text, but this is by no means a requirement, and parseNonEmpty is a perfectly cromulent parser: it parses lists into non-empty lists, signaling failure by terminating the program with an error message.
Parsing with a static type system should therefore be simple: "if the parsing and processing logic go out of sync, the program will fail to even compile."
-
Shotgun parsing:: an antipatternwhereby parsing and input-validating code is mixed with and spread across processing code—throwing a cloud of checks at the input, and hoping, without any systematic justification, that one or another would catch all the "bad" cases
In practice, parsing without validation looks like focusing on datatypes Specifically:
-
Use data structures that make illegal states unrepresentable.
-
Push the burden of proof upward as far as possible, but no further.
Alternatively, "write functions on the data representation you wish you had, not the data representation that you are given."
- public document at doc.anagora.org/20210516163844-parse_don_t_validate
- video call at meet.jit.si/20210516163844-parse_don_t_validate