packages feed

tree-diff 0.2.2 → 0.4.1

raw patch · 10 files changed

Files

ChangeLog.md view
@@ -1,3 +1,44 @@+## 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.+  This way you may `--accept` new results even when expected files are broken, e.g. due merge conflict markers.+  For now the change is a bit a hack to avoid breaking change in type-signature of `ediffGolden/1`.++## 0.3.2++- Add 'ediffGolden1', a variant of 'ediffGolden' with an additional argument.++## 0.3.1++- Support GHC-8.6.5...9.10.1++## 0.3++- Breaking change:+  Make HashSet and HashMap ToExpr instances sort the resulting+  lists of expressions.+  This makes the results deterministic.+  ... but your golden files will need adjustment.+  https://github.com/haskellari/tree-diff/issues/67++- Add `Ord Expr` and `Ord OMap` instances+- Depend on `data-array-byte` to provide more `ByteArray` instances+ ## 0.2.2  - Add instances for base and primitive's `ByteArray`s.
src/Data/TreeDiff/Class.hs view
@@ -1,14 +1,12 @@ {-# LANGUAGE CPP                 #-} {-# LANGUAGE ConstraintKinds     #-} {-# LANGUAGE DefaultSignatures   #-}+{-# LANGUAGE EmptyCase           #-} {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeOperators       #-}-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708-{-# LANGUAGE EmptyCase           #-}-#endif -- | A 'ToExpr' class. module Data.TreeDiff.Class (     ediff,@@ -20,9 +18,9 @@     GToExpr,     ) where -import Data.Foldable    (toList)-import Data.List.Compat (uncons)-import Data.Proxy       (Proxy (..))+import Data.Foldable (toList)+import Data.List     (sort, uncons)+import Data.Proxy    (Proxy (..)) import GHC.Generics        (Constructor (..), Generic (..), K1 (..), M1 (..), Selector (..),        U1 (..), V1, (:*:) (..), (:+:) (..))@@ -42,10 +40,6 @@ import Data.Word import Numeric.Natural       (Natural) -#ifdef MIN_VERSION_generic_deriving-import Generics.Deriving.Instances ()-#endif- import qualified Data.Monoid    as Mon import qualified Data.Ratio     as Ratio import qualified Data.Semigroup as Semi@@ -93,11 +87,9 @@ import qualified Data.HashSet        as HS  -- aeson-import qualified Data.Aeson as Aeson-#if MIN_VERSION_aeson(2,0,0)+import qualified Data.Aeson        as Aeson import qualified Data.Aeson.Key    as Key import qualified Data.Aeson.KeyMap as KM-#endif  -- strict import qualified Data.Strict as Strict@@ -106,11 +98,7 @@ import Data.These (These (..))  -- primitive-import qualified Data.Primitive as Prim--#if MIN_VERSION_base(4,17,0)-import Data.Array.Byte (ByteArray (..))-#endif+import qualified Data.Primitive  as Prim  -- $setup -- >>> :set -XDeriveGeneric@@ -201,11 +189,7 @@     gsumToExpr (R1 x) = gsumToExpr x  instance GSumToExpr V1 where-#if __GLASGOW_HASKELL__ >= 708     gsumToExpr x = case x of {}-#else-    gsumToExpr x = x `seq` error "panic: V1 value"-#endif  instance (Constructor c, GProductToExpr f) => GSumToExpr (M1 i c f) where     gsumToExpr z@(M1 x) = case gproductToExpr x of@@ -550,9 +534,9 @@ -------------------------------------------------------------------------------  instance (ToExpr k, ToExpr v) => ToExpr (HM.HashMap k v) where-    toExpr x = App "HM.fromList" [ toExpr $ HM.toList x ]+    toExpr x = App "HM.fromList" [ Lst $ sort $ map toExpr $ HM.toList x ] instance (ToExpr k) => ToExpr (HS.HashSet k) where-    toExpr x = App "HS.fromList" [ toExpr $ HS.toList x ]+    toExpr x = App "HS.fromList" [ Lst $ sort $ map toExpr $ HS.toList x ]  ------------------------------------------------------------------------------- -- aeson@@ -560,13 +544,11 @@  instance ToExpr Aeson.Value -#if MIN_VERSION_aeson(2,0,0) instance ToExpr Key.Key where     toExpr = stringToExpr "Key.concat" . unconcat T.uncons . Key.toText  instance ToExpr a => ToExpr (KM.KeyMap a) where     toExpr x = App "KM.fromList" [ toExpr $ KM.toList x ]-#endif  ------------------------------------------------------------------------------- -- strict@@ -600,11 +582,3 @@ -- | @since 0.2.2 instance ToExpr Prim.ByteArray where     toExpr ba = App "Prim.byteArrayFromList" [toExpr (Prim.foldrByteArray (:) [] ba :: [Word8])]--#if MIN_VERSION_base(4,17,0)--- | @since 0.2.2-instance ToExpr ByteArray where-    toExpr (ByteArray ba) = App "byteArrayFromList" [toExpr (Prim.foldrByteArray (:) [] (Prim.ByteArray ba) :: [Word8])]-#endif---- TODO: add more instances
src/Data/TreeDiff/Expr.hs view
@@ -9,9 +9,6 @@     exprDiff,     ) where -import Prelude ()-import Prelude.Compat- import Control.DeepSeq (NFData (..)) import Data.Semialign  (alignWith) import Data.These      (These (..))@@ -35,7 +32,7 @@     = App ConstructorName [Expr]                 -- ^ application     | Rec ConstructorName (OMap FieldName Expr)  -- ^ record constructor     | Lst [Expr]                                 -- ^ list constructor-  deriving (Eq, Show)+  deriving (Eq, Ord, Show)  instance NFData Expr where     rnf (App n es) = rnf n `seq` rnf es
src/Data/TreeDiff/Golden.hs view
@@ -1,19 +1,21 @@+{-# LANGUAGE ScopedTypeVariables #-} -- | "Golden tests" using 'ediff' comparison. module Data.TreeDiff.Golden (     ediffGolden,+    ediffGolden1, ) where  import Data.TreeDiff-import Prelude ()-import Prelude.Compat import System.Console.ANSI (SGR (Reset), setSGRCode) 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,25 +39,46 @@ -- 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"     -> IO a      -- ^ result value     -> testTree-ediffGolden impl testName fp x = impl testName expect actual cmp wrt+ediffGolden impl testName fp x = ediffGolden1 impl' testName fp (\() -> x) where+    impl' n expect actual = impl n expect (actual ())++-- | Like 'ediffGolden1' but with an additional argument for generation of actual value.+--+-- @since 0.3.2+--+ediffGolden1+    :: 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"+    -> (arg -> IO a)      -- ^ result value+    -> testTree+ediffGolden1 impl testName fp x = impl testName expect actual cmp wrt   where-    actual = fmap toExpr x+    actual :: arg -> IO Expr+    actual arg = fmap toExpr (x arg)++    expect :: IO Expr     expect = do         contents <- BS.readFile fp         case parse (exprParser <* eof) fp $ TE.decodeUtf8 contents of-            Left err -> print err >> fail "parse error"+            Left err -> return $ App "ParseError" [toExpr fp, toExpr (show err)]             Right r  -> return r++    cmp :: Expr -> Expr -> IO (Maybe [Char])     cmp a b         | 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
src/Data/TreeDiff/OMap.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP           #-} {-# LANGUAGE DeriveFunctor #-} -- | Map which remembers the 'fromList' order. -- This module is minimal on purpose.@@ -15,18 +14,15 @@     elems, ) where -import Data.List      (sortBy)-import Data.Ord       (comparing)-import Data.Semialign (Semialign (..))-import Data.These     (These (..))-import Control.DeepSeq  (NFData (..))+import Prelude hiding (zipWith) -#if MIN_VERSION_containers(0,5,0)-import qualified Data.Map.Strict as Map-#else-import qualified Data.Map as Map-#endif+import Control.DeepSeq (NFData (..))+import Data.List       (sortBy)+import Data.Ord        (comparing)+import Data.Semialign  (Semialign(..), Unzip (..), Zip (..), unzipDefault)+import Data.These      (These (..)) +import qualified Data.Map.Strict as Map import qualified Test.QuickCheck as QC  -- $setup@@ -61,13 +57,11 @@ -- False -- instance (Eq k, Eq v) => Eq (OMap k v) where-    xs == ys = go (toAscList xs) (toAscList ys) where-        go [] [] = True-        go _  [] = False-        go [] _  = False-        go ((k1, v1) : kvs1) ((k2, v2) : kvs2) =-            k1 == k2 && v1 == v2 && go kvs1 kvs2+    xs == ys = toAscList xs == toAscList ys +instance (Ord k, Ord v) => Ord (OMap k v) where+    compare xs ys = compare (toAscList xs) (toAscList ys)+ ------------------------------------------------------------------------------- -- deepseq -------------------------------------------------------------------------------@@ -156,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
src/Data/TreeDiff/Parser.hs view
@@ -8,8 +8,6 @@  import Control.Applicative (many, optional, (<|>)) import Data.Char           (chr, isAlphaNum, isPunctuation, isSymbol)-import Prelude ()-import Prelude.Compat  import Text.Parser.Char            (CharParsing (anyChar, char, satisfy)) import Text.Parser.Combinators     (between, (<?>))
src/Data/TreeDiff/Pretty.hs view
@@ -10,7 +10,7 @@     prettyExpr,     prettyEditExpr,     prettyEditExprCompact,-    -- * ansi-wl-pprint+    -- * prettyprinter     ansiWlPretty,     ansiWlExpr,     ansiWlEditExpr,@@ -28,11 +28,12 @@ import Data.Either        (partitionEithers) import Data.TreeDiff.Expr import Numeric            (showHex)-import Text.Read.Compat   (readMaybe)+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
src/Data/TreeDiff/QuickCheck.hs view
@@ -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
tests/Tests.hs view
@@ -1,20 +1,21 @@ {-# LANGUAGE DeriveGeneric #-} module Main (main) where +import Data.Array.Byte            (ByteArray (..)) import Data.Proxy                 (Proxy (..)) import Data.Word                  (Word8) import GHC.Generics               (Generic)-import Prelude ()-import Prelude.Compat import Test.QuickCheck            (Property, counterexample, (===)) import Test.Tasty                 (TestTree, defaultMain, testGroup) import Test.Tasty.Golden.Advanced (goldenTest) import Test.Tasty.QuickCheck      (testProperty) -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@@ -72,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@@ -151,6 +152,14 @@ instance ToExpr Positional instance ToExpr Empty +-- test that we have both instances.+data ByteArrays = ByteArrays+    Prim.ByteArray+    ByteArray+  deriving Generic++instance ToExpr ByteArrays+ goldenTests :: TestTree goldenTests = testGroup "Golden"     [ ediffGolden goldenTest "exFoo" "fixtures/exfoo.expr" $@@ -163,5 +172,9 @@         return $ MyInt3 42     , ediffGolden goldenTest "Positional" "fixtures/Positional.expr" $         return $ Positional 12 True 'z'++    -- issue #67+    , ediffGolden goldenTest "HashSet" "fixtures/HashSet.expr" $+        return $ HS.fromList [ [x,y] | x <- "abcd", y <- "xyz" ]     ] 
tree-diff.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               tree-diff-version:            0.2.2+version:            0.4.1 synopsis:           Diffing of (expression) trees. category:           Data, Testing description:@@ -44,20 +44,17 @@   README.md  tested-with:-    GHC ==7.4.2-     || ==7.6.3-     || ==7.8.4-     || ==7.10.3-     || ==8.0.2-     || ==8.2.2-     || ==8.4.4-     || ==8.6.5-     || ==8.8.4-     || ==8.10.4-     || ==9.0.2-     || ==9.2.4-     || ==9.4.1-  , GHCJS ==8.4+  GHC ==8.6.5+   || ==8.8.4+   || ==8.10.7+   || ==9.0.2+   || ==9.2.8+   || ==9.4.8+   || ==9.6.7+   || ==9.8.4+   || ==9.10.3+   || ==9.12.2+   || ==9.14.1  extra-source-files:   fixtures/exfoo.expr@@ -70,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@@ -85,48 +87,32 @@    -- GHC boot libraries   build-depends:-    , base        >=4.5      && <4.18-    , bytestring  ^>=0.9.2.1 || ^>=0.10.0.2 || ^>=0.11.0.0-    , containers  ^>=0.4.2.1 || ^>=0.5.0.0 || ^>=0.6.0.1-    , deepseq     ^>=1.3.0.0 || ^>=1.4.0.0+    , 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      || ^>=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-    , time        >=1.4      && <1.5 || >=1.5.0.1 && <1.6 || >=1.6.0.1 && <1.7 || >=1.8.0.2 && <1.9 || >=1.9.3 && <1.13+    , text        ^>=1.2.3.0  || ^>=2.0      || ^>=2.1+    , time        ^>=1.8.0.2  || ^>=1.9.3    || ^>=1.10     || ^>=1.11 || ^>=1.12 || ^>=1.14 || ^>=1.15    build-depends:-    , aeson                 ^>=1.4.6.0 || ^>=1.5.6.0 || ^>=2.0.0.0 || ^>=2.1.0.0-    , ansi-terminal         >=0.10       && <0.12-    , ansi-wl-pprint        ^>=0.6.8.2-    , base-compat           >=0.10.5     && <0.11 || >=0.11.0 && <0.13-    , bytestring-builder    ^>=0.10.8.2.0-    , hashable              ^>=1.2.7.0 || ^>=1.3.0.0 || ^>=1.4.0.1-    , parsers               ^>=0.12.10-    , primitive             ^>=0.7.1.0-    , QuickCheck            ^>=2.14.2-    , scientific            ^>=0.3.6.2-    , semialign             ^>=1.2.0.1-    , strict                ^>=0.4.0.1-    , tagged                ^>=0.8.6-    , these                 ^>=1.1.1.1-    , unordered-containers  ^>=0.2.8.0-    , uuid-types            ^>=1.0.3-    , vector                ^>=0.12.0.0 || ^>=0.13.0.0--  if impl(ghc <7.5)-    build-depends: ghc-prim--  if !impl(ghc >=8.0)-    build-depends: semigroups >=0.19.1 && <0.21--  if !impl(ghc >=7.8)-    build-depends: generic-deriving >=1.13.1 && <1.15--  if !impl(ghc >=7.10)-    build-depends:-      , nats          ^>=1.1.2-      , transformers  ^>=0.3.0.0 || ^>=0.4.2.0 || ^>=0.5.2.0-      , void          ^>=0.7.3+    , 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@@ -151,26 +137,30 @@    -- dependencies from library   build-depends:-    , ansi-terminal-    , ansi-wl-pprint     , base-    , base-compat     , parsec+    , prettyprinter     , primitive     , QuickCheck-    , tagged     , tree-diff+    , unordered-containers -  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:-    , tasty             ^>=1.2 || ^>=1.3.1 || ^>=1.4.2-    , tasty-golden      ^>=2.3.1.1-    , tasty-quickcheck  ^>=0.10.1-    , trifecta          >=2       && <2.2+    , tasty             ^>=1.5+    , tasty-golden      ^>=2.3.5+    , 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@@ -186,5 +176,5 @@    -- extra dependencies   build-depends:-    , criterion  ^>=1.6.0.0-    , Diff       ^>=0.4.0+    , criterion  ^>=1.6.3.0+    , Diff       ^>=1.0