部分字典/记录统一?

时间:2012-10-09 22:02:16

标签: prolog clojure-core.logic minikanren

据我所知,一些Prolog支持开箱即用的类字典关联数据结构。对于这样做的实现,它们是否支持部分统一的概念与另一个实际上不包含所有键的结构?

例如,在core.logic / miniKanren的语法中:

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

这将返回单个结果,其中q绑定为1.

Prologs是否为此操作或此部分结构命名?

3 个答案:

答案 0 :(得分:5)

一般来说,一种方法是以标准的方式解决Prolog中基本数据类型选择不当的问题:通过添加库和使用接口。例如,SWI-Prolog附带assoc library,它实现了基于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)).

如果Left关联是Right关联的子集,则此谓词将为true,如上所述。我们可以测试它,看它是否正在做我们想要的事情:

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.

我意识到这个答案并没有真正回答你提出的问题,但我希望它能回答问题背后的问题。换句话说,需要不是对这些数据结构的特殊支持 - 上面的谓词也可以在关联列表上定义,你可以看到你需要的只是通常的方式制作空关联,添加,测试和生成关联的键/值以及基础数据结构变得无关紧要。无论是数据结构还是统一,都不需要特别的支持。特殊的语法肯定会让它看起来更好!但是没有必要得到你想要的行为。

答案 1 :(得分:3)

某些Prolog系统(如Eclipse)具有记录符号。这可以使用 当您事先知道地图的可能键时。但它需要 类型声明。记录符号也可以在Prolog decendant中找到 Erlang等语言。

这个想法非常简单。你首先申报 记录类型(这里发明了一些语法):

:- 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

再见

答案 2 :(得分:1)

我不清楚你真正想要的是什么,(你已经删除了散列方面),但是你可能更想要特征术语或特征结构?

他们受到语言学家的欢迎,并且是生活的一部分。

可以在属性变量的帮助下实现它们,但到目前为止,我还没有看到对它们的大量需求。

你也可以通过句法统一来模拟它们。它很笨拙,因为你需要用一个单独的参数来表示每个特征(你可以稍微好一些,但它也更复杂)。因此,如果您的程序包含n个特征,则特征结构将包含n个不同的参数,其中大多数参数永远不会被触及。但是,统一将直接按预期工作。