module Darcs.Patch.CommuteFn
( CommuteFn,
commuterIdFL, commuterFLId,
commuterIdRL, commuterRLId,
commuterRLFL,
MergeFn,
PartialMergeFn,
mergerIdFL,
TotalCommuteFn,
totalCommuterIdFL, totalCommuterFLId, totalCommuterFLFL,
invertCommuter
) where
import Darcs.Prelude
import Darcs.Patch.Invert ( Invert(..) )
import Darcs.Patch.Witnesses.Ordered
( (:>)(..)
, (:\/:)(..)
, (:/\:)(..)
, FL(..)
, RL(..)
)
type CommuteFn p1 p2 = forall wX wY . (p1 :> p2) wX wY -> Maybe ((p2 :> p1) wX wY)
type TotalCommuteFn p1 p2 = forall wX wY . (p1 :> p2) wX wY -> (p2 :> p1) wX wY
type MergeFn p1 p2 = forall wX wY . (p1 :\/: p2) wX wY -> (p2 :/\: p1) wX wY
type PartialMergeFn p1 p2 = forall wX wY . (p1 :\/: p2) wX wY -> Maybe ((p2 :/\: p1) wX wY)
commuterIdRL :: CommuteFn p1 p2 -> CommuteFn p1 (RL p2)
commuterIdRL _ (x :> NilRL) = return (NilRL :> x)
commuterIdRL commuter (x :> (ys :<: y))
= do ys' :> x' <- commuterIdRL commuter (x :> ys)
y' :> x'' <- commuter (x' :> y)
return ((ys' :<: y') :> x'')
commuterIdFL :: CommuteFn p1 p2 -> CommuteFn p1 (FL p2)
commuterIdFL _ (x :> NilFL) = return (NilFL :> x)
commuterIdFL commuter (x :> (y :>: ys))
= do y' :> x' <- commuter (x :> y)
ys' :> x'' <- commuterIdFL commuter (x' :> ys)
return ((y' :>: ys') :> x'')
mergerIdFL :: MergeFn p1 p2 -> MergeFn p1 (FL p2)
mergerIdFL _ (x :\/: NilFL) = NilFL :/\: x
mergerIdFL merger (x :\/: (y :>: ys))
= case merger (x :\/: y) of
y' :/\: x' -> case mergerIdFL merger (x' :\/: ys) of
ys' :/\: x'' -> (y' :>: ys') :/\: x''
totalCommuterIdFL :: TotalCommuteFn p1 p2 -> TotalCommuteFn p1 (FL p2)
totalCommuterIdFL _ (x :> NilFL) = NilFL :> x
totalCommuterIdFL commuter (x :> (y :>: ys)) =
case commuter (x :> y) of
y' :> x' -> case totalCommuterIdFL commuter (x' :> ys) of
ys' :> x'' -> (y' :>: ys') :> x''
commuterFLId :: CommuteFn p1 p2 -> CommuteFn (FL p1) p2
commuterFLId _ (NilFL :> y) = return (y :> NilFL)
commuterFLId commuter ((x :>: xs) :> y)
= do y' :> xs' <- commuterFLId commuter (xs :> y)
y'' :> x' <- commuter (x :> y')
return (y'' :> (x' :>: xs'))
commuterRLId :: CommuteFn p1 p2 -> CommuteFn (RL p1) p2
commuterRLId _ (NilRL :> y) = return (y :> NilRL)
commuterRLId commuter ((xs :<: x) :> y)
= do y' :> x' <- commuter (x :> y)
y'' :> xs' <- commuterRLId commuter (xs :> y')
return (y'' :> (xs' :<: x'))
commuterRLFL :: forall p1 p2. CommuteFn p1 p2 -> CommuteFn (RL p1) (FL p2)
commuterRLFL commuter (xs :> ys) = right xs ys
where
right :: RL p1 wX wY -> FL p2 wY wZ -> Maybe ((FL p2 :> RL p1) wX wZ)
right as NilFL = Just (NilFL :> as)
right as (b :>: bs) = do
b' :> as' <- commuterRLId commuter (as :> b)
bs' :> as'' <- left as' bs
return (b' :>: bs' :> as'')
left :: RL p1 wX wY -> FL p2 wY wZ -> Maybe ((FL p2 :> RL p1) wX wZ)
left NilRL bs = Just (bs :> NilRL)
left (as :<: a) bs = do
bs' :> a' <- commuterIdFL commuter (a :> bs)
bs'' :> as' <- right as bs'
return (bs'' :> as' :<: a')
totalCommuterFLId :: TotalCommuteFn p1 p2 -> TotalCommuteFn (FL p1) p2
totalCommuterFLId _ (NilFL :> y) = y :> NilFL
totalCommuterFLId commuter ((x :>: xs) :> y) =
case totalCommuterFLId commuter (xs :> y) of
y' :> xs' -> case commuter (x :> y') of
y'' :> x' -> y'' :> (x' :>: xs')
totalCommuterFLFL :: TotalCommuteFn p1 p2 -> TotalCommuteFn (FL p1) (FL p2)
totalCommuterFLFL commuter = totalCommuterFLId (totalCommuterIdFL commuter)
{-# INLINE invertCommuter #-}
invertCommuter :: (Invert p, Invert q) => CommuteFn p q -> CommuteFn q p
invertCommuter commuter (x :> y) = do
ix' :> iy' <- commuter (invert y :> invert x)
return (invert iy' :> invert ix')