(define unify
   X Y -> (unify-loop X Y []))

(define unify-loop
   X X MGU -> MGU
   X Y MGU -> [[X | Y] | MGU]    where (and (variable? X) (occurs-check? X Y))
   X Y MGU -> [[Y | X] | MGU]    where (and (variable? Y) (occurs-check? Y X))
   [X | Y] [W | Z] MGU -> (let NewMGU (unify-loop X W MGU)
                               (unify-loop (deref Y NewMGU) 
                                           (deref Z NewMGU) 
                                           NewMGU))
    _ _ _ ->  (error "unification failure"))

(define occurs-check?
   X X -> false
   X [Y | Z] -> (and (occurs-check? X Y) (occurs-check? X Z))
   _ _ -> true)

(define deref
   [X | Y] MGU -> (map (/. Term (deref Term MGU)) [X | Y])
   X MGU -> (let Binding (assoc X MGU)
                 (if (empty? Binding) 
                     X 
                     (deref (tl Binding) MGU))))
