The following OBJ code specifies unification, first without occur check, and then with occur check; the code is executable, and a number of examples are given. This example is taken from

obj LIST[X :: TRIV] is sorts List NeList . op nil : -> List . subsorts Elt < NeList < List . op __ : List List -> List [assoc id: nil] . op __ : NeList List -> NeList . op __ : NeList NeList -> NeList . protecting NAT . op |_| : List -> Nat . eq | nil | = 0 . var E : Elt . var L : List . eq | E L | = 1 + | L | . op tail_ : NeList -> List [prec 120] . var E : Elt . var L : List . eq tail E L = L . endo obj SUBST is sorts Eqn Term . protecting QID . subsorts Id < Term . pr TERMS is (LIST *(sort List to TermList, sort NeList to NeTermList))[Term]. dfn Op is QID . op _[_] : Op TermList -> Term [prec 1] . op _=_ : Term Term -> Eqn [comm prec 120] . pr SYSTEM is (LIST *(sort List to System, sort NeList to NeSystem, op nil to null, op (__) to (_&_)))[Eqn]. op {_} : System -> System . *** scope delimiter op _=_ : TermList TermList -> System [comm prec 120] . vars T U V : Term . var Us : NeTermList . var S : NeSystem . var Ts : TermList . eq (T Ts = U Us) = (T = U)& (Ts = Us). op let_be_in_ : Id Term Term -> Term . op let_be_in_ : Id Term TermList -> TermList . op let_be_in_ : Id Term Eqn -> Eqn . op let_be_in_ : Id Term System -> System . vars X Y : Id . var F : Op . eq let X be T in nil = nil . eq let X be T in Y = if X == Y then T else Y fi . eq let X be T in F[Ts] = F[let X be T in Ts]. eq let X be T in (U Us) = (let X be T in U)(let X be T in Us). eq let X be T in (U = V) = ((let X be T in U) = (let X be T in V)) . eq let X be T in null = null . eq let X be T in ((U = V)& S) = (let X be T in(U = V))& (let X be T in S). endo ***> first without occur check obj UNIFY is using SUBST with SYSTEM and TERMS . op unify_ : System -> System [prec 120]. op fail : -> Eqn . var T : Term . vars Ts Us : TermList . vars S S' S'' : System . var X : Id . eq unify S = {{S}} . eq S &(T = T)& S' = S & S' . eq S & fail & S' = fail . eq let X be T in fail = fail . eq {null} = null . eq {fail} = fail . vars F G : Op . vars X : Id . eq {S & (F[Ts] = G[Us])& S'} = if F == G and | Ts | == | Us | then {S & (Ts = Us) & S'} else fail fi . eq {S & {S' &(X = T)& S''}} = if X == T then {S & {S' & S''}} else {(X = T)& (let X be T in S)& {let X be T in (S' & S'')}} fi . endo reduce unify 'f['g['X] 'Y] = 'f['g['h['Y]] 'h['Z]]. reduce unify 'f['X 'Y] = 'f['Y 'g['Y]]. reduce unify ('f['g['X] 'Y] = 'f['g['h['Y]] 'h['Z]])& ('h['X] = 'Z). reduce unify 'f['X 'g['Y]] = 'f['Z 'Z]. reduce unify 'f['X 'g['Y]] = 'f['Z]. reduce unify 'f['Y 'g['Y]] = 'f['h['Z] 'Z]. reduce unify 'f['Y 'a[nil]] = 'f['g['a[nil]] 'Z]. ***> now add occur check obj UNIFY-OCH is using UNIFY . op _in_ : Id TermList -> Bool . vars X Y : Id . var F : Op . var T : Term . var Ts : NeTermList . eq X in Y = X == Y . eq X in F[Ts] = X in Ts . eq X in T Ts = X in T or X in Ts . cq (X = T) = fail if X in T . endo reduce unify 'f['g['X] 'Y] = 'f['g['h['Y]] 'h['Z]]. reduce unify 'f['X 'Y] = 'f['Y 'g['Y]]. reduce unify ('f['g['X] 'Y] = 'f['g['h['Y]] 'h['Z]])& ('h['X] = 'Z). reduce unify 'f['X 'g['Y]] = 'f['Z 'Z]. reduce unify 'f['X 'g['Y]] = 'f['Z]. ***> reduce unify 'f['Y 'g['Y]] = 'f['h['Z] 'Z]. ***> this blows up! reduce unify 'f['Y 'a[nil]] = 'f['g['a[nil]] 'Z].

Click here to see the OBJ3 output from this example.

Notice that `LIST`

is a **generic module**, also called a
**parameterized module** in OBJ; it can be thought of as a template that
creates new modules, by instantiating the formal parameter `X`

with
some actual parameter, which could be just a sort, as in the expression
`LIST[Eqn]`

, or could be a whole module, as in the expression
`LIST[LIST[INT]]`

. (The details of how this works are rather
complex, but are not needed for this example; see **Introducing OBJ** if you really want to
know. OBJ generic modules are similar to those of Ada, but much more general;
in fact, the Ada notion was inspired by the one used in OBJ.)

Another OBJ construction used in the above is **renaming**, which allows
you to change the names of sorts and the syntax of operations in modules, as
in the expression `LIST *(sort List to System)`

, which renames the
sort `List`

to be `System`

. In the example above, the
syntax for the concatenation operation on lists is also renamed using this
construction. Notice that the parameter instantiation is done after the
renaming, although it could also have been done in the other order.

Back to CSE 230 homepage

Maintained by Joseph Goguen

© 2000, 2001 Joseph Goguen

Last modified: Fri Apr 12 15:54:34 PDT 2002