Подтвердить что ты не робот

Частичный словарь/объединение записей?

Я понимаю, что некоторые Prologs поддерживают словарно-подобные ассоциативные структуры данных из коробки. Для реализации, которые это делают, поддерживают ли они некоторое понятие частичной унификации с другой структурой, которая фактически не содержит всех ключей?

Например, в синтаксисе core.logic/miniKanren:

(run* [q]
  (== {:foo 1 :bar 2} (partial-map :foo q)))

Это вернет единственный результат, где q связано с 1.

Предоставляют ли Prologs эту операцию или эту частичную структуру имя?

4b9b3361

Ответ 1

Некоторые системы Prolog, такие как Eclipse, имеют запись записи. Это можно использовать когда вы заранее знаете возможные ключи вашей карты. Но это необходимо объявление типа. Запись записи также содержится в Prolog decendant такие языки, как Эрланг.

Идея очень проста. Вы сначала объявляете тип записи (какой-то синтаксис, изобретенный здесь):

:- rectype T{K1,...,Kn}.

Теперь вы можете использовать внутри своей программы Prolog записи, просто напишите (опять-таки какой-то синтаксис, изобретенный здесь):

... T{F1 = V1, .., Fn = Vm} ...

При компиляции тип записи будет преобразован в состав и тогда их можно легко использовать при нормальном объединении. Преобразование переупорядочивает пары значений ключа в соответствии с типом записи декларации, затем отбрасывает ключи и использует только позиции. Неиспользованные позиции заменяются анонимными переменными или по умолчанию, если объявление типа записи также охватывает это.

... T(W1, ..., Wn) ...

Ваш пример будет работать следующим образом:

:- rectype myrec{foo, bar}

?- myrec{foo=1,bar=2} = myrec{foo=q}

Последний запрос будет внутренне выполнен как:

?- myrec(1,2) = myrec(q,_).

Подробнее о том, как это работает Eclipse, см. здесь:
http://www.eclipseclp.org/doc/bips/kernel/syntax/struct-1.html

Для динамических карт, где набор ключей не является статическим, вы можете реализовать динамические структуры данных, как и другие сообщения о SWI-Prolog AVL деревья показывают. Или попросите систему Prolog описать конкретную структура данных. Реализуйте их с помощью FFI (интерфейс внешних функций) или доступ к ним, которые уже включены в систему Prolog. Например, Eclipse связывает пару, см. Раздел "Описание" в следующей статье:
http://www.eclipseclp.org/doc/bips/kernel/record/index.html

Bye

Ответ 2

Как правило, в Prolog используется стандартный выбор основных типов данных в Prolog: путем добавления библиотек и использования интерфейсов. SWI-Prolog, например, поставляется с библиотекой assoc, которая реализует основанную на AVL ассоциацию структура данных. (В стороне сбалансированные деревья чаще встречаются в функциональном и логическом программировании, чем хеш-таблицы, потому что легче создавать "постоянные" структуры данных на деревьях, чем хеш-таблицы, - стойкие в смысле использования внутренней структуры FP.)

Использование этой библиотеки выглядит примерно так:

?- [library(assoc)].
% library(assoc) compiled into assoc 0.00 sec, 97 clauses
true.

?- empty_assoc(Assoc).
Assoc = t.

?- empty_assoc(Assoc), get_assoc(test, Assoc, V).
false.

?- empty_assoc(Assoc), put_assoc(test, Assoc, foo, Assoc2).
Assoc = t,
Assoc2 = t(test, foo, -, t, t).

?- empty_assoc(Assoc), 
   put_assoc(test, Assoc, foo, Assoc2), 
   get_assoc(test, Assoc2, Value).
Assoc = t,
Assoc2 = t(test, foo, -, t, t),
Value = foo.

Как только у вас есть что-то, что дает вам такой интерфейс, вы можете определить все виды логических отношений поверх него. Когда у вас есть логические отношения, система нормального унификации Prolog позаботится об остальном - никакой специальной поддержки для того или иного типа данных не требуется. Основываясь на ваших требованиях, я думаю, что вы хотите, как отношение подмножества, за исключением проверки того, что все одна ассоциация находится в другой, и все они имеют одинаковое значение. Я предполагаю, что это будет выглядеть примерно так:

association_subset(Left, Right) :-
  forall(gen_assoc(Assoc, Left, Value), get_assoc(Assoc, Right, Value)).

Этот предикат будет действителен только в том случае, если левая ассоциация является подмножеством правой ассоциации, как определено выше. Мы можем проверить его и посмотреть, делает ли он то, что мы хотим:

simple(Assoc) :- 
  empty_assoc(Empty),
  put_assoc(foo, Empty, foo_test, V1),
  put_assoc(bar, V1, bar_test, Assoc).

complex(Assoc) :-
  simple(Assoc1),
  put_assoc(baz, Assoc1, bazzle, Assoc).

unrelated(Assoc) :-
  empty_assoc(Empty),
  put_assoc(baz, Empty, bazzle, Assoc).

...

?- simple(X), complex(Y), association_subset(X, Y).
X = t(foo, foo_test, <, t(bar, bar_test, -, t, t), t),
Y = t(baz, bazzle, -, t(bar, bar_test, -, t, t), t(foo, foo_test, -, t, t)).

?- simple(X), simple(Y), association_subset(X, Y).
X = Y, Y = t(foo, foo_test, <, t(bar, bar_test, -, t, t), t).

?- simple(X), unrelated(Y), association_subset(X, Y).
false.

?- complex(X), simple(Y), association_subset(X, Y).
false.

Мы можем перевести это на ваш точный вопрос так:

left(Assoc) :- 
  empty_assoc(Empty),
  put_assoc(foo, Empty, 1, Assoc).

right(Assoc) :-
  left(Assoc1),
  put_assoc(bar, Assoc1, 2, Assoc).

?- left(L), right(R), association_subset(L, R), get_assoc(foo, L, Q).
L = t(foo, 1, -, t, t),
R = t(foo, 1, <, t(bar, 2, -, t, t), t),
Q = 1.

Я понимаю, что этот ответ на самом деле не отвечает на заданный вами вопрос, но я надеюсь, что он ответит на вопрос под вопросом. Другими словами, для этих структур данных не требуется особой поддержки - вышеуказанный предикат можно определить и по спискам ассоциаций, вы можете видеть, что все, что вам нужно, это обычные способы создания пустых ассоциаций, добавления, тестирование и генерация ключей/значений ассоциации и базовой структуры данных становится неуместным. Никакая специальная поддержка не нужна ни по структуре данных, ни по унификации. Специальный синтаксис, безусловно, сделает его приятнее смотреть! Но вам не обязательно получать желаемое поведение.

Ответ 3

Мне не совсем понятно, что вы на самом деле хотите (вы удалили хэширующий аспект), но, может быть, вам скорее нужны функции или структуры функций?

Они популярны для лингвистов и были частью Жизни.

Их можно реализовать с помощью атрибутов, но до сих пор я не видел их большого спроса.

Вы также можете имитировать их немного неуклюже с синтаксической унификацией. Это неуклюже, потому что вам нужно представлять каждую функцию с отдельным аргументом (вы можете сделать это немного лучше, но это также более сложно). Поэтому, если ваша программа содержит n функций, структура объектов будет содержать n разных аргументов, большинство из которых никогда не будут затронуты. Однако унификация будет работать напрямую, как и предполагалось.