--
-- Substitutions and Unification of Prolog Terms
-- Mark P. Jones November 1990
--
-- uses Haskell B. version 0.99.3
--
module Subst(Subst, nullSubst, (->>), (@@), apply, unify) where
import PrologData
infixr 3 @@
infix 4 ->>
--- Substitutions:
type Subst = Id -> Term
-- substitutions are represented by functions mapping identifiers to terms.
--
-- apply s extends the substitution s to a function mapping terms to terms
-- nullSubst is the empty substitution which maps every identifier to the
-- same identifier (as a term).
-- i ->> t is the substitution which maps the identifier i to the term t,
-- but otherwise behaves like nullSubst.
-- s1 @@ s2 is the composition of substitutions s1 and s2
-- N.B. apply is a monoid homomorphism from (Subst,nullSubst,(@@))
-- to (Term -> Term, id, (.)) in the sense that:
-- apply (s1 @@ s2) = apply s1 . apply s2
-- s @@ nullSubst = s = nullSubst @@ s
apply :: Subst -> Term -> Term
apply s (Var i) = s i
apply s (Struct a ts) = Struct a (map (apply s) ts)
nullSubst :: Subst
nullSubst i = Var i
(->>) :: Id -> Term -> Subst
(->>) i t j | j==i = t
| otherwise = Var j
(@@) :: Subst -> Subst -> Subst
s1 @@ s2 = apply s1 . s2
--- Unification:
-- unify t1 t2 returns a list containing a single substitution s which is
-- the most general unifier of terms t1 t2. If no unifier
-- exists, the list returned is empty.
unify :: Term -> Term -> [Subst]
unify (Var x) (Var y) = if x==y then [nullSubst] else [x->>Var y]
unify (Var x) t2 = [ x ->> t2 | not (x `elem` varsIn t2) ]
unify t1 (Var y) = [ y ->> t1 | not (y `elem` varsIn t1) ]
unify (Struct a ts) (Struct b ss) = [ u | a==b, u<-listUnify ts ss ]
listUnify :: [Term] -> [Term] -> [Subst]
listUnify [] [] = [nullSubst]
listUnify [] (r:rs) = []
listUnify (t:ts) [] = []
listUnify (t:ts) (r:rs) = [ u2 @@ u1 | u1<-unify t r,
u2<-listUnify (map (apply u1) ts)
(map (apply u1) rs) ]
--- End of Subst.hs
|