module Darcs.Patch.Merge
(
Merge(..)
, selfMerger
, mergeFL
, naturalMerge
, prop_mergeSymmetric
, prop_mergeCommute
) where
import Darcs.Patch.Commute ( Commute(..) )
import Darcs.Patch.CommuteFn ( MergeFn )
import Darcs.Patch.Invert ( Invert(..) )
import Darcs.Patch.Witnesses.Eq ( Eq2(..), isIsEq )
import Darcs.Patch.Witnesses.Ordered
( (:\/:)(..)
, (:/\:)(..)
, FL(..)
, RL
, (:>)(..)
, reverseFL
, reverseRL
)
class Commute p => Merge p where
merge :: (p :\/: p) wX wY
-> (p :/\: p) wX wY
selfMerger :: Merge p => MergeFn p p
selfMerger = merge
instance Merge p => Merge (FL p) where
merge (NilFL :\/: x) = x :/\: NilFL
merge (x :\/: NilFL) = NilFL :/\: x
merge ((x:>:xs) :\/: ys) = case mergeFL (x :\/: ys) of
ys' :/\: x' -> case merge (ys' :\/: xs) of
xs' :/\: ys'' -> ys'' :/\: (x' :>: xs')
instance Merge p => Merge (RL p) where
merge (x :\/: y) = case merge (reverseRL x :\/: reverseRL y) of
(ry' :/\: rx') -> reverseFL ry' :/\: reverseFL rx'
mergeFL :: Merge p
=> (p :\/: FL p) wX wY
-> (FL p :/\: p) wX wY
mergeFL (p :\/: NilFL) = NilFL :/\: p
mergeFL (p :\/: (x :>: xs)) = case merge (p :\/: x) of
x' :/\: p' -> case mergeFL (p' :\/: xs) of
xs' :/\: p'' -> (x' :>: xs') :/\: p''
naturalMerge :: (Invert p, Commute p)
=> (p :\/: p) wX wY -> Maybe ((p :/\: p) wX wY)
naturalMerge (p :\/: q) = do
q' :> ip' <- commute (invert p :> q)
_ <- commute (p :> q')
return (q' :/\: invert ip')
prop_mergeSymmetric :: (Eq2 p, Merge p) => (p :\/: p) wX wY -> Bool
prop_mergeSymmetric (p :\/: q) =
case merge (p :\/: q) of
q' :/\: p' ->
case merge (q :\/: p) of
p'' :/\: q'' ->
isIsEq (q' =\/= q'') && isIsEq (p' =\/= p'')
prop_mergeCommute :: (Eq2 p, Merge p) => (p :\/: p) wX wY -> Bool
prop_mergeCommute (p :\/: q) =
case merge (p :\/: q) of
q' :/\: p' ->
case commute (p :> q') of
Nothing -> False
Just (q'' :> p'') ->
isIsEq (q'' =\/= q) && isIsEq (p'' =/\= p')
&&
case commute (q :> p') of
Nothing -> False
Just (p'' :> q'') ->
isIsEq (p'' =\/= p) && isIsEq (q'' =/\= q')