Globals

Overview

Globals are spec definitions that globally apply to all types and instances under a given type. They provide a way to force the use of a consistent covariant slot type across all specs of the parent type. Additionally all instance data inheriting from the parent type is restricted by global definitions.

We use the term member to describe a slot or global defined with a given type spec. Slots are used to declare that a type has an expected field. Globals are used to ensure consistency of a given field across different types. A good example is the 'PhEntity.area' global that requires all usage of the 'area' slot to be a Number type with an area unit. Not all PhEntity's have an area, but when they do such as 'Site' and 'Space' that tag must be used consistently.

Names

Globals follow same rules as slot names:

  • Must contain only ASCII lower case letters, digits, or underbar
  • Must start with an ASCII lower case letter
  • Convention is to use camel case

Additionally, it is invalid to declare a global that is already defined by the parent type.

Maybe

Globals are implicitly maybe types: a global declares what a name means, not that any type must carry it, so it has no containing type to be required of. Because the maybe is implied, it is an error to declare it:

MyType: {
  *badTag: Str?          // Error: Global cannot be maybe
  *alsoBad: Str <maybe>  // Error: Global cannot be maybe
}

Requiredness is decided where a type declares a slot for the name:

Person: {
  *height: Number <quantity:"length", minVal:0>
}

// explicit type: height is required
A: Person { height: Number }

// explicit maybe type: height is optional
B: Person { height: Number? }

// value only: type is inferred from the global, height is optional
C: Person { height: 100cm }

Syntax

Global members look just like slot specs with a leading "*" asterisk:

MyType: {
  *globalTag: Type <meta1, meta2> "default"
}

The asterisk is syntax sugar for adding the <global> meta tag:

MyType: {
  globalTag: Type <global, meta1, meta2> "default"
}

Examples

Here is an example of a global spec:

Person: {
  *height: Number <quantity:"length", minVal:0>
}

This forces all specs that subtype from Person to conform to this global spec. Example subtypes:

// This spec is OK because it matches global type
SomePerson: Person {
  height: Number
}

// This spec is OK because it is a covariant override
// compatible with the global since Int is a subtype of Number
AnotherPerson: Person {
  height: Int
}

// This will not compile because the slot type is not
// compatible with the global; Str is not a subtype of Number
InvalidPerson: Person {
  height: Str
}

Globals also restrict instance data:

// OK because slot matches global slot restrictions
@instance-1: Person { height: Number "12m" }

// Error: Global type is 'sys::Number', value type is 'sys::Date'
@instance-2: Person { height: Date "2024-12-03" }

// Error: Number must be 'length' unit; '°C' has quantity of 'temperature'
@instance-3: Person { height: Number 12°C }

Inheritance

When a dict spec declares a slot that overrides a global, then it automatically inherits from that spec. In the reflection APIs and AST the slot will have a 'base' which references the global. The dict slot will inherit all the global's metadata. In the example above, both 'SomePerson.height' and 'AnotherPerson.height' will inherit the 'quantity' and 'minVal' metadata tag from the global spec.

A slot declared with only a value also inherits from the global and infers its type from it:

// height slot infers Number type from the Person.height global
SomePerson: Person {
  height: 100cm
}

Globals may also be contributed to a type by another library using a mixin; such globals participate in inheritance the same way for libraries that declare the mixin's library as a dependency.

Representation

Global members are modeled just like any slot with the 'global' meta tag.

Project Haystack Tags

Historically the Project Haystack ontology has required consistent use of all tags across all entity types. The ph library uses globals to enforce this design pattern. Every tag from 'ph' is defined as a global in the base 'PhEntity' type:

PhEntity: Entity {
  // Area of a shape or floor space
  *area: Number <quantity:"area">

  // Equipment used to store electric energy
  *battery: Marker

  ...
}

Haxall 4.0.7 ∙ 27-Oct-2026 09:10 EDT