问题
The algorithm "A" according to Antoni Diller looks fairly simple:
http://www.cantab.net/users/antoni.diller/brackets/intro.html
Can we do this in Prolog?
回答1:
% associate formulas to left
associate_left(F, A, B) :-
append(A, [B], F).
% apply algorithm
reduce(b(_, []), []).
reduce(b(A, B), 'K'(B)) :- atom(B), dif(A, B).
reduce(b(A, A), 'I').
reduce(b(A, [F]), R) :- reduce(b(A, F), R). % uncessary paranthesis case
reduce(b(A, F), 'S'(Pr, Qr)) :-
associate_left(F, P, Q),
reduce(b(A, P), Pr),
reduce(b(A, Q), Qr).
I am assuming bound formulas are b(x, F)
where x is bound in F.
?- reduce(b(x, [x]), A).
A = 'I'
?- reduce(b(x, [y]), A).
A = 'K'(y)
?- reduce(b(x, [u, v]), A).
A = 'S'('K'(u), 'K'(v))
Example from your link
?- reduce(b(x, [u, v, [w, z, x], [x, z, y], [z, x, [y, x]]]), A).
A = 'S'('S'('S'('S'('K'(u), 'K'(v)), 'S'('S'('K'(w), 'K'(z)), 'I')), 'S'('S'('I', 'K'(z)), 'K'(y))), 'S'('S'('K'(z), 'I'), 'S'('K'(y), 'I')))
I tried algorithm B too. It is a bit hairy but here it is.
回答2:
Used a slightly different coding for application
with a Prolog operator that is already left associative:
?- X = ((a*b)*c).
X = a*b*c
And added a predicate unlambda/2:
unlambda(b(X,Y), Z) :- !,
unlambda(Y, H),
reduce(H, X, Z).
unlambda(P*Q, W) :- !,
unlambda(P, R),
unlambda(Q, S),
W = R*S.
unlambda(X, X).
reduce(X, X, W) :- !,
W = 'I'.
reduce(P*Q, Z, W) :- !,
reduce(P, Z, R),
reduce(Q, Z, S),
W = 'S'*R*S.
reduce(X, _, 'K'*X).
But we see that there is a problem,
results can get quite long:
?- unlambda(b(x,b(y,x)), X).
X = 'S'*('K'*'K')*'I'
?- unlambda(b(x,b(y,b(z,(x*z)*(y*z)))), X).
X = 'S'*('S'*('K'*'S')*('S'*('S'*('K'*'S')*('S'*('K'*'K')*('K'*'S')))*
('S'*('S'*('K'*'S')*('S'*('S'*('K'*'S')*('S'*('K'*'K')*('K'*'S')))*
('S'*('S'*('K'*'S')*('S'*('K'*'K')*('K'*'K')))*('S'*('K'*'K')*'I'))))*
('S'*('K'*'K')*('K'*'I')))))*('S'*('S'*('K'*'S')*('S'*('S'*('K'*'S')*
('S'*('K'*'K')*('K'*'S')))*('S'*('S'*('K'*'S')*('S'*('K'*'K')*
('K'*'K')))*('K'*'I'))))*('S'*('K'*'K')*('K'*'I')))
We can use two identities already documented by Curien(*),
that have the effect of [x]E = 'K'E
and [x]Ex = E
:
reduce(P*Q, Z, W) :- !,
reduce(P, Z, R),
reduce(Q, Z, S),
(S = 'I', R = 'K'*L ->
W = L;
S = 'K'*M, R = 'K'*L ->
W = 'K'*(L*M);
W = 'S'*R*S).
The result are much better now:
?- unlambda(b(x,b(y,x)), X).
X = 'K'
?- unlambda(b(x,b(y,b(z,(x*z)*(y*z)))), X).
X = 'S'
(*) See page 215 rule (abs) and rule (eta):
Categorical Combinators
P.-L. Curien - 1986
https://core.ac.uk/download/pdf/82017242.pdf
来源:https://stackoverflow.com/questions/65066544/bracket-abstraction-in-prolog