prolog——生成整数“;“不可理解地”;
我试图用De Bruijn指数定义lambda微积分项。我正在OSX上使用swi prolog 如果我使用自然数的prolog——生成整数“;“不可理解地”;,prolog,Prolog,我试图用De Bruijn指数定义lambda微积分项。我正在OSX上使用swi prolog 如果我使用自然数的zero |后继者表示,我可以交互式地完成部分指定的项 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在ap
zero |后继者
表示,我可以交互式地完成部分指定的项
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
在ap(Z,X)
中统一为0
但是,使用length
检查数字会产生类型错误,除非debruijn
的参数只是一个整数
debruijn(N) :- length(_, N).
debruijn(ap(M, N)) :- debruijn(M), debruijn(N).
debruijn(lambda(M)) :- debruijn(M).
?- 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
查询debruijn(X)。
成功并且X
与0
相结合
?- debruijn(X).
X = 0 .
但是,查询debruijn(ap(Z,X))。
失败,就好像length(u,·)
不可撤销地将其第二个参数约束为整数一样
debruijn(N) :- length(_, N).
debruijn(ap(M, N)) :- debruijn(M), debruijn(N).
debruijn(lambda(M)) :- debruijn(M).
?- 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
?-debruijn(ap(Z,X))。
错误:类型错误:应为'integer',找到'ap(_2944,_2946)'(复合)
错误:在:
错误:[10]抛出(错误(类型_错误(整数,…),上下文(…,_3008)))
错误:[8]Debrijn(ap(_3036,_3038))位于:2
错误:[7]
错误:
错误:注意:由于上次调用优化,某些帧丢失。
错误:在调试模式(:-debug.)下重新运行程序以获取更多详细信息。
例外情况:(8)Debrijn(ap(_2362,_2364))?爬行
为什么
length/2
会产生类型错误而不是无法应用于参数?我怀疑这是因为Prolog在搜索过程中试图计算length/2
谓词。根据,如果第二个参数绑定到非整数,则会引发错误。这不同于简单地不通过检查
您可以使用将失败转换为假谓词:
debruijn(N) :- catch(length(_, N), _, false).
debruijn(ap(M, N)) :- debruijn(M), debruijn(N).
debruijn(lambda(M)) :- debruijn(M).
但手册上说,从异常中恢复相当缓慢。无论如何,我都不是Prolog专家,所以可能有更好的解决方案。在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
包装将转换为失败。是否有技巧,例如引入额外变量或其他什么,在基本情况下,debruijn/1
?@GregoryNisbet扩展了我的答案。生成所有debruijn术语看起来是一个相当不平凡的挑战。。。也许这也会导致一个具有改进的终止属性的检查谓词(例如,debruijn(0)
成功,然后进入无限循环)。。。我考虑过在从N开始倒数到0时,为顶部索引N生成项,每N从0开始递增,但即使如此,每N的项数似乎也是无限的。。。