22-- | A list diff.
33module Data.TreeDiff.List (diffBy , Edit (.. )) where
44
5- import Control.DeepSeq (NFData (.. ))
6- import Data.List.Compat (sortOn )
5+ import Control.DeepSeq (NFData (.. ))
76
87import qualified Data.Vector as V
98
@@ -39,36 +38,35 @@ instance NFData a => NFData (Edit a) where
3938-- of more obviously correct implementation.
4039--
4140diffBy :: forall a . (a -> a -> Bool ) -> [a ] -> [a ] -> [Edit a ]
42- diffBy eq xs' ys' = reverse (snd (lcs xn yn))
41+ diffBy eq xs' ys' = reverse (getCell (lcs xn yn))
4342 where
4443 xn = V. length xs
4544 yn = V. length ys
4645
4746 xs = V. fromList xs'
4847 ys = V. fromList ys'
4948
50- memo :: V. Vector (Int , [Edit a ])
49+ memo :: V. Vector (Cell [Edit a ])
5150 memo = V. fromList
5251 [ impl xi yi
5352 | xi <- [0 .. xn]
5453 , yi <- [0 .. yn]
5554 ]
5655
57- lcs :: Int -> Int -> ( Int , [Edit a ])
56+ lcs :: Int -> Int -> Cell [Edit a ]
5857 lcs xi yi = memo V. ! (yi + xi * (yn + 1 ))
5958
60- impl :: Int -> Int -> ( Int , [Edit a ])
61- impl 0 0 = ( 0 , [] )
59+ impl :: Int -> Int -> Cell [Edit a ]
60+ impl 0 0 = Cell 0 []
6261 impl 0 m = case lcs 0 (m- 1 ) of
63- (w, edit) -> (w + 1 , Ins (ys V. ! (m - 1 )) : edit)
62+ Cell w edit -> Cell (w + 1 ) ( Ins (ys V. ! (m - 1 )) : edit)
6463 impl n 0 = case lcs (n - 1 ) 0 of
65- (w, edit) -> (w + 1 , Del (xs V. ! (n - 1 )) : edit)
64+ Cell w edit -> Cell (w + 1 ) ( Del (xs V. ! (n - 1 )) : edit)
6665
67- impl n m = head $ sortOn fst
68- [ edit
69- , bimap (+ 1 ) (Ins y : ) (lcs n (m - 1 ))
70- , bimap (+ 1 ) (Del x : ) (lcs (n - 1 ) m)
71- ]
66+ impl n m = bestOfThree
67+ edit
68+ (bimap (+ 1 ) (Ins y : ) (lcs n (m - 1 )))
69+ (bimap (+ 1 ) (Del x : ) (lcs (n - 1 ) m))
7270 where
7371 x = xs V. ! (n - 1 )
7472 y = ys V. ! (m - 1 )
@@ -77,5 +75,18 @@ diffBy eq xs' ys' = reverse (snd (lcs xn yn))
7775 | eq x y = bimap id (Cpy x : ) (lcs (n - 1 ) (m - 1 ))
7876 | otherwise = bimap (+ 1 ) (Swp x y : ) (lcs (n - 1 ) (m - 1 ))
7977
80- bimap :: (a -> c ) -> (b -> d ) -> (a , b ) -> (c , d )
81- bimap f g (x, y) = (f x, g y)
78+ data Cell a = Cell ! Int ! a
79+
80+ getCell :: Cell a -> a
81+ getCell (Cell _ x) = x
82+
83+ bestOfThree :: Cell a -> Cell a -> Cell a -> Cell a
84+ bestOfThree a@ (Cell i _x) b@ (Cell j _y) c@ (Cell k _z)
85+ | i <= j
86+ = if i <= k then a else c
87+
88+ | otherwise
89+ = if j <= k then b else c
90+
91+ bimap :: (Int -> Int ) -> (a -> b ) -> Cell a -> Cell b
92+ bimap f g (Cell i x) = Cell (f i) (g x)
0 commit comments