问题描述
是的,您可以在没有 dif/2
的情况下实现图灵机。但是你甚至不能实现交集或类似的谓词。
假设我们确实使用 call/N
、dif/2
和 {{1} 扩展了纯 Prolog (Horn FOL + CWA + UNA) }},用于 (=)/3
中,它的表现力是否仍然存在差距,ie 定义一些微不足道的东西,例如,Scheme,但要困难得多在如此扩展的(几乎是纯粹的)Prolog 中声明?
特别是,这样的 Prolog 是否允许操作 Prolog 列表与 Scheme 允许操作 Scheme 列表一样方便?
编辑: 假设 Scheme 没有突变、宏、延续、懒惰、流、数字、字符串、向量或字符。只是符号、布尔值和列表(树)。
解决方法
只是符号和列表(树)。
如果您不想在纯 lambda 演算中编码所有内容,您还需要 Scheme 布尔值 #t
和 #f
。您还排除了函数值,幸好这使这个答案更简单。尽管您必须允许顶级 (define name (lambda ...))
表单的特殊情况。 (其他任何东西,包括扩展的 let
表达式,都可以是 defunctionalized。)
所以,我的主张是:不,这个模糊的 Scheme 子集与您定义的纯 Prolog 之间的表达能力没有差距。我的论点(不是证明)是有建设性的,将列表交集的 Scheme 代码从 this answer 翻译成 Prolog。
具体来说:
(define intersect
(lambda (set1 set2)
(cond
((null? set1)(quote ()))
((member? (car set1) set2)
(cons (car set1)
(intersect (cdr set1) set2)))
(else (intersect (cdr set1) set2)))))
变成:
intersect(Set1,Set2,Result) :-
cond([
['null?'(Set1),result([])],[cond_1(Set1,Set2),body_1(Set1,Set2)],[else,body_2(Set1,Set2)]],Result).
cond_1(Set1,Result) :-
car(Set1,Car),'member?'(Car,Result).
body_1(Set1,cdr(Set1,Cdr),intersect(Cdr,PartialIntersection),cons(Car,PartialIntersection,Result).
body_2(Set1,Result) :-
cdr(Set1,Result).
还有这个:
(define member?
(lambda (a lat)
(cond
((null? lat) #f)
(else (or (equal? (car lat) a)
(member? a (cdr lat)))))))
变成:
'member?'(A,Lat,Result) :-
cond([
['null?'(Lat),result('#f')],or([or_case_1(Lat,A),or_case_2(Lat,A)])]],Result).
or_case_1(Lat,A,Result) :-
car(Lat,'equal?'(Car,Result).
or_case_2(Lat,Result) :-
cdr(Lat,'member?'(A,Cdr,Result).
请注意,嵌套表达式需要取消嵌套,除了最琐碎的情况外,最简单的方法是定义辅助 Prolog 谓词。这不会非线性地增加代码大小。
这些定义使用标准 Scheme 结构的以下翻译:
'equal?'(X,Y,'#t') :-
=(X,true).
'equal?'(X,'#f') :-
=(X,false).
'null?'(Value,Result) :-
'equal?'(Value,[],Result).
car([Car | _Cdr],Car).
cdr([_Car | Cdr],Cdr).
cons(Car,[Car | Cdr]).
or([],'#f').
or([Goal | Goals],Result) :-
if(Goal,Result = '#t',or(Goals,Result)).
cond([],_Result) :-
throw(error(cond_without_else,_)).
cond([[Condition,Body] | OtherCases],Result) :-
if(Condition,call(Body,Result),cond(OtherCases,Result)).
一些支持从 cond
案例主体和 else
案例中获取简单值的内容:
result(Result,Result).
else('#t').
这就是您需要的所有内部不纯、外部纯 Prolog 支持:
if(Goal,True,False) :-
call(Goal,Truth),( Truth == '#t' -> call(True)
; Truth == '#f' -> call(False)
; throw(error(type_or_instantiation_error(Truth),_)) ).
我称之为 if/3
而不是 if_/3
因为它不完全是“标准”if_/3
:它期望条件评估为 Scheme 真值而不是 true
或false
。随意将其按摩成“标准”形式。 编辑:有几种“足够好”的方法可以定义在此答案的上下文中起作用的 (=)/3
,但为了避免进一步的自行车棚,只需使用 {{3} }.
测试:
?- 'member?'(a,[x,y,a,c],Result).
Result = '#t' ;
false.
?- intersect([a,b,c,d],[c,d,e,f],Result).
Result = [c,d] ;
false.
,
如果您采用纯 Scheme。可能纯 Prolog 就足够了。 Pure Scheme 将是具有某种严格的按值调用评估策略的 lambda 表达式。所以我们可以在 Prolog 中实现纯 Scheme 如下,利用 deBruijn indexes:
eval(P*Q,H) :- !,eval(P,R),eval(Q,S),reduce(R,S,H).
eval(X,X).
reduce(b(R),J) :- !,subst(R,H),eval(H,J).
reduce(R,R*S).
如果你稍微改变一下表示,我想你可以摆脱削减。也许通过皮亚诺公理做必要的算术。嗯,你在纯 Prolog 中得到了纯 Scheme。
这是一个示例查询,SUCC 和 ZERO 来自 here:
?- ZERO = b(b(0)),SUCC = b(b(b(1*(2*1*0)))),eval(SUCC*(SUCC*ZERO)*f*a,X).
ZERO = b(b(0)),X = f*(f*a)
,
只要 symbol/1
和 dif/2
是逻辑纯 Prolog 的足够扩展。
证明:
This answer 包含 Scheme 表达式的求值器 evil/2
。它理解 lambda
和 quote
,并且可以轻松扩展以处理内置列表过程,例如 list
、car
、cdr
等。除了 纯(喇叭)序言,它只使用 symbol/1
和 dif/2
。虽然它是一个解释器并且运行缓慢,但它的存在表明,Scheme 所做的相同列表操作可以在这种几乎纯 Prolog 中完成。 (我认为 symbol/1
也不需要,如果 Scheme 符号被翻译成 symb(prolog_atom)
而不是直接翻译成 prolog_symbol
)
编辑
这扩展了 evil/2
以处理 if
、#t
和 #f
(由 true
和 false
表示):
evil(true,_,true).
evil(false,false).
evil([if,E1,E2,E3],Env,Val) :-
evil(E1,false),symbols(E2),evil(E3,Val).
evil([if,V),dif(V,symbols(E3),evil(E2,Val).
这扩展了 evil/2
以处理 equalp
。它比 Scheme 的 eq*
更强大,因为它也等同于一些闭包:
evil([equalp,E2],true) :-
evil(E1,V).
evil([equalp,false) :-
evil(E1,V1),V2),dif(V1,V2).