Îõ³h*1Ì. ­      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨© ª « ¬ 0.3.3  Safe-InferredÝ¢ 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-Inferred9 ,  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.     Safe-Inferred P  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. !"$#% !"$#% Safe-Inferred )*/=ÃØÚÛÝëA. 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" []]]1 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"}2 tree-diffCompare different types.Note:? Use with care as you can end up comparing apples with oranges. xs == concat (unconcat uncons xs)5 tree-diffF tree-diffprettyExpr $ toExpr UUID.nil+UUID "00000000-0000-0000-0000-000000000000"G tree-diff+prettyExpr $ toExpr (123.456 :: Scientific)scientific 123456 `-3`H tree-diffõtraverse_ (print . prettyExpr . toExpr . SBS.toShort . BS8.pack) ["", "\n", "foo", "foo\n", "foo\nbar", "foo\nbar\n"]"""\n""foo""foo\n"mconcat ["foo\n", "bar"]mconcat ["foo\n", "bar\n"]I tree-diffçtraverse_ (print . prettyExpr . toExpr . BS8.pack) ["", "\n", "foo", "foo\n", "foo\nbar", "foo\nbar\n"]"""\n""foo""foo\n"BS.concat ["foo\n", "bar"]BS.concat ["foo\n", "bar\n"]J tree-diffètraverse_ (print . prettyExpr . toExpr . LBS8.pack) ["", "\n", "foo", "foo\n", "foo\nbar", "foo\nbar\n"]"""\n""foo""foo\n"LBS.concat ["foo\n", "bar"]LBS.concat ["foo\n", "bar\n"]L tree-diff-prettyExpr $ toExpr $ ModifiedJulianDay 58014Day "2017-09-18"M tree-diffåtraverse_ (print . prettyExpr . toExpr . T.pack) ["", "\n", "foo", "foo\n", "foo\nbar", "foo\nbar\n"]"""\n""foo""foo\n"T.concat ["foo\n", "bar"]T.concat ["foo\n", "bar\n"]N tree-diffætraverse_ (print . prettyExpr . toExpr . LT.pack) ["", "\n", "foo", "foo\n", "foo\nbar", "foo\nbar\n"]"""\n""foo""foo\n"LT.concat ["foo\n", "bar"]LT.concat ["foo\n", "bar\n"]b tree-diff"prettyExpr $ toExpr $ Identity 'a' Identity 'a'd tree-diff(prettyExpr $ toExpr (3 % 12 :: Rational)_%_ 1 4l tree-diffprettyExpr $ toExpr 'a''a'!prettyExpr $ toExpr "Hello world" "Hello world""prettyExpr $ toExpr "Hello\nworld"concat ["Hello\n", "world"]Ütraverse_ (print . prettyExpr . toExpr) ["", "\n", "foo", "foo\n", "foo\nbar", "foo\nbar\n"]"""\n""foo""foo\n"concat ["foo\n", "bar"]concat ["foo\n", "bar\n"]° tree-diffname of concat12./034-12./034- Safe-InferredÝ;‰ tree-diff Parsers for  using parsers type-classes.ÁYou can use this with your parser-combinator library of choice: parsec,  attoparsec, trifecta...‰‰ Safe-Inferred# Š tree-diffßBecause we don't want to commit to single pretty printing library, we use explicit dictionary.Œ tree-diffDisplay $ tree-diffDisplay  Ž tree-diffDisplay ! tree-diffDisplay " tree-diffDisplay unchanged parts‘ tree-diffDisplay added parts’ tree-diffDisplay removed parts“ tree-diffCombined edits (usually some sep combinator)” tree-diffEllipsis• tree-diffParens an expression– tree-diff Escape field or constructor nameputStrLn $ escapeName "Foo"FooputStrLn $ escapeName "_×_"_×_putStrLn $ escapeName "-3"`-3`"putStrLn $ escapeName "kebab-case" kebab-case#putStrLn $ escapeName "inner space" `inner space`2putStrLn $ escapeName $ show "looks like a string""looks like a string".putStrLn $ escapeName $ show "tricky" ++ " " `"tricky" `putStrLn $ escapeName "[]"`[]`putStrLn $ escapeName "_,_"`_,_`— tree-diffPretty print an + using explicit pretty-printing dictionary.˜ tree-diffPretty print an  + using explicit pretty-printing dictionary.™ tree-diffLike ˜) but print unchanged parts only shallowlyš tree-diffŠ via pretty library.› tree-diff Pretty print  using pretty.https://github.com/phadej/tree-diff/blob/master/tests/Tests.hs for a proper example.§ tree-diffLike §À but with an additional argument for generation of actual value.¦ tree-diff goldenTest tree-diff test name tree-diffpath to "golden file" tree-diff result value§ tree-diff goldenTest tree-diff test name tree-diffpath to "golden file" tree-diff result value¦§¦§ Safe-Inferred(g¨ tree-diff A variant of ===/, which outputs a diff when values are inequal.¨¨  Safe-Inferred-ò© 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.3.3-24y5nzbntACLhqHDdFYAFrData.TreeDiff.ListData.TreeDiff.OMapData.TreeDiff.ExprData.TreeDiff.ClassData.TreeDiff.ParserData.TreeDiff.PrettyData.TreeDiff.GoldenData.TreeDiff.QuickCheckData.TreeDiff.Tree tree-diff Data.TreeDiffEditInsDelCpySwpdiffBy $fNFDataEdit $fShowCell$fEqEdit $fShowEditOMapemptyelems toAscListtoListfromList $fNFDataVal$fSemialignOMap$fArbitrary1OMap$fArbitraryOMap $fNFDataOMap $fOrdOMap$fEqOMap $fShowOMap $fFunctorOMap $fFunctorValEditExprEditAppEditRecEditLstEditExpExprAppRecLst FieldNameConstructorNameexprDiff$fArbitraryExpr $fNFDataExpr$fNFDataEditExpr$fShowEditExpr$fEqExpr $fOrdExpr $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 $fToExprLast0$fToExprFirst0$fToExprProduct $fToExprSum $fToExprDual $fToExprVoid$fToExprNonEmpty$fToExprZipList $fToExprConst$fToExprIdentity $fToExprFixed $fToExprRatio$fToExpr(,,,,) $fToExpr(,,,) $fToExpr(,,) $fToExpr(,) $fToExprList$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 ediffGolden ediffGolden1ediffEqEditTreeEditNodetreeDiff$fShowEditTreeghc-prim GHC.ClassesEqbaseGHC.Showshowunconcat stringToExprcontainers-0.6.7 Data.TreeTree