Моделирование exists_check=ошибка в SICStus Prolog

Оказывается, что SICStus Prolog не имеет флага Prolog exists_check. По крайней мере, мы не смогли найти его, и здесь выдается сообщение об ошибке:

      /* SICStus 4.6.0 (x86_64-win32-nt-4) */

?- set_prolog_flag(occurs_check, true).
Domain error in argument 1 of set_prolog_flag/2 

Кажется, что значение "true" не так уж и проблема, критические унификации могут быть реализованы с помощью существующих встроенных unify_with_occurs_check/2. Интересным значением флага Prolog exists_check является значение "ошибка".

Как можно реализовать предикат unify_with_occurs_check_and_error/2? Обратите внимание, что решение для unify_with_occurs_check_and_error/2 должно вести себя как unify_with_occurs_check/2, то есть не запускать переменные с атрибутами.

Вот пример использования флага Пролога, если он присутствует:

      ?- set_prolog_flag(occurs_check, error).
true.

?- X = f(X).
ERROR: ...

И это то, что можно было бы сделать в SICStus Prolog:

      ?- unify_with_occurs_check_and_error(X, f(X)).
ERROR: ...

1 ответ

Адаптировал код отсюда и получил следующее решение:

      unify_with_error(X, Y) :- var(X), var(Y), !, X = Y.
unify_with_error(X, Y) :- var(X), !, must_notin(X, Y), X = Y.
unify_with_error(X, Y) :- var(Y), !, must_notin(Y, X), X = Y.
unify_with_error(X, Y) :- functor(X, F, A), functor(Y, G, B),
   F/A = G/B,
   X =.. [_|L],
   Y =.. [_|R],
   maplist(unify_with_error, L, R).

must_notin(X, Y) :-
   term_variables(Y, L),
   maplist(\==(X), L), !.
must_notin(X, Y) :-
   throw(error(occurs_check(X, Y),_)).

Кажется, работает и не мешает атрибутированным переменным:

      /* SICStus 4.6.0 (x86_64-win32-nt-4) */

?- unify_with_error(X, f(X)). 
error(occurs_check(_413,f(_413)),_409)

?- freeze(X, throw(ball)), unify_with_error(X, f(X)).
error(occurs_check(_413,f(_413)),_409)
Другие вопросы по тегам