Defs are organized into a tree structured taxonomy via the is tag. A def is a subtype if it defines a subset or narrowing of a broader term. For example we say that water is a subtype of liquid because it is a specific type of liquid. The converse is that liquid is a supertype of water.
In the context of natural language, a subtype is a hyponym and a supertype is a hypernym. If you have ever played Mad Libs, then subtyping is intuitively like filling in the blanks. For example if we say that a pipe conveys a fluid, then the term fluid encompasses specific types of fluids including water, steam, gasoline, or fuel oil.
We can also evaluate subtyping in the context of set theory. If we say that elec-meter is a subtype of meter, then we are saying the set of all things that are elec meters is wholly contained by the set of all meters.
Subtyping is a powerful knowledge modeling tool. However remember that modeling the real world is a messy business. Its impossible to design a taxonomy that fits all situations. Consider the platypus and its difficulty to fit into a biological taxonomy. Haystack attempts to define a pragmatic approach between simplicity and the common use cases. But you will likely find use cases which aren't a perfect fit for Haystack's ontology.
Subtyping is defined to be a transitive relationship. If B
is a subtype of A
and C
is a subtype of B
, then it is implied that C
is a subtype of A
. A concrete example: water is a subtype of liquid and liquid is a subtype of fluid, therefore water is inferred to be a subtype of fluid.
Subtyping is declared via the is tag on a def. The value of the is
tag is a symbol or list of symbols. Since most defs subtype from a single def, we typically use just a symbol:
def: ^water is: ^liquid
In cases where multiple supertypes are required, use a list of symbols:
def: ^building is: [^site, ^space]
All terms are required to have an is
tag with the exception of the root terms which are marker, val, aspect, and feature. Feature keys have implied subtyping rules and must not declare an is
tag.
It is invalid to create cyclic subtyping relationships. Subtyping must result in a strict tree structure.
Defs are themselves specified a set of tag name/value pairs. Subtypes automatically inherit these tags into their own definitions. We call this process inheritance and it works similar to inheritance in traditional object-oriented languages.
We call the tags explicitly defined in a def the declared tags. The tags that are effective after inheritance is applied are called the normalized tags. Normalization rules are as follows:
is
tagIn the case of ambiguity from multiple inheritance, a subtype should explicitly declare the tag value.
Consider this completely fictional example for an El Camino which is a hybrid between a car and a pickup truck:
// declarations def: ^car numDoors: 4 color: "red" engine: "V8" ---- def: ^pickupTruck numDoors: 2 color: "blue" bedLength: 80in ---- def: ^elCamino is: [^pickup, ^car] color: "purple"
The normalized definition with inheritance would be:
def: ^elCamino // declared is: [^pickup, ^car] // declared color: "purple" // declared numDoors: 2 // inherited from pickup first engine: "V8" // inherited from car bedLength: 80in // inherited from pickup