Pos does not have an Integral instance, because that would require
implementing quotRem :: Pos -> Pos -> (Pos, Pos), which doesn’t make much
sense. Therefore we can’t use toInteger on Pos. Instead we use our own
ToNat class to convert positive numbers to natural numbers.

Loc

A Loc is a Line and a Column.

data Loc = Loc
{ line :: Line
, column :: Column
}
deriving (Eq, Ord)

Note that this library has chosen to be remain entirely agnostic of the text
that the positions are referring to. Therefore there is no “plus one” operation
on Loc, because the next Loc after 4:17 could be either 4:18 or 5:1 -
we can’t tell without knowing the line lengths.

Span

A Span is a start Loc and an end Loc.

data Span = Span
{ start :: Loc
, end :: Loc
} deriving (Eq, Ord)

A Span is not allowed to be empty; in other words, start and end must be
different.

There are two functions for constructing a Span. They both reorder their
arguments as appropriate to make sure the start comes before the end (so that
spans are never backwards). They take different approaches to ensuring that
spans are never empty: the first can throw an exception, whereas the second is
typed as Maybe.

The choice to use an exclusive upper bound [start, end) rather than two
inclusive bounds [start, end] is forced by the decision to be text-agnostic.
With inclusive ranges, you couldn’t tell whether span 4:16-4:17 abuts span
5:1-5:2 without knowing whether the character at position 4:17 is a newline.

Area

Conceptually, an area is a set of spans. To support efficient union and
difference operations, Area is defined like this: