A header is the structured opening data that tells a parser how to interpret what follows. In PNM images, it records a magic number, width, height, and—when the format requires it—an optional maximum pixel value. The magic number distinguishes P1 through P6; P1 and P4 omit the maximum value. section 12.2.2
For a simple P1 bitmap, the header can be a single space-separated line: the fixed magic number P1, then width and height. A parser reads these parts in order and constructs a Header value from the two dimensions. Fixed text establishes the format, while numeric parsers supply the fields. section 12.1.3
A minimal P1 header
`P1 100 100` identifies a P1 image that is 100 pixels wide and 100 pixels high. Parsing it with a Header constructor produces a value whose width is 100 and height is 100; a different magic number, such as P2, fails this P1-specific parser. section 12.1.3
A practical parser must also handle the separators allowed by the file format. PNM whitespace includes spaces, line breaks, tabs, carriage returns, vertical tabs, and form feeds. It can also skip comments before reading each significant header field. Library decimal parsers replace an earlier hand-written integer parser that could crash on empty input. section 12.2.2 section 12.1.3
Listing 12.23 A parser for PNM headers with Attoparsec
headerP :: Parser Header
headerP = do
skipWhitespace
magicNumber <-
choice #1
[ magicNumberP1P,
magicNumberP2P,
magicNumberP3P,
magicNumberP4P,
magicNumberP5P,
magicNumberP6P
]
skipWhitespace
width <- C8.decimal #2
skipWhitespace
height <- C8.decimal #2
maxVal <- do
if magicNumber == P1 || magicNumber == P4
then return Nothing
else Just <$> (skipWhitespace *> C8.decimal) #3
whitespace
return Header {..}
This parser shows the complete sequence: skip ignorable input, select a magic number, read dimensions, conditionally read the maximum value, and return a Header. section 12.2.2
Header parsing also demonstrates applicative and monadic parser composition. Applicative operators combine parsers that read ordered values and apply them to a constructor, propagating failures instead of producing a completed value. The later PNM parser uses `do` notation for the same staged work, including the format-dependent maximum value. section 12.1.3 section 12.2.2
Not every header has the same role. A CSV header is an optional first record rather than image metadata, and software cannot reliably infer whether it is present. Parsing options therefore explicitly choose `WithHeader` or `WithoutHeader`, with no header as the default. section 8.1
