When a rule creates something new, give it a name that says where it came from.
witnesses.pl · output · proof · check · try it in the playground
Suppose a rule says: every person has a record. For Alice and Bob, that means two new records exist. But what are they called? And how do we keep the record and its owner tied together?
A name for something a rule brings into existence is called a witness: it stands as evidence that the thing exists.
Can we make each witness say exactly which rule made it, and for whom — and conclude two facts about it at once?
Two people, and one rule with two conclusions:
person(alice).
person(bob).
(has_record(Name, record(person_rule, Name)), record_owner(record(person_rule, Name), Name)) :+ person(Name).
The witness is the term record(person_rule, Name): a record labelled with
the rule’s name and the person it was made for.
The left side holds two conclusions in brackets. Both share that same witness, so they always talk about the same record.
has_record(alice, record(person_rule, alice)).
record_owner(record(person_rule, alice), alice).
has_record(bob, record(person_rule, bob)).
record_owner(record(person_rule, bob), bob).
Two facts per person. Alice’s record is record(person_rule, alice) —
readable, stable from run to run, and impossible to mix up with Bob’s.
Eyedia can invent placeholder names for things a rule leaves unnamed. But an explicit witness is better when you want one per rule and per binding:
record(person_rule, alice) — rule 3, with
Name = alice.Bob’s two facts follow the same way from fact 2. Both conclusions cite the
same rule and the same value for Name: that is how a shared multi-part
conclusion shows up in the proof.
A separate checker read all 6 steps against the program and confirmed that:
Verdict: checked. Nothing taken on trust.
node bin/eyedia.js examples/witnesses.pl # the four facts
node bin/eyedia.js --proof examples/witnesses.pl # with their proof
Or open it in the playground.
Add person(carol). and run again: two more facts appear, with the
witness record(person_rule, carol).
A good name carries its own history. By building the witness from the rule and the binding, every new thing Eyedia concludes can be traced to where it came from — even before you look at the proof.