EDIT 2021-08-28T15:00:00Z (Signature Added for kind rules (pac-1.6.2) )
example signature for set operations
Note that closures are allowed for semantics of signature symbols.
:- bekind(set, [nonvar, stop]).
sgn(emptyset, 0, []).
sgn([], 0, []).
sgn([X|Y], 0, [X|Y]).
sgn(+, 2, union).
sgn(plus, 2, pred([X, Y, Z]:-union(X, Y, Z))).
sgn(yaplus, 2, fun([X, Y]>> :union(X, Y))).
sgn(yayaplus, 2, fun([X, Y]>> :union@X@Y)).
sgn(&, 2, intersection).
sgn(\, 2, subtract).
sgn(pow, 1, powerset).
sgn(++, 2, direct_sum).
sgn(*, 2, cartesian).
sgn(#, 2, scramble_cons).
singleton(A) = xargs([X] -> [X])@ A.
:- ekind.
expanded clauses for the set signature
% ?- listing(set).
%@ set(A, []) :-
%@ var(A),
%@ !,
%@ false.
%@ set(emptyset, []) :-
%@ !.
%@ set([], []) :-
%@ !.
%@ set([A|B], [A|B]) :-
%@ !.
%@ set(A+B, C) :-
%@ !,
%@ set(A, D),
%@ set(B, E),
%@ union(D, E, C).
%@ set(plus(A, B), C) :-
%@ !,
%@ set(A, D),
%@ set(B, E),
%@ 'pac#4'(D, E, C).
%@ set(yaplus(A, B), C) :-
%@ !,
%@ set(A, D),
%@ set(B, E),
%@ 'pac#5'(D, E, C).
%@ set(yayaplus(A, B), C) :-
%@ !,
%@ set(A, D),
%@ set(B, E),
%@ 'pac#6'(D, E, C).
%@ set(&(A, B), C) :-
%@ !,
%@ set(A, D),
%@ set(B, E),
%@ intersection(D, E, C).
%@ set(\(A, B), C) :-
%@ !,
%@ set(A, D),
%@ set(B, E),
%@ subtract(D, E, C).
%@ set(pow(A), B) :-
%@ !,
%@ set(A, C),
%@ powerset(C, B).
%@ set(++(A, B), C) :-
%@ !,
%@ set(A, D),
%@ set(B, E),
%@ direct_sum(D, E, C).
%@ set(A*B, C) :-
%@ !,
%@ set(A, D),
%@ set(B, E),
%@ cartesian(D, E, C).
%@ set(#(A, B), C) :-
%@ !,
%@ set(A, D),
%@ set(B, E),
%@ scramble_cons(D, E, C).
%@ set(singleton(A), [B]) :-
%@ !,
%@ set(A, B).
%@ set(A, A) :-
%@ !.
%@
%@ true.
old style example for kind rules
% :- bekind(yaset, [nonvar, stop, flip([2,1])]).
:- bekind(yaset, [nonvar, stop]).
emptyset = [].
X = `X :- is_list(X), !.
singleton(A) = xargs([X] -> [X])@ A.
+(A, B) = :union@A@B.
&(A, B) = :intersection @ A @ B.
\(A, B) = :subtract@ A @ B.
pow(A) = :powerset@ A.
++(A, B) = :direct_sum @ A @ B.
*(A, B) = :cartesian @ A @ B.
#(A, B) = :scramble_cons @ A@ B.
:- ekind.
expanded clauses for the old style kind rules
% ?- listing(yaset).
%@ yaset(A, []) :-
%@ var(A),
%@ !,
%@ false.
%@ yaset(emptyset, []) :-
%@ !.
%@ yaset(A, A) :-
%@ is_list(A),
%@ !.
%@ yaset(singleton(A), [B]) :-
%@ !,
%@ yaset(A, B).
%@ yaset(A+B, C) :-
%@ !,
%@ yaset(A, D),
%@ yaset(B, E),
%@ union(D, E, C).
%@ yaset(&(A, B), C) :-
%@ !,
%@ yaset(A, D),
%@ yaset(B, E),
%@ intersection(D, E, C).
%@ yaset(\(A, B), C) :-
%@ !,
%@ yaset(A, D),
%@ yaset(B, E),
%@ subtract(D, E, C).
%@ yaset(pow(A), B) :-
%@ !,
%@ yaset(A, C),
%@ powerset(C, B).
%@ yaset(++(A, B), C) :-
%@ !,
%@ yaset(A, D),
%@ yaset(B, E),
%@ direct_sum(D, E, C).
%@ yaset(A*B, C) :-
%@ !,
%@ yaset(A, D),
%@ yaset(B, E),
%@ cartesian(D, E, C).
%@ yaset(#(A, B), C) :-
%@ !,
%@ yaset(A, D),
%@ yaset(B, E),
%@ scramble_cons(D, E, C).
%@ yaset(A, A) :-
%@ !.
%@
%@ true.
EDIT 2021.8.28
I have updated pac-1.6.0 to pac-1.6.1, to which I have added a minor simplification on expand_exp/8
in library(pac(prolog/pac/expand-pac.pl)
, which seems more close to the policy along the semantic equation below. I will edit document on functional macros of the pac later.
% ?- eval( (X\X)@ (Y\Y)@ (Z\Z), V).
%@ V = pac:'pac#3'(pac:'pac#1', pac:'pac#2').
% ?- eval( :((X\X)@ (Y\Y)), V).
%@ V = pac:'pac#7'.
Expanded codes are displayed with show_exp/1
like this.
% ?- show_exp((X\X)@ (Y\Y)@ (Z\Z)).
%@ pac#14(pac#12,pac#13), where
%@ pac#12(A,A):-true
%@ pac#13(A,A):-true
%@ pac#14(A,A):-true
%@ true .
EDIT END.
As I found my package pac-1.5.7 broken after some recent swipl-devel git, fixing a bug in pac-1.5.7, on this occasion I have reviewed codes on functional macros expansion mainly in expand-exp.pl
and updated to pac-1.6.0. The trouble was caused by a bad use of b_setval``, which is related, I guess, to what Jan warned. While reviewing, I kept in in mind that behavior of functional macros, that is,
eval/2, eval/3```should follow a simple semantic equation as possible as I could, though there must be much room to be revised further.
\def\sem#1{[\![#1]\!]}
\sem{ e_0@e_1@e_2@\cdots@e_n}=\sem{e_0}(\sem{e_1}, \sem{e_2}, \ldots, \sem{e_n})
A few of sample queries on eval
follows.
% swipl
?- pack_install(pac).
% Contacting server at https://www.swi-prolog.org/pack/query ... ok
% Pack `pac' is already installed @1.6.0
true.
?- use_module(library(pac)).
true.
?- module(pac).
true.
?- eval(append, V).
V = append.
?- eval(append@[a,b], V).
V = append([a, b]).
?- eval(append@[a,b]@[c,d], V).
V = append([a, b], [c, d]).
?- eval(append@[a,b]@[c,d]@U, V).
V = append([a, b], [c, d], U).
?- eval(:append@[a,b]@[c,d], V).
V = [a, b, c, d].
?- eval(:append@ (:append@[a,b]@[c,d]) @ (:append@([e,f])@[g,h]) , V).
V = [a, b, c, d, e, f, g, h].
?- eval(:fun([F,X,Y]-> (:F)@X@Y) @ append @ [1,2,3] @ [a, b, c], V).
V = [1, 2, 3, a, b, c].
Kuniaki Mukai