Skip to content

MAP Type System (old)

Steve Melville edited this page Apr 16, 2025 · 1 revision

MAP Type System

The MAP Type System is designed to support a living, evolving agent-centric ecosystem — one in which all data structures are self-describing, composable, and extensible by agents.

This page introduces the MAP Type System by walking through the foundational concepts, built-in types, and extension mechanisms that power it.

Layer 1: BaseTypes and BaseValues (a.k.a. Storage Type)

BaseTypes are the foundational, portable types in the MAP system. The BaseType determines how a given value will actually be represented in different programming language environments. (i.e., TypeScript and JSON on the client and Rust on the server-side).

pub enum BaseType {
    Holon,
    Collection,
    Property,
    Relationship,
    EnumVariant,
    Value(ValueType),
    ValueArray(ValueType),
}

The BaseTypes layer includes types (e.g., MapInteger, MapString) and compound types (e.g., MapBytes). It also includes types defined by the Holochain hdk (e.g., ActionHash, Record). The set of BaseTypes is fixed for any given version of the MAP. Changes or additions to any of these types requires a recompile of the MAP code and an evolution of the persistent data stored using a prior version of the MAP.

Key Characteristics

  1. Scalar Types: Simple, atomic values such as integers, strings, and booleans.
  2. Non-Scalar Types: Includes MapBytes, which is used to represent raw binary data, such as hash digests, commonly used as identifiers in the system.

BaseTypes Enum

#[derive(Clone, PartialEq, Eq, new)]
pub enum BaseType {
    String(MapString),       // Portable string type
    Integer(MapInteger),     // Portable integer type
    Boolean(MapBoolean),     // Portable boolean type
    Bytes(MapBytes),         // Portable binary type (e.g., hash digest)
    Enum(MapEnumValue),      // Portable enum value
}


🔧 All Types Are Defined as Holons

In the MAP every type — from simple scalar types like strings and booleans to rich structures like relationships and holons — is described by holons. In MAP, everything is a holon, including types themselves. Holons are linked by meaningful relationships, own structured values, and participate in shared schemas that define the logic of entire domains. At the core of this system is a type architecture that supports:

  • ✅ Clear, consistent structure
  • ✅ Runtime introspection and validation
  • ✅ Agent-driven extension
  • ✅ Shared semantics without central control

Each type descriptor is composed of:

  • A TypeHeader holon — shared metadata for all types (e.g., name, label, description)
  • A type-specific holon — such as PropertyType, HolonType, RelationshipType, etc.

Together, these elements make up what we informally call a type descriptor — the complete specification for a type in MAP.

These components are linked together and stored in a Schema, which is itself a holon and can be shared, versioned, and reused.


🧱 Foundation: Base Types and Value Types

All types are ultimately grounded in a small, portable set of Base Types and Value Types. These are defined in the MAP’s Rust core and act as the low-level building blocks for everything else.

BaseType

The BaseType enum defines the broad category a type belongs to:

enum BaseType {
  Holon,
  Collection,
  Property,
  Relationship,
  EnumVariant,
  Value(ValueType),
  ValueArray(ValueType),
}

This allows the MAP to reason generically about types, e.g., “this field holds an integer value” or “this link points to a collection of holons.”

ValueType and BaseValue

  • ValueType defines the kind of a scalar value: String, Integer, Boolean, or Enum
  • BaseValue holds actual instances of those values, wrapped in types like MapString, MapInteger, etc.

These types are designed to be:

  • Portable across platforms (e.g., serialized to JSON)
  • Easy to validate and format
  • Extensible through agent-defined constraints (see below)

🧩 Defining New Types

MAP provides a consistent mechanism for defining new types, both in system code and at runtime.

Every BaseType (except ValueType) has a corresponding definer function, such as:

  • define_property_type
  • define_relationship_type
  • define_enum_type
  • define_holon_type

Each definer accepts a corresponding <BaseTypeName>Spec struct containing the fields needed to define that type — like its name, required properties, relationships, or cardinality.

Each definer creates:

  • A new TypeHeader holon
  • A <BaseTypeName>Type holon (e.g., PropertyType, RelationshipType)
  • Optionally, a linked ValueType holon

This pattern applies to both core MAP types and user-defined extensions.


🧬 Core Types in MAP

MAP comes with a small set of core types baked into the system. These are the building blocks for modeling schemas and behaviors. Examples include:

  • HolonType — defines the structure and semantics of a class of holons (e.g., BookType, PersonType)
  • PropertyType — defines named fields on holons
  • RelationshipType — defines uni-directional links between holons
  • HolonCollectionType — defines structure of relationship targets
  • SchemaType — a container for related types
  • HolonSpaceType — defines boundaries of ownership and federation
  • DanceType — defines actions holons can perform

Each core type is:

  • A holon
  • Defined with a TypeHeader + TypeDetails
  • Stored in a core Schema
  • Usable by agent-defined extensions

🌱 Extension Types: Agent-Defined and Runtime-Created

The MAP Type System is built for extensibility. Agents can define new types without recompiling the MAP core, and these types behave exactly like core types:

  • A new BookType holon might use PropertyTypes like title, published_date, and summary
  • A PersonType could be linked via a RelationshipType like AUTHORED_BY or MEMBER_OF
  • A custom EnumValueType might define options for status or affiliation

Agent-defined types:

  • Use the same definer pattern (<BaseTypeName>Spec)
  • Are stored in Schemas owned by that agent’s HolonSpace
  • May reference types from other Schemas (via REFERENCE links)
  • Are fully introspectable, validatable, and composable

🔄 How It All Connects

Each MAP type is made up of three core elements:

Component Role
TypeHeader Shared metadata and schema links
<BaseTypeName>Type Type-specific constraints and fields
ValueType (optional) Scalar validation and formatting rules

These holons are connected via:

  • HAS_ASPECT → links from the type to each of its components
  • VALUE_TYPE_FOR → links from ValueType to PropertyType
  • PROPERTY_OF, SOURCE_FOR, etc. → define how types relate to one another

🧭 Summary

The MAP Type System:

  • 📦 Is built from holons that represent types and relationships
  • 🧱 Begins with a portable set of base types and values
  • 🔧 Defines new types through consistent define_<type> functions
  • 🧠 Expresses all types through self-describing holons
  • 🌱 Allows any agent to define, share, and evolve their own schemas
  • 🔗 Makes all aspects of type definition introspectable and queryable

In MAP, types are not just code — they are living data structures, versioned and governed like any other shared knowledge.


====================== PRIOR CONTENT =====================================

Layer 2: CoreTypes

Definition

  • CoreTypes build upon BaseTypes to introduce semantically meaningful types required by the MAP core code. Examples, include PropertyName, RelationshipName, HolonId.

Characteristics

  • CoreTypes are defined in terms of BaseTypes to ensure portability and consistency.
  • Examples include identifiers, names, and other semantically enriched types.

Examples

  • PropertyName: Wraps MapString, representing a property name.
  • HolonId: Represents a unique identifier for a Holon.
  • RelationshipName: Wraps MapString, representing the name of a relationship.

CoreTypes are organized into the following groups via the CoreType enum. Numbers in parentheses indicate the current number of core types within that group:

  • DanceType (TBD)
  • EnumVariantType (16)
  • HolonType (24)
  • IndexedType (2)
  • PropertyType (24)
  • RelationshipType (27)
  • ValueType (8)

Layer 3: DescriptorTypes

Definition

  • DescriptorTypes define metadata and constraints for the values of a given type. Each BaseType has a corresponding DescriptorType. For example, IntegerDescriptorType defines the metadata about MapIntegers. This could include min and max allowable values for instances of that type, a human-readable name and description of the type and more.

Characteristics

  • Each BaseType has a corresponding DescriptorType.
  • DescriptorTypes can specify constraints like minimum/maximum values, length restrictions, or other rules.

Examples

  • IntegerDescriptorType: Specifies min/max constraints for MapInteger.
  • StringDescriptorType: Specifies length constraints for MapString.

Layer 4: CoreDescriptorTypes

Definition

  • CoreDescriptorTypes describe the types that the MAP core code depends on. are the reserved DescriptorTypes that the MAP core code depends on.

Characteristics

  • Each BaseType can be associated with one or more CoreDescriptorTypes.
  • CoreDescriptorTypes are critical to the functioning of the MAP and are not customizable by agents.

Example

pub enum CoreStringDescriptorType {
    #[default]
    MapStringType,
    PropertyNameType,
    RelationshipNameType,
    SemanticVersionType,
}

Layer 5: ExtensionDescriptorTypes

Overview

ExtensionDescriptorTypes allow agents (developers) to define custom types dynamically without requiring recompilation of the MAP core. These types provide a flexible way for agents to extend the MAP Type System for their own applications, tailoring it to specific use cases.


Key Characteristics

  1. Agent-Defined:

    • ExtensionDescriptorTypes are created and managed by agents to support application-specific needs.
    • They are not part of the MAP core and operate independently of core system upgrades.
  2. Dynamic:

    • Developers can add new types without recompiling the MAP core or migrating data structures.
  3. Flexibility:

    • These types allow agents to define rich metadata for custom types, including validation rules, relationships, and semantics.
  4. Reserved Names:

    • To avoid conflicts, agents cannot use reserved CoreDescriptorType names when defining their own types.

Clone this wiki locally