是否有任何版本的Prolog支持累加器的高阶抽象



我想知道一个可以包含像这样的内置调用的Prolog:

accum(generator, filter, accumulator)
Calculates all solutions to generator.
For each one, if filter can be proved, accumulator is proved.
Backtracks to find all solutions to filter and generator.
Accumulator may backtrack internally, but multiple proofs of accumulator are 
  conjoined, not backtracked.

因此,例如,要在不使用递归的情况下对列表求和,您可以编写:

X is 0, accum(member(Val,List), True, X is X + Val).

是否有具有此结构的Prolog或等效结构?请记住,我是Prolog的新手,可能会错过一些明显的东西。

SWI-Prolog library(aggregate)具有强大的界面,例如

aggregate_all(sum(Val), member(Val,List), Sum)

聚合和生成之间变量的(显然很简单)共享是使用谓词 foreach/2 获得的,您可能会感兴趣。

在SWI-Prolog中,您可以做?- edit(library(aggregate)).来研究内部结构...

library(聚合)效率相对较低,但结合SWI-Prolog nb_(不可回溯)数据结构应该可以很好地完成它的工作......

关于不可回溯的数据结构:这是我的"自建"累加器的示例,通过 nb_setarg/3 实现。

我假设你的意思是没有明确的递归?如果是这样,您可以使用高阶谓词列表左折叠的实现以及 lambda 表达式来避免需要辅助谓词。以 Logtalk 为例,您可以编写:

?- Sum0 is 0, meta::fold_left([X,Y,Z]>>(Z is Y+X), Sum0, [1,2,3], Sum).
Sum0 = 0,
Sum = 6.

Logtalk可以用作大多数Prolog实现(http://logtalk.org/)的后端编译器。您还可以将 Ulrich 的 lambda 库 (http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord.html) 与受支持的 Prolog 编译器一起使用,以及为相同结果提供左折叠谓词的 Prolog 库。以现在的 YAP 为例:

$ yap
...
 ?- use_module(library(lambda)).
...
 ?- use_module(library(maplist)).
...
 ?- Sum0 is 0, foldl(X^Y^Z^(Z is Y+X), [1,2,3], Sum0, Sum).
Sum = 6,
Sum0 = 0.

简而言之,fold left 谓词遍历列表,递归地将第一个参数中的闭包应用于列表元素和累加器,返回最终累加器值。

在 Mercury 的标准库中,"解决方案"模块提供了这样的功能。

请注意,X is X + Val不会为 X 分配新值。如果 Val 为零,则为真,如果它是任何其他数字,则为假,这可能不是你的意思。像这样的累加器通常表示为初始值和最终值之间的关系。

在水星中,你的例子可以写成:

:- import_module solutions.
...
sumlist(List, Sum) :-
    Generator = (pred(Val::out) is nondet :- member(Val, List), true),
    Accumulator = (pred(X::in, Y::in, Z::out) is det :- Z = X + Y),
    aggregate(Generator, Accumulator, 0, Sum).

不需要单独的筛选器参数,因为它可以作为生成器的一部分包含在内。

最新更新