Reputation:
I am looking for ways to make a Prolog program "look" more like first order logic. Things I would like to have are for example:
Or is there other software that already implements this?
Thanks in advance!
/JC
Update 20190313 I followed the suggestions in the answers below and tried this:
:- op(1200, xfx, ==>).
:- op(1000, xfy, /\).
:- op(1100, xfy, \/).
term_expansion(A ==> B, B:- A).
term_expansion(A /\ B, A, B).
term_expansion(A \/ B, A; B).
man(X) /\ unmarried(X) ==> bachelor(X).
man(john).
man(peter).
unmarried(john).
main:-bachelor(X), writeln(X), nl, fail.
But i get the following error:
ERROR: bachelor/1: Undefined procedure: (/\)/2
Exception: (5) man(_1740)/\unmarried(_1740) ?
Only using the op/3 and term_expansion/3 for ==> however works as expected. Not sure why this is so...
Upvotes: 1
Views: 157
Reputation: 18726
This answer refers to your updated question ("Update 20190313").
Be careful when defining operators:
Don't redefine standard operators, changing their specifier/precedence.
This can introduce errors in existing code which are very hard to find.
Weigh benefits and costs upfront.
Aim at readability, shorter code, and fewer parentheses.
Keep in mind that using too many custom Prolog operators can also obfuscate code and confuse the reader.
Think twice before using standard operators in different domains.
Let's take the predefined (\/)/2
as an example.
It is an evaluable functor in arithmetic expressions—used with (is)/2
, (=:=)/2
, (<)/2
, etc.
clpfd uses it for representing set unions like 1..3 \/ 5..7
—fine!
However, using it for denoting list concatenation is questionable.
Let's get to your actual question!
Consider these queries decomposing some terms using (=..)/2
("univ"):
?- term_expansion(A /\ B, A, B) =.. Xs.
Xs = [term_expansion, A/\B, A, B].
?- term_expansion(A \/ B, A; B) =.. Xs.
Xs = [term_expansion, A\/B, (A;B)].
So it's term_expansion/2
for (\/)/2
, but term_expansion/3
for (/\)/2
!
The bottom line: (',')/2
terms as arguments need parentheses.
?- term_expansion(A /\ B, (A,B)) =.. Xs. Xs = [term_expansion, A/\B, (A,B)].
Upvotes: 0
Reputation: 53
Use term_expansion/2 that is macro of Prolog on SWI-Prolog:
% calc.pl
:- op(1200,xfx,--).
term_expansion(A--B,B:-A).
integer(I)
--%----------------------- (E-Int)
I => I.
E1=>I1, E2=>I2, I is I1+I2
--%----------------------- (E-Add)
E1+E2 => I.
:- 1+2+3=>6.
:- 1+2+3=>I,writeln(I).
:- halt.
and run
$ swipl calc.pl
6
Upvotes: 4
Reputation: 40768
Here are a few Unicode characters that can help you:
¬ → ⇒ ← ⇐ ∨ ∧ ∀ ∃
I leave defining suitable precedences as a challenge, using op/3
.
Once you have these definitions, you can write first-order sentences with them. You can then convert these sentences to Prolog, or interpret them with Prolog.
Upvotes: 3