liveBook · Manning

Header

As explained in Learn Haskell by Example

A header is the initial structured portion of an image file that identifies its format and describes basic image properties.

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

How Learn Haskell by Example covers it

How deep it goes
Builds complete PNM header parsers, including whitespace, comments, magic numbers, dimensions, and conditional maximum values.
Examples
Uses `P1 100 100`, a successful `P1 100 200` parse, and rejected or incomplete P1 inputs.
What it assumes
Introduces parser composition from a fixed P1 header, then adopts library parser instances and decimal parsing.
What you can do after
Apply it via Attoparsec to parse PNM header fields into a Header value while skipping permitted separators and comments.
How it connects
Connects Header parsing to PNM, MagicNumber, RawData, Attoparsec, Applicative, Monad, whitespace, and comments.

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.