-- 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 -- | 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) ---- -- Note: currently this has O(n*m) memory requirements, for the -- sake of more obviously correct implementation. diffBy :: forall 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) -- | 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 :: 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) -- | 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 -> (Map 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 -> (Map 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.EditExpr instance GHC.Show.Show Data.TreeDiff.Expr.Expr instance GHC.Classes.Eq Data.TreeDiff.Expr.Expr instance Test.QuickCheck.Arbitrary.Arbitrary Data.TreeDiff.Expr.Expr -- | 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) -> ([(FieldName, doc)] -> doc) -> ([doc] -> doc) -> (doc -> doc) -> (doc -> doc) -> (doc -> doc) -> ([doc] -> doc) -> (doc -> doc) -> (doc -> doc -> doc) -> Pretty doc [ppCon] :: Pretty doc -> ConstructorName -> doc [ppRec] :: Pretty doc -> [(FieldName, doc)] -> doc [ppLst] :: Pretty doc -> [doc] -> doc [ppCpy] :: Pretty doc -> doc -> doc [ppIns] :: Pretty doc -> doc -> doc [ppDel] :: Pretty doc -> doc -> doc [ppSep] :: Pretty doc -> [doc] -> doc [ppParens] :: Pretty doc -> doc -> doc [ppHang] :: Pretty doc -> 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 -- | Pretty via pretty library. prettyPretty :: Pretty Doc -- | Pretty print Expr using pretty. -- --
-- >>> prettyExpr $ Rec "ex" (Map.fromList [("[]", App "bar" [])])
-- ex {`[]` = bar}
--
prettyExpr :: Expr -> Doc
-- | Pretty print Edit EditExpr using
-- pretty.
prettyEditExpr :: 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
-- | 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
-- | 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 -- | 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 {fooBool = [Just True], fooInt = Right -2 +3, fooString = "fo"}
--
--
--
-- >>> prettyEditExpr $ ediff (Foo (Right 42) [Just True, Just False] "old") (Foo (Right 42) [Nothing, Just False, Just True] "new")
-- Foo
-- {fooBool = [-Just True, +Nothing, Just False, +Just True],
-- fooInt = Right 42,
-- 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 where toExpr x = sopToExpr (gdatatypeInfo (Proxy :: Proxy a)) (gfrom x) listToExpr = Lst . map toExpr toExpr :: ToExpr a => a -> Expr toExpr :: (ToExpr a, Generic a, All2 ToExpr (GCode a), GFrom a, GDatatypeInfo 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 -- |
-- >>> prettyExpr $ sopToExpr (gdatatypeInfo (Proxy :: Proxy String)) (gfrom "foo") -- _:_ 'f' "oo" --sopToExpr :: (All2 ToExpr xss) => DatatypeInfo xss -> SOP I xss -> Expr 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.Integer.Type.Integer instance Data.TreeDiff.Class.ToExpr GHC.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.Base.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 (Data.List.NonEmpty.NonEmpty a) instance Data.TreeDiff.Class.ToExpr Data.Void.Void instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Monoid.Dual a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Monoid.Sum a) instance Data.TreeDiff.Class.ToExpr a => Data.TreeDiff.Class.ToExpr (Data.Monoid.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.Option 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.Base.Map k v) instance Data.TreeDiff.Class.ToExpr k => Data.TreeDiff.Class.ToExpr (Data.Set.Base.Set k) instance Data.TreeDiff.Class.ToExpr v => Data.TreeDiff.Class.ToExpr (Data.IntMap.Base.IntMap v) instance Data.TreeDiff.Class.ToExpr Data.IntSet.Base.IntSet instance Data.TreeDiff.Class.ToExpr v => Data.TreeDiff.Class.ToExpr (Data.Sequence.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.UTC.UTCTime instance Data.TreeDiff.Class.ToExpr Data.ByteString.Lazy.Internal.ByteString instance Data.TreeDiff.Class.ToExpr Data.ByteString.Internal.ByteString 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.Base.HashMap k v) instance Data.TreeDiff.Class.ToExpr k => Data.TreeDiff.Class.ToExpr (Data.HashSet.HashSet k) instance Data.TreeDiff.Class.ToExpr Data.Aeson.Types.Internal.Value -- | 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 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 -- | 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