diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+* 0.2.3.3: 31 March 2026
+
+- Fix [#17](https://github.com/diagrams/dual-tree/issues/17): Restore
+  compatibility with GHC <= 9.6.
+
 * 0.2.3.2: 28 March 2026
 
 - Fix [#16](https://github.com/diagrams/dual-tree/issues/16): Contrary
diff --git a/dual-tree.cabal b/dual-tree.cabal
--- a/dual-tree.cabal
+++ b/dual-tree.cabal
@@ -1,5 +1,5 @@
 name:                dual-tree
-version:             0.2.3.2
+version:             0.2.3.3
 synopsis:            Rose trees with cached and accumulating monoidal annotations
 description:         Rose (n-ary) trees with both upwards- (/i.e./
                      cached) and downwards-traveling (/i.e./
diff --git a/src/Data/Tree/DUAL/Internal.hs b/src/Data/Tree/DUAL/Internal.hs
--- a/src/Data/Tree/DUAL/Internal.hs
+++ b/src/Data/Tree/DUAL/Internal.hs
@@ -58,7 +58,6 @@
 ) where
 
 import Control.Arrow ((***))
-import qualified Data.Functor as F
 import Data.List.NonEmpty (NonEmpty (..))
 import qualified Data.List.NonEmpty as NEL
 import Data.Maybe (catMaybes, fromMaybe)
@@ -119,7 +118,7 @@
 --   into nested calls to '(<>)'.
 instance (Action d u, Semigroup u) => Semigroup (DUALTreeU d u a l) where
   DUALTreeU t1 <> DUALTreeU t2 = DUALTreeU (t1 <> t2)
-  sconcat = DUALTreeU . (sconcat *** sconcat) . F.unzip . fmap unDUALTreeU
+  sconcat = DUALTreeU . (sconcat *** sconcat) . NEL.unzip . fmap unDUALTreeU
 
 overDUALTreeU ::
   ((u, DUALTreeNE d u a l) -> (u', DUALTreeNE d u' a l)) ->
