> (2) not actually explicitly stated in the article!
the difference between validation and parsing lies almost entirely in how information is preserved. Consider the following pair of functions:
validateNonEmpty :: [a] -> IO ()
parseNonEmpty :: [a] -> IO (NonEmpty a)
Both of these functions check the same thing, but parseNonEmpty gives the caller access to the information it learned, while validateNonEmpty just throws it away.
I know we can infer the point from the information buried in the middle of the article. But your quote is significantly edited for clarity, and, after all, is a code example, not a statement of definitions.