diff --git a/CHANGES.markdown b/CHANGES.markdown
--- a/CHANGES.markdown
+++ b/CHANGES.markdown
@@ -1,3 +1,6 @@
+# 0.3.1.1
+ * Add support for GHC 9.10
+
 # 0.3.1
  * Add support for GHC 9.8
  * Drop support for GHC 8.2
diff --git a/cabal.project b/cabal.project
--- a/cabal.project
+++ b/cabal.project
@@ -3,7 +3,12 @@
 
 write-ghc-environment-files: always
 
+tests: true
 
+source-repository-package
+  type: git
+  location: https://github.com/haskell-unordered-containers/unordered-containers.git
+  tag: d52a0fd10bfa701cbbc9d7ac06bd7eb7664b3972
+
 allow-newer:
-    *:base
-  , *:ghc-bignum
+  unordered-containers:template-haskell
diff --git a/doctest-parallel.cabal b/doctest-parallel.cabal
--- a/doctest-parallel.cabal
+++ b/doctest-parallel.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.0
 
 name:           doctest-parallel
-version:        0.3.1
+version:        0.3.1.1
 synopsis:       Test interactive Haskell examples
 description:    The doctest program checks examples in source code comments.  It is modeled
                 after doctest for Python (<https://docs.python.org/3/library/doctest.html>).
@@ -26,6 +26,7 @@
   , GHC == 9.4.7
   , GHC == 9.6.3
   , GHC == 9.8.1
+  , GHC == 9.10.1
 
 extra-source-files:
     example/example.cabal
@@ -102,7 +103,7 @@
     , directory
     , exceptions
     , filepath
-    , ghc >=8.2 && <9.9
+    , ghc >=8.2 && <9.11
     , ghc-paths >=0.1.0.9
     , process
     , random >= 1.2
diff --git a/src/Test/DocTest/Internal/Extract.hs b/src/Test/DocTest/Internal/Extract.hs
--- a/src/Test/DocTest/Internal/Extract.hs
+++ b/src/Test/DocTest/Internal/Extract.hs
@@ -329,8 +329,10 @@
 #else
 #if __GLASGOW_HASKELL__ < 904
   HsPar _ (L l e) -> extractLit (locA l) e
-#else
+#elif __GLASGOW_HASKELL__ < 909
   HsPar _ _ (L l e) _ -> extractLit (locA l) e
+#else
+  HsPar _ (L l e) -> extractLit (locA l) e
 #endif
 #if __GLASGOW_HASKELL__ < 807
   ExprWithTySig _ (L l e) -> extractLit l e
diff --git a/src/Test/DocTest/Internal/Interpreter.hs b/src/Test/DocTest/Internal/Interpreter.hs
--- a/src/Test/DocTest/Internal/Interpreter.hs
+++ b/src/Test/DocTest/Internal/Interpreter.hs
@@ -1,5 +1,9 @@
 {-# LANGUAGE CPP #-}
 
+#if __GLASGOW_HASKELL__ <= 906
+{-# LANGUAGE LambdaCase #-}
+#endif
+
 module Test.DocTest.Internal.Interpreter (
   Interpreter
 , safeEval
@@ -18,6 +22,11 @@
 import Control.Monad
 import Control.Exception hiding (handle)
 import Data.Char
+#if __GLASGOW_HASKELL__ > 906
+import Data.List (unsnoc)
+#else
+import Data.Bifunctor (first)
+#endif
 import GHC.Paths (ghc)
 
 import Test.DocTest.Internal.GhciWrapper
@@ -27,6 +36,23 @@
 -- >>> import Test.DocTest.Internal.GhciWrapper (eval)
 -- >>> import Test.DocTest.Internal.Logging (noLogger)
 
+#if __GLASGOW_HASKELL__ <= 906
+-- | If the list is empty returns 'Nothing', otherwise returns the 'init' and the 'last'.
+--
+-- > unsnoc "test" == Just ("tes",'t')
+-- > unsnoc ""     == Nothing
+-- > \xs -> unsnoc xs == if null xs then Nothing else Just (init xs, last xs)
+unsnoc :: [a] -> Maybe ([a], a)
+unsnoc = \case
+  []   -> Nothing
+  x:xs -> Just $ unsnoc1 x xs
+  where
+    unsnoc1 :: a -> [a] -> ([a], a)
+    unsnoc1 x = \case
+      []   -> ([], x)
+      y:ys -> first (x:) $ unsnoc1 y ys
+#endif
+
 haveInterpreterKey :: String
 haveInterpreterKey = "Have interpreter"
 
@@ -76,13 +102,13 @@
 
 filterExpression :: String -> Either String String
 filterExpression e =
-  case lines e of
+  case map strip (lines e) of
     [] -> Right e
-    l  -> if firstLine == ":{" && lastLine /= ":}" then fail_ else Right e
-      where
-        firstLine = strip $ head l
-        lastLine  = strip $ last l
-        fail_ = Left "unterminated multiline command"
+    (firstLine:ls) ->
+      let lastLine = maybe firstLine snd (unsnoc ls) in
+      if firstLine == ":{" && lastLine /= ":}" then fail_ else Right e
   where
+    fail_ = Left "unterminated multiline command"
+
     strip :: String -> String
     strip = dropWhile isSpace . reverse . dropWhile isSpace . reverse
diff --git a/src/Test/DocTest/Internal/Runner/Example.hs b/src/Test/DocTest/Internal/Runner/Example.hs
--- a/src/Test/DocTest/Internal/Runner/Example.hs
+++ b/src/Test/DocTest/Internal/Runner/Example.hs
@@ -27,7 +27,7 @@
     -- use show to escape special characters in output lines if any output line
     -- contains any unsafe character
     escapeOutput
-      | any (not . isSafe) $ concat (expectedAsString ++ actual_) = init . tail . show . stripEnd
+      | any (not . isSafe) $ concat (expectedAsString ++ actual_) = init . drop 1 . show . stripEnd
       | otherwise = id
 
     actual :: [String]
diff --git a/test/PropertySpec.hs b/test/PropertySpec.hs
--- a/test/PropertySpec.hs
+++ b/test/PropertySpec.hs
@@ -46,7 +46,7 @@
       runProperty repl "x == 23" `shouldReturn` Failure "*** Failed! Falsified (after 1 test):\n0"
 
     it "reports the values for which a property that takes multiple arguments fails" $ withInterpreter noLogger [] $ \repl -> do
-      let vals x = case x of (Failure r) -> tail (lines r); _ -> error "Property did not fail!"
+      let vals x = case x of (Failure r) -> drop 1 (lines r); _ -> error "Property did not fail!"
       vals `fmap` runProperty repl "x == True && y == 10 && z == \"foo\"" `shouldReturn` ["False", "0", show ("" :: String)]
 
     it "defaults ambiguous type variables to Integer" $ withInterpreter noLogger [] $ \repl -> do
