Does any version of Prolog support higher order battery abstraction?

I was wondering about Prolog, which might include an inline call like this:

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. 

So, for example, to summarize a list without using recursion, you can write:

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

Is there any prologue with this construct or equivalent? Keep in mind that I'm a little new to Prolog and may not see anything obvious.

+6
source share
3 answers

SWI-Prolog library (aggregate) has a powerful interface, for example

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

The (apparently simple) separation of variables among aggregation and generation is obtained using the foreach / 2 predicate, which might interest you.

In SWI-Prolog you can do ?- edit(library(aggregate)). to study the internal elements ...

Library

(aggregate) is relatively inefficient, but in combination with SWI-Prolog nb_ (non backtrackable) data structures should do its job well ...

About irreproducible data structures: here is an example of my "self-mounted" battery implemented using nb_setarg / 3.

+5
source

I assume you mean without explicit recursion? If so, you can use the implementation of the high-order predicate list fold left along with the lambda expression to avoid the need for an auxiliary predicate. Using Logtalk as an example, you can write:

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

Logtalk can use most Prolog implementations ( http://logtalk.org/ ) as the main compiler. You can also use the Ulrich lambda library ( http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord.html ) with the supported Prolog compiler along with the Prolog library providing a folded left predicate for the same result. Using now YAP as an example:

 $ 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. 

In short, the folded left predicate iterates over the list, recursively applying the closure in its first argument to the list item and battery, returning the final battery value.

+3
source

In the Mercury Standard Library, the "solutions" module provides features such as this.

Note that X is X + Val does not assign a new value to X. This is a statement that is true if Val is zero, and false if it is any other number, which is probably not what you mean. Batteries like this are usually expressed as the ratio between the start and end value.

In Mercury, your example can be written as:

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

There is no need for a separate filter argument, as it can be included as part of the generator.

+2
source

Source: https://habr.com/ru/post/956169/


All Articles