diff --git a/simple-parser.cabal b/simple-parser.cabal
--- a/simple-parser.cabal
+++ b/simple-parser.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: ce19476ac6cda5f690dbd36c08a1e3ea7f6a18139c3cda8ae878b3d0f18aea6a
+-- hash: 30149b888c19d3f8c0f4ec90adef691a37befb566bb620eb5fc386bcc57224dd
 
 name:           simple-parser
-version:        0.8.1
+version:        0.8.2
 synopsis:       Simple parser combinators
 description:    Please see the README on GitHub at <https://github.com/ejconlon/simple-parser#readme>
 category:       Parsing
diff --git a/src/SimpleParser/Errata.hs b/src/SimpleParser/Errata.hs
--- a/src/SimpleParser/Errata.hs
+++ b/src/SimpleParser/Errata.hs
@@ -13,13 +13,17 @@
 import Errata (Block, Style, blockMerged')
 import SimpleParser.Explain (ErrorExplanation (..), Explainable, ParseErrorExplanation (..), explainParseError)
 import SimpleParser.Result (ParseError, ParseResult (..))
-import SimpleParser.Stream (Col (..), Line (..), LinePos (..), Pos, Span (..))
+import SimpleParser.Stream (Col (..), HasLinePos (..), Line (..), Pos, Span (..))
 
-type LinePosExplainable l s e = (Explainable l s e, Pos s ~ LinePos)
+type LinePosExplainable l s e = (Explainable l s e, HasLinePos (Pos s))
 
-errataExplanation :: Style -> FilePath -> ParseErrorExplanation LinePos -> Block
+errataExplanation :: HasLinePos p => Style -> FilePath -> ParseErrorExplanation p -> Block
 errataExplanation style fp (ParseErrorExplanation sp context mayDetails  (ErrorExplanation reason mayExpected mayActual)) =
-  let Span (LinePos _ (Line startLine) (Col startCol)) (LinePos _ (Line endLine) (Col endCol)) = sp
+  let Span startPos endPos = sp
+      startLine = unLine (viewLine startPos)
+      startCol = unCol (viewCol startPos)
+      endLine = unLine (viewLine endPos)
+      endCol = unCol (viewCol endPos)
       mayLabel = Just reason
       mayHeader =
        case context of
diff --git a/src/SimpleParser/Explain.hs b/src/SimpleParser/Explain.hs
--- a/src/SimpleParser/Explain.hs
+++ b/src/SimpleParser/Explain.hs
@@ -22,7 +22,7 @@
 import SimpleParser.Common (CompoundTextLabel (..), TextLabel (..))
 import SimpleParser.Result (CompoundError (..), ParseError (..), RawError (..), StreamError (..),
                             parseErrorEnclosingLabels, parseErrorNarrowestSpan)
-import SimpleParser.Stream (LinePos (..), PosStream (..), Span (..), Stream (..), TextualStream)
+import SimpleParser.Stream (HasLinePos (..), PosStream (..), Span (..), Stream (..), TextualStream)
 import Text.Builder (Builder)
 import qualified Text.Builder as TB
 
@@ -125,9 +125,17 @@
       errExp = explainError (peError pe)
   in ParseErrorExplanation sp context mayDetails errExp
 
-buildSpan :: Span LinePos -> Builder
-buildSpan (Span (LinePos _ sl sc) (LinePos _ el ec)) =
-  TB.decimal (succ sl) <> ":" <> TB.decimal (succ sc) <> "-" <> TB.decimal (succ el) <> ":" <> TB.decimal (succ ec)
+buildSpan :: HasLinePos p => Span p -> Builder
+buildSpan (Span p1 p2) =
+  let l1 = viewLine p1
+      c1 = viewCol p1
+      l2 = viewLine p2
+      c2 = viewCol p2
+      r1 = TB.decimal (succ l1) <> ":" <> TB.decimal (succ c1)
+      r2 = TB.decimal (succ l2) <> ":" <> TB.decimal (succ c2)
+  in if l1 == l2 && c1 == c2
+    then r1
+    else r1 <> "-" <> r2
 
 buildErrorExplanation :: Maybe Builder -> ErrorExplanation -> [Builder]
 buildErrorExplanation mayDetails (ErrorExplanation reason mayExpected mayActual) = join
@@ -137,7 +145,7 @@
   , maybe [] (\ac -> ["[Actual  ] " <> TB.text ac]) mayActual
   ]
 
-buildParseErrorExplanation :: ParseErrorExplanation LinePos -> Builder
+buildParseErrorExplanation :: HasLinePos p => ParseErrorExplanation p -> Builder
 buildParseErrorExplanation (ParseErrorExplanation sp context mayDetails errExp) =
   let hd = join
         [ ["[Pos     ] " <> buildSpan sp]
@@ -146,5 +154,5 @@
       tl = buildErrorExplanation (fmap TB.text mayDetails) errExp
   in TB.intercalate "\n" (hd ++ tl)
 
-buildAllParseErrorExplanations :: Foldable f => f (ParseErrorExplanation LinePos) -> Builder
+buildAllParseErrorExplanations :: (HasLinePos p, Foldable f) => f (ParseErrorExplanation p) -> Builder
 buildAllParseErrorExplanations = TB.intercalate "\n\n" . fmap buildParseErrorExplanation . toList
diff --git a/src/SimpleParser/Stream.hs b/src/SimpleParser/Stream.hs
--- a/src/SimpleParser/Stream.hs
+++ b/src/SimpleParser/Stream.hs
@@ -13,6 +13,7 @@
   , LinePosStream (..)
   , newLinePosStream
   , Span (..)
+  , HasLinePos (..)
   ) where
 
 import Data.Bifunctor (first, second)
@@ -231,3 +232,12 @@
   { spanStart :: !p
   , spanEnd :: !p
   } deriving (Eq, Show, Ord)
+
+-- | Allows projections into (Line, Col) for more exotic stream positions.
+class HasLinePos p where
+  viewLine :: p -> Line
+  viewCol :: p -> Col
+
+instance HasLinePos LinePos where
+  viewLine = lpLine
+  viewCol = lpCol
