There has been a missing piece when it comes to set and maps regarding how to interpret unification identity and structural unification or arbritrary unificatoins. Also in exploring how to do this it is advicable to puiggy pack on attributed variables which already enables unification for it's content. The quest is to extend this to a higher degree to allow general extensible unifications and other constructs. So currently we have in guile log internal ways to do this but it's easy to extend this to prolog. So the predicate needed for prolog unifier writers is to have a `get_attr_data(X,L)`

, where `X`

is the attributed variable (or this will fail), and `L=[[Unify|Data],...]`

with the `Fkn`

and `Data`

taken from `put_attr(X,Unify,Data)`

. in guile-log we don't use modfues as a field for `Unify`

but in stead it is an identifying predicate, it has arbritrary signature, but when testing for `=`

unification you do `Unify(X,Y,#t)`

and for `==`

you do `Unify(X,Y,#f)`

. We added the following hook in guile-log for `=@=`

e.g. `Unify(X,Y,IX,IY,HX,HY,EX,EY,'mk-variant')`

I will later change this to `Unify(X,Y,variant)`

. With variant taken from `(logic guile-log prolog variant)`

. Ot turns out that we can have this code for general unify in guile-log:

```
fall2([],_,_).
fall2([K-A|L],Y,Op) :- K-B∈Y, call(Op,A,B), fall(L,Y,Op)
forall2(X,Y,Op) :-
set_to_kvlist(X,L),
fall2(L,Y,Op).
set_unify(V,W,#t) :- set_unify(V,W,=).
set_unify(V,W,#f) :- set_unify(V,W,==).
set_unify(V,W,Op) :-
(get_attr(V,set_unify,X) -> true; X=V),
(get_attr(W,set_unify,Y) -> true; Y=W),
X==Y,
forall2(X,Y,Op),
set_complement_as_set(X,XX),
set_complement_as_set(Y,YY),
XX==YY,
forall2(XX,YY,Op).
```

It's a cludge to use `#t`

and `#f`

here and this should be fixed. What we do is to take out the actual sets from the attributes and then check of they are identical. Pure sets and maps are identical if the keys are we also check the complement if they are the same. If the keys are the same (we keep a hash so if they are different the test is really quick), then we callect all key value pairs and match them with the other set and then iterate the operation on the value elements. Some experiments.

In comparison one of the set/maps has to be in a attribute. if it is a pure set then it is not needed to wrap them in a attribute. Anyway attribute generated operatoins is needed, so I added.

```
mk({1},X).
```

Makes a attributed variable from the set in the first argument.

`u`

is attributed generating union
`n`

is attributed generating intersection
`o`

is attributed generating set addition
`m`

is attributed generating set minus
`c`

is attributed generating complement.

So now we have

```
> mk({1-A,2-A},X),mk({1-C,2-B},Y),X=Y.
C = A,
X = Y,
B = A,
put_attr(Y, set_unify, ({1-X0,2-X0}∖∅ ∪ ∅)).
```

Note that the printer is not ecognizing that `X0`

is `A`

, this can be fixed by writing a custom `Unify(X,Y,write)`

that translates the set back to custom printer.

We also have.

```
> mk({1-A,2-B},X),mk({1-A,2-C},Y),[A,X]=@=[A,Y].
put_attr(Y, set_unify, ({1-X0,2-X1}∖∅ ∪ ∅)),
put_attr(X, set_unify, ({1-X0,2-X1}∖∅ ∪ ∅)).
```

Happy hacking!

## Comments

comments powered by Disqus