eyedia

Witnesses

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


The question

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?


What we tell Eyedia

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.


What Eyedia concludes

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.


Why not let Eyedia invent names?

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:


Why: the proof in plain words

  1. Alice is a person — a fact we gave (fact 1).
  2. So Alice has the record record(person_rule, alice) — rule 3, with Name = alice.
  3. And that record’s owner is Alice — rule 3 again, same binding.

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.


Checked, not just claimed

A separate checker read all 6 steps against the program and confirmed that:

Verdict: checked. Nothing taken on trust.


Try it

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).


Takeaway

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.