PP structure

June 22, 2026 ยท View on GitHub

Up to index

The PP structure is a combinator library for pretty-printing, in the style of Wadler and Leijen. A value of type doc is an abstract document that describes a piece of text together with the points at which it may be broken across lines. The render function lays a doc out into a string, choosing the most compact layout that fits a given line width.

Documents are built from text, the line-break primitives (line, lineBreak, softLine, softBreak, hardLine), and combinators such as beside, nest, group, and the list operators sep, cat, fillSep, and fillCat. A group lays its contents out on a single line if they fit, and otherwise breaks them.

The combinators follow Philip Wadler's A prettier printer, extended with the alignment and fill operators of Daan Leijen's wl-pprint library. The renderer follows Christian Lindig's Strictly Pretty, an eager implementation that suits a strict language such as Standard ML: it decides each group in a single forward pass, rather than relying on the laziness of Wadler's original Haskell version.

Synopsis

type doc

val empty : doc
val line : doc
val lineBreak : doc
val softLine : doc
val softBreak : doc
val hardLine : doc
val text : string -> doc
val beside : doc * doc -> doc
val nest : int * doc -> doc
val group : doc -> doc
val align : doc -> doc
val hang : int * doc -> doc
val indent : int * doc -> doc
val hsep : doc list -> doc
val vsep : doc list -> doc
val sep : doc list -> doc
val hcat : doc list -> doc
val vcat : doc list -> doc
val cat : doc list -> doc
val fillSep : doc list -> doc
val fillCat : doc list -> doc
val punctuate : doc * doc list -> doc list
val encloseSep : doc * doc * doc * doc list -> doc
val parens : doc -> doc
val braces : doc -> doc
val brackets : doc -> doc
val render : int * doc -> string

type doc

is the type of a pretty-printer document.

empty

empty is the empty document.

line

line is a line break. It is rendered as a single space when the enclosing group fits on one line, and as a newline otherwise.

lineBreak

lineBreak is a line break. It is rendered as nothing when the enclosing group fits on one line, and as a newline otherwise.

softLine

softLine is a line break that is rendered as a single space when flattened.

softBreak

softBreak is a line break that is rendered as nothing when flattened.

hardLine

hardLine is a line break that is always rendered as a newline, even inside a group that would otherwise fit on one line.

text

text s is a document containing the literal string s.

beside

beside (a, b) is a placed directly to the left of b, with nothing between them.

nest

nest (i, d) increases the indentation of d by i columns.

group

group d lays d out on one line if it fits, otherwise lays it out broken across lines.

align

align d sets the indentation of d to the current column.

hang

hang (i, d) renders d with its nesting set to the current column plus i, placing the first line at the current column.

indent

indent (i, d) indents d by i columns, including its first line.

hsep

hsep ds concatenates the documents ds, separating them with spaces.

vsep

vsep ds concatenates the documents ds, separating them with line breaks.

sep

sep ds concatenates the documents ds, separating them with spaces if the result fits on one line, and with line breaks otherwise.

hcat

hcat ds concatenates the documents ds with nothing between them.

vcat

vcat ds concatenates the documents ds, separating them with line breaks.

cat

cat ds concatenates the documents ds with nothing between them if the result fits on one line, and with line breaks otherwise.

fillSep

fillSep ds concatenates the documents ds, separating them with spaces, and inserting a line break whenever the next document does not fit.

fillCat

fillCat ds concatenates the documents ds with nothing between them, inserting a line break whenever the next document does not fit.

punctuate

punctuate (sep, ds) inserts the separator sep between each of the documents ds, returning the resulting list of documents.

encloseSep

encloseSep (open_, close, sep, ds) concatenates the documents ds, separating them with sep and enclosing the result between open_ and close.

parens

parens d encloses d between parentheses.

braces

braces d encloses d between braces.

brackets

brackets d encloses d between square brackets.

render

render (w, d) renders d to a string, choosing the best layout for line width w.