Пролог: разница между var, nonvar и ground

#prolog

#пролог

Вопрос:

В Prolog, особенно в его аспектах метапрограммирования, люди часто говорят о основных и неосновных переменных. А также использование таких предикатов, как var/1, nonvar/1 и ground/1. Но в чем именно разница между ними?

Мое текущее понимание заключается в следующем:

  • Var полностью деинсталлируется (например. X)
  • Создается экземпляр nonvar, но он может содержать некоторые переменные глубже (например, term(1,2,Y)). Это похоже на слабую головную нормальную форму из Haskell.
  • Экземпляр основного var создается полностью, вплоть до самого низа (например, term(1,2,3)).

Правильно ли это?

Комментарии:

1. Да, ваша интуиция верна. Просто имейте в виду, что, например, X = a, ground(X) успешно, но ground(X), X = a терпит неудачу. Другими словами, металогические предикаты предоставляют вам информацию о статусе создания термина в текущем деривации (при текущей замене ответа), а не о синтаксической структуре его аргумента.

Ответ №1:

Почти.

  • Если var(X) то переменная X обозначает что-то, что не было создано, «дыру». X является «новой переменной». Примечание: Этот предикат действительно должен быть назван fresh(...) . Является ли X переменной, на самом деле вопрос о тексте программы. Но что мы хотим знать, так это является ли то, что находится между круглыми скобками, новой переменной (в момент выполнения этого вызова, потому что, совершенно нелогично, это может измениться.)

  • nonvar(X) является просто дополнением var(X) , таким же, как var(X) . Все, что находится между круглыми скобками, обозначает что-то (если это переменная) или является чем-то (если это непеременный термин, как в nonvar(foo) ), что не является «дырой».

  • ground(X) означает, что все, что находится между круглыми скобками, обозначает что-то или является чем-то, что не имеет отверстий в своей структуре (по сути, никаких отверстий в конце термина).

Немного тестового кода. Я ожидал, что компилятор выдаст больше предупреждений, чем он выдал.

 :- begin_tests(var_nonvar).

% Amazingly, the compiler does not warn about the code below.

test("var(duh) is always false", fail) :-
  var(duh). 

% Amazingly, the compiler does not warn about the code below.

test("var(X) is true if X is a fresh variable (X designates a 'hole')") :-
   var(_). 

% Compiler warning: " Singleton variable, Test is always true: var(X)"

test("var(X) is true if X is a fresh variable (X designates a 'hole')") :-
   var(X). 
   
% The hole designated by X is filled with f(_), which has its own hole.
% the result is nonvar (and also nonground)

test("var(X) maybe true but become false as computation progresses") :-
   var(X),X=f(_),nonvar(X).
   
test("var(X) is false otherwise") :-
   var(_).   

% The hole is designated by an anonymous variable

test("a fresh variable is not ground, it designates a 'hole'", fail) :-
   ground(_). 
   
% Both hhe holes are designated by anonymous variables

test("a structure with 'holes' at the leaves is non-ground", fail) :-
   ground(f(_,_)). 
   
test("a structure with no 'holes' is ground") :-
   ground(f(x,y)).

test("a structure with no 'holes' is ground, take 2") :-
   X=f(x,y), ground(X).
   
% var/1 or ground/1 are questions about the state of computation,
% not about any problem in logic that one models. For example:

test("a structure that is non-ground can be filled as computation progresses") :-
   K=f(X,Y),   ground(f(X,Y)), X=x, Y=y, ground(f(X,Y)).
   
:- end_tests(var_nonvar).

  

Комментарии:

1. Почему вы настаиваете на fresh? X = Y, var(Y). выполняется успешно, хотя Y является псевдонимом для Y и встречается ранее в запросе.

2. @lambda.xy.x Это личное дело каждого. «Ранее в запросе» (или, скорее, цель) на самом деле не важна. В идеальном мире Prolog переставил бы элементы цели, чтобы найти «наилучший способ разрешения ограничений между переменными» — поэтому действительно важно «ранее в обработке» или просто «пока неинициализированный», следовательно, «свежий», что является хорошим словом, как и любое другое.

3. Но это то, что я имел в виду: X не является собственной переменной, иначе мы могли бы ввести квантификатор. Но X = Y ∧ var(Y) не эквивалентно X = Y ∧ ∀Z var(Z) . (Кроме того, var/1 в любом случае является внелогическим предикатом, он не учитывает коммутативность соединения).

4. @DavidTonhofer Обсуждение логики отвлекает, но исходный пункт остается неизменным: запрос X = Y, var(X), var(Y) выполнен успешно. Тем не менее, по крайней мере, одно из X или Y не является ни «свежим», ни «еще неинициализированным», ни даже «несвязанным» во время выполнения var/1 вызовов.

5. @Penelope да, это понятие может быть полезным. var(X) соответствует утверждению, которое X не «заполнено» в этом смысле. nonvar(X) это означало бы, что он «заполнен» по крайней мере частично, т. Е. он привязан к термину, но этот термин все еще может содержать «незаполненные» переменные. ground(X) означает, что X привязано к термину, который не содержит никаких «незаполненных» переменных.