-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Diffing of (expression) trees. -- -- Common diff algorithm works on list structures: -- --
-- diff :: Eq a => [a] -> [a] -> [Edit a] ---- -- This package works on trees. -- --
-- treeDiff :: Eq a => Tree a -> Tree a -> Edit (EditTree a) ---- -- This package also provides a way to diff arbitrary ADTs, using -- Generics-derivable helpers. -- -- This package differs from gdiff, in a two ways: -- tree-diff doesn't have patch function, and the "edit-script" -- is a tree itself, which is useful for pretty-printing. -- --
-- >>> prettyEditExpr $ ediff (Foo 42 [True, False] "old") (Foo 42 [False, False, True] "new")
-- Foo
-- {fooBool = [-True, +False, False, +True],
-- fooInt = 42,
-- fooString = -"old" +"new"}
--
@package tree-diff
@version 0.3.2
-- | A list diff.
module Data.TreeDiff.List
-- | List difference.
--
-- -- >>> diffBy (==) "hello" "world" -- [Swp 'h' 'w',Swp 'e' 'o',Swp 'l' 'r',Cpy 'l',Swp 'o' 'd'] ---- --
-- >>> diffBy (==) "kitten" "sitting" -- [Swp 'k' 's',Cpy 'i',Cpy 't',Cpy 't',Swp 'e' 'i',Cpy 'n',Ins 'g'] ---- --
-- \xs ys -> length (diffBy (==) xs ys) >= max (length xs) (length (ys :: String)) ---- --
-- \xs ys -> length (diffBy (==) xs ys) <= length xs + length (ys :: String) --diffBy :: forall a. Show a => (a -> a -> Bool) -> [a] -> [a] -> [Edit a] -- | List edit operations -- -- The Swp constructor is redundant, but it let us spot a -- recursion point when performing tree diffs. data Edit a -- | insert Ins :: a -> Edit a -- | delete Del :: a -> Edit a -- | copy unchanged Cpy :: a -> Edit a -- | swap, i.e. delete + insert Swp :: a -> a -> Edit a instance GHC.Show.Show a => GHC.Show.Show (Data.TreeDiff.List.Edit a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.TreeDiff.List.Edit a) instance GHC.Show.Show a => GHC.Show.Show (Data.TreeDiff.List.Cell a) instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Data.TreeDiff.List.Edit a) -- | Map which remembers the fromList order. This module is minimal -- on purpose. module Data.TreeDiff.OMap data OMap k v -- |
-- >>> toAscList $ fromList [('a', "alpha"), ('b', "beta"), ('g', "gamma")]
-- [('a',"alpha"),('b',"beta"),('g',"gamma")]
--
--
--
-- >>> toAscList $ fromList [('g', "gamma"), ('b', "beta"), ('a', "alpha")]
-- [('a',"alpha"),('b',"beta"),('g',"gamma")]
--
toAscList :: OMap k v -> [(k, v)]
-- | O(n log n). List in creation order. Doesn't respect Eq
-- instance.
--
--
-- >>> toList $ fromList [('a', "alpha"), ('b', "beta"), ('g', "gamma")]
-- [('a',"alpha"),('b',"beta"),('g',"gamma")]
--
--
--
-- >>> toList $ fromList [('g', "gamma"), ('b', "beta"), ('a', "alpha")]
-- [('g',"gamma"),('b',"beta"),('a',"alpha")]
--
toList :: OMap k v -> [(k, v)]
-- |
-- >>> fromList [('g', "gamma"), ('b', "beta"), ('a', "alpha")]
-- fromList [('g',"gamma"),('b',"beta"),('a',"alpha")]
--
fromList :: Ord k => [(k, v)] -> OMap k v
-- | -- >>> empty :: OMap String Integer -- fromList [] --empty :: OMap k v -- | Elements in key ascending order. elems :: OMap k v -> [v] instance GHC.Base.Functor Data.TreeDiff.OMap.Val instance GHC.Base.Functor (Data.TreeDiff.OMap.OMap k) instance (GHC.Show.Show k, GHC.Show.Show v) => GHC.Show.Show (Data.TreeDiff.OMap.OMap k v) instance (GHC.Classes.Eq k, GHC.Classes.Eq v) => GHC.Classes.Eq (Data.TreeDiff.OMap.OMap k v) instance (GHC.Classes.Ord k, GHC.Classes.Ord v) => GHC.Classes.Ord (Data.TreeDiff.OMap.OMap k v) instance (Control.DeepSeq.NFData k, Control.DeepSeq.NFData v) => Control.DeepSeq.NFData (Data.TreeDiff.OMap.OMap k v) instance (GHC.Classes.Ord k, Test.QuickCheck.Arbitrary.Arbitrary k, Test.QuickCheck.Arbitrary.Arbitrary v) => Test.QuickCheck.Arbitrary.Arbitrary (Data.TreeDiff.OMap.OMap k v) instance (GHC.Classes.Ord k, Test.QuickCheck.Arbitrary.Arbitrary k) => Test.QuickCheck.Arbitrary.Arbitrary1 (Data.TreeDiff.OMap.OMap k) instance GHC.Classes.Ord k => Data.Semialign.Internal.Semialign (Data.TreeDiff.OMap.OMap k) instance Control.DeepSeq.NFData v => Control.DeepSeq.NFData (Data.TreeDiff.OMap.Val v) -- | This module uses Expr for richer diffs than based on -- Tree. module Data.TreeDiff.Expr -- | A untyped Haskell-like expression. -- -- Having richer structure than just Tree allows to have richer -- diffs. data Expr -- | application App :: ConstructorName -> [Expr] -> Expr -- | record constructor Rec :: ConstructorName -> OMap FieldName Expr -> Expr -- | list constructor Lst :: [Expr] -> Expr -- | Constructor name is a string type ConstructorName = String -- | Record field name is a string too. type FieldName = String -- | Type used in the result of ediff. data EditExpr EditApp :: ConstructorName -> [Edit EditExpr] -> EditExpr EditRec :: ConstructorName -> OMap FieldName (Edit EditExpr) -> EditExpr EditLst :: [Edit EditExpr] -> EditExpr -- | unchanged tree EditExp :: Expr -> EditExpr -- | List edit operations -- -- The Swp constructor is redundant, but it let us spot a -- recursion point when performing tree diffs. data Edit a -- | insert Ins :: a -> Edit a -- | delete Del :: a -> Edit a -- | copy unchanged Cpy :: a -> Edit a -- | swap, i.e. delete + insert Swp :: a -> a -> Edit a -- | Diff two Expr. -- -- For examples see ediff in Data.TreeDiff.Class. exprDiff :: Expr -> Expr -> Edit EditExpr instance GHC.Show.Show Data.TreeDiff.Expr.Expr instance GHC.Classes.Ord Data.TreeDiff.Expr.Expr instance GHC.Classes.Eq Data.TreeDiff.Expr.Expr instance GHC.Show.Show Data.TreeDiff.Expr.EditExpr instance Control.DeepSeq.NFData Data.TreeDiff.Expr.EditExpr instance Control.DeepSeq.NFData Data.TreeDiff.Expr.Expr instance Test.QuickCheck.Arbitrary.Arbitrary Data.TreeDiff.Expr.Expr -- | A ToExpr class. module Data.TreeDiff.Class -- | Difference between two ToExpr values. -- --
-- >>> let x = (1, Just 2) :: (Int, Maybe Int) -- -- >>> let y = (1, Nothing) -- -- >>> prettyEditExpr (ediff x y) -- _×_ 1 -(Just 2) +Nothing ---- --
-- >>> data Foo = Foo { fooInt :: Either Char Int, fooBool :: [Maybe Bool], fooString :: String } deriving (Eq, Generic)
--
-- >>> instance ToExpr Foo
--
--
--
-- >>> prettyEditExpr $ ediff (Foo (Right 2) [Just True] "fo") (Foo (Right 3) [Just True] "fo")
-- Foo {fooInt = Right -2 +3, fooBool = [Just True], fooString = "fo"}
--
--
--
-- >>> prettyEditExpr $ ediff (Foo (Right 42) [Just True, Just False] "old") (Foo (Right 42) [Nothing, Just False, Just True] "new")
-- Foo {
-- fooInt = Right 42,
-- fooBool = [-Just True, +Nothing, Just False, +Just True],
-- fooString = -"old" +"new"}
--
ediff :: ToExpr a => a -> a -> Edit EditExpr
-- | Compare different types.
--
-- Note: Use with care as you can end up comparing apples with
-- oranges.
--
-- -- >>> prettyEditExpr $ ediff' ["foo", "bar"] [Just "foo", Nothing] -- [-"foo", +Just "foo", -"bar", +Nothing] --ediff' :: (ToExpr a, ToExpr b) => a -> b -> Edit EditExpr -- | toExpr converts a Haskell value into untyped Haskell-like -- syntax tree, Expr. -- --
-- >>> toExpr ((1, Just 2) :: (Int, Maybe Int)) -- App "_\215_" [App "1" [],App "Just" [App "2" []]] --class ToExpr a toExpr :: ToExpr a => a -> Expr toExpr :: (ToExpr a, Generic a, GToExpr (Rep a)) => a -> Expr listToExpr :: ToExpr a => [a] -> Expr -- | An alternative implementation for literal types. We use show -- representation of them. defaultExprViaShow :: Show a => a -> Expr -- | Generic toExpr. -- --
-- >>> data Foo = Foo Int Char deriving Generic -- -- >>> genericToExpr (Foo 42 'x') -- App "Foo" [App "42" [],App "'x'" []] --genericToExpr :: (Generic a, GToExpr (Rep a)) => a -> Expr class GToExpr f instance GHC.Show.Show Data.TreeDiff.Class.AppOrRec instance (GHC.Generics.Constructor c, Data.TreeDiff.Class.GProductToExpr f) => Data.TreeDiff.Class.GSumToExpr (GHC.Generics.M1 i c f) instance (Data.TreeDiff.Class.GProductToExpr f, Data.TreeDiff.Class.GProductToExpr g) => Data.TreeDiff.Class.GProductToExpr (f GHC.Generics.:*: g) instance Data.TreeDiff.Class.GProductToExpr GHC.Generics.U1 instance (GHC.Generics.Selector s, Data.TreeDiff.Class.GLeafToExpr f) => Data.TreeDiff.Class.GProductToExpr (GHC.Generics.M1 i s f) instance Data.TreeDiff.Class.ToExpr x => Data.TreeDiff.Class.GLeafToExpr (GHC.Generics.K1 i x) instance Data.TreeDiff.Class.GSumToExpr f => Data.TreeDiff.Class.GToExpr (GHC.Generics.M1 i c f) instance (Data.TreeDiff.Class.GSumToExpr f, Data.TreeDiff.Class.GSumToExpr g) => Data.TreeDiff.Class.GSumToExpr (f GHC.Generics.:+: g) instance Data.TreeDiff.Class.GSumToExpr GHC.Generics.V1 instance Data.TreeDiff.Class.ToExpr Data.TreeDiff.Expr.Expr instance Data.TreeDiff.Class.ToExpr () instance Data.TreeDiff.Class.ToExpr GHC.Types.Bool instance Data.TreeDiff.Class.ToExpr GHC.Types.Ordering instance Data.TreeDiff.Class.ToExpr GHC.Num.Integer.Integer instance Data.TreeDiff.Class.ToExpr GHC.Num.Natural.Natural instance Data.TreeDiff.Class.ToExpr GHC.Types.Float instance Data.TreeDiff.Class.ToExpr GHC.Types.Double instance Data.TreeDiff.Class.ToExpr GHC.Types.Int instance Data.TreeDiff.Class.ToExpr GHC.Int.Int8 instance Data.TreeDiff.Class.ToExpr GHC.Int.Int16 instance Data.TreeDiff.Class.ToExpr GHC.Int.Int32 instance Data.TreeDiff.Class.ToExpr GHC.Int.Int64 instance Data.TreeDiff.Class.ToExpr GHC.Types.Word instance Data.TreeDiff.Class.ToExpr GHC.Word.Word8 instance Data.TreeDiff.Class.ToExpr GHC.Word.Word16 instance Data.TreeDiff.Class.ToExpr GHC.Word.Word32 instance Data.TreeDiff.Class.ToExpr GHC.Word.Word64 instance Data.TreeDiff.Class.ToExpr (Data.Proxy.Proxy a) instance Data.TreeDiff.Class.ToExpr GHC.Types.Char instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (GHC.Maybe.Maybe a) instance (Data.TreeDiff.Class.ToExpr a, Data.TreeDiff.Class.ToExpr b) => Data.TreeDiff.Class.ToExpr (Data.Either.Either a b) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr [a] instance (Data.TreeDiff.Class.ToExpr a, Data.TreeDiff.Class.ToExpr b) => Data.TreeDiff.Class.ToExpr (a, b) instance (Data.TreeDiff.Class.ToExpr a, Data.TreeDiff.Class.ToExpr b, Data.TreeDiff.Class.ToExpr c) => Data.TreeDiff.Class.ToExpr (a, b, c) instance (Data.TreeDiff.Class.ToExpr a, Data.TreeDiff.Class.ToExpr b, Data.TreeDiff.Class.ToExpr c, Data.TreeDiff.Class.ToExpr d) => Data.TreeDiff.Class.ToExpr (a, b, c, d) instance (Data.TreeDiff.Class.ToExpr a, Data.TreeDiff.Class.ToExpr b, Data.TreeDiff.Class.ToExpr c, Data.TreeDiff.Class.ToExpr d, Data.TreeDiff.Class.ToExpr e) => Data.TreeDiff.Class.ToExpr (a, b, c, d, e) instance (Data.TreeDiff.Class.ToExpr a, GHC.Real.Integral a) => Data.TreeDiff.Class.ToExpr (GHC.Real.Ratio a) instance Data.Fixed.HasResolution a => Data.TreeDiff.Class.ToExpr (Data.Fixed.Fixed a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Functor.Identity.Identity a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Functor.Const.Const a b) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Control.Applicative.ZipList a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (GHC.Base.NonEmpty a) instance Data.TreeDiff.Class.ToExpr GHC.Base.Void instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Semigroup.Internal.Dual a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Semigroup.Internal.Sum a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Semigroup.Internal.Product a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Monoid.First a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Monoid.Last a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Semigroup.Min a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Semigroup.Max a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Semigroup.First a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Semigroup.Last a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Tree.Tree a) instance (Data.TreeDiff.Class.ToExpr k, Data.TreeDiff.Class.ToExpr v) => Data.TreeDiff.Class.ToExpr (Data.Map.Internal.Map k v) instance Data.TreeDiff.Class.ToExpr k => Data.TreeDiff.Class.ToExpr (Data.Set.Internal.Set k) instance Data.TreeDiff.Class.ToExpr v => Data.TreeDiff.Class.ToExpr (Data.IntMap.Internal.IntMap v) instance Data.TreeDiff.Class.ToExpr Data.IntSet.Internal.IntSet instance Data.TreeDiff.Class.ToExpr v => Data.TreeDiff.Class.ToExpr (Data.Sequence.Internal.Seq v) instance Data.TreeDiff.Class.ToExpr Data.Text.Internal.Lazy.Text instance Data.TreeDiff.Class.ToExpr Data.Text.Internal.Text instance Data.TreeDiff.Class.ToExpr Data.Time.Calendar.Days.Day instance Data.TreeDiff.Class.ToExpr Data.Time.Clock.Internal.UTCTime.UTCTime instance Data.TreeDiff.Class.ToExpr Data.ByteString.Lazy.Internal.ByteString instance Data.TreeDiff.Class.ToExpr Data.ByteString.Internal.Type.ByteString instance Data.TreeDiff.Class.ToExpr Data.ByteString.Short.Internal.ShortByteString instance Data.TreeDiff.Class.ToExpr Data.Scientific.Scientific instance Data.TreeDiff.Class.ToExpr Data.UUID.Types.Internal.UUID instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Vector.Vector a) instance (Data.TreeDiff.Class.ToExpr a, Data.Vector.Unboxed.Base.Unbox a) => Data.TreeDiff.Class.ToExpr (Data.Vector.Unboxed.Base.Vector a) instance (Data.TreeDiff.Class.ToExpr a, Foreign.Storable.Storable a) => Data.TreeDiff.Class.ToExpr (Data.Vector.Storable.Vector a) instance (Data.TreeDiff.Class.ToExpr a, Data.Primitive.Types.Prim a) => Data.TreeDiff.Class.ToExpr (Data.Vector.Primitive.Vector a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Tagged.Tagged t a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Hashable.Class.Hashed a) instance (Data.TreeDiff.Class.ToExpr k, Data.TreeDiff.Class.ToExpr v) => Data.TreeDiff.Class.ToExpr (Data.HashMap.Internal.HashMap k v) instance Data.TreeDiff.Class.ToExpr k => Data.TreeDiff.Class.ToExpr (Data.HashSet.Internal.HashSet k) instance Data.TreeDiff.Class.ToExpr Data.Aeson.Types.Internal.Value instance Data.TreeDiff.Class.ToExpr Data.Aeson.Key.Key instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Aeson.KeyMap.KeyMap a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Strict.Maybe.Maybe a) instance (Data.TreeDiff.Class.ToExpr a, Data.TreeDiff.Class.ToExpr b) => Data.TreeDiff.Class.ToExpr (Data.Strict.Either.Either a b) instance (Data.TreeDiff.Class.ToExpr a, Data.TreeDiff.Class.ToExpr b) => Data.TreeDiff.Class.ToExpr (Data.Strict.These.These a b) instance (Data.TreeDiff.Class.ToExpr a, Data.TreeDiff.Class.ToExpr b) => Data.TreeDiff.Class.ToExpr (Data.Strict.Tuple.Pair a b) instance (Data.TreeDiff.Class.ToExpr a, Data.TreeDiff.Class.ToExpr b) => Data.TreeDiff.Class.ToExpr (Data.These.These a b) instance Data.TreeDiff.Class.ToExpr Data.Array.Byte.ByteArray -- | Utilities to parse Expr. -- -- Note: we don't parse diffs. module Data.TreeDiff.Parser -- | Parsers for Expr using parsers type-classes. -- -- You can use this with your parser-combinator library of choice: -- parsec, attoparsec, trifecta... exprParser :: (Monad m, TokenParsing m) => m Expr -- | Utilities to pretty print Expr and EditExpr module Data.TreeDiff.Pretty -- | Because we don't want to commit to single pretty printing library, we -- use explicit dictionary. data Pretty doc Pretty :: (ConstructorName -> doc) -> (doc -> [doc] -> doc) -> (doc -> [(FieldName, doc)] -> doc) -> ([doc] -> doc) -> (doc -> doc) -> (doc -> doc) -> (doc -> doc) -> ([doc] -> doc) -> doc -> (doc -> doc) -> Pretty doc -- | Display ConstructorName [ppCon] :: Pretty doc -> ConstructorName -> doc -- | Display App [ppApp] :: Pretty doc -> doc -> [doc] -> doc -- | Display Rec [ppRec] :: Pretty doc -> doc -> [(FieldName, doc)] -> doc -- | Display Lst [ppLst] :: Pretty doc -> [doc] -> doc -- | Display unchanged parts [ppCpy] :: Pretty doc -> doc -> doc -- | Display added parts [ppIns] :: Pretty doc -> doc -> doc -- | Display removed parts [ppDel] :: Pretty doc -> doc -> doc -- | Combined edits (usually some sep combinator) [ppEdits] :: Pretty doc -> [doc] -> doc -- | Ellipsis [ppEllip] :: Pretty doc -> doc -- | Parens an expression [ppParens] :: Pretty doc -> doc -> doc -- | Pretty print an Expr using explicit pretty-printing dictionary. ppExpr :: Pretty doc -> Expr -> doc -- | Pretty print an Edit EditExpr using explicit -- pretty-printing dictionary. ppEditExpr :: Pretty doc -> Edit EditExpr -> doc -- | Like ppEditExpr but print unchanged parts only shallowly ppEditExprCompact :: Pretty doc -> Edit EditExpr -> doc -- | Pretty via pretty library. prettyPretty :: Pretty Doc -- | Pretty print Expr using pretty. -- --
-- >>> prettyExpr $ Rec "ex" (OMap.fromList [("[]", App "bar" [])])
-- ex {`[]` = bar}
--
prettyExpr :: Expr -> Doc
-- | Pretty print Edit EditExpr using
-- pretty.
prettyEditExpr :: Edit EditExpr -> Doc
-- | Compact prettyEditExpr.
prettyEditExprCompact :: Edit EditExpr -> Doc
-- | Pretty via ansi-wl-pprint library (with colors).
ansiWlPretty :: Pretty Doc
-- | Pretty print Expr using ansi-wl-pprint.
ansiWlExpr :: Expr -> Doc
-- | Pretty print Edit EditExpr using
-- ansi-wl-pprint.
ansiWlEditExpr :: Edit EditExpr -> Doc
-- | Compact ansiWlEditExpr
ansiWlEditExprCompact :: Edit EditExpr -> Doc
-- | Like ansiWlPretty but color the background.
ansiWlBgPretty :: Pretty Doc
-- | Pretty print Expr using ansi-wl-pprint.
ansiWlBgExpr :: Expr -> Doc
-- | Pretty print Edit EditExpr using
-- ansi-wl-pprint.
ansiWlBgEditExpr :: Edit EditExpr -> Doc
-- | Compact ansiWlBgEditExpr.
ansiWlBgEditExprCompact :: Edit EditExpr -> Doc
-- | Escape field or constructor name
--
-- -- >>> putStrLn $ escapeName "Foo" -- Foo ---- --
-- >>> putStrLn $ escapeName "_×_" -- _×_ ---- --
-- >>> putStrLn $ escapeName "-3" -- `-3` ---- --
-- >>> putStrLn $ escapeName "kebab-case" -- kebab-case ---- --
-- >>> putStrLn $ escapeName "inner space" -- `inner space` ---- --
-- >>> putStrLn $ escapeName $ show "looks like a string" -- "looks like a string" ---- --
-- >>> putStrLn $ escapeName $ show "tricky" ++ " " -- `"tricky" ` ---- --
-- >>> putStrLn $ escapeName "[]" -- `[]` ---- --
-- >>> putStrLn $ escapeName "_,_" -- `_,_` --escapeName :: String -> String -- | Diffing of (expression) trees. -- -- Diffing arbitrary Haskell data. First we convert values to untyped -- haskell-like expression Expr using generically derivable -- ToExpr class. Then we can diff two Expr values. The -- conversion and diffing is done by ediff function. See type and -- function haddocks for an examples. -- -- Interesting modules: -- --
-- exTest :: TestTree -- exTest = ediffGolden goldenTest "golden test" "fixtures/ex.expr" $ -- action constructing actual value ---- -- The ediffGolden will read an Expr from provided path to -- golden file, and compare it with a toExpr of a result. If -- values differ, the (compact) diff of two will be printed. -- -- See -- https://github.com/phadej/tree-diff/blob/master/tests/Tests.hs -- for a proper example. ediffGolden :: (Eq a, ToExpr a) => (testName -> IO Expr -> IO Expr -> (Expr -> Expr -> IO (Maybe String)) -> (Expr -> IO ()) -> testTree) -> testName -> FilePath -> IO a -> testTree -- | Like ediffGolden1 but with an additional argument for -- generation of actual value. ediffGolden1 :: (Eq a, ToExpr a) => (testName -> IO Expr -> (arg -> IO Expr) -> (Expr -> Expr -> IO (Maybe String)) -> (Expr -> IO ()) -> testTree) -> testName -> FilePath -> (arg -> IO a) -> testTree -- | QuickCheck related utilities. module Data.TreeDiff.QuickCheck -- | A variant of ===, which outputs a diff when values are -- inequal. ediffEq :: (Eq a, ToExpr a) => a -> a -> Property -- | Tree diffing working on containers Tree. module Data.TreeDiff.Tree -- | A breadth-traversal diff. -- -- It's different from gdiff, as it doesn't produce a flat edit -- script, but edit script iself is a tree. This makes visualising the -- diff much simpler. -- --
-- >>> let x = Node 'a' [Node 'b' [], Node 'c' [return 'd', return 'e'], Node 'f' []] -- -- >>> ppTree PP.char x -- (a b (c d e) f) ---- -- If we modify an argument in a tree, we'll notice it's changed: -- --
-- >>> let y = Node 'a' [Node 'b' [], Node 'c' [return 'x', return 'e'], Node 'f' []] -- -- >>> ppTree PP.char y -- (a b (c x e) f) ---- --
-- >>> ppEditTree PP.char (treeDiff x y) -- (a b (c -d +x e) f) ---- -- If we modify a constructor, the whole sub-trees is replaced, though -- there might be common subtrees. -- --
-- >>> let z = Node 'a' [Node 'b' [], Node 'd' [], Node 'f' []] -- -- >>> ppTree PP.char z -- (a b d f) ---- --
-- >>> ppEditTree PP.char (treeDiff x z) -- (a b -(c d e) +d f) ---- -- If we add arguments, they are spotted too: -- --
-- >>> let w = Node 'a' [Node 'b' [], Node 'c' [return 'd', return 'x', return 'e'], Node 'f' []] -- -- >>> ppTree PP.char w -- (a b (c d x e) f) ---- --
-- >>> ppEditTree PP.char (treeDiff x w) -- (a b (c d +x e) f) --treeDiff :: (Show a, Eq a) => Tree a -> Tree a -> Edit (EditTree a) -- | Type used in the result of treeDiff. -- -- It's essentially a Tree, but the forest list is changed from -- [tree a] to [Edit (tree a)]. This highlights -- that treeDiff performs a list diff on each tree level. data EditTree a EditNode :: a -> [Edit (EditTree a)] -> EditTree a -- | List edit operations -- -- The Swp constructor is redundant, but it let us spot a -- recursion point when performing tree diffs. data Edit a -- | insert Ins :: a -> Edit a -- | delete Del :: a -> Edit a -- | copy unchanged Cpy :: a -> Edit a -- | swap, i.e. delete + insert Swp :: a -> a -> Edit a instance GHC.Show.Show a => GHC.Show.Show (Data.TreeDiff.Tree.EditTree a)