diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,230 @@
+# loc
+
+Overview of the concepts:
+
+![Example text illustrating Loc, Span, and Area](example.png)
+
+* `Loc` - a cursor position, starting at the origin `1:1`
+* `Span` - a nonempty contiguous region between two locs
+* `Area` - a set of zero or more spans with gaps between them
+
+See also:
+
+* [loc-test](https://hackage.haskell.org/package/loc-test) -
+  Test-related utilities for this package.
+
+## `Pos`
+
+Since all of the numbers we're dealing with in this domain are positive, we
+define a "positive integer" type. This is a newtype for `Natural` that doesn't
+allow zero.
+
+```haskell
+newtype Pos = Pos Natural
+  deriving (Eq, Ord)
+
+instance Num Pos where
+  fromInteger = Pos . checkForUnderflow . fromInteger
+  Pos x + Pos y = Pos (x + y)
+  Pos x - Pos y = Pos (checkForUnderflow (x - y))
+  Pos x * Pos y = Pos (x * y)
+  abs = id
+  signum _ = Pos 1
+  negate _ = throw Underflow
+
+checkForUnderflow :: Natural -> Natural
+checkForUnderflow n =
+  if n == 0 then throw Underflow else n
+```
+
+`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.
+
+```haskell
+class ToNat a where
+  toNat :: a -> Natural
+
+instance ToNat Pos where
+  toNat (Pos n) = n
+```
+
+## `Line`, `Column`
+
+We then add some newtypes to be more specific about whether we're talking about
+line or column numbers.
+
+```haskell
+newtype Line = Line Pos
+  deriving (Eq, Ord, Num, Real, Enum, ToNat)
+
+newtype Column = Column Pos
+  deriving (Eq, Ord, Num, Real, Enum, ToNat)
+```
+
+## `Loc`
+
+A `Loc` is a `Line` and a `Column`.
+
+```haskell
+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`.
+
+```haskell
+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`.
+
+```haskell
+fromTo :: Loc -> Loc -> Span
+fromTo a b =
+  maybe (throw EmptySpan) id (fromToMay a b)
+
+fromToMay :: Loc -> Loc -> Maybe Span
+fromToMay a b =
+  case compare a b of
+    LT -> Just (Span a b)
+    GT -> Just (Span b a)
+    EQ -> Nothing
+```
+
+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:
+
+```haskell
+data Terminus = Start | End
+  deriving (Eq, Ord)
+
+newtype Area = Area (Map Loc Terminus)
+  deriving (Eq, Ord)
+```
+
+You can think of this as a sorted list of the spans' start and end positions,
+along with a tag indicating whether each is a start or an end.
+
+## `Show`
+
+We define custom `Show` and `Read` instances to be able to write terse
+[doctests](https://hackage.haskell.org/package/doctest) like
+
+```haskell
+>>> addSpan (read "1:1-6:1") (read "[1:1-3:1,6:1-6:2,7:4-7:5]")
+[1:1-6:2,7:4-7:5]
+```
+
+These are the `showsPrec` implementations for `Loc` and `Span`:
+
+```haskell
+locShowsPrec :: Int -> Loc -> ShowS
+locShowsPrec _ (Loc l c) =
+  shows l .
+  showString ":" .
+  shows c
+
+spanShowsPrec :: Int -> Span -> ShowS
+spanShowsPrec _ (Span a b) =
+  locShowsPrec 10 a .
+  showString "-" .
+  locShowsPrec 10 b
+```
+
+## `Read`
+
+The parser for `Pos` is based on the parser for `Natural`, applying `mfilter (/=
+0)` to make the parser fail if the input represents a zero.
+
+```haskell
+posReadPrec :: ReadPrec Pos
+posReadPrec =
+  Pos <$> mfilter (/= 0) readPrec
+```
+
+As a reminder, the type of `mfilter` is:
+
+```haskell
+mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a
+```
+
+The `Loc` parser uses a very typical `Applicative` pattern:
+
+```haskell
+-- | Parses a single specific character.
+readPrecChar :: Char -> ReadPrec ()
+readPrecChar = void . readP_to_Prec . const . ReadP.char
+
+locReadPrec :: ReadPrec Loc
+locReadPrec =
+  Loc              <$>
+  readPrec         <*
+  readPrecChar ':' <*>
+  readPrec
+```
+
+We used `mfilter` above to introduce failure into the `Pos` parser; for `Span`
+we use `empty`.
+
+```haskell
+empty :: Alternative f => f a
+```
+
+First we use `fromToMay` to produce a `Maybe Span`, and then in the case where
+the result is `Nothing` we use `empty` to make the parser fail.
+
+```haskell
+spanReadPrec :: ReadPrec Span
+spanReadPrec =
+  locReadPrec      >>= \a ->
+  readPrecChar '-' *>
+  locReadPrec      >>= \b ->
+  maybe empty pure (fromToMay a b)
+```
+
+## Comparison to similar packages
+
+### `srcloc`
+
+[srcloc](https://hackage.haskell.org/package/srcloc) has a similar general
+purpose: defining types related to positions in text files.
+
+Some differences:
+
+* `srcloc`'s `Pos` type (comparable to our `Loc` type) has a `FilePath`
+  parameter, whereas this library doesn't consider file paths at all.
+* `srcloc` has nothing comparable to the `Area` type.
+
+There are some undocumented aspects of `srcloc` we find confusing:
+
+* What does "character offset" mean?
+* Does `srcloc`'s `Loc` type use inclusive or exclusive bounds?
diff --git a/example.png b/example.png
new file mode 100644
Binary files /dev/null and b/example.png differ
diff --git a/example.svg b/example.svg
new file mode 100644
--- /dev/null
+++ b/example.svg
@@ -0,0 +1,411 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="119.54762mm"
+   height="52.56461mm"
+   viewBox="0 0 119.54762 52.56461"
+   version="1.1"
+   id="svg8"
+   inkscape:version="0.92.0 r15299"
+   sodipodi:docname="example.svg"
+   inkscape:export-filename="/home/chris/chris-martin.org/in/posts/2017-05-09-loc/example.png"
+   inkscape:export-xdpi="185.481"
+   inkscape:export-ydpi="185.481">
+  <defs
+     id="defs2" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="184.29443"
+     inkscape:cy="134.58074"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:snap-nodes="false"
+     inkscape:snap-global="false"
+     inkscape:window-width="1920"
+     inkscape:window-height="1016"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     fit-margin-top="2"
+     fit-margin-left="2"
+     fit-margin-right="2"
+     fit-margin-bottom="2" />
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-40.943916,-27.525532)">
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.13800001;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#898200;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="rect4898"
+       width="12.552429"
+       height="4.21416"
+       x="74.334846"
+       y="48.584148" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="43.832203"
+       y="52.181114"
+       id="text4487"><tspan
+         sodipodi:role="line"
+         id="tspan4485"
+         x="43.832203"
+         y="52.181114"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono';stroke-width:0.26458332px">Lorem ipsum dolor sit amet, consectetur</tspan><tspan
+         sodipodi:role="line"
+         x="43.832203"
+         y="57.202133"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono';stroke-width:0.26458332px"
+         id="tspan4489">adipiscing elit, sed do eiusmod tempor</tspan><tspan
+         sodipodi:role="line"
+         x="43.832203"
+         y="62.223156"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono';stroke-width:0.26458332px"
+         id="tspan4491">incididunt ut labore et dolore magna aliqua.</tspan></text>
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#d69000;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 53.861606,47.913689 v 5.575149"
+       id="path4493"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d69000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="52.474232"
+       y="40.50515"
+       id="text4497"><tspan
+         sodipodi:role="line"
+         id="tspan4495"
+         x="52.474232"
+         y="40.50515"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#d69000;fill-opacity:1;stroke-width:0.26458332px">Loc 1:5</tspan></text>
+    <text
+       id="text4787"
+       y="37.443539"
+       x="79.263298"
+       style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#898200;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#898200;fill-opacity:1;stroke-width:0.26458332px"
+         y="37.443539"
+         x="79.263298"
+         sodipodi:role="line"
+         id="tspan4853">Span 1:13-1:18</tspan></text>
+    <path
+       style="fill:#d69000;fill-opacity:1;fill-rule:evenodd;stroke:#d69000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 53.821401,41.54614 v 4.482401"
+       id="path4499"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       sodipodi:type="star"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d69000;fill-opacity:1;fill-rule:nonzero;stroke:#d69000;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="path4815"
+       sodipodi:sides="3"
+       sodipodi:cx="53.721176"
+       sodipodi:cy="45.499374"
+       sodipodi:r1="1.7372519"
+       sodipodi:r2="0.86862594"
+       sodipodi:arg1="1.5707963"
+       sodipodi:arg2="2.6179939"
+       inkscape:flatsided="false"
+       inkscape:rounded="0"
+       inkscape:randomized="0"
+       d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"
+       inkscape:transform-center-y="0.068559171"
+       transform="matrix(0.42264893,0,0,0.41327698,31.116206,27.39379)" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4817"
+       d="m 44.069338,47.913689 v 5.575149"
+       style="fill:none;fill-rule:evenodd;stroke:#d60000;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <text
+       id="text4839"
+       y="32.671593"
+       x="42.741344"
+       style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d60000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#d60000;fill-opacity:1;stroke-width:0.26458332px"
+         y="32.671593"
+         x="42.741344"
+         id="tspan4837"
+         sodipodi:role="line">Loc 1:1</tspan></text>
+    <path
+       inkscape:connector-curvature="0"
+       id="path4841"
+       d="m 43.899526,33.806143 v 12.2224"
+       style="fill:#d60000;fill-opacity:1;fill-rule:evenodd;stroke:#d60000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       sodipodi:nodetypes="cc" />
+    <path
+       transform="matrix(0.42264893,0,0,0.41327698,21.194331,27.39379)"
+       inkscape:transform-center-y="0.068559171"
+       d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"
+       inkscape:randomized="0"
+       inkscape:rounded="0"
+       inkscape:flatsided="false"
+       sodipodi:arg2="2.6179939"
+       sodipodi:arg1="1.5707963"
+       sodipodi:r2="0.86862594"
+       sodipodi:r1="1.7372519"
+       sodipodi:cy="45.499374"
+       sodipodi:cx="53.721176"
+       sodipodi:sides="3"
+       id="path4843"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d60000;fill-opacity:1;fill-rule:nonzero;stroke:#d60000;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       sodipodi:type="star" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4857"
+       d="m 80.468723,38.834159 v 7.723547"
+       style="fill:#898200;fill-opacity:1;fill-rule:evenodd;stroke:#898200;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       transform="matrix(0.42264893,0,0,0.41327698,57.763529,27.922957)"
+       inkscape:transform-center-y="0.068559171"
+       d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"
+       inkscape:randomized="0"
+       inkscape:rounded="0"
+       inkscape:flatsided="false"
+       sodipodi:arg2="2.6179939"
+       sodipodi:arg1="1.5707963"
+       sodipodi:r2="0.86862594"
+       sodipodi:r1="1.7372519"
+       sodipodi:cy="45.499374"
+       sodipodi:cx="53.721176"
+       sodipodi:sides="3"
+       id="path4859"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#898200;fill-opacity:1;fill-rule:nonzero;stroke:#898200;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       sodipodi:type="star" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4888"
+       d="m 142.76163,47.913689 v 5.575149"
+       style="fill:none;fill-rule:evenodd;stroke:#6ab59b;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <text
+       id="text4892"
+       y="40.50515"
+       x="141.37424"
+       style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#6ab59b;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#6ab59b;fill-opacity:1;stroke-width:0.26458332px"
+         y="40.50515"
+         x="141.37424"
+         id="tspan4890"
+         sodipodi:role="line">Loc 1:40</tspan></text>
+    <path
+       inkscape:connector-curvature="0"
+       id="path4894"
+       d="m 142.72142,41.612956 v 4.482401"
+       style="fill:#6ab59b;fill-opacity:1;fill-rule:evenodd;stroke:#6ab59b;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       sodipodi:nodetypes="cc" />
+    <path
+       transform="matrix(0.42264893,0,0,0.41327698,120.01621,27.460606)"
+       inkscape:transform-center-y="0.068559171"
+       d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"
+       inkscape:randomized="0"
+       inkscape:rounded="0"
+       inkscape:flatsided="false"
+       sodipodi:arg2="2.6179939"
+       sodipodi:arg1="1.5707963"
+       sodipodi:r2="0.86862594"
+       sodipodi:r1="1.7372519"
+       sodipodi:cy="45.499374"
+       sodipodi:cx="53.721176"
+       sodipodi:sides="3"
+       id="path4896"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6ab59b;fill-opacity:1;fill-rule:nonzero;stroke:#6ab59b;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       sodipodi:type="star" />
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.18600003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="rect4898-4"
+       width="15.331899"
+       height="4.3347769"
+       x="86.98941"
+       y="53.612862" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4915"
+       d="m 74.332062,48.592293 v 4.215314"
+       style="fill:none;fill-rule:evenodd;stroke:#898200;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#898200;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 86.965246,48.592293 v 4.215314"
+       id="path4917"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4915-3"
+       d="m 86.965246,53.626655 v 4.321584"
+       style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 102.39444,53.626655 v 4.321584"
+       id="path4934"
+       inkscape:connector-curvature="0" />
+    <rect
+       y="53.570915"
+       x="125.20956"
+       height="4.7904701"
+       width="15.331899"
+       id="rect4936"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.18600003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 125.18544,53.586154 v 4.775892"
+       id="path4938"
+       inkscape:connector-curvature="0" />
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.18600003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="rect4898-4-7"
+       width="10.019917"
+       height="4.5752463"
+       x="43.959404"
+       y="58.546028" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 54.005945,58.560582 v 4.561323"
+       id="path4934-3"
+       inkscape:connector-curvature="0" />
+    <rect
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.18600003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="rect4898-4-8"
+       width="15.331899"
+       height="4.568501"
+       x="79.387222"
+       y="58.50029" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4915-3-0"
+       d="m 79.363058,58.514829 v 4.554598"
+       style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 94.792252,58.514829 v 4.554598"
+       id="path4934-9"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#2865a3;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="52.028664"
+       y="77.157898"
+       id="text4992"><tspan
+         id="tspan4990"
+         sodipodi:role="line"
+         x="52.028664"
+         y="77.157898"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#2865a3;fill-opacity:1;stroke-width:0.26458332px">Area [2:18-2:24, 2:33-3:5, 3:15-3:21]</tspan></text>
+    <path
+       inkscape:connector-curvature="0"
+       id="path4841-7"
+       d="M 96.163115,73.02495 V 59.589093"
+       style="fill:#2865a3;fill-opacity:1;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       transform="matrix(0.42264894,0,0,-0.41327697,73.457922,78.223848)"
+       inkscape:transform-center-y="-0.068556884"
+       d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"
+       inkscape:randomized="0"
+       inkscape:rounded="0"
+       inkscape:flatsided="false"
+       sodipodi:arg2="2.6179939"
+       sodipodi:arg1="1.5707963"
+       sodipodi:r2="0.86862594"
+       sodipodi:r1="1.7372519"
+       sodipodi:cy="45.499374"
+       sodipodi:cx="53.721176"
+       sodipodi:sides="3"
+       id="path4843-9"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:#2865a3;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       sodipodi:type="star" />
+    <path
+       style="fill:#2865a3;fill-opacity:1;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 86.638115,73.038044 V 64.88076"
+       id="path5014"
+       inkscape:connector-curvature="0" />
+    <path
+       sodipodi:type="star"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:#2865a3;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="path5016"
+       sodipodi:sides="3"
+       sodipodi:cx="53.721176"
+       sodipodi:cy="45.499374"
+       sodipodi:r1="1.7372519"
+       sodipodi:r2="0.86862594"
+       sodipodi:arg1="1.5707963"
+       sodipodi:arg2="2.6179939"
+       inkscape:flatsided="false"
+       inkscape:rounded="0"
+       inkscape:randomized="0"
+       d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"
+       inkscape:transform-center-y="-0.068556884"
+       transform="matrix(0.42264894,0,0,-0.41327697,63.932922,83.515515)" />
+    <path
+       style="fill:#2865a3;fill-opacity:1;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 127.51224,73.02495 V 59.589093"
+       id="path5022"
+       inkscape:connector-curvature="0" />
+    <path
+       sodipodi:type="star"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:#2865a3;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       id="path5024"
+       sodipodi:sides="3"
+       sodipodi:cx="53.721176"
+       sodipodi:cy="45.499374"
+       sodipodi:r1="1.7372519"
+       sodipodi:r2="0.86862594"
+       sodipodi:arg1="1.5707963"
+       sodipodi:arg2="2.6179939"
+       inkscape:flatsided="false"
+       inkscape:rounded="0"
+       inkscape:randomized="0"
+       d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"
+       inkscape:transform-center-y="-0.068556884"
+       transform="matrix(0.42264894,0,0,-0.41327697,104.80703,78.223848)" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path5026"
+       d="M 53.434247,73.038044 V 64.88076"
+       style="fill:#2865a3;fill-opacity:1;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       transform="matrix(0.42264894,0,0,-0.41327697,30.729054,83.515515)"
+       inkscape:transform-center-y="-0.068556884"
+       d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"
+       inkscape:randomized="0"
+       inkscape:rounded="0"
+       inkscape:flatsided="false"
+       sodipodi:arg2="2.6179939"
+       sodipodi:arg1="1.5707963"
+       sodipodi:r2="0.86862594"
+       sodipodi:r1="1.7372519"
+       sodipodi:cy="45.499374"
+       sodipodi:cx="53.721176"
+       sodipodi:sides="3"
+       id="path5028"
+       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:#2865a3;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       sodipodi:type="star" />
+  </g>
+</svg>
diff --git a/loc.cabal b/loc.cabal
--- a/loc.cabal
+++ b/loc.cabal
@@ -3,7 +3,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           loc
-version:        0.1.2.1
+version:        0.1.2.2
 synopsis:       Types representing line and column positions and ranges in text files.
 
 description:    The package name /loc/ stands for “location” and is also an allusion to the
@@ -20,6 +20,11 @@
 license-file:   license.txt
 build-type:     Simple
 cabal-version:  >= 1.10
+
+extra-source-files:
+    example.png
+    example.svg
+    README.md
 
 library
   hs-source-dirs:
