PROLOG-REQUEST@SUSHI.STANFORD.EDU (Chuck Restivo, The Moderator) (11/13/87)
PROLOG Digest Saturday, 14 Nov 1987 Volume 5 : Issue 86 Today's Topics: Announcement - Final CADE9 Call, Implementation - Types, LP Library - List Package & Type Checker ---------------------------------------------------------------------- Date: Wed, 4 Nov 87 12:45:07 cst From: stevens@anl-mcs.ARPA (Rick L. Stevens) Subject: Final CADE-9 Call for Papers Final Call for Papers 9th International Conference on Automated Deduction May 23-26, 1988 CADE-9 will be held at Argonne National Laboratory (near Chicago) in celebration of the 25th anniversary of the discovery of the resolution principle at Argonne in the sum- mer of 1963. Papers are invited in the following or related fields: Theorem Proving Logic Programming Unification Deductive Databases Term Rewriting ATP for Non-Standard Logics Program Verification Inference Systems Papers are solicited in three categories: Long papers: 20 pages, about 5000 words Short papers: 10 pages, about 2500 words Extended Abstracts of Working Systems: 2 pages Problem sets: 5 pages Long papers are expected to present substantial research results. Short papers are a forum for briefer presentations of the results of ongoing research. Extended abstracts are descriptions of existing automated reasoning systems and their areas of application. Problem sets should present a complete, formal representation of some collection of interesting problems for automated systems to attack. The problems should currently unavailable in the existing literature. Three copies should be sent to arrive before November 23rd, 1987 to Ewing Lusk and Ross Overbeek, chairmen CADE-9 Mathematics and Computer Science Division Argonne National Laboratory 9700 South Cass Avenue Argonne, IL 60439 Schedule: November 23, 1987: papers due January 25, 1988: notification of authors February 21, 1988: final manuscripts due Questions should be directed to E. L. Lusk (lusk@anl- mcs.arpa, phone 312-972-7852) or Ross Overbeek (overbeek@anl-mcs.arpa, phone 312-972-7856) ------------------------------ Date: 31 Oct 87 16:19:00 GMT From: reddy@b.cs.uiuc.edu Subject: Types Utilizations in Prolog I don't know if Lee's message got cut off in the middle somewhere on the net. But, I didn't see an important reference mentioned in his list. Mycroft and O'Keefe, A polymorphic type system for Prolog, Artificial Intelligence, 23:295-307 (1984). An implementation of this system exists. But, it needs lots of declarations. You can probably ask O'Keefe for a copy of the system. For an early reference on the theory of type "inference", see Mishra, Towards a theory of types in Prolog, IEEE Intl. Symp on Logic Programming, 1984, 289-298. ------------------------------ Date: 3 Nov 87 03:02:00 GMT From: munnari!mulga!philip@uunet.uu.net (Philip Dart) Subject: Doubly-linked list package % Following the comments about Fortran as an AI language, % Melbourne University Department of Artificial Intelligence % has decided to convert all of its Fortran AI programs to NU-Prolog. % This package has been written as an aid to this conversion. % For non-NU-Prolog users, simply comment out the when declarations. % Doubly-linked list package. % Why use boring old single-linked lists when doubly-linked % list could make your list processing applications % run as never before. % ?- dAdj(L, R) when L and R. % Are these adjacent nodes? % ?- dPrev(D, _) when D. % Get previous node. % ?- dNext(D, _) when D. % Get next node. % ?- dHead(D, _) when D. % Get head of list % ?- dTail(D, _) when D. % Get tail of list % ?- isD(D) when D. % Is this a doubly-linked list? % ?- portray(D) when ever. % Portray doubly-linked list % ?- dAppend(X, Y, Z) when X or Z. % Append for doubly-linked lists test :- L1 = [1, 2, 3], listToD(L1, D1), write(L1), write(' <=> '), portray(D1), nl, L2 = [4, 5, 6, 7], listToD(L2, D2), write(L2), write(' <=> '), portray(D2), nl, dAppend(D1, D2, D3), listToD(L3, D3), isD(D3), write(L3), write(' <=> '), portray(D3), nl. ?- dAdj(L, R) when L and R. % Are these adjacent nodes? dAdj(L, R) :- L = d(_, _, R), R = d(L, _, _). ?- dPrev(D, _) when D. % Get previous node. dPrev(d(L, _, _), L). ?- dNext(D, _) when D. % Get next node. dNext(d(_, _, R), R). ?- dHead(D, _) when D. % Get head of list dHead([], []). dHead(d([], D, R), d([], D, R)). dHead(d(d(L, D, R), _, _), H) :- dHead(d(L, D, R), H). ?- dTail(D, _) when D. % Get tail of list dTail([], []). dTail(d(L, D, []), d(L, D, [])). dTail(d(_, _, d(L, D, R)), T) :- dTail(d(L, D, R), T). ?- listToD(List, D) when List or D. % Convert single to doubly-linked list listToD([], []). listToD(H.T, D) :- D = d([], H, R), $listToD(T, D, R). ?- $listToD(List, _, D) when List or D. $listToD([], _, []). $listToD(H.T, L, D) :- D = d(L, H, R), $listToD(T, D, R). ?- isD(D) when D. % Is this a doubly-linked list? isD([]). isD(D) :- D = d([], _, R), $isD(D, R). ?- $isD(_, D) when D. $isD(_, []). $isD(L, D) :- D = d(L, V, R), $isD(D, R). ?- portray(D) when ever. % Portray doubly-linked list portray(D) :- nonvar(D), D = d([], _, _), display('[]:'), $dPrint(D). ?- $dPrint(D) when D. $dPrint([]) :- display('[]'). $dPrint(d(_, V, R)) :- display(V), display(':'), $dPrint(R). ?- dAppend(X, Y, Z) when X or Z. % Append for doubly-linked lists dAppend(X, [], X). dAppend([], d([], D, R), d([], D, R)). dAppend(d(L, X, R), d([], Y, RY), Z) :- $dAppend([], d(L, X, R), Y, RY, Z). ?- $dAppend(X, _, _, Z) when X or Z. $dAppend(L, d(_, X, []), Y, R, Z) :- Z = d(L, X, H), H = d(Z, Y, R1), $dAppend1(H, R, R1). $dAppend(L, d(_, X, d(L1, X1, R1)), Y, RY, d(L, X, RZ)) :- Z = d(L, X, RZ), $dAppend(Z, d(L1, X1, R1), Y, RY, RZ). ?- $dAppend(_, Y, Z) when Y or Z. $dAppend1(_, [], []). $dAppend1(L, d(_, D, R), Z) :- Z = d(L, D, R1), $dAppend1(Z, R, R1). % P.S. Don't forget to turn off the occur-check in your version of Prolog! ------------------------------ Date: Sun, 8 Nov 87 17:35:58 PST From: quintus!ok@Sun.COM (Richard A. O'Keefe) Subject: Type checker Disclaimer: the timestamps on the following two files are correct. This is the type-checker as it stood in 1984 for DEC-10 Prolog + Edinburgh library (pretty much the code that was handed out at the Albufeira Workshop in '83, in fact). It has not been upgraded to Quintus Prolog; it doesn't handle modules, and it was never considered to be particularly good code. Comments and improvements welcome. ------------------------------------------------------------------------ % File : TYPECH.PL % Author : Alan Mycroft & R.A.O'Keefe % Updated: 8 June 1984 % Purpose: Prolog type-checker :- public load/1, % for users type_check/5. % for setof/3 %>> This module uses unify/2 from Util:MetUtl.Pl . %>> It also uses append/3 from the utilities. % This program defines a "type-checked consult" operation % load(Files) % where Files is an atom or a list of atoms. There is no % analogue of the reconsult operation. In the Files type % declarations may be given in addition to the usual sort % of commands, questions, clauses, and declarations. You % can put the type declarations in separate files, so that % load(['foo.typ','foo.pl']) can be used to type-check and % load the interpreted version, and compile('foo.pl') can % be used to compile the same code. Note that declarations % have to be processed before clauses using the things % declared. % There are two new declarations: % type <type term> --> <constr>{| <constr>}.. . % e.g. type tree(T) --> empty | tree(T,tree(T),tree(T)). % and % pred <pred decl>{, <pred decl>}.. . % e.g. pred append(list(T), list(T), list(T)). % You may use a semicolon instead of a vertical bar if you like. % As a convenience for defining grammar rules, % rule p(T1,...,Tk). % has the same effect as % pred p(T1,...,Tk,list(T_),list(T_)). % where T_ is not further specified. 'C'/3 is predefined as % pred 'C'(list(X), X, list(X)). :- op(1199, fx, [(type), (pred), (rule)]). :- op(1198, xfy, (-->)). :- op( 999, xfy, (:)). % load/1 is defined in the usual way. The juggling with (no)fileerrors % is to determine whether failure to find a file causes an error message % and abort, or just (as here) a failure. expandterm/2 is where grammar % rules are translated to ordinary Prolog. In Dec-10 Prolog, the style % of programming which uses failure-driven loops is nearly obsolete, % thanks to the introduction of TRO to the compiler, and it was never % considered to be anything other than a hack. However, this stuff has % to be useful in C Prolog and other Prologs which still lack TRO, so % the hack remains. load(Files) :- recorded(void, (type), _), !, % the definitions have been loaded load1(Files). load(Files) :- recordz(void, (type), _), recordz(any, (type), _), recordz((_:-_), type((void:-void), void), _), % for assert load1(['util:prolog.typ'|Files]). load1(Var) :- var(Var), !, write('! load: argument contains a variable'), nl, fail. load1([Head|Tail]) :- !, load1(Head), !, % discard this cut on non-TRO systems load1(Tail). load1(File) :- atom(File), !, nofileerrors, seeing(Old), load2(File), fileerrors, see(Old). load1(File) :- write('! load: argument not list or atom: '), write(File), nl, fail. load2(File) :- see(File), repeat, read(Term), expand_term(Term, Expanded), process_term(Expanded, File), Expanded = end_of_file, !, seen, write(File), write(' loaded.'), nl. load2(File) :- write('! load: can''t see '), write(File), nl, fail. % process_term(Expansion, File) % handles a command, question, clause, or declaration. % Questions are treated as if they were commands, which is just plain % wrong, but only in Prolog-X is a version of 'read' standardly % available which gives you a name->variable list so that you can % print the answers. Type checking wants to be built into a Prolog % system top level from the word go, not added on as an afterthought. process_term(end_of_file, File) :- !. process_term((:- Command), File) :- !, process_command(Command, File). process_term((?- Question), File) :- !, process_command(Question, File). process_term({Unchecked}, File) :- !, assertz(Unchecked). process_term((Head :- Body), File) :- !, type_check((Head:-Body), Clause), assertz(Clause). process_term(Head, File) :- type_check((Head:-true), Clause), assertz(Clause). % process_command(Command, File) % mainly handles declarations. process_command((type Type --> Constructors), File) :- !, process_type(Type, Constructors). process_command((pred Predicates), File) :- !, process_pred(Predicates, (pred)). process_command((rule GrammarRules), File) :- !, process_pred(GrammarRules, (rule)). process_command([Files], File) :- !, load1(Files). process_command((mode Modes), File) :- !, true. % could maybe note that we expect a type? process_command((public PublicDeclarations), File) :- !, true. % could maybe note that we expect a type? process_command(Question, user) :- !, ( type_check(Question, Checked) ; write('! ill-typed '), nl, fail ), ( call(Checked), write(Checked), nl, write('more? '), ttyflush, read(no) ; write('no (more) answers'), nl ). process_command(Command, File) :- ( type_check(Command, Checked) ; write('! ill-typed '), write(Command), write(' in '), write(File), nl, fail ), ( call(Checked), ! ; write('! failed command '), write(Command), write(' in '), write(File), nl, fail ). % The "typed premise" described in Mycroft & O'Keefe is stored two % ways. The types of variables are held in a dynamic data structure % used only within a single clause. The types of predicates and % functors are held in the data base. We use the Dec-10 "recorded" % data base here to reduce clashes with user clauses and make access % a little bit faster, but ordinary clauses could just as easily be % used. There are three cases: % % recorded(Key, (type), _) % - use type_def(Key) as clauses % means that the Key is a type constructor. E.g. after % processing the declaration :- type tree(T) --> ... . % recorded(tree(T), (type), _) % would be true. % % recorded(Key, type(Pat,void), _) % - use has_type(Key, Pat, void) as clauses % means that the Key is defined as a predicate. The Pat looks like % the Key, but has type terms for its arguments. E.g. after % processing the declaration :- pred elem(T, tree(T)). % recorded(elem(_,_), type(elem(T,tree(T)),void), _) % would be true. % % recorded(Key, type(Pat,Val), _) % - use has_type(Key, Pat, Val) as clauses % means that the Key is defined as a function. The Pat looks like % the Key, but has type terms for its arguments. E.g. after % processing the declaration % :- type tree(T) --> empty | t(T,tree(T),tree(T)). % recorded(empty, type(empty,tree(T)), _) and % recorded(t(_,_,_), type(t(T,tree(T),tree(T)),tree(T)), _) % would both be true. % % These declarations are the only way that data of the given forms % are recorded. % process_type(<type head>, <type body>) % checks that its arguments are well formed, and if they are, % records the type information about the <type head> and the % constructors. process_type(Head, Body) :- check_type_head(Head), recordz(Head, (type), _), % recorded here for recursive types check_type_body(Head, Body, Constructors), process_type_body(Constructors, Head). process_type_body([Constructor|Constructors], Head) :- recordz(Constructor, type(Constructor,Head), _), !, process_type_body(Constructors, Head). process_type_body([], _). check_type_head(Head) :- var(Head), !, write('! Type head is a variable.'), nl, fail. check_type_head(Head) :- recorded(Head, (type), _), !, write('! Already a type: '), write(Head), nl, fail. check_type_head(Head) :- functor(Head, _, N), check_type_head(N, Head), !, fail. check_type_head(_). check_type_head(N, Head) :- arg(N, Head, Arg), nonvar(Arg), write('! Type head argument '), write(N), write(' is bad.'), nl. check_type_head(N, Head) :- arg(N, Head, N), M is N-1, check_type_head(M, Head). % is_type_expr(Term) % succeeds when Term is a type expression, that is, when all the % constructors it is made from are type constructors. If we had % type macros (:- type Lhs = Rhs) this is where we would expand % them. That will come later. is_type_expr(Type) :- var(Type), !. is_type_expr(Type) :- recorded(Type, (type), _), !, functor(Type, _, N), is_type_expr(N, Type). is_type_expr(Type) :- write('! not a type: '), write(Type), nl, fail. is_type_expr(0, Type) :- !. is_type_expr(N, Type) :- arg(N, Type, Arg), is_type_expr(Arg), M is N-1, !, is_type_expr(M, Type). check_type_body(Head, Body, _) :- numbervars(Head, 0, M), numbervars(Body, M, N), N > M, !, write('! Rhs of type def contains variables not in lhs.'), nl, fail. check_type_body(Head, Body, Constructors) :- check_type_body_(Body, Constructors, []). check_type_body_(( Constr1 ; Constr2 ), CL, CR) :- !, check_type_body_(Constr1, CL, CM), check_type_body_(Constr2, CM, CR). check_type_body_({Constructor}, [Constructor|CR], CR) :- nonvar(Constructor), functor(Constructor, _, N), is_type_expr(N, Constructor), !. check_type_body_({Constructor}, _, _) :- !, write('! Dud constructor : '), write(Constructor), nl, fail. check_type_body_(Constructor, CL, CR) :- check_type_body_({Constructor}, CL, CR). % process_pred(Preds, Sort) % processes pred (Sort=pred) and rule (Sort=rule) declarations. % Several predicates may be declared in one declaration, and they % may be separated by any mixture of commas and semicolons. To % declare comma or semicolon as a predicate, you have to put it % inside braces { }, e.g. :- pred {void,void}. The same escape % convention is used to let you define these symbols as constructors % in type declarations. process_pred(Var, Sort) :- var(Var), !, write('! variable in '), write(Sort), write(' declaration.'), nl, fail. process_pred((Preds1 , Preds2), Sort) :- !, process_pred(Preds1, Sort), process_pred(Preds2, Sort). process_pred((Preds1 ; Preds2), Sort) :- !, process_pred(Preds1, Sort), process_pred(Preds2, Sort). process_pred({Pred}, (pred)) :- recorded(Pred, type(_,void), _), !, write('! already declared: '), write(Pred), nl, fail. process_pred({Pred}, (pred)) :- !, functor(Pred, _, N), is_type_expr(N, Pred), recordz(Pred, type(Pred,void), _). process_pred({Rule}, (rule)) :- !, Rule =.. List, append(List, [list(T),list(T)], Full), Pred =.. Full, process_pred({Pred}, (pred)). process_pred(Other, Sort) :- process_pred({Other}, Sort). % To perform type checking we use the Milner algorithm with overloading. % The idea is that we consider (via backtracking) all the type resolutions % possible, and accept the typing if exactly one type assignment exists. % For this (second order) operation we use 'setof'. The typed premise % is in two parts. The predicate and functor assignments are held in the % data base, the variable assignments (which only have significance within % the current clause) in held in Tenv (type environment) variables. % type tenv --> var | var(variable,type,tenv). type_check(Given, Pruned) :- setof(P, To^type_check(Given, P, var, To, void), PP), ( PP = [Pruned], ! ; write('! ambiguous overloaded functor.'), nl, !, fail ). type_check(:-(Head,Body), _) :- write('% no type can be assigned to the rule'), nl, !, pp_explicit(:-(Head,Body), Head). type_check(Head, _) :- write('% no type can be assigned to the fact'), nl, !, pp_explicit(Head, Head). % type_check(Given, Pruned, TenvIn, TenvOut, Expected) % checks a Given term which is expected to have type Expected. % It may extend the type environment, as well as further specifying % existing variable assignments, and it returns the Given term % Pruned of ":Type" annotations. The point of the latter is to % help the type system when it comes across an overloaded term that % it is otherwise unable to resolve. type_check(X, X, Ti, Ti, Expected) :- Expected == any, !. % X had better not contain :annotations! type_check(Var, Var, Ti, To, Context) :- var(Var), !, type_check(Var, Ti, To, Context). type_check((Given:Type), Pruned, Ti, To, Expected) :- !, unify(Type, Expected), type_check(Given, Pruned, Ti, To, Expected). type_check((Head:-Body), (Lhs:-Rhs), Ti, To, void) :- !, recorded(Head, type(HeadT,void), _), numbervars(HeadT, 0, _), % crucial functor(Head, F, N), functor(Lhs, F, N), type_check(N, Head, Lhs, Ti, Tm, HeadT), type_check(Body, Rhs, Tm, To, void). type_check(Int, Int, Ti, Ti, integer) :- integer(Int), !. % special hack for numbers type_check(Given, Pruned, Ti, To, Expected) :- recorded(Given, type(GivenT, ResultT), _), unify(ResultT, Expected), functor(Given, F, N), functor(Pruned, F, N), type_check(N, Given, Pruned, Ti, To, GivenT). % Type check a variable type_check(Var, Ti, Ti, Expected) :- varassoc(Ti, Var, VarT), !, unify(VarT, Expected). type_check(Var, Ti, var(Var,Expected,Ti), Expected). varassoc(var(V,T,_), Var, T) :- V == Var, !. varassoc(var(_,_,R), Var, T) :- varassoc(R, Var, T). % Type check the arguments of a term. The Given, Pruned, and Expected % arguments all have the same principal functor, and N is the number % of arguments still to be checked. type_check(0, _, _, Ti, Ti, _) :- !. type_check(N, Given, Pruned, Ti, To, Expected) :- arg(N, Given, Agiven), arg(N, Expected, Aexpected), type_check(Agiven, Apruned, Ti, Tm, Aexpected), arg(N, Pruned, Apruned), M is N-1, % There *MUSTN'T* be a cut here, as we want type_check/5 % to be able to back-track and try another assignment. type_check(M, Given, Pruned, Tm, To, Expected). ------------------------------------------------------------------------ % File : PROLOG.TYP % Author : R.A.O'Keefe % Updated: 23 June 1983 % Purpose: Type definitions for Prolog & utilities % the two built in types are % void -- type of goals, truth values % any -- matches anything at all :- type integer --> % integers and expressions integer + integer | integer - integer | integer * integer | integer //integer % was /, should be div | integer mod integer | integer /\ integer % bitwise and | integer \/ integer % bitwise or | integer << integer % left shift | integer >> integer % right shift | + integer | - integer | [integer|any]. :- type list(T) --> [] | [T|list(T)]. :- type dbref --> ''. % this is a sort of abstract data type :- type op --> xf | yf | yfx | xfx | xfy | fy | fx. :- type order --> < | = | > . % for compare :- type pair(X,Y) --> X-Y. % for keysort :- pred {void,void}, % , = conjunction {void;void}, % ; = disjunction {void->void}. % -> = if-then :- pred abolish(any, integer). :- pred revive(any, integer). :- pred incore(void). :- pred asserta(void, dbref). :- pred asserta(void). :- pred assertz(void, dbref). :- pred assertz(void). :- pred retract(void). :- pred clause(void, void, dbref). :- pred clause(void, void). :- pred recorda(any, any, dbref). :- pred recordz(any, any, dbref). :- pred recorded(any, any, dbref). :- pred instance(dbref, any). :- pred erase(dbref). :- pred true. :- pred length(list(_), integer). :- pred name(any, list(integer)). :- pred op(integer, op, any). :- pred var(any). :- pred atom(any). :- pred !. :- pred statistics. :- pred statistics(any, any). :- pred functor(any, any, integer). :- pred call(void). :- pred expand_term(any, any). :- pred debug. :- pred debugging. :- pred display(any). :- pred get(integer). :- pred get0(integer). :- pred leash(any). :- pred nl. :- pred nodebug. :- pred print(any). :- pred put(integer). :- pred skip(integer). :- pred tab(integer). :- pred trace. :- pred ttyflush. :- pred ttyget(integer). :- pred ttyget0(integer). :- pred ttynl. :- pred ttyput(integer). :- pred ttyskip(integer). :- pred ttytab(integer). :- pred write(any). :- pred writeq(any). :- pred ancestors(list(void)). :- pred depth(integer). :- pred maxdepth(integer). :- pred subgoal_of(void). :- pred abort. :- pred arg(integer, any, any). :- pred assert(void). :- pred atomic(any). :- pred bagof(T, void, list(T)). :- pred break. :- pred close(any). :- pred compare(order, any, any). :- pred compile(any). :- pred consult(any). :- pred current_atom(any). :- pred current_functor(any,any). :- pred current_predicate(any,any). :- pred current_op(integer, op, any). :- pred fail. :- pred fileerrors. :- pred gc. :- pred gcguide(any). :- pred halt. :- pred integer(any). :- pred keysort(list(pair(X,Y)), list(pair(X,Y))). :- pred listing. :- pred listing(any). :- pred log. :- pred nofileerrors. :- pred nogc. :- pred nolog. :- pred nonvar(any). :- pred numbervars(any, integer, integer). :- pred phrase(any, list(_)). :- pred prompt(any, any). :- pred read(any). :- pred reconsult(any). :- pred rename(any, any). :- pred repeat. :- pred restore(any). :- pred save(any). :- pred see(any). :- pred seeing(any). :- pred seen. :- pred setof(T, void, list(T)). :- pred sort(list(T), list(T)). :- pred tell(any). :- pred telling(any). :- pred told. :- pred trimcore. :- pred plsys(any). :- pred 'LC'. :- pred 'NOLC'. :- pred spy void. :- pred nospy void. :- pred \+ void. :- pred T = T. :- pred integer is integer. :- pred T == T. :- pred T \== T. :- pred any =.. list(any). :- pred integer < integer. :- pred integer > integer. :- pred integer =< integer. :- pred integer >= integer. :- pred any @< any. :- pred any @=< any. :- pred any @>= any. :- pred any @> any. :- pred any^void. :- pred integer =\= integer. :- pred integer =:= integer. % From here on belong to UTIL. :- pred &(void, void). :- pred \=(T, T). :- pred \\(void, void). :- pred any(list(void)). :- pred append(list(T), list(T), list(T)). :- pred apply(any, list(any)). :- pred binding(any, void). :- pred casserta(void). :- pred cassertz(void). :- pred cgensym(any, any). :- pred check_exists(any). :- pred checkand(any, any). :- pred checklist(any, list(_)). :- pred clean. :- pred close(any, any). :- pred concat(any, any, any). :- pred continue. :- pred convlist(any, list(_), list(_)). :- pred delete(any). :- pred diff(T, T). :- pred disjoint(list(_)). :- pred edit(any). :- pred error(any, any, any). :- pred eval(void). :- pred eval(integer, integer). :- pred file_exists(any). :- pred findall(T, void, list(T)). :- pred flag(any, T, T). :- pred for(integer, void). :- pred forall(void, void). :- pred gcc(void). :- pred gensym(any, any). :- pred intersect(list(T), list(T), list(T)). :- pred last(T, list(T)). :- pred listtoset(list(T), list(T)). :- pred mapand(any, any, any). :- pred maplist(any, list(_), list(_)). :- pred member(T, list(T)). :- pred nextto(T, T, list(T)). :- pred nmember(T, list(T), integer). :- pred nobt(void). :- pred not(void). :- pred number(any). :- pred numlist(integer, integer, list(integer)). :- pred occ(any, any, integer). :- pred open(any). :- pred open(any, any). :- pred pairfrom(list(T), T, T, list(T)). :- pred perm(list(T), list(T)). :- pred perm2(T, T, T, T). :- pred read_in(list(T)). :- pred redo(any). :- pred remove_dups(list(T), list(T)). :- pred rev(list(T), list(T)). :- pred select(T, list(T), list(T)). :- pred seteq(list(T), list(T)). :- pred some(any, list(_)). :- pred subgoal(any, void). :- pred subset(list(T), list(T)). :- pred subst(any, T, T). :- pred subtract(list(T), list(T), list(T)). :- pred sumlist(list(integer), integer). :- pred thnot(void). :- pred tidy(any, any). :- pred tlim(integer). :- pred ton(any). :- pred toff. :- pred toff(any). :- pred trace(any, integer). :- pred trace(any, any, integer). :- pred union(list(T), list(T), list(T)). :- pred variables(any, list(T)). :- pred writef(any). :- pred writef(any, any). ------------------------------ End of PROLOG Digest ********************