Îõ³h$0,\«      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§ ¨ © ª NoneÙˆ tree-diffList edit operationsThe Ü constructor is redundant, but it let us spot a recursion point when performing tree diffs. tree-diffinsert tree-diffdelete tree-diffcopy unchanged tree-diffswap, i.e. delete + insert tree-diffList difference.diffBy (==) "hello" "world"9[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) Safe-Inferred5   tree-diffempty :: OMap String Integer fromList []  tree-diff Elements in key ascending order.  tree-diffÄ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")] tree-diff O(n log n)+. List in creation order. Doesn't respect « 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")] tree-diff8fromList [('g', "gamma"), ('b', "beta"), ('a', "alpha")]3fromList [('g',"gamma"),('b',"beta"),('a',"alpha")] tree-diff1let xs = fromList [('a', "alpha"), ('b', "beta")]-let ys = fromList [('c', 3 :: Int), ('b', 2)]alignWith id xs ys?fromList [('a',This "alpha"),('c',That 3),('b',These "beta" 2)] tree-diffÉxs = toAscList $ fromList [('a', "alpha"), ('b', "beta"), ('g', "gamma")]Éys = toAscList $ fromList [('g', "gamma"), ('b', "beta"), ('a', "alpha")]xs == ysTrueÉzs = toAscList $ fromList [('d', "delta"), ('b', "beta"), ('a', "alpha")]xs == zsFalse tree-diffNote: The instance uses , so «ual  s can be shown differently.   None -  tree-diffType used in the result of ediff. tree-diffunchanged tree tree-diff"A untyped Haskell-like expression."Having richer structure than just Tree allows to have richer diffs. tree-diff application  tree-diffrecord constructor! tree-difflist constructor" tree-diff"Record field name is a string too.# tree-diffConstructor name is a string$ tree-diff Diff two .For examples see ediff in Data.TreeDiff.Class. !"#$ !#"$None '(-9?ÔÖ×Ùçª, tree-diff- converts a Haskell value into untyped Haskell-like syntax tree, .(toExpr ((1, Just 2) :: (Int, Maybe Int))1App "_\215_" [App "1" [],App "Just" [App "2" []]]/ tree-diffDifference between two , 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"}0 tree-diffCompare different types.Note:? Use with care as you can end up comparing apples with oranges.https://github.com/phadej/tree-diff/blob/master/tests/Tests.hs for a proper example.¥ tree-diff goldenTest tree-diff test name tree-diffpath to "golden file" tree-diff result value¥¥None&À¦ tree-diff A variant of ===/, which outputs a diff when values are inequal.¦¦ None,B§ tree-diffType used in the result of ©.It's essentially a ­', but the forest list is changed from [tree a] to [ (tree a)]. This highlights that ©) performs a list diff on each tree level.© tree-diffA 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.ExamplesÄLet's start from simple tree. We pretty print them as s-expressions.Î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.8let 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)§¨©©§¨®    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“””•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯° ± ² ³ ´µ¶·¸¹º»¼½¾&tree-diff-0.2.2-8wWxAfXAEbtLRYpI4kyn9uData.TreeDiff.ListData.TreeDiff.OMapData.TreeDiff.ExprData.TreeDiff.ClassData.TreeDiff.ParserData.TreeDiff.PrettyData.TreeDiff.GoldenData.TreeDiff.QuickCheckData.TreeDiff.Tree Data.TreeDiffEditInsDelCpySwpdiffBy $fNFDataEdit $fShowCell$fEqEdit $fShowEditOMapemptyelems toAscListtoListfromList $fNFDataVal$fSemialignOMap$fArbitrary1OMap$fArbitraryOMap $fNFDataOMap$fEqOMap $fShowOMap $fFunctorOMap $fFunctorValEditExprEditAppEditRecEditLstEditExpExprAppRecLst FieldNameConstructorNameexprDiff$fArbitraryExpr $fNFDataExpr$fNFDataEditExpr$fShowEditExpr$fEqExpr $fShowExprGToExprToExprtoExpr listToExprediffediff'defaultExprViaShow genericToExpr$fToExprByteArray $fToExprThese $fToExprPair$fToExprThese0$fToExprEither $fToExprMaybe$fToExprKeyMap $fToExprKey $fToExprValue$fToExprHashSet$fToExprHashMap$fToExprHashed$fToExprTagged$fToExprVector$fToExprVector0$fToExprVector1$fToExprVector2 $fToExprUUID$fToExprScientific$fToExprShortByteString$fToExprByteString$fToExprByteString0$fToExprUTCTime $fToExprDay $fToExprText $fToExprText0 $fToExprSeq$fToExprIntSet$fToExprIntMap $fToExprSet $fToExprMap $fToExprTree $fToExprLast $fToExprFirst $fToExprMax $fToExprMin$fToExprOption $fToExprLast0$fToExprFirst0$fToExprProduct $fToExprSum $fToExprDual $fToExprVoid$fToExprNonEmpty$fToExprZipList $fToExprConst$fToExprIdentity $fToExprFixed $fToExprRatio$fToExpr(,,,,) $fToExpr(,,,) $fToExpr(,,) $fToExpr(,) $fToExpr[]$fToExprEither0$fToExprMaybe0 $fToExprChar $fToExprProxy$fToExprWord64$fToExprWord32$fToExprWord16 $fToExprWord8 $fToExprWord $fToExprInt64 $fToExprInt32 $fToExprInt16 $fToExprInt8 $fToExprInt$fToExprDouble $fToExprFloat$fToExprNatural$fToExprInteger$fToExprOrdering $fToExprBool $fToExpr() $fToExprExpr$fGSumToExprV1$fGSumToExpr:+: $fGToExprM1$fGLeafToExprK1$fGProductToExprM1$fGProductToExprU1$fGProductToExpr:*:$fGSumToExprM1$fShowAppOrRec exprParserPrettyppConppAppppRecppLstppCpyppInsppDelppEditsppEllipppParens escapeNameppExpr ppEditExprppEditExprCompact prettyPretty prettyExprprettyEditExprprettyEditExprCompact ansiWlPretty ansiWlExpransiWlEditExpransiWlEditExprCompactansiWlBgPretty ansiWlBgExpransiWlBgEditExpransiWlBgEditExprCompact ediffGoldenediffEqEditTreeEditNodetreeDiff$fShowEditTreeghc-prim GHC.ClassesEqbaseGHC.Showshowcontainers-0.6.2.1 Data.TreeTree