标签: meta-predicate

从谓词中收集所有"最小"解决方案

鉴于数据库中的以下事实:

foo(a, 3).
foo(b, 2).
foo(c, 4).
foo(d, 3).
foo(e, 2).
foo(f, 6).
foo(g, 3).
foo(h, 2).
Run Code Online (Sandbox Code Playgroud)

我想收集所有具有最小第二个参数的第一个参数,加上第二个参数的值.第一次尝试:

find_min_1(Min, As) :-
    setof(B-A, foo(A, B), [Min-_|_]),
    findall(A, foo(A, Min), As).

?- find_min_1(Min, As).
Min = 2,
As = [b, e, h].
Run Code Online (Sandbox Code Playgroud)

而不是setof/3,我可以使用aggregate/3:

find_min_2(Min, As) :-
    aggregate(min(B), A^foo(A, B), Min),
    findall(A, foo(A, Min), As).

?- find_min_2(Min, As).
Min = 2,
As = [b, e, h].
Run Code Online (Sandbox Code Playgroud)

NB

如果我正在寻找最小数字,这只会给出相同的结果.如果涉及算术表达式,结果可能会有所不同.如果涉及非数字,aggregate(min(...), ...)将抛出错误!

或者,我可以使用完整的键排序列表:

find_min_3(Min, As) :-
    setof(B-A, foo(A, …
Run Code Online (Sandbox Code Playgroud)

prolog backtracking aggregates prolog-setof meta-predicate

7
推荐指数
1
解决办法
946
查看次数

依靠规则顺序

为了计算两个相同长度的列表之间的汉明距离,我使用foldl(hamm, A, B, 0, R).这个定义hamm/4:

hamm(A, A, V, V) :- !.
hamm(A, B, V0, V1) :- A \= B, V1 is V0 + 1.
Run Code Online (Sandbox Code Playgroud)

第一条规则中的切入可以防止不必要的回溯.但是,第二条规则的写法可能不同:

hamm2(A, A, V, V) :- !.
hamm2(_, _, V0, V1) :- V1 is V0 + 1.
Run Code Online (Sandbox Code Playgroud)

并且对于A和B都被接地的查询hamm2/4仍然是正确的foldl/5.

那么有一个很好的理由更喜欢一个而不是另一个吗?或者有理由按规定保留规则或切换它们吗?

我知道查询

hamm(a, B, 0, 1).
Run Code Online (Sandbox Code Playgroud)

是假的,而

hamm2(a, B, 0, 1).
Run Code Online (Sandbox Code Playgroud)

是的,但我无法确定哪一个更有意义...

prolog meta-predicate

6
推荐指数
1
解决办法
124
查看次数

目标模块扩展传递给库元谓词

使用SWI-Prolog(多线程,64位,版本7.3.5),我们一步一步地进行:

  1. 限定非终结a//1在模块dcgAux(发音: " 二SEE-吴 "):

    :- module(dcgAux,[a//1]).
    
    a(0)    --> [].
    a(s(N)) --> [a], a(N).
    
  2. 运行以下查询 - 使用phrase/2apply:foldl/4:

    ?- use_module([library(apply),dcgAux]).
    true.
    
    ?- phrase(      foldl(       a,[s(0),s(s(0))]),[a,a,a]).
    true.
    
    ?- phrase(      foldl(dcgAux:a,[s(0),s(s(0))]),[a,a,a]).
    true.
    
    ?- phrase(apply:foldl(dcgAux:a,[s(0),s(s(0))]),[a,a,a]).
    true.
    
    ?- phrase(apply:foldl(       a,[s(0),s(s(0))]),[a,a,a]).
    ERROR: apply:foldl_/4: Undefined procedure: apply:a/3
    

    Нет!相当惊讶 - 而不是一个好的.我们是否遗漏了一些未知的未知数?

  3. 为了摆脱上述恼人的行为,我们必须首先找出导致它的原因:

    ?- import_module(apply,M), M=user.
    false.
    
    ?- phrase(apply:foldl(a,[s(0),s(s(0))]),[a,a,a]).
    ERROR: apply:foldl_/4: Undefined procedure: apply:a/3
    
    ?- add_import_module(apply,user,end).
    true.
    
    ?- import_module(apply,M), M=user. …

module prolog meta-predicate

5
推荐指数
1
解决办法
129
查看次数

Prolog 高阶归约谓词

我们可以将高阶映射谓词定义为:

map([], [], F).
map([A|As], [B|Bs], F) :-
   call(F, A, B),
   map(As, Bs, F).
Run Code Online (Sandbox Code Playgroud)

同样,我们可以将fold (left)定义为:

fold([], Acc, Acc, _F).
fold([A|As], B, Acc1, F) :-
   call(F, Acc1, A, Acc2),
   fold(As, B, Acc2, F).
Run Code Online (Sandbox Code Playgroud)

reduce(左)的正确定义是什么?我们可以这样定义吗?

reduce([A|As], Bs, F) :-   
   fold(As, Bs, A, F).
Run Code Online (Sandbox Code Playgroud)

减少(右)如下?

reduceback([], Ident, F) :-
   identity(F, Ident).
reduceback([A|As], B, F) :-
   reduceback(As, C, F),
   call(F, C, A, B).
Run Code Online (Sandbox Code Playgroud)

这些正确吗?

prolog higher-order-functions meta-predicate

5
推荐指数
1
解决办法
578
查看次数

带有参数化谓词的映射列表

是否可以在 中使用参数化谓词mapList

例如,我想执行以下操作:按列表迭代,对于每个偶数元素(列表仅包含数字)将此元素映射到某个值(该值由谓词的参数设置)。

示例查询:

?- mapList(p(red, blue), [1,2,3,4], [red, blue, red, blue]).
true.

?- mapList(p(green, blue), [1,2,3,4], [green, blue, green, blue]).
true.
Run Code Online (Sandbox Code Playgroud)

list prolog meta-predicate

5
推荐指数
1
解决办法
1503
查看次数

不合格的断言将术语添加到哪些模块?

?- assertz(:- module(foo1, [f/1])).
true.

?- foo1:assertz(f(1)).
true.

?- foo1:f(1).
true.

?- foo2:f(1).
Correct to: "foo1:f(1)"? no
ERROR: Undefined procedure: foo2:f/1
ERROR: In:
ERROR:    [8] foo2:f(1)
ERROR:    [7] <user>
Run Code Online (Sandbox Code Playgroud)

我感觉合理。但是然后(从头开始)......

?- assertz(:- module(foo1, [f/1])).
true.

?- assertz(f(1)).
true.

?- foo1:f(1).
true.

?- foo2:f(1).
true.    # Wait, what? foo2 doesn't appear in my program. Should fail?

?- frobnoz:f(1).
true.    # Also odd!
Run Code Online (Sandbox Code Playgroud)

但是之后...

?- foo2:assertz(f(1)).
true.

?- foo2:f(1).
true.

?- frobnoz:f(1).
ERROR: Undefined procedure: frobnoz:f/1
Run Code Online (Sandbox Code Playgroud)

如何F取得加入到foo2时候我不提foo2。为什么frobnoz:f …

module swi-prolog meta-predicate

5
推荐指数
1
解决办法
121
查看次数

Prolog中的Lambda?

我通常能够通过 maplist 找出 Lambda 的一些用法,但通常很难在 prolog 中使用 lambda。这可能是因为它与其他语言不同,因为统一。

这是症结之一:如何应用声明的 Lambda 表达式?铁

LAM = \X^R^(....)
Run Code Online (Sandbox Code Playgroud)

(奇怪,= 和 \ 之间必须有空格)

你好吗 :

\(LAM)(abc,R)
Run Code Online (Sandbox Code Playgroud)

我想做的另一件事是像 FACT 一样存储 Lambda 表达式,以便我可以查询它,但也可以像 lambda 函数一样使用它,以便我可以稍后进行绑定......我可以认为它错了..

move = \Obj^From^To(move(Obj,From,To))
Run Code Online (Sandbox Code Playgroud)

实例化:

?- \(move)(ball,ground,table).
Run Code Online (Sandbox Code Playgroud)

或部分:

?- L2 = \(move)(ball).
?- L3 = \(L2)(table,floor)
Run Code Online (Sandbox Code Playgroud)

询问 :

?- move(ball,F,T).
Run Code Online (Sandbox Code Playgroud)

lambda prolog meta-predicate

5
推荐指数
1
解决办法
173
查看次数

为什么 maplist/3 不使用模板?

所述MAPLIST / 3谓词具有以下形式

maplist(:Goal, ?List1, ?List2)
Run Code Online (Sandbox Code Playgroud)

然而,非常相似的函数findall/3具有以下形式

findall(+Template, :Goal, -Bag)
Run Code Online (Sandbox Code Playgroud)

它不仅有一个目标,还有一个模板。我发现这个模板在很多地方都非常有用,并开始想知道为什么 maplist/3 没有一个。

为什么 maplist/3 没有模板参数而 findall/3 有?这些谓词之间的显着区别是什么?

prolog meta-predicate

4
推荐指数
1
解决办法
533
查看次数

是否可以将maplist/3与'anonymous'谓词一起使用?

我想用maplist/3实现的目标可以是跟随伪代码:

maplist(
   lambda X: Z/Y=X, to_lower(Z,LC), char_code(L,LC), return L/Y,
   ['A'/42, 'B'/500],
   Res).
Res = ['a'/42, 'b'/500]
Run Code Online (Sandbox Code Playgroud)

我知道可以写例如

maplist(plus(1), [1,2,3,4], Res).
Res = [2,3,4,5].
Run Code Online (Sandbox Code Playgroud)

所以我可以将伪代码定义lambda X: Z/Y=X, to_lower(Z,LC), char_code(L,LC), return L/Y为普通谓词,并在maplist中使用此谓词...

但是,我很好奇是否可以在不创建全新谓词的情况下执行此操作?

我想这样做的原因是因为我觉得阅读更自然,而不是在代码中跳转来找到谓词

lambda prolog meta-predicate

3
推荐指数
1
解决办法
90
查看次数

Prolog 绑定参数

在 sicstus prolog 中,有一个谓词:

maplist(:Pred, +List)
Run Code Online (Sandbox Code Playgroud)

Pred应该只采用一个参数 -List元素。如何通过定义第一个参数的 2 参数谓词?在其他语言中,它会被写成:

maplist(pred.bind(SomeValue), List)
Run Code Online (Sandbox Code Playgroud)

prolog meta-predicate

2
推荐指数
1
解决办法
3138
查看次数

高阶谓词

boolean(true).
boolean(false).
formula_0(P, Q):- (P; Q), \+ P.

solution_for_formula(P, Q, Formula):-
    maplist(boolean, [P, Q]), call([Formula, P, Q]).
Run Code Online (Sandbox Code Playgroud)

对我之前的问题的跟进。为什么这行不通?(如果我call([Formula, P, Q])formula_0(P, Q)它替换它有效。)

prolog higher-order-functions meta-predicate

1
推荐指数
1
解决办法
918
查看次数

努力将 Prolog 的 maplist/2 用作函数映射函数

我正在使用 SWI-prolog,我正在尝试创建一个辅助函数,该函数将映射到一个列表并将每个元素与给定的整数相乘。我的目的是创建一个对应于 Haskell 函数的谓词multByN x n = x * n并在这个意义上使用它:

map (multByN 3) [1,2,3] 这会将所有元素乘以 3 并产生 [3,6,9]

我在 Prolog 中搜索了相应的谓词,maplist/2但发现我只能使用它来检查列表中每个元素的布尔条件是否成立,而不是实际返回一个新的、处理过的列表。我了解这是如何工作的:

isEven(X) :- 0 is X mod 2

maplist(isEven, [2,4,6])true.

但是,我不明白人们会如何将maplist(multByN(3), [1,2,3])某些变量与[3,6,9]. 由于我无法弄清楚这一点,因此我尝试实现我自己的映射函数,将谓词映射multByN到列表,我得到了一些看起来正确的东西,但事实并非如此。我有这个:

multByN(X, N, Y) :- Y is N*X.

mapFunc(_, [], L) :-
    write(L), nl.

mapFunc(N, [H|T], L) :-
    multByN(H, N, Z),
    mapFunc(N, T, [Z|L]).
Run Code Online (Sandbox Code Playgroud)

使用这个谓词我得到:

?- mapFunc(3, [1,2,3], X).
[9,6,3|_1746]
true ;
Run Code Online (Sandbox Code Playgroud)

在这里,我实际上是在打印最终列表以查看它的样子,但是我们可以看到查询实际上并没有说,X = …

mapping prolog meta-predicate

0
推荐指数
1
解决办法
710
查看次数