ideas-0.6: src/Common/Rewriting/Unification.hs
-----------------------------------------------------------------------------
-- Copyright 2010, Open Universiteit Nederland. This file is distributed
-- under the terms of the GNU General Public License. For more information,
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer : bastiaan.heeren@ou.nl
-- Stability : provisional
-- Portability : portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Common.Rewriting.Unification (match, Matcher, associativeMatcher) where
import Common.Rewriting.Term
import Common.Rewriting.AC
import Common.Rewriting.MetaVar
import Common.Rewriting.Substitution
import Control.Monad
import qualified Data.IntSet as IS
import qualified Data.Map as M
-----------------------------------------------------------
-- Unification (in both ways)
{-
class ShallowEq a where
shallowEq :: a -> a -> Bool
-- The arbitrary type class is a quick solution to have smart generators
-- (in combination with lifting rules). The function in the RewriteRule module
-- cannot have a type class for this reason
-- The show type class is added for pretty-printing rules
class (MetaVar a, Uniplate a, ShallowEq a, Arbitrary a, Show a) => Rewrite a where
operators :: [Operator a]
-- default definition: no associative/commutative operators
operators = []
unify :: Rewrite a => a -> a -> [Substitution a]
unify = unifyWith operators
unifyM :: (MonadPlus m, Rewrite a) => a -> a -> m (Substitution a)
unifyM x y = msum $ map return $ unify x y
unifyWith :: Rewrite a => [Operator a] -> a -> a -> [Substitution a]
unifyWith ops = rec
where
rec x y =
case (isMetaVar x, isMetaVar y) of
(Just i, Just j) | i==j -> return emptySubst
(Just i, _) | not (hasMetaVar i y) -> return $ singletonSubst i y
(_, Just j) | not (hasMetaVar j x) -> return $ singletonSubst j x
_ -> do
guard (shallowEq x y)
case findOperator ops x of
Just op ->
concatMap (uncurry recList . unzip) (pairings op x y)
Nothing ->
recList (children x) (children y)
recList [] [] = return emptySubst
recList (x:xs) (y:ys) = do
s1 <- rec x y
s2 <- recList (map (s1 |->) xs) (map (s1 |->) ys)
return (s2 @@ s1)
recList _ _ = []
-}
-----------------------------------------------------------
-- Matching (or: one-way unification)
match :: Matcher -> Term -> Term -> [Substitution Term]
match m x y = do
s <- rec x y
guard (IS.null $ dom s `IS.intersection` getMetaVars y)
return s
where
rec (Meta i) y = do
guard (not (hasMetaVar i y))
return (singletonSubst i y)
rec x y = do
let (a, as) = getSpine x
(b, bs) = getSpine y
case isCon a >>= (`M.lookup` m) of
Just f ->
concatMap (uncurry recList . unzip) (f x y)
Nothing -> do
guard (a == b)
recList as bs
recList [] [] = return emptySubst
recList (x:xs) (y:ys) = do
s1 <- rec x y
s2 <- recList (map (s1 |->) xs) (map (s1 |->) ys)
return (s2 @@ s1)
recList _ _ = []
type Matcher = M.Map Symbol (Term -> Term -> [[(Term, Term)]])
associativeMatcher :: Symbol -> Matcher
associativeMatcher s = M.singleton s f
where
f a b = map (map make) result
where
(as, bs) = onBoth collect (a, b)
result = pairingsA2 True as bs
make = onBoth construct
collect = ($ []) . rec
where
rec term =
case isBinary s term of
Just (a, b) -> rec a . rec b
Nothing -> (term:)
construct xs
| null xs = error "associativeMatcher: empty list"
| otherwise = foldr1 (binary s) xs