Pure functions. GHC optimises aggressively when compiling with
-O, so it is easy to write innocent-looking benchmark code that
doesn't measure the performance of a pure function at all. We
work around this by benchmarking both a function and its final
argument together.

Benchmarking IO actions

Benchmarking pure code

Because GHC optimises aggressively when compiling with -O, it is
potentially easy to write innocent-looking benchmark code that will
only be evaluated once, for which all but the first iteration of
the timing loop will be timing the cost of doing nothing.

To work around this, we provide a special type, Pure, for
benchmarking pure code. Values of this type are constructed using
one of two functions.

The first is a function which will cause results to be evaluated to
head normal form (NF):

The compiler will correctly infer that the number 1000 must have
the type Int, and the type of the expression is Pure.

Fully evaluating a result

The whnf harness for evaluating a pure function only evaluates
the result to weak head normal form (WHNF). If you need the result
evaluated all the way to normal form, use the nf function to
force its complete evaluation.

Using the firstN example from earlier, to naive eyes it might
appear that the following code ought to benchmark the production
of the first 1000 list elements: