module Ideas.Common.Rewriting.Difference (difference, differenceWith) where
import Control.Monad
import Data.Function
import Data.Maybe
import Ideas.Common.Rewriting.Term
import Ideas.Common.View
difference :: IsTerm a => a -> a -> Maybe (a, a)
difference = differenceWith termView
differenceWith :: View Term a -> a -> a -> Maybe (a, a)
differenceWith v a b = do
(t1, t2) <- diffTerm (build v a) (build v b)
liftM2 (,) (match v t1) (match v t2)
diffTerm :: Term -> Term -> Maybe (Term, Term)
diffTerm p q =
case (getFunctionA p, getFunctionA q) of
(Just (s1, ps), Just (s2, qs))
| s1 == s2 -> diffList ps qs
| otherwise -> here
_ | p == q -> Nothing
| otherwise -> here
where
here = Just (p, q)
diffList xs ys
| length xs /= length ys = here
| otherwise =
case catMaybes (zipWith diffTerm xs ys) of
[] -> Nothing
[one] -> Just one
_ -> here
getFunctionA :: (Monad m, WithFunctions a) => a -> m (Symbol, [a])
getFunctionA a = f <$> getFunction a
where
f (s, xs) = (s, if isAssociative s then collectSym s a else xs)
collectSym :: WithFunctions a => Symbol -> a -> [a]
collectSym s a = maybe [a] (uncurry ((++) `on` collectSym s)) (isBinary s a)