module Precis.Diff
(
Edit4(..)
, Edit3(..)
, diff4
, diff3
, addedRemoved
, conflictRemoved
, addedConflictRemoved
) where
import Precis.Utils.Common
import Data.List ( find )
data Edit4 a = ADD a | DIF a a | EQU a | DEL a
deriving (Eq,Show)
data Edit3 a = Add a | Equ a | Del a
deriving (Eq,Show)
instance Functor Edit4 where
fmap f (ADD a) = ADD (f a)
fmap f (DIF a b) = DIF (f a) (f b)
fmap f (EQU a) = EQU (f a)
fmap f (DEL a) = DEL (f a)
instance Functor Edit3 where
fmap f (Add a) = Add (f a)
fmap f (Equ a) = Equ (f a)
fmap f (Del a) = Del (f a)
diff4 :: (a -> a -> Bool) -> (a -> a -> Bool) -> [a] -> [a] -> [Edit4 a]
diff4 matches conflict as bs = toListH $ checkShort bs (checkLong as id)
where
checkLong [] f = f
checkLong (x:xs) f = case find (matches x) bs of
Just b | conflict x b -> checkLong xs (f `snocH` DIF x b)
| otherwise -> checkLong xs (f `snocH` EQU x)
Nothing -> checkLong xs (f `snocH` ADD x)
checkShort [] f = f
checkShort (y:ys) f = case find (matches y) as of
Just _ -> checkShort ys f
Nothing -> checkShort ys (f `snocH` DEL y)
diff3 :: (a -> a -> Bool) -> [a] -> [a] -> [Edit3 a]
diff3 matches as bs = toListH $ checkShort bs (checkLong as id)
where
checkLong [] f = f
checkLong (x:xs) f = case find (matches x) bs of
Just _ -> checkLong xs (f `snocH` Equ x)
Nothing -> checkLong xs (f `snocH` Add x)
checkShort [] f = f
checkShort (y:ys) f = case find (matches y) as of
Just _ -> checkShort ys f
Nothing -> checkShort ys (f `snocH` Del y)
addedRemoved :: [Edit4 a] -> ([a],[a])
addedRemoved = foldr fn ([],[])
where
fn (ADD a) (as,rs) = (a:as,rs)
fn (DEL r) (as,rs) = (as,r:rs)
fn _ acc = acc
addedConflictRemoved :: [Edit4 a] -> ([a],[(a,a)],[a])
addedConflictRemoved = foldr fn ([],[],[])
where
fn (ADD a) (as,cs,rs) = (a:as,cs,rs)
fn (DIF a b) (as,cs,rs) = (as,(a,b):cs,rs)
fn (DEL r) (as,cs,rs) = (as,cs,r:rs)
fn _ acc = acc
conflictRemoved :: [Edit4 a] -> ([(a,a)],[a])
conflictRemoved = foldr fn ([],[])
where
fn (DIF a b) (cs,rs) = ((a,b):cs,rs)
fn (DEL r) (cs,rs) = (cs,r:rs)
fn _ acc = acc