Datatype relations are not a distinct kind of data structure but are in fact
simply algebraic datatypes declared to have a relation
attribute. For example, in
the following definition three relation types Person
, Parent
and Gen
are defined.
datatype Person :: relation = person (const char *) and Parent :: relation = parent (const char *, const char *) and Gen :: relation = same_generation (const char *, const char *); instantiate datatype Person, Parent, Gen;
Using these relations we can define an inference class that computes whether two persons are in the same generation. Nine axioms are defined (i.e. those whose lhs are empty) in the following. The two inference rules state that (1) a person is in the same generation as him/herself, and (2) two persons are in the same generation if their parents are in the same generation.
inference class SameGeneration {}; inference SameGeneration { -> person("p1") and person("p2") and person("p3") and person("p4") and person("p5"); -> parent("p1", "p2") and parent("p1", "p3") and parent("p2", "p4") and parent("p3", "P5"); person ?p -> same_generation (?p, ?p); parent (?x, ?y) and parent (?z, ?w) and same_generation (?x, ?z) -> same_generation(?y, ?w); };
In general, datatypes qualified as relation
s will inherit
from the base class Fact
, while a rewrite class definition
implicitly defines two member functions used to assert and retract facts
in the internal database. For example, in the above example, the following
protocol will be automatically generated by the inference compiler.
class SameGeneration : ... { public: virtual Rete& infer (); // start the inference process virtual ReteNet& operator += (Fact *); // assert fact virtual ReteNet& operator -= (Fact *); // retract fact };
Using these methods, an application can insert or remove relations from an inference class. This will in turn trigger any attached inference rules of the class.