Decides which alpha nodes a fact must be offered to.
Internal. A condition declares the fact type it is written against. But the alpha
expression it compiles to matches a fact of any shape. Type filtering happens here
instead, at propagation time. So derive/2 and underive/2 widen what a condition
sees, without recompiling an expression.
derive(:premium, :customer) reads "a premium is a customer". A :premium fact
reaches every condition written against :customer. A :customer fact must not
reach a condition written against :premium. So a fact of type t is offered to t
plus its ancestors, never its descendants.
iex> taxonomy =
...> Rete.Taxonomy.new([{:derive, :premium, :customer}],
...> alphas: %{customer: [:a1], premium: [:a2]}
...> )
iex> Rete.Taxonomy.alpha_ids(taxonomy, {:premium, 1})
[:a2, :a1]
iex> Rete.Taxonomy.alpha_ids(taxonomy, {:customer, 1})
[:a1]alpha_ids/2 runs for every inserted fact. So index/2 precomputes the whole
type => ids map. Empty entries are dropped. A type absent from the index answers
[], without allocating. This keeps a session that inserts foreign facts from
leaking. See docs/design/network.md §2.
Summary
Types
Alpha node ids, keyed by the fact type the condition is written against.
An ordered taxonomy declaration, as returned by Rete.get_taxo_data/1.
A fact type: an atom tag, or a module for a struct fact.
Fields
Functions
The ids of the alpha nodes fact must be offered to.
The ids of the alpha nodes a fact of type type must be offered to.
The ancestors of type, sorted. [] for a type in no derivation.
The default :fact_type_fn.
The condition types a fact of type type must be matched against.
The type of fact, according to the taxonomy's :fact_type_fn.
Builds a taxonomy from the derive/underive declarations of ruleset modules.
Precomputes the fact type => alpha node ids index for alphas.
Whether a fact of type child reaches a condition written against parent.
Builds a taxonomy from an ordered list of declarations.
Types
Alpha node ids, keyed by the fact type the condition is written against.
An ordered taxonomy declaration, as returned by Rete.get_taxo_data/1.
A fact type: an atom tag, or a module for a struct fact.
@type t() :: %Rete.Taxonomy{ alphas: alphas(), fact_type_fn: (term() -> fact_type()), index: %{optional(fact_type()) => [term()]}, taxo: %Taxo{ancestors: term(), descendants: term(), parents: term()} }
Fields:
:taxo— the foldedTaxohierarchy.:fact_type_fn— a one-argument function that returns a fact's type.:alphas— thecondition type => alpha node idsmap last indexed.:index— the memoizedfact type => alpha node idsmap. It never holds an empty entry. A type absent from it propagates to nothing.
Functions
The ids of the alpha nodes fact must be offered to.
Answers [] for a fact whose type no condition is written against, directly or through
a derivation.
The ids of the alpha nodes a fact of type type must be offered to.
See alpha_ids/2, which derives type from a fact.
The ancestors of type, sorted. [] for a type in no derivation.
The default :fact_type_fn.
- a struct is typed by its module.
- a tagged tuple
{:type, ...}, of any arity, is typed by its first element. - a tagged map
%{__type__: type}is typed by that value.
Anything else raises an error. If a fact had the wrong type by accident, it would match nothing, silently. You could not tell that case apart from a rule that simply does not apply.
iex> Rete.Taxonomy.default_fact_type({:order, 1, 99})
:order
iex> Rete.Taxonomy.default_fact_type(%{__type__: :order, id: 1})
:order
iex> Rete.Taxonomy.default_fact_type(%Rete.IR.Test{})
Rete.IR.Test
The condition types a fact of type type must be matched against.
type first, then its ancestors, sorted. The order does not depend on the order the
derivations were declared in.
iex> taxonomy = Rete.Taxonomy.new([{:derive, :dog, :mammal}, {:derive, :mammal, :animal}])
iex> Rete.Taxonomy.expand(taxonomy, :dog)
[:dog, :animal, :mammal]
iex> Rete.Taxonomy.expand(taxonomy, :rock)
[:rock]
The type of fact, according to the taxonomy's :fact_type_fn.
Builds a taxonomy from the derive/underive declarations of ruleset modules.
The declarations of all the modules are concatenated in module order, so a module can only undo a derivation declared by a module before it.
Precomputes the fact type => alpha node ids index for alphas.
alphas maps the type a condition is written against to the ids of the alpha
nodes built for it. The result answers alpha_ids/2 in one map lookup.
Whether a fact of type child reaches a condition written against parent.
True when the two are the same type, and when child derives from parent directly or
transitively.
iex> taxonomy = Rete.Taxonomy.new([{:derive, :dog, :mammal}])
iex> {Rete.Taxonomy.is_a?(taxonomy, :dog, :mammal), Rete.Taxonomy.is_a?(taxonomy, :mammal, :dog)}
{true, false}
@spec new( [declaration()], keyword() ) :: t()
Builds a taxonomy from an ordered list of declarations.
Options:
:fact_type_fn— a one-argument function that returns a fact's type. Defaults todefault_fact_type/1.:alphas— thecondition type => alpha node idsmap toindex/2right away. Defaults to%{}, which makes every lookup answer[].
Declarations are folded in order, so a later :underive undoes an earlier :derive.
This raises if a declaration is not a :derive or :underive tuple. It lets Taxo
raise on a cyclic derivation instead.
iex> taxonomy = Rete.Taxonomy.new([{:derive, :dog, :mammal}, {:derive, :mammal, :animal}])
iex> Rete.Taxonomy.ancestors(taxonomy, :dog)
[:animal, :mammal]