diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -48,7 +48,7 @@
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-Copyright (c) 2015-2016
+Copyright (c) 2015-2024
         Drexel University.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/Text/PrettyPrint/Mainland.hs b/Text/PrettyPrint/Mainland.hs
--- a/Text/PrettyPrint/Mainland.hs
+++ b/Text/PrettyPrint/Mainland.hs
@@ -2,7 +2,7 @@
 -- Module      :  Text.PrettyPrint.Mainland
 -- Copyright   :  (c) 2006-2011 Harvard University
 --                (c) 2011-2012 Geoffrey Mainland
---                (c) 2015-2016 Drexel University
+--                (c) 2015-2017 Drexel University
 -- License     :  BSD-style
 -- Maintainer  :  mainland@drexel.edu
 --
@@ -41,7 +41,7 @@
     -- ** Basic document combinators
     empty,
     srcloc, line, softline, softbreak,
-    (<>), (<|>), (<+>), (</>), (<+/>), (<//>),
+    (<|>), (<+>), (</>), (<+/>), (<//>),
     group, flatten,
 
     -- ** Wrapping documents in delimiters
@@ -66,19 +66,15 @@
 
     -- * Document rendering
     render, renderCompact,
-    displayS, prettyS, pretty,
+    displayS, prettyS, pretty, prettyCompactS, prettyCompact,
     displayPragmaS, prettyPragmaS, prettyPragma,
     displayLazyText, prettyLazyText,
     displayPragmaLazyText, prettyPragmaLazyText,
 
     -- * Document output
-    putDoc, putDocLn, hPutDoc, hPutDocLn,
-
-    -- * The 'Pretty' type class for pretty printing
-    Pretty(..)
+    putDoc, putDocLn, hPutDoc, hPutDocLn
   ) where
 
-import Data.Int
 import Data.Loc (L(..),
                  Loc(..),
                  Located(..),
@@ -86,19 +82,18 @@
                  posFile,
                  posLine)
 import qualified Data.Map as Map
-#if MIN_VERSION_base(4,5,0)
+#if !(MIN_VERSION_base(4,9,0))
 import Data.Monoid (Monoid(..), (<>))
-#else /* !MIN_VERSION_base(4,5,0) */
-import Data.Monoid (Monoid(..))
-#endif /* !MIN_VERSION_base(4,5,0) */
+#endif /* !(MIN_VERSION_base(4,9,0)) */
+#if MIN_VERSION_base(4,9,0) && !(MIN_VERSION_base(4,11,0))
+import Data.Semigroup (Semigroup(..))
+#endif
 import qualified Data.Set as Set
 import Data.String (IsString(..))
 import qualified Data.Text as T
 import qualified Data.Text.Lazy.IO as TIO
 import qualified Data.Text.Lazy as L
 import qualified Data.Text.Lazy.Builder as B
-import Data.Word
-import GHC.Real (Ratio(..))
 import System.IO (Handle)
 
 -- | The abstract type of documents.
@@ -128,9 +123,16 @@
          -- | Calculate document based on current nesting
          | Nesting (Int -> Doc)
 
+#if MIN_VERSION_base(4,9,0)
+instance Semigroup Doc where
+    (<>) = Cat
+#endif
+
 instance Monoid Doc where
     mempty  = empty
+#if !(MIN_VERSION_base(4,11,0))
     mappend = Cat
+#endif
 
 instance IsString Doc where
     fromString s = string s
@@ -310,9 +312,11 @@
 x     <+> Empty = x
 x     <+> y     = x <> space <> y
 
--- | Concatenates two documents with a 'line' in between.
+-- | Concatenates two documents with a 'line' in between, with identity 'empty'.
 (</>) :: Doc -> Doc -> Doc
-x </> y = x <> line <> y
+Empty </> y     = y
+x     </> Empty = x
+x     </> y     = x <> line <> y
 
 -- | Concatenates two documents with a 'softline' in between, with identity
 -- 'empty'.
@@ -333,7 +337,8 @@
 -- | The document @'group' d@ will flatten @d@ to /one/ line if there is
 -- room for it, otherwise the original @d@.
 group :: Doc -> Doc
-group d = flatten d `Alt` d
+group Empty = Empty
+group d     = flatten d `Alt` d
 
 -- | The document @'flatten' d@ will flatten @d@ to /one/ line.
 flatten :: Doc -> Doc
@@ -475,9 +480,10 @@
 -- | The document @'align' d@ renders @d@ with a nesting level set to the current
 -- column.
 align :: Doc -> Doc
-align d = column  $ \k ->
-          nesting $ \i ->
-          nest (k - i) d
+align Empty = Empty
+align d     = column  $ \k ->
+              nesting $ \i ->
+              nest (k - i) d
 
 -- | The document @'hang' i d@ renders @d@ with a nesting level set to the
 -- current column plus @i@, /not including/ the first line.
@@ -528,7 +534,11 @@
                 else spaces (f - w)
 
 -- | Equivalent of 'fail', but with a document instead of a string.
+#if MIN_VERSION_base(4,13,0)
+faildoc :: MonadFail m => Doc -> m a
+#else
 faildoc :: Monad m => Doc -> m a
+#endif
 faildoc = fail . pretty 80
 
 -- | Equivalent of 'error', but with a document instead of a string.
@@ -684,6 +694,14 @@
 pretty :: Int -> Doc -> String
 pretty w x = prettyS w x ""
 
+-- | Render and display a document compactly.
+prettyCompactS :: Doc -> ShowS
+prettyCompactS x = displayS (renderCompact x)
+
+-- | Render and convert a document to a 'String' compactly.
+prettyCompact :: Doc -> String
+prettyCompact x = prettyCompactS x ""
+
 -- | Display a rendered document with #line pragmas.
 displayPragmaS :: RDoc -> ShowS
 displayPragmaS = go
@@ -780,10 +798,10 @@
         renderPosFile p
 
     renderPosLine :: Pos -> B.Builder
-    renderPosLine = go . renderCompact . ppr . posLine
+    renderPosLine = go . renderCompact . int . posLine
 
     renderPosFile :: Pos -> B.Builder
-    renderPosFile = go . renderCompact . enclose dquote dquote . ppr . posFile
+    renderPosFile = go . renderCompact . enclose dquote dquote . string . posFile
 
 -- | Render and convert a document to 'L.Text' with #line pragmas. Uses a builder.
 prettyPragmaLazyText :: Int -> Doc -> L.Text
@@ -806,214 +824,3 @@
 -- followed by a newline.
 hPutDocLn :: Handle -> Doc -> IO ()
 hPutDocLn h = TIO.hPutStrLn h . prettyLazyText 80
-
-class Pretty a where
-#if __GLASGOW_HASKELL__ >= 708
-    {-# MINIMAL pprPrec | ppr #-}
-#endif
-    ppr     :: a -> Doc
-    pprPrec :: Int -> a -> Doc
-    pprList :: [a] -> Doc
-
-    ppr        = pprPrec 0
-    pprPrec _  = ppr
-    pprList xs = list (map ppr xs)
-
-instance Pretty a => Pretty [a] where
-    ppr = pprList
-
-instance Pretty a => Pretty (Maybe a) where
-    pprPrec _ Nothing  = empty
-    pprPrec p (Just a) = pprPrec p a
-
-instance Pretty Bool where
-    ppr = bool
-
-instance Pretty Char where
-    ppr     = char
-    pprList = string
-
-instance Pretty Int where
-    ppr = int
-
-instance Pretty Integer where
-    ppr = integer
-
-instance Pretty Float where
-    ppr = float
-
-instance Pretty Double where
-    ppr = double
-
-ratioPrec, ratioPrec1 :: Int
-ratioPrec  = 7  -- Precedence of ':%' constructor
-ratioPrec1 = ratioPrec + 1
-
-instance (Integral a, Pretty a) => Pretty (Ratio a)  where
-    {-# SPECIALIZE instance Pretty Rational #-}
-    pprPrec p (x:%y) =
-        parensIf (p > ratioPrec) $
-        pprPrec ratioPrec1 x <+> char '%' <+> pprPrec ratioPrec1 y
-
-instance Pretty Word8 where
-    ppr = text . show
-
-instance Pretty Word16 where
-    ppr = text . show
-
-instance Pretty Word32 where
-    ppr = text . show
-
-instance Pretty Word64 where
-    ppr = text . show
-
-instance Pretty Int8 where
-    ppr = text . show
-
-instance Pretty Int16 where
-    ppr = text . show
-
-instance Pretty Int32 where
-    ppr = text . show
-
-instance Pretty Int64 where
-    ppr = text . show
-
-instance Pretty T.Text where
-    ppr = strictText
-
-instance Pretty L.Text where
-    ppr = lazyText
-
-instance Pretty Pos where
-    ppr p@(Pos _ l c _) =
-        text (posFile p) <> colon <> ppr l <> colon <> ppr c
-
-instance Pretty Loc where
-    ppr NoLoc = text "<no location info>"
-
-    ppr (Loc p1@(Pos f1 l1 c1 _) p2@(Pos f2 l2 c2 _))
-        | f1 == f2   = text (posFile p1) <> colon <//> pprLineCol l1 c1 l2 c2
-        | otherwise  = ppr p1 <> text "-" <> ppr p2
-      where
-        pprLineCol :: Int -> Int -> Int -> Int -> Doc
-        pprLineCol l1 c1 l2 c2
-            | l1 == l2 && c1 == c2  =  ppr l1 <//> colon <//> ppr c1
-            | l1 == l2 && c1 /= c2  =  ppr l1 <//> colon <//>
-                                       ppr c1 <> text "-" <> ppr c2
-            | otherwise             =  ppr l1 <//> colon <//> ppr c1
-                                       <> text "-" <>
-                                       ppr l2 <//> colon <//> ppr c2
-
-instance Pretty x => Pretty (L x) where
-    pprPrec p (L _ x) = pprPrec p x
-
-instance (Pretty k, Pretty v) => Pretty (Map.Map k v) where
-    ppr = pprList . Map.toList
-
-instance Pretty a => Pretty (Set.Set a) where
-    ppr = pprList . Set.toList
-
-instance Pretty () where
-    ppr () =
-        tuple []
-
-instance (Pretty a, Pretty b)
-  => Pretty (a, b) where
-    ppr (a, b) =
-        tuple [ppr a, ppr b]
-
-instance (Pretty a, Pretty b, Pretty c)
-  => Pretty (a, b, c) where
-    ppr (a, b, c) =
-        tuple [ppr a, ppr b, ppr c]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d)
-  => Pretty (a, b, c, d) where
-    ppr (a, b, c, d) =
-        tuple [ppr a, ppr b, ppr c, ppr d]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e)
-  => Pretty (a, b, c, d, e) where
-    ppr (a, b, c, d, e) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f)
-  => Pretty (a, b, c, d, e, f) where
-    ppr (a, b, c, d, e, f) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f, Pretty g)
-  => Pretty (a, b, c, d, e, f, g) where
-    ppr (a, b, c, d, e, f, g) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f, ppr g]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f, Pretty g, Pretty h)
-  => Pretty (a, b, c, d, e, f, g, h) where
-    ppr (a, b, c, d, e, f, g, h) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f, ppr g, ppr h]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f, Pretty g, Pretty h, Pretty i)
-  => Pretty (a, b, c, d, e, f, g, h, i) where
-    ppr (a, b, c, d, e, f, g, h, i) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f, ppr g, ppr h, ppr i]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j)
-  => Pretty (a, b, c, d, e, f, g, h, i, j) where
-    ppr (a, b, c, d, e, f, g, h, i, j) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f, ppr g, ppr h, ppr i, ppr j]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
-          Pretty k)
-  => Pretty (a, b, c, d, e, f, g, h, i, j, k) where
-    ppr (a, b, c, d, e, f, g, h, i, j, k) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f, ppr g, ppr h, ppr i, ppr j,
-               ppr k]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
-          Pretty k, Pretty l)
-  => Pretty (a, b, c, d, e, f, g, h, i, j, k, l) where
-    ppr (a, b, c, d, e, f, g, h, i, j, k, l) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f, ppr g, ppr h, ppr i, ppr j,
-               ppr k, ppr l]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
-          Pretty k, Pretty l, Pretty m)
-  => Pretty (a, b, c, d, e, f, g, h, i, j, k, l, m) where
-    ppr (a, b, c, d, e, f, g, h, i, j, k, l, m) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f, ppr g, ppr h, ppr i, ppr j,
-               ppr k, ppr l, ppr m]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
-          Pretty k, Pretty l, Pretty m, Pretty n)
-  => Pretty (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where
-    ppr (a, b, c, d, e, f, g, h, i, j, k, l, m, n) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f, ppr g, ppr h, ppr i, ppr j,
-               ppr k, ppr l, ppr m, ppr n]
-
-instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
-          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
-          Pretty k, Pretty l, Pretty m, Pretty n, Pretty o)
-  => Pretty (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where
-    ppr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) =
-        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
-               ppr f, ppr g, ppr h, ppr i, ppr j,
-               ppr k, ppr l, ppr m, ppr n, ppr o]
diff --git a/Text/PrettyPrint/Mainland/Class.hs b/Text/PrettyPrint/Mainland/Class.hs
new file mode 100644
--- /dev/null
+++ b/Text/PrettyPrint/Mainland/Class.hs
@@ -0,0 +1,279 @@
+{-# LANGUAGE CPP #-}
+
+-- |
+-- Module      :  Text.PrettyPrint.Mainland
+-- Copyright   :  (c) 2006-2011 Harvard University
+--                (c) 2011-2012 Geoffrey Mainland
+--                (c) 2015-2017 Drexel University
+-- License     :  BSD-style
+-- Maintainer  :  mainland@drexel.edu
+--
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- This module is based on /A Prettier Printer/ by Phil Wadler in
+-- /The Fun of Programming/, Jeremy Gibbons and Oege de Moor (eds)
+-- <http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf>
+--
+-- At the time it was originally written I didn't know about Daan Leijen's
+-- pretty printing module based on the same paper. I have since incorporated
+-- many of his improvements. This module is geared towards pretty printing
+-- source code; its main advantages over other libraries are the ability to
+-- automatically track the source locations associated with pretty printed
+-- values and output appropriate #line pragmas and the use of
+-- 'Data.Text.Lazy.Text' for output.
+
+module Text.PrettyPrint.Mainland.Class (
+    -- * The 'Pretty' type class for pretty printing
+    Pretty(..),
+
+    pprint
+  ) where
+
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import Data.Complex (Complex, realPart, imagPart)
+import Data.Int
+import Data.Loc (L(..),
+                 Loc(..),
+                 Pos(..),
+                 posFile)
+import qualified Data.Map as Map
+#if !(MIN_VERSION_base(4,9,0))
+import Data.Monoid (Monoid(..), (<>))
+#endif /* !(MIN_VERSION_base(4,9,0)) */
+#if MIN_VERSION_base(4,9,0) && !(MIN_VERSION_base(4,11,0))
+import Data.Semigroup (Semigroup(..))
+#endif
+import qualified Data.Set as Set
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as L
+import Data.Word
+import Data.Ratio (Ratio(..), denominator, numerator)
+
+import Text.PrettyPrint.Mainland
+
+-- | The 'pprint' function outputs a value of any type that is an instance of
+-- 'Pretty' to the standard output device by calling 'ppr' and adding a newline.
+pprint :: (Pretty a, MonadIO m) => a -> m ()
+pprint = liftIO . putDocLn . ppr
+
+class Pretty a where
+#if __GLASGOW_HASKELL__ >= 708
+    {-# MINIMAL pprPrec | ppr #-}
+#endif
+    ppr     :: a -> Doc
+    pprPrec :: Int -> a -> Doc
+    pprList :: [a] -> Doc
+
+    ppr        = pprPrec 0
+    pprPrec _  = ppr
+    pprList xs = list (map ppr xs)
+
+instance Pretty a => Pretty [a] where
+    ppr = pprList
+
+instance Pretty a => Pretty (Maybe a) where
+    pprPrec _ Nothing  = empty
+    pprPrec p (Just a) = pprPrec p a
+
+instance Pretty Bool where
+    ppr = bool
+
+instance Pretty Char where
+    ppr     = char
+    pprList = string
+
+instance Pretty Int where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Integer where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Float where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Double where
+    pprPrec p x = text (showsPrec p x "")
+
+ratioPrec, ratioPrec1 :: Int
+ratioPrec  = 7  -- Precedence of ':%' constructor
+ratioPrec1 = ratioPrec + 1
+
+instance (Integral a, Pretty a) => Pretty (Ratio a)  where
+    pprPrec p x =
+        parensIf (p > ratioPrec) $
+        pprPrec ratioPrec1 (numerator x) <+> char '%' <+> pprPrec ratioPrec1 (denominator x)
+
+addPrec :: Int
+addPrec  = 6  -- Precedence of '+'
+
+instance (RealFloat a, Pretty a) => Pretty (Complex a)  where
+    pprPrec p x =
+        parensIf (p > addPrec) $
+        pprPrec addPrec (realPart x) <+> text ":+" <+> pprPrec addPrec (imagPart x)
+
+instance Pretty Word8 where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Word16 where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Word32 where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Word64 where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Int8 where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Int16 where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Int32 where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty Int64 where
+    pprPrec p x = text (showsPrec p x "")
+
+instance Pretty T.Text where
+    ppr = strictText
+
+instance Pretty L.Text where
+    ppr = lazyText
+
+instance Pretty Doc where
+    ppr doc = doc
+
+instance Pretty Pos where
+    ppr p@(Pos _ l c _) =
+        text (posFile p) <> colon <> ppr l <> colon <> ppr c
+
+instance Pretty Loc where
+    ppr NoLoc = text "<no location info>"
+
+    ppr (Loc p1@(Pos f1 l1 c1 _) p2@(Pos f2 l2 c2 _))
+        | f1 == f2   = text (posFile p1) <> colon <//> pprLineCol l1 c1 l2 c2
+        | otherwise  = ppr p1 <> text "-" <> ppr p2
+      where
+        pprLineCol :: Int -> Int -> Int -> Int -> Doc
+        pprLineCol l1 c1 l2 c2
+            | l1 == l2 && c1 == c2  =  ppr l1 <//> colon <//> ppr c1
+            | l1 == l2 && c1 /= c2  =  ppr l1 <//> colon <//>
+                                       ppr c1 <> text "-" <> ppr c2
+            | otherwise             =  ppr l1 <//> colon <//> ppr c1
+                                       <> text "-" <>
+                                       ppr l2 <//> colon <//> ppr c2
+
+instance Pretty x => Pretty (L x) where
+    pprPrec p (L _ x) = pprPrec p x
+
+instance (Pretty k, Pretty v) => Pretty (Map.Map k v) where
+    ppr = pprList . Map.toList
+
+instance Pretty a => Pretty (Set.Set a) where
+    ppr = pprList . Set.toList
+
+instance Pretty () where
+    ppr () =
+        tuple []
+
+instance (Pretty a, Pretty b)
+  => Pretty (a, b) where
+    ppr (a, b) =
+        tuple [ppr a, ppr b]
+
+instance (Pretty a, Pretty b, Pretty c)
+  => Pretty (a, b, c) where
+    ppr (a, b, c) =
+        tuple [ppr a, ppr b, ppr c]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d)
+  => Pretty (a, b, c, d) where
+    ppr (a, b, c, d) =
+        tuple [ppr a, ppr b, ppr c, ppr d]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e)
+  => Pretty (a, b, c, d, e) where
+    ppr (a, b, c, d, e) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f)
+  => Pretty (a, b, c, d, e, f) where
+    ppr (a, b, c, d, e, f) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f, Pretty g)
+  => Pretty (a, b, c, d, e, f, g) where
+    ppr (a, b, c, d, e, f, g) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f, ppr g]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f, Pretty g, Pretty h)
+  => Pretty (a, b, c, d, e, f, g, h) where
+    ppr (a, b, c, d, e, f, g, h) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f, ppr g, ppr h]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f, Pretty g, Pretty h, Pretty i)
+  => Pretty (a, b, c, d, e, f, g, h, i) where
+    ppr (a, b, c, d, e, f, g, h, i) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f, ppr g, ppr h, ppr i]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j)
+  => Pretty (a, b, c, d, e, f, g, h, i, j) where
+    ppr (a, b, c, d, e, f, g, h, i, j) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f, ppr g, ppr h, ppr i, ppr j]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
+          Pretty k)
+  => Pretty (a, b, c, d, e, f, g, h, i, j, k) where
+    ppr (a, b, c, d, e, f, g, h, i, j, k) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f, ppr g, ppr h, ppr i, ppr j,
+               ppr k]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
+          Pretty k, Pretty l)
+  => Pretty (a, b, c, d, e, f, g, h, i, j, k, l) where
+    ppr (a, b, c, d, e, f, g, h, i, j, k, l) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f, ppr g, ppr h, ppr i, ppr j,
+               ppr k, ppr l]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
+          Pretty k, Pretty l, Pretty m)
+  => Pretty (a, b, c, d, e, f, g, h, i, j, k, l, m) where
+    ppr (a, b, c, d, e, f, g, h, i, j, k, l, m) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f, ppr g, ppr h, ppr i, ppr j,
+               ppr k, ppr l, ppr m]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
+          Pretty k, Pretty l, Pretty m, Pretty n)
+  => Pretty (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where
+    ppr (a, b, c, d, e, f, g, h, i, j, k, l, m, n) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f, ppr g, ppr h, ppr i, ppr j,
+               ppr k, ppr l, ppr m, ppr n]
+
+instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e,
+          Pretty f, Pretty g, Pretty h, Pretty i, Pretty j,
+          Pretty k, Pretty l, Pretty m, Pretty n, Pretty o)
+  => Pretty (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where
+    ppr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) =
+        tuple [ppr a, ppr b, ppr c, ppr d, ppr e,
+               ppr f, ppr g, ppr h, ppr i, ppr j,
+               ppr k, ppr l, ppr m, ppr n, ppr o]
diff --git a/mainland-pretty.cabal b/mainland-pretty.cabal
--- a/mainland-pretty.cabal
+++ b/mainland-pretty.cabal
@@ -1,35 +1,52 @@
 name:           mainland-pretty
-version:        0.4.1.4
-cabal-version:  >= 1.6
+version:        0.7.1.1
+cabal-version:  >= 1.10
 license:        BSD3
 license-file:   LICENSE
 copyright:      (c) 2006-2011 Harvard University
                 (c) 2011-2012 Geoffrey Mainland
-                (c) 2015-2016 Drexel University
+                (c) 2015-2024 Drexel University
 author:         Geoffrey Mainland <mainland@drexel.edu>
 maintainer:     Geoffrey Mainland <mainland@drexel.edu>
 stability:      alpha
-homepage:       http://www.cs.drexel.edu/~mainland/
+homepage:       https://github.com/mainland/mainland-pretty
+bug-reports:    https://github.com/mainland/mainland-pretty/issues
 category:       Text
 synopsis:       Pretty printing designed for printing source code.
 description:    Pretty printing designed for printing source code based on
-		Wadler's paper /A Prettier Printer/. The main advantage of this
-		library is its ability to automatically track the source
-		locations associated with pretty printed values and output
-		appropriate #line pragmas and its ability to produce output
+                Wadler's paper /A Prettier Printer/. The main advantage of this
+                library is its ability to automatically track the source
+                locations associated with pretty printed values and output
+                appropriate #line pragmas and its ability to produce output
                 in the form of lazy text using a builder.
+tested-with:    GHC==8.0.2,
+                GHC==8.2.2,
+                GHC==8.4.3,
+                GHC==8.6.5,
+                GHC==8.8.4,
+                GHC==8.10.7,
+                GHC==9.0.2,
+                GHC==9.2.2,
+                GHC==9.4.8,
+                GHC==9.6.4,
+                GHC==9.8.2,
+                GHC==9.10.1
 
 build-type:     Simple
 
 library
+  default-language: Haskell2010
+
   exposed-modules:
     Text.PrettyPrint.Mainland
+    Text.PrettyPrint.Mainland.Class
 
   build-depends:
-    base       >= 4    && < 5,
-    containers >= 0.2  && < 0.6,
-    srcloc     >= 0.2  && < 0.6,
-    text       >  0.11 && < 1.3
+    base         >= 4.5  && < 5,
+    containers   >= 0.2  && < 0.8,
+    srcloc       >= 0.2  && < 0.7,
+    text         >  0.11 && < 2.2,
+    transformers >  0.3  && < 0.7
 
 source-repository head
   type:     git
