diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # Revision history for aeson-gadt-th
 
+## 0.2.5.3 - 2025-01-14
+
+* Loosen version bounds
+* Support GHC 9.10
+
 ## 0.2.5.2 - 2024-05-28
 
 * Loosen version bounds
diff --git a/README.lhs b/README.lhs
--- a/README.lhs
+++ b/README.lhs
@@ -16,7 +16,7 @@
 > {-# LANGUAGE UndecidableInstances #-}
 > {-# LANGUAGE MultiParamTypeClasses #-}
 > {-# OPTIONS_GHC -ddump-splices #-}
->
+
 > import Data.Aeson
 > import Data.Aeson.GADT.TH
 > import Data.Dependent.Map (DMap)
@@ -24,48 +24,49 @@
 > import Data.Functor.Identity
 > import Data.GADT.Compare
 > import Data.GADT.Show.TH
+> import Data.Kind (Type)
 > import Data.Some (Some(..))
->
-> data A :: * -> * where
+
+> data A :: Type -> Type where
 >   A_a :: A a
 >   A_b :: Int -> A ()
->
+
 > deriveJSONGADT ''A
 > deriveGShow ''A
->
-> data B c :: * -> * where
+
+> data B c :: Type -> Type where
 >   B_a :: c -> A a -> B c a
 >   B_x :: B c a
->
+
 > deriveJSONGADT ''B
->
-> data C t :: * -> * where
+
+> data C t :: Type -> Type where
 >   C_t :: t -> C t t
->
+
 > deriveJSONGADT ''C
->
-> data D t x :: * -> * where
+
+> data D t x :: Type -> Type where
 >   D_t :: t -> D t x t
 >   D_x :: x -> D t x x
 >   D_i :: Int -> D t x Int
->
+
 > deriveJSONGADT ''D
->
+
 > data Auth token a where
 >   Auth_Login :: String -> String -> Auth token (Either String token)
->
+
 > deriveJSONGADT ''Auth
->
+
 > -- Some real-world-ish examples.
->
+
 > -- | Edit operations for `LabelledGraph`
-> data LabelledGraphEdit v vm em :: * -> * where
+> data LabelledGraphEdit v vm em :: Type -> Type where
 >   LabelledGraphEdit_ClearAll :: LabelledGraphEdit v vm em ()
 >   LabelledGraphEdit_AddVertex :: vm -> LabelledGraphEdit v vm em v
 >   LabelledGraphEdit_AddEdge :: v -> v -> em -> LabelledGraphEdit v vm em ()
 >   LabelledGraphEdit_SetVertexProperties :: v -> vm -> LabelledGraphEdit v vm em ()
 >   LabelledGraphEdit_SetEdgeProperties :: v -> v -> em -> LabelledGraphEdit v vm em ()
->
+
 > -- | PropertyGraphEdit operatios for `PropertyGraph`
 > data PropertyGraphEdit v vp ep r where
 >   PropertyGraphEdit_ClearAll :: PropertyGraphEdit v vp ep ()
@@ -73,17 +74,17 @@
 >   PropertyGraphEdit_AddEdge :: v -> v -> (DMap ep Identity) -> PropertyGraphEdit v vp ep ()
 >   PropertyGraphEdit_SetVertexProperty :: GCompare vp => v -> DSum vp Identity -> PropertyGraphEdit v vp ep ()
 >   PropertyGraphEdit_SetEdgeProperty :: GCompare ep => v -> v -> DSum ep Identity -> PropertyGraphEdit v vp ep ()
->
+
 > -- | View operations for `LabelledGraph`
-> data LabelledGraphView v vm em :: * -> * where
+> data LabelledGraphView v vm em :: Type -> Type where
 >   LabelledGraphView_All :: LabelledGraphView v vm em ()
 >   LabelledGraphView_GetVertexProperties :: v -> LabelledGraphView v vm em vm
 >   LabelledGraphView_GetEdgeProperties :: v -> v -> LabelledGraphView v vm em em
->
+
 > deriveJSONGADT ''LabelledGraphEdit
 > deriveJSONGADT ''PropertyGraphEdit
 > deriveJSONGADT ''LabelledGraphView
->
+
 > main :: IO ()
 > main = do
 >   putStrLn $ unlines
@@ -92,14 +93,14 @@
 >     , "Decoding of encoded A_a:"
 >     , show (decode $ encode A_a :: Maybe (Some A))
 >     ]
->
+
 >   putStrLn $ unlines
 >     [ "Encoding of (A_b 1):"
 >     , show $ encode (A_b 1)
 >     , "Decoding of encoded (A_b 1):"
 >     , show (decode $ encode (A_b 1) :: Maybe (Some A))
 >     ]
->
+
 >   putStrLn $ unlines
 >     [ "Encoding of (B_a 'a' (A_b 1)):"
 >     , show $ encode (B_a 'a' (A_b 1))
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
 > {-# LANGUAGE UndecidableInstances #-}
 > {-# LANGUAGE MultiParamTypeClasses #-}
 > {-# OPTIONS_GHC -ddump-splices #-}
->
+
 > import Data.Aeson
 > import Data.Aeson.GADT.TH
 > import Data.Dependent.Map (DMap)
@@ -24,48 +24,49 @@
 > import Data.Functor.Identity
 > import Data.GADT.Compare
 > import Data.GADT.Show.TH
+> import Data.Kind (Type)
 > import Data.Some (Some(..))
->
-> data A :: * -> * where
+
+> data A :: Type -> Type where
 >   A_a :: A a
 >   A_b :: Int -> A ()
->
+
 > deriveJSONGADT ''A
 > deriveGShow ''A
->
-> data B c :: * -> * where
+
+> data B c :: Type -> Type where
 >   B_a :: c -> A a -> B c a
 >   B_x :: B c a
->
+
 > deriveJSONGADT ''B
->
-> data C t :: * -> * where
+
+> data C t :: Type -> Type where
 >   C_t :: t -> C t t
->
+
 > deriveJSONGADT ''C
->
-> data D t x :: * -> * where
+
+> data D t x :: Type -> Type where
 >   D_t :: t -> D t x t
 >   D_x :: x -> D t x x
 >   D_i :: Int -> D t x Int
->
+
 > deriveJSONGADT ''D
->
+
 > data Auth token a where
 >   Auth_Login :: String -> String -> Auth token (Either String token)
->
+
 > deriveJSONGADT ''Auth
->
+
 > -- Some real-world-ish examples.
->
+
 > -- | Edit operations for `LabelledGraph`
-> data LabelledGraphEdit v vm em :: * -> * where
+> data LabelledGraphEdit v vm em :: Type -> Type where
 >   LabelledGraphEdit_ClearAll :: LabelledGraphEdit v vm em ()
 >   LabelledGraphEdit_AddVertex :: vm -> LabelledGraphEdit v vm em v
 >   LabelledGraphEdit_AddEdge :: v -> v -> em -> LabelledGraphEdit v vm em ()
 >   LabelledGraphEdit_SetVertexProperties :: v -> vm -> LabelledGraphEdit v vm em ()
 >   LabelledGraphEdit_SetEdgeProperties :: v -> v -> em -> LabelledGraphEdit v vm em ()
->
+
 > -- | PropertyGraphEdit operatios for `PropertyGraph`
 > data PropertyGraphEdit v vp ep r where
 >   PropertyGraphEdit_ClearAll :: PropertyGraphEdit v vp ep ()
@@ -73,17 +74,17 @@
 >   PropertyGraphEdit_AddEdge :: v -> v -> (DMap ep Identity) -> PropertyGraphEdit v vp ep ()
 >   PropertyGraphEdit_SetVertexProperty :: GCompare vp => v -> DSum vp Identity -> PropertyGraphEdit v vp ep ()
 >   PropertyGraphEdit_SetEdgeProperty :: GCompare ep => v -> v -> DSum ep Identity -> PropertyGraphEdit v vp ep ()
->
+
 > -- | View operations for `LabelledGraph`
-> data LabelledGraphView v vm em :: * -> * where
+> data LabelledGraphView v vm em :: Type -> Type where
 >   LabelledGraphView_All :: LabelledGraphView v vm em ()
 >   LabelledGraphView_GetVertexProperties :: v -> LabelledGraphView v vm em vm
 >   LabelledGraphView_GetEdgeProperties :: v -> v -> LabelledGraphView v vm em em
->
+
 > deriveJSONGADT ''LabelledGraphEdit
 > deriveJSONGADT ''PropertyGraphEdit
 > deriveJSONGADT ''LabelledGraphView
->
+
 > main :: IO ()
 > main = do
 >   putStrLn $ unlines
@@ -92,14 +93,14 @@
 >     , "Decoding of encoded A_a:"
 >     , show (decode $ encode A_a :: Maybe (Some A))
 >     ]
->
+
 >   putStrLn $ unlines
 >     [ "Encoding of (A_b 1):"
 >     , show $ encode (A_b 1)
 >     , "Decoding of encoded (A_b 1):"
 >     , show (decode $ encode (A_b 1) :: Maybe (Some A))
 >     ]
->
+
 >   putStrLn $ unlines
 >     [ "Encoding of (B_a 'a' (A_b 1)):"
 >     , show $ encode (B_a 'a' (A_b 1))
diff --git a/aeson-gadt-th.cabal b/aeson-gadt-th.cabal
--- a/aeson-gadt-th.cabal
+++ b/aeson-gadt-th.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.24
 name: aeson-gadt-th
-version: 0.2.5.2
+version: 0.2.5.3
 synopsis: Derivation of Aeson instances for GADTs
 category: JSON
 description: Template Haskell for generating ToJSON and FromJSON instances for GADTs. See <https://github.com/obsidiansystems/aeson-gadt-th/blob/master/README.md README.md> for examples.
@@ -20,12 +20,12 @@
 
 library
   exposed-modules: Data.Aeson.GADT.TH
-  build-depends: base >= 4.8 && < 4.20
+  build-depends: base >= 4.9 && < 4.21
                , aeson >= 1.3 && < 2.3
-               , containers >= 0.5 && < 0.7
+               , containers >= 0.5 && < 0.8
                , dependent-sum >= 0.4 && < 0.8
                , transformers >= 0.5 && < 0.7
-               , template-haskell >= 2.11.0 && < 2.22
+               , template-haskell >= 2.11.0 && < 2.23
                , th-abstraction >= 0.4 && < 0.8
   if impl(ghc < 8.2)
     build-depends: dependent-sum < 0.6.2.2
diff --git a/src/Data/Aeson/GADT/TH.hs b/src/Data/Aeson/GADT/TH.hs
--- a/src/Data/Aeson/GADT/TH.hs
+++ b/src/Data/Aeson/GADT/TH.hs
@@ -37,7 +37,8 @@
 import Control.Monad.Trans.Class (lift)
 import Control.Monad.Trans.Writer (WriterT, runWriterT, tell)
 import Data.Aeson (FromJSON(..), ToJSON(..))
-import Data.List (group, intercalate, partition, sort)
+import Data.List (intercalate, partition, sort)
+import qualified Data.List.NonEmpty as NonEmpty
 import Data.Map (Map)
 import qualified Data.Map as Map
 import Data.Set (Set)
@@ -117,7 +118,7 @@
   topVars <- makeTopVars n
   let n' = foldl (\c v -> AppT c (VarT v)) (ConT n) topVars
   (matches, constraints') <- runWriterT (mapM (fmap pure . conMatchesToJSON opts topVars) cons)
-  let constraints = map head . group . sort $ constraints' -- This 'head' is safe because 'group' returns a list of non-empty lists
+  let constraints = map NonEmpty.head . NonEmpty.group . sort $ constraints'
   impl <- funD 'toJSON
     [ clause [] (normalB $ lamCaseE matches) []
     ]
@@ -149,7 +150,7 @@
   topVars <- makeTopVars n
   let n' = foldl (\c v -> AppT c (VarT v)) (ConT n) $ init topVars
   (matches, constraints') <- runWriterT $ mapM (conMatchesParseJSON opts topVars [|_v'|]) cons
-  let constraints = map head . group . sort $ constraints' -- This 'head' is safe because 'group' returns a list of non-empty lists
+  let constraints = map NonEmpty.head . NonEmpty.group . sort $ constraints'
   v <- newName "v"
   parser <- funD 'parseJSON
     [ clause [varP v] (normalB [e|
