core-logic

noprompt 2017-12-06T22:15:19.000391Z

is there a rationale for why lvars as map keys do not unify?

(run* [q]
  (fresh [a b]
    (== {a b} {:a 2})
    (== q (list a b))))
;; => ()

noprompt 2017-12-06T22:19:46.000616Z

in my spare time i’ve been working on a term rewriting engine and was also confronted with the problem of unifying maps. i was able to find a solution that achieves this. i was surprised to find that core.logic doesn’t support this, however, i wouldn’t be surprised if i may have overlooked something in my own algorithm.

2017-12-06T22:44:27.000219Z

there is no one way to do it

noprompt 2017-12-06T22:48:25.000038Z

@hiredman explain.

2017-12-06T22:49:11.000027Z

(== {a b c d} {:a 1 😛 2})

2017-12-06T22:49:17.000194Z

(== {a b c d} {:a 1 :b 2})

noprompt 2017-12-06T22:50:09.000510Z

the algorithm i wrote unifies ground entries, then entries with ground values, then entries with ground keys, then entries where both the key and value are variable.

2017-12-06T22:50:35.000396Z

there is no single unification for that

noprompt 2017-12-06T22:50:42.000255Z

your example can be unified in multiple ways, the values can be streamed to a, b, c, and d in those cases.

noprompt 2017-12-06T22:50:57.000466Z

actually, that’s not true.

noprompt 2017-12-06T22:51:14.000085Z

the fact there exists a solution refutes that argument.

noprompt 2017-12-06T22:52:09.000035Z

so maybe my understanding here is misguided.

noprompt 2017-12-06T22:52:27.000448Z

can you explain your emphasis on “single”?

2017-12-06T22:54:08.000213Z

lists are defined inductively via cons, so there is a one order they can be walked for unification, and that orders arises from the definition

2017-12-06T22:55:20.000058Z

maps are not inductively defined, so there is no single iteration order, so there is no fixed thing to wire in to the unifier

2017-12-06T22:56:09.000185Z

you can do it, but you will have to make some choices to do it that preclude being general, which is what a library like core.logic is trying to do

noprompt 2017-12-06T22:57:18.000055Z

i see. can you elaborate more on why the inductive property is important?

noprompt 2017-12-06T22:58:12.000111Z

wrt core.logic?

noprompt 2017-12-06T23:03:00.000094Z

i’m guessing the solution here would be to use another goal in favor of == which does stream the substitutions.

2017-12-06T23:03:30.000068Z

because unification has to traverse datastructures, if a datastructure is defined inductively, that is an order the structure can be traversed

2017-12-06T23:04:46.000255Z

I bet you could make it work if you either only used one concrete map type, or sorted it before unifying

noprompt 2017-12-06T23:06:05.000200Z

the strategy i mentioned above works pretty well. although, again, my setting is term rewriting which expects the left-hand side of the equation to be ground.

2017-12-06T23:06:43.000490Z

sure, if your model is less general then you can do more

noprompt 2017-12-06T23:14:07.000297Z

so, in the context of core logic, would the solution then be two stream the solutions via a custom goal?

noprompt 2017-12-06T23:16:07.000182Z

i understand the rationale above now.