A parser reads input against an expected structure, rejects invalid input with an error, and turns valid characters or bytes into native data. A useful parser definition also makes that expected structure visible and lets small parsing steps combine into larger ones. section 12.1.2
A parser can begin as a function from Text to a value, but real input can fail. Encoding success or failure with Either avoids crashes and allows an error message to explain what was expected. A fuller parser also returns unconsumed input, so later parsers can continue from the correct position. section 12.1.2
Listing 12.3 A data type for parsers
type ErrorMessage = String #1
type ParseResult a = Either ErrorMessage (T.Text, a) #2
newtype Parser a = Parser
{runParser :: T.Text -> ParseResult a} #3
The Parser representation records either an error or both the parsed value and the remaining Text. section 12.1.2
Compose parsers to describe a format step by step:
- Parse fixed input, such as a PNM magic number, then map it to a domain value like P1. section 12.1.2
- Use functor and applicative composition when independent pieces of input form one result. section 12.1.2
- Use monadic composition when a later parsing choice depends on an earlier value, such as whether a PNM header contains a maximum value. section 12.1.5
- Select among alternatives with choice, and repeat a parser when a header determines how many values to read. section 12.1.5 section 12.2.4
Parsing a PNM image
A PNM parser first reads a header, including its magic number, width, height, and optional maximum value. That header then selects the correct pixel parser: ASCII values, one-byte binary values, two-byte binary values, or packed bitmap bits. The final parser combines header and image data, requires complete input, and returns either an error or a RawPnm value. section 12.2.2 section 12.2.3 section 12.2.4
Libraries can supply the same building blocks. Attoparsec parses ByteString data and can report success, failure, or that more input is needed; parseOnly is suitable when parsing a complete input. Aeson uses Parser values to validate JSON shapes and fields, while optparse-applicative combines option parsers into typed command-line arguments and generated help text. section 12.2.1 section 15.3.1 section 16.1.1
