Prolog中基于debruijn索引的替换

Prolog中基于debruijn索引的替换,prolog,lambda-prolog,Prolog,Lambda Prolog,荷兰数学家Nicolaas Govert de Bruijn发明了这些索引 用于表示lambda演算的项,而不命名绑定变量。 让我们采用以下lambda表达式: K = λx.λy.x 使用de Bruijn索引时,当我们使用约定as时,它表示零de Bruijn索引指的是第一个封闭的lambda活页夹: K = λλ1 de Bruijn索引1指第二个lambda活页夹,该活页夹包含 德布鲁因指数。那么,如何为替换编写Prolog代码呢 我们可以计算beta减少,例如: Kab = a

荷兰数学家Nicolaas Govert de Bruijn发明了这些索引 用于表示lambda演算的项,而不命名绑定变量。 让我们采用以下lambda表达式:

K = λx.λy.x
使用de Bruijn索引时,当我们使用约定as时,它表示零de Bruijn索引指的是第一个封闭的lambda活页夹:

K = λλ1
de Bruijn索引1指第二个lambda活页夹,该活页夹包含 德布鲁因指数。那么,如何为替换编写Prolog代码呢 我们可以计算beta减少,例如:

Kab = a

De Bruijn索引是一种工具,用于替换比Prolog更困难的设置。逻辑变量是一种优越的工具。我认为您永远不会想要编写Prolog代码来处理de Bruijn索引。(下面将返回元问题。)

无论如何,的第二页包含了所需的所有内容的Prolog实现。它只是使用了非标准的,所谓的“功能性”语法

以下是正确语法中的移位关系:

funny_arrow(I, C, Term, Shifted) :-
    (   number(Term)
    ->  (   Term < C
        ->  Shifted = Term
        ;   Shifted is Term + I )
    ;   Term = lambda(E)
    ->  Shifted = lambda(Shifted1),
        C1 is C + 1,
        funny_arrow(I, C1, E, Shifted1)
    ;   Term = apply(E1, E2)
    ->  Shifted = apply(Shifted1, Shifted2),
        funny_arrow(I, C, E1, Shifted1),
        funny_arrow(I, C, E2, Shifted2) ).
你可以用同样的方法转录beta减少规则

然后我们可以测试这个。在PDF中使用的搞笑语言中,每个基本术语都必须编码为数字,因此我们将选择将
a
编码为
123
b
编码为
456
。术语
(KA)b
的缩减将通过应用两个缩减步骤来完成,首先将
KA
缩减为
KA
,然后将
KA
缩减为
b
。给你:

?- K = lambda(lambda(1)),
   A = 123,
   B = 456,
   reduce(apply(K, A), KA),
   reduce(apply(KA, B), KAB).
K = lambda(lambda(1)),
A = KAB, KAB = 123,
B = 456,
KA = lambda(124).
结果
KAB
A
相同。通过定义以下内容,您可以更简单、更高效地获得相同的结果:

apply(lambda(X, E), X, E).
然后:

?- K = lambda(X, lambda(Y, X)),
   apply(K, a, KA),
   apply(KA, b, KAB).
K = lambda(a, lambda(b, a)),
X = KAB, KAB = a,
Y = b,
KA = lambda(b, a).
你当然知道


Meta:关于编码符号逻辑中模糊主题的问题没有得到太多关注。这部分是因为它们中的大多数都不是很有趣。部分原因是因为他们缺乏所有细节和你的努力的示范。但我认为第三部分是社区不理解你对这些问题的全部观点。您是一个有造诣的Prolog程序员和实现者,这并不是什么秘密。显然,您可以将一些简单的方程转录到Prolog中。那为什么要问别人呢?这是否意味着要建立一个“社区wiki”或标准符号算法的Prolog实现数据库?这甚至可能很有趣,但如果您告知项目存在,以及项目的目的是什么,您可能会有更多的参与者参与该项目。

De Bruijn索引是一种工具,适用于替换比Prolog更困难的设置。逻辑变量是一种优越的工具。我认为您永远不会想要编写Prolog代码来处理de Bruijn索引。(下面将返回元问题。)

无论如何,的第二页包含了所需的所有内容的Prolog实现。它只是使用了非标准的,所谓的“功能性”语法

以下是正确语法中的移位关系:

funny_arrow(I, C, Term, Shifted) :-
    (   number(Term)
    ->  (   Term < C
        ->  Shifted = Term
        ;   Shifted is Term + I )
    ;   Term = lambda(E)
    ->  Shifted = lambda(Shifted1),
        C1 is C + 1,
        funny_arrow(I, C1, E, Shifted1)
    ;   Term = apply(E1, E2)
    ->  Shifted = apply(Shifted1, Shifted2),
        funny_arrow(I, C, E1, Shifted1),
        funny_arrow(I, C, E2, Shifted2) ).
你可以用同样的方法转录beta减少规则

然后我们可以测试这个。在PDF中使用的搞笑语言中,每个基本术语都必须编码为数字,因此我们将选择将
a
编码为
123
b
编码为
456
。术语
(KA)b
的缩减将通过应用两个缩减步骤来完成,首先将
KA
缩减为
KA
,然后将
KA
缩减为
b
。给你:

?- K = lambda(lambda(1)),
   A = 123,
   B = 456,
   reduce(apply(K, A), KA),
   reduce(apply(KA, B), KAB).
K = lambda(lambda(1)),
A = KAB, KAB = 123,
B = 456,
KA = lambda(124).
结果
KAB
A
相同。通过定义以下内容,您可以更简单、更高效地获得相同的结果:

apply(lambda(X, E), X, E).
然后:

?- K = lambda(X, lambda(Y, X)),
   apply(K, a, KA),
   apply(KA, b, KAB).
K = lambda(a, lambda(b, a)),
X = KAB, KAB = a,
Y = b,
KA = lambda(b, a).
你当然知道


Meta:关于编码符号逻辑中模糊主题的问题没有得到太多关注。这部分是因为它们中的大多数都不是很有趣。部分原因是因为他们缺乏所有细节和你的努力的示范。但我认为第三部分是社区不理解你对这些问题的全部观点。您是一个有造诣的Prolog程序员和实现者,这并不是什么秘密。显然,您可以将一些简单的方程转录到Prolog中。那为什么要问别人呢?这是否意味着要建立一个“社区wiki”或标准符号算法的Prolog实现数据库?这甚至可能很有趣,但如果你告诉他们一个项目的存在,以及它的目的是什么,你可能会在项目中获得更多的参与者。

我提出了另一个想法,它是针对线性逻辑量身定制的。这意味着它避免了每次访问活页夹时调用有趣的箭头/4 in replacement/4。下面是一个测试用例:

/* example from PDF */
?- apply(b(b(1*2)), 1, X).
X = b(2*1).
源代码如下。还可以更正PDF中的键入错误,但将有趣的箭头/4大写不仅可以取-1和1,还可以取其他值:

警告:以下代码不稳定

% apply(+Expr, +Expr, -Expr)
apply(b(R), S, T) :-
   subst(R, 0, S, T).

% subst(+Expr, +Integer, +Expr, -Expr)
subst(P*Q, J, D, R*S) :- !,
   subst(P, J, D, R),
   subst(Q, J, D, S).
subst(b(P), J, D, b(R)) :- !,
   K is J+1,
   subst(P, K, D, R).
subst(J, K, _, J) :- integer(J), J < K, !.
subst(0, 0, D, D) :- !.
subst(J, J, D, R) :- integer(J), !,
   shift(D, 0, J, R).
subst(J, _, _, K) :- integer(J), !, K is J-1.
subst(I, _, _, I).

% shift(+Expr, +Integer, +Integer, -Expr)
shift(P*Q, J, D, R*S) :- !,
   shift(P, J, D, R),
   shift(Q, J, D, S).
shift(b(P), J, D, b(R)) :- !,
   K is J+1,
   shift(P, K, D, R).
shift(J, K, _, J) :- integer(J), J < K, !.
shift(J, _, D, K) :- integer(J), !, K is J+D.
shift(I, _, _, I).
%apply(+Expr,+Expr,-Expr)
适用(b(R)、S、T):-
subst(R,0,S,T)。
%subst(+Expr,+Integer,+Expr,-Expr)
subst(P*Q,J,D,R*S):-!,
subst(P,J,D,R),
subst(Q,J,D,S)。
(b(P),J,D,b(R)):-!,
K是J+1,
subst(P,K,D,R)。
subst(J,K,uj):-整数(J),J
我提出了另一种方法,它是针对线性逻辑量身定制的。这意味着它避免了每次访问活页夹时调用有趣的箭头/4 in replacement/4。这是