diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,18 @@
+## 0.4.1
+
+- Fix build with semialign-1.3
+
+## 0.4
+
+- Drop `ansi-wl-pprint` dependency, use `prettyprinter` directly.
+  The naming of functions still uses `ansiWl*` naming scheme, to avoid breaking
+  too many things. Technically, these functions are still compatible with
+  `ansi-wl-pprint` versions which use `prettyprinter` underneath.
+
+## 0.3.4
+
+- Remove 'Eq a' requirement from 'ediffGolden'. The constraint wasn't used, as we only compare 'Expr' representations.
+
 ## 0.3.3
 
 - Change 'ediffGolden' so that parse errors in expected file don't cause the hard failure.
diff --git a/src/Data/TreeDiff/Golden.hs b/src/Data/TreeDiff/Golden.hs
--- a/src/Data/TreeDiff/Golden.hs
+++ b/src/Data/TreeDiff/Golden.hs
@@ -10,10 +10,12 @@
 import Text.Parsec         (eof, parse)
 import Text.Parsec.Text ()
 
-import qualified Data.ByteString              as BS
-import qualified Data.Text                    as T
-import qualified Data.Text.Encoding           as TE
-import qualified Text.PrettyPrint.ANSI.Leijen as WL
+import qualified Data.ByteString               as BS
+import qualified Data.Text                     as T
+import qualified Data.Text.Encoding            as TE
+import qualified Data.Text.Lazy                as TL
+import qualified Prettyprinter                 as PP
+import qualified Prettyprinter.Render.Terminal as PP.A
 
 -- | Make a golden tests.
 --
@@ -37,7 +39,7 @@
 -- for a proper example.
 --
 ediffGolden
-    :: (Eq a, ToExpr a)
+    :: ToExpr a
     => (testName -> IO Expr -> IO Expr -> (Expr -> Expr -> IO (Maybe String)) -> (Expr -> IO ()) -> testTree) -- ^ 'goldenTest'
     -> testName  -- ^ test name
     -> FilePath  -- ^ path to "golden file"
@@ -51,7 +53,7 @@
 -- @since 0.3.2
 --
 ediffGolden1
-    :: forall a arg testName testTree. (Eq a, ToExpr a)
+    :: forall a arg testName testTree. ToExpr a
     => (testName -> IO Expr -> (arg -> IO Expr) -> (Expr -> Expr -> IO (Maybe String)) -> (Expr -> IO ()) -> testTree) -- ^ 'goldenTest'
     -> testName  -- ^ test name
     -> FilePath  -- ^ path to "golden file"
@@ -74,7 +76,9 @@
         | a == b    = return Nothing
         | otherwise = return $ Just $
             setSGRCode [Reset] ++ showWL (ansiWlEditExprCompact $ ediff a b)
-    wrt expr = BS.writeFile fp $ TE.encodeUtf8 $ T.pack $ showWL (WL.plain (ansiWlExpr expr)) ++ "\n"
+    wrt expr = BS.writeFile fp $ TE.encodeUtf8 $ T.pack $ showWL (PP.unAnnotate (ansiWlExpr expr)) ++ "\n"
 
-showWL :: WL.Doc -> String
-showWL doc = WL.displayS (WL.renderSmart 0.4 80 doc) ""
+showWL :: PP.Doc PP.A.AnsiStyle -> String
+showWL doc
+    = TL.unpack $ PP.A.renderLazy
+    $ PP.layoutSmart PP.LayoutOptions { PP.layoutPageWidth = PP.AvailablePerLine 80 0.4  } doc
diff --git a/src/Data/TreeDiff/OMap.hs b/src/Data/TreeDiff/OMap.hs
--- a/src/Data/TreeDiff/OMap.hs
+++ b/src/Data/TreeDiff/OMap.hs
@@ -14,10 +14,12 @@
     elems,
 ) where
 
+import Prelude hiding (zipWith)
+
 import Control.DeepSeq (NFData (..))
 import Data.List       (sortBy)
 import Data.Ord        (comparing)
-import Data.Semialign  (Semialign (..))
+import Data.Semialign  (Semialign(..), Unzip (..), Zip (..), unzipDefault)
 import Data.These      (These (..))
 
 import qualified Data.Map.Strict as Map
@@ -148,3 +150,11 @@
         g (This (Val i x))            = Val i (f (This x))
         g (That (Val j y))            = Val j (f (That y))
         g (These (Val i x) (Val j y)) = Val (min i j) (f (These x y))
+
+instance Ord k => Zip (OMap k) where
+    zipWith f (OMap xs) (OMap ys) = OMap (zipWith g xs ys) where
+        g (Val i x) (Val j y) = Val (min i j) (f x y)
+
+-- Ord k is required for semialign <1.4
+instance Ord k => Unzip (OMap k) where
+    unzip = unzipDefault
diff --git a/src/Data/TreeDiff/Pretty.hs b/src/Data/TreeDiff/Pretty.hs
--- a/src/Data/TreeDiff/Pretty.hs
+++ b/src/Data/TreeDiff/Pretty.hs
@@ -10,7 +10,7 @@
     prettyExpr,
     prettyEditExpr,
     prettyEditExprCompact,
-    -- * ansi-wl-pprint
+    -- * prettyprinter
     ansiWlPretty,
     ansiWlExpr,
     ansiWlEditExpr,
@@ -30,9 +30,10 @@
 import Numeric            (showHex)
 import Text.Read          (readMaybe)
 
-import qualified Data.TreeDiff.OMap           as OMap
-import qualified Text.PrettyPrint             as HJ
-import qualified Text.PrettyPrint.ANSI.Leijen as WL
+import qualified Data.TreeDiff.OMap            as OMap
+import qualified Prettyprinter                 as PP
+import qualified Prettyprinter.Render.Terminal as PP.A
+import qualified Text.PrettyPrint              as HJ
 
 -- $setup
 -- >>> import qualified Data.TreeDiff.OMap as OMap
@@ -215,56 +216,73 @@
 -- ansi-wl-pprint
 -------------------------------------------------------------------------------
 
--- | 'Pretty' via @ansi-wl-pprint@ library (with colors).
-ansiWlPretty :: Pretty WL.Doc
+-- | 'Pretty' via @prettyprinter@ library (with colors).
+ansiWlPretty :: Pretty (PP.Doc PP.A.AnsiStyle)
 ansiWlPretty = Pretty
-    { ppCon    = WL.text
-    , ppRec    = \c xs -> ansiGroup (c WL.<+> WL.lbrace) WL.rbrace
-               $ map (\(fn, d) -> WL.text fn WL.<+> WL.equals WL.</> d) xs
-    , ppLst    = ansiGroup WL.lbracket WL.rbracket
-    , ppCpy    = WL.dullwhite
-    , ppIns    = \d -> WL.green $ WL.plain $ WL.char '+' WL.<> d
-    , ppDel    = \d -> WL.red   $ WL.plain $ WL.char '-' WL.<> d
-    , ppApp    = \f xs -> WL.group $ WL.nest 2 $ f WL.<$> WL.vsep xs
-    , ppEdits  = WL.sep
-    , ppEllip  = WL.text "..."
-    , ppParens = WL.parens
+    { ppCon    = ppText
+    , ppRec    = \c xs -> ansiGroup (c PP.<+> PP.lbrace) PP.rbrace
+               $ map (\(fn, d) -> ppText fn PP.<+> (PP.equals PP.<> PP.softline PP.<> d)) xs
+    , ppLst    = ansiGroup PP.lbracket PP.rbracket
+    , ppCpy    = ppDullWhite
+    , ppIns    = \d -> ppGreen $ PP.unAnnotate $ ppChar '+' PP.<> d
+    , ppDel    = \d -> ppRed   $ PP.unAnnotate $ ppChar '-' PP.<> d
+    , ppApp    = \f xs -> PP.group $ PP.nest 2 $ f PP.<> PP.line PP.<> PP.vsep xs
+    , ppEdits  = PP.sep
+    , ppEllip  = ppText "..."
+    , ppParens = PP.parens
     }
 
-ansiGroup :: WL.Doc -> WL.Doc -> [WL.Doc] -> WL.Doc
-ansiGroup l r xs = WL.group $ WL.nest 2 (l WL.<$$> WL.vsep (WL.punctuate WL.comma xs) WL.<> r)
+ansiGroup :: PP.Doc PP.A.AnsiStyle -> PP.Doc PP.A.AnsiStyle -> [PP.Doc PP.A.AnsiStyle] -> PP.Doc PP.A.AnsiStyle
+ansiGroup l r xs = PP.group $ PP.nest 2 (l PP.<> ppLinebreak PP.<> PP.vsep (PP.punctuate PP.comma xs) PP.<> r)
 
 -- | Pretty print 'Expr' using @ansi-wl-pprint@.
-ansiWlExpr :: Expr -> WL.Doc
+ansiWlExpr :: Expr -> PP.Doc PP.A.AnsiStyle
 ansiWlExpr = ppExpr ansiWlPretty
 
 -- | Pretty print @'Edit' 'EditExpr'@ using @ansi-wl-pprint@.
-ansiWlEditExpr :: Edit EditExpr -> WL.Doc
+ansiWlEditExpr :: Edit EditExpr -> PP.Doc PP.A.AnsiStyle
 ansiWlEditExpr = ppEditExpr ansiWlPretty
 
 -- | Compact 'ansiWlEditExpr'
-ansiWlEditExprCompact :: Edit EditExpr -> WL.Doc
+ansiWlEditExprCompact :: Edit EditExpr -> PP.Doc PP.A.AnsiStyle
 ansiWlEditExprCompact = ppEditExprCompact ansiWlPretty
 
+ppChar :: Char -> PP.Doc PP.A.AnsiStyle
+ppChar = PP.pretty
+
+ppText :: String -> PP.Doc PP.A.AnsiStyle
+ppText = PP.pretty
+
+ppLinebreak :: PP.Doc a
+ppLinebreak = PP.flatAlt PP.line mempty
+
+ppWhite, ppDullWhite, ppRed, ppGreen, ppOnDullRed, ppOnDullGreen :: PP.Doc PP.A.AnsiStyle -> PP.Doc PP.A.AnsiStyle
+ppWhite         = PP.annotate (PP.A.color       PP.A.White)
+ppDullWhite     = PP.annotate (PP.A.colorDull   PP.A.White)
+ppRed           = PP.annotate (PP.A.color       PP.A.Red)
+ppGreen         = PP.annotate (PP.A.color       PP.A.Green)
+ppOnDullRed     = PP.annotate (PP.A.bgColorDull PP.A.Red)
+ppOnDullGreen   = PP.annotate (PP.A.bgColorDull PP.A.Green)
+
 -------------------------------------------------------------------------------
 -- Background
 -------------------------------------------------------------------------------
 
 -- | Like 'ansiWlPretty' but color the background.
-ansiWlBgPretty :: Pretty WL.Doc
+ansiWlBgPretty :: Pretty (PP.Doc PP.A.AnsiStyle)
 ansiWlBgPretty = ansiWlPretty
-    { ppIns    = \d -> WL.ondullgreen $ WL.white $ WL.plain $ WL.char '+' WL.<> d
-    , ppDel    = \d -> WL.ondullred   $ WL.white $ WL.plain $ WL.char '-' WL.<> d
+    { ppIns    = \d -> ppOnDullGreen $ ppWhite $ PP.unAnnotate $ ppChar '+' PP.<> d
+    , ppDel    = \d -> ppOnDullRed   $ ppWhite $ PP.unAnnotate $ ppChar '-' PP.<> d
     }
 
 -- | Pretty print 'Expr' using @ansi-wl-pprint@.
-ansiWlBgExpr :: Expr -> WL.Doc
+ansiWlBgExpr :: Expr -> PP.Doc PP.A.AnsiStyle
 ansiWlBgExpr = ppExpr ansiWlBgPretty
 
 -- | Pretty print @'Edit' 'EditExpr'@ using @ansi-wl-pprint@.
-ansiWlBgEditExpr :: Edit EditExpr -> WL.Doc
+ansiWlBgEditExpr :: Edit EditExpr -> PP.Doc PP.A.AnsiStyle
 ansiWlBgEditExpr = ppEditExpr ansiWlBgPretty
 
 -- | Compact 'ansiWlBgEditExpr'.
-ansiWlBgEditExprCompact :: Edit EditExpr -> WL.Doc
+ansiWlBgEditExprCompact :: Edit EditExpr -> PP.Doc PP.A.AnsiStyle
 ansiWlBgEditExprCompact = ppEditExprCompact ansiWlBgPretty
diff --git a/src/Data/TreeDiff/QuickCheck.hs b/src/Data/TreeDiff/QuickCheck.hs
--- a/src/Data/TreeDiff/QuickCheck.hs
+++ b/src/Data/TreeDiff/QuickCheck.hs
@@ -7,8 +7,15 @@
 import System.Console.ANSI (SGR (Reset), setSGRCode)
 import Test.QuickCheck     (Property, counterexample)
 
+import qualified Data.Text.Lazy                as TL
+import qualified Prettyprinter                 as PP
+import qualified Prettyprinter.Render.Terminal as PP.A
+
 -- | A variant of '===', which outputs a diff when values are inequal.
 ediffEq :: (Eq a, ToExpr a) => a -> a -> Property
 ediffEq x y = counterexample
-    (setSGRCode [Reset] ++ show (ansiWlEditExpr $ ediff x y))
+    (setSGRCode [Reset] ++ render (ansiWlEditExpr $ ediff x y))
     (x == y)
+
+render :: PP.Doc PP.A.AnsiStyle -> String
+render = TL.unpack . PP.A.renderLazy . PP.layoutPretty PP.defaultLayoutOptions
diff --git a/tests/Tests.hs b/tests/Tests.hs
--- a/tests/Tests.hs
+++ b/tests/Tests.hs
@@ -10,12 +10,12 @@
 import Test.Tasty.Golden.Advanced (goldenTest)
 import Test.Tasty.QuickCheck      (testProperty)
 
-import qualified Data.HashSet                 as HS
-import qualified Data.Primitive               as Prim
-import qualified Text.Parsec                  as P
-import qualified Text.PrettyPrint.ANSI.Leijen as WL
-import qualified Text.Trifecta                as T (eof, parseString)
-import qualified Text.Trifecta.Result         as T (ErrInfo (..), Result (..))
+import qualified Data.HashSet         as HS
+import qualified Data.Primitive       as Prim
+import qualified Prettyprinter        as PP
+import qualified Text.Parsec          as P
+import qualified Text.Trifecta        as T (eof, parseString)
+import qualified Text.Trifecta.Result as T (ErrInfo (..), Result (..))
 
 import Data.TreeDiff
 import Data.TreeDiff.Golden
@@ -73,7 +73,7 @@
 roundtripParsecAnsiWl :: Expr -> Property
 roundtripParsecAnsiWl e = counterexample info $ ediffEq (Just e) res'
   where
-    doc = show (WL.plain (ansiWlExpr e))
+    doc = show (PP.unAnnotate (ansiWlExpr e))
     res = P.parse (exprParser <* P.eof) "<memory>" doc
 
     info = case res of
diff --git a/tree-diff.cabal b/tree-diff.cabal
--- a/tree-diff.cabal
+++ b/tree-diff.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.2
 name:               tree-diff
-version:            0.3.3
+version:            0.4.1
 synopsis:           Diffing of (expression) trees.
 category:           Data, Testing
 description:
@@ -50,9 +50,11 @@
    || ==9.0.2
    || ==9.2.8
    || ==9.4.8
-   || ==9.6.5
-   || ==9.8.2
-   || ==9.10.1
+   || ==9.6.7
+   || ==9.8.4
+   || ==9.10.3
+   || ==9.12.2
+   || ==9.14.1
 
 extra-source-files:
   fixtures/exfoo.expr
@@ -65,6 +67,11 @@
   type:     git
   location: https://github.com/phadej/tree-diff.git
 
+flag base-ge-4-17
+  description: @base >=4.17@ (GHC-9.4)
+  default:     True
+  manual:      False
+
 library
   exposed-modules:
     Data.TreeDiff
@@ -80,34 +87,32 @@
 
   -- GHC boot libraries
   build-depends:
-    , base        >=4.12.0.0  && <4.21
+    , base        >=4.12.0.0  && <4.23
     , bytestring  ^>=0.10.8.2 || ^>=0.11.0.0 || ^>=0.12.0.2
-    , containers  ^>=0.6.0.1  || ^>=0.7
+    , containers  ^>=0.6.0.1  || ^>=0.7      || ^>=0.8
     , deepseq     ^>=1.4.4.0  || ^>=1.5.0.0
     , parsec      ^>=3.1.13.0
     , pretty      ^>=1.1.1.0
     , text        ^>=1.2.3.0  || ^>=2.0      || ^>=2.1
-    , time        ^>=1.8.0.2  || ^>=1.9.3    || ^>=1.10     || ^>=1.11 || ^>=1.12
+    , time        ^>=1.8.0.2  || ^>=1.9.3    || ^>=1.10     || ^>=1.11 || ^>=1.12 || ^>=1.14 || ^>=1.15
 
   build-depends:
-    , aeson                 ^>=2.2.0.0
-    , ansi-terminal         ^>=1.1
-    , ansi-wl-pprint        ^>=1.0.2
-    , hashable              ^>=1.4.4.0  || ^>=1.5.0.0
-    , parsers               ^>=0.12.11
-    , primitive             ^>=0.9.0.0
-    , QuickCheck            ^>=2.14.2   || ^>=2.15
-    , scientific            ^>=0.3.8.0
-    , semialign             ^>=1.3.1
-    , strict                ^>=0.5
-    , tagged                ^>=0.8.8
-    , these                 ^>=1.2.1
-    , unordered-containers  ^>=0.2.20
-    , uuid-types            ^>=1.0.6
-    , vector                ^>=0.13.1.0
-
-  if (impl(ghc >=8) && !impl(ghc >=9.4))
-    build-depends: data-array-byte ^>=0.1.0.1
+    , aeson                        ^>=2.2.0.0
+    , ansi-terminal                ^>=1.1
+    , hashable                     ^>=1.4.4.0  || ^>=1.5.0.0
+    , parsers                      ^>=0.12.11
+    , prettyprinter                ^>=1.7.2
+    , prettyprinter-ansi-terminal  ^>=1.1.4
+    , primitive                    ^>=0.9.0.0
+    , QuickCheck                   ^>=2.14.2   || ^>=2.15    || ^>=2.16.0.0 || ^>=2.18.0.0
+    , scientific                   ^>=0.3.8.0
+    , semialign                    ^>=1.3.1    || ^>=1.4
+    , strict                       ^>=0.5
+    , tagged                       ^>=0.8.8
+    , these                        ^>=1.2.1
+    , unordered-containers         ^>=0.2.20
+    , uuid-types                   ^>=1.0.6
+    , vector                       ^>=0.13.1.0
 
   other-extensions:
     CPP
@@ -132,21 +137,16 @@
 
   -- dependencies from library
   build-depends:
-    , ansi-terminal
-    , ansi-wl-pprint
     , base
     , parsec
+    , prettyprinter
     , primitive
     , QuickCheck
-    , tagged
     , tree-diff
     , unordered-containers
 
-  if (impl(ghc >=8) && !impl(ghc >=9.4))
-    build-depends: data-array-byte
-
-  if impl(ghc <7.5)
-    build-depends: ghc-prim
+  if !flag(base-ge-4-17)
+    build-depends: data-array-byte >=0.1.0.1 && <0.2
 
   -- extra dependencies
   build-depends:
@@ -155,6 +155,12 @@
     , tasty-quickcheck  ^>=0.10.3 || ^>=0.11
     , trifecta          ^>=2.1.4
 
+  if flag(base-ge-4-17)
+    build-depends: base >=4.17
+
+  else
+    build-depends: base <4.17
+
 benchmark tree-diff-bench
   default-language: Haskell2010
   type:             exitcode-stdio-1.0
@@ -171,4 +177,4 @@
   -- extra dependencies
   build-depends:
     , criterion  ^>=1.6.3.0
-    , Diff       ^>=0.5
+    , Diff       ^>=1.0
