我正在尝试使用De Bruijn索引定义lambda微积分项。我在OS X上使用swi prolog。
如果我使用自然数的title = {content}
title3 = {entry}
title1 = {entry, entry, entry}
title2 = {entry, entry}
表示形式,则可以交互式完成部分指定的术语。
zero|successor
例如,nat(zero).
nat(s(X)) :- nat(X).
debruijn2(N) :- nat(N).
debruijn2(ap(M, N)) :- debruijn2(M), debruijn2(N).
debruijn2(lambda(M)) :- debruijn2(M).
和Z
与X
中的zero
统一。
ap(Z, X)
但是,使用?- debruijn2(ap(X, Z)).
X = Z, Z = zero .
检查数字like this会产生类型错误,除非length
的参数只是一个整数。
debruijn
查询debruijn(N) :- length(_, N).
debruijn(ap(M, N)) :- debruijn(M), debruijn(N).
debruijn(lambda(M)) :- debruijn(M).
成功,并且debruijn(X).
与X
统一。
0
但是,查询?- debruijn(X).
X = 0 .
失败,好像debruijn(ap(Z, X)).
不可撤销地将其第二个参数约束为整数。
length(_, ·)
为什么?- debruijn(ap(Z, X)).
ERROR: Type error: `integer' expected, found `ap(_2944,_2946)' (a compound)
ERROR: In:
ERROR: [10] throw(error(type_error(integer,...),context(...,_3008)))
ERROR: [8] debruijn(ap(_3036,_3038)) at <...>:2
ERROR: [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
Exception: (8) debruijn(ap(_2362, _2364)) ? creep
会产生类型错误,而不仅仅是不应用于参数?
答案 0 :(得分:3)
一种在SWI-Prolog上运行而不使用昂贵的对length/2
和catch/3
的调用的替代方法:
debruijn(N) :- simple(N), nat(N).
debruijn(ap(M, N)) :- debruijn(M), debruijn(N).
debruijn(lambda(M)) :- debruijn(M).
nat(0).
nat(I) :-
nat(1, I).
nat(I, I).
nat(I, J) :-
I2 is I + 1,
nat(I2, J).
如果simple/1
谓词未实例化为复合词,则谓词成功。这是一个从未被标准化但仍在某些Prolog系统中发现的传统谓词(例如,它是SWI-Prolog中的一个库谓词,而在SICStus Prolog中是一个内置谓词)。
与基于length/2
的解决方案的不同之处可能与您的用例无关,也可能与您的用例无关,这是当使用负数调用debruijn/1
时的行为。在这种情况下,此解决方案将陷入循环并最终出错,但是length/2
将引发一个异常,catch/3
包装器将转换为失败。
答案 1 :(得分:2)
我怀疑是因为Prolog尝试在搜索过程中评估length/2
谓词。根据{{3}},如果第二个参数绑定到非整数,则会引发错误。不同于仅使检查失败。
您可以使用manual将失败变成错误的谓词:
debruijn(N) :- catch(length(_, N), _, false).
debruijn(ap(M, N)) :- debruijn(M), debruijn(N).
debruijn(lambda(M)) :- debruijn(M).
Manual说,从异常中恢复很慢。无论如何我都不是Prolog专家,所以也许有更好的解决方案。