Skip to content

🧬 Starting Point: Types as Holons

In MAP, every type description is, itself, a holon.

This means that every type must: - Be described by a TypeDescriptor - Be owned by a HolonSpace

These aren't optional conventions β€” they are defining structural obligations of being a holon.

βœ… Every type in MAP is a holon.
Therefore: every type must have DescribedBy and OwnedBy relationships.


Modeling MAP Value Types

πŸ”  Example: MapStringValueType and PropertyNameValueType

Consider two value types:

  • MapStringValueType: A general-purpose string type
  • PropertyNameValueType: A string type used specifically for property names

They both represent strings at the data level, but differ in usage and constraint.

Both are:

  • Holons β†’ Must be DescribedBy and OwnedBy
  • TypeDescriptors β†’ Must be instances of MetaValueType

So the following relationships apply:

MapStringValueType β€”[DescribedBy]β†’ MetaValueType  
PropertyNameValueType β€”[DescribedBy]β†’ MetaValueType

At this point, we know these two holons are not just any holons β€” they are type descriptors used in the schema.


🧱 Shared Constraints via Compositional Inheritance

Different value types require different constraints:

  • Strings β†’ min/max length, format, case convention
  • Integers β†’ min/max values
  • Enums β†’ allowed variants
  • Bytes β†’ fixed length, encoding

But many types share these constraints. For example:

MapStringValueType        ─┐
                          β”œβ”€[Extends]β†’ StringValueConstraints
PropertyNameValueType     β”€β”˜

In this pattern:

  • MapStringValueType and PropertyNameValueType are both holons and descriptors.
  • StringValueConstraints is just a constraint facet β€” it contributes properties like min_length, max_length, or case_convention.

Importantly:

StringValueConstraints is not a type. It’s not a descriptor.
It doesn’t have a type_name, doesn’t need to be DescribedBy, and doesn’t appear in any schema.

It just extends the value type it’s associated with, in a purely compositional way.


🧷 Why Keys Matter

Semantic keys are foundational to the MAP architecture β€” not just for expressing relationships during import, but for enabling retrieval, referencing, and bootstrapping in a decentralized, descriptor-driven system.

They enable holons to be meaningfully identified and linked across the full lifecycle β€” from initial import to runtime introspection β€” even before they've been committed to the system or assigned a permanent ID.


πŸ”„ Staged Relationships Without IDs

In staged or import workflows, holons frequently reference other holons that haven’t yet been committed β€” and therefore lack a system-assigned ID (e.g., a Holochain ActionHash).

Keys solve this by allowing holons to be referenced using $ref: "key" rather than relying on fragile temporary identifiers or rigid load ordering.

βœ… Keys enable: - Cross-file linkage between staged holons - ID-free $ref expressions in JSON - Relationship validation prior to commit - Deduplication and merging of equivalent entries

πŸ“˜ Example:

{
  "type_name": "RelationshipType",
  "key": "(PersonType)-[MentoredBy]->(PersonType)",
  "relationships": [
    { "name": "SOURCE_FOR", "target": [{ "$ref": "PersonType" }] },
    { "name": "TARGET_FOR", "target": [{ "$ref": "PersonType" }] }
  ]
}

This relationship type can be referenced by other holons using its key, without requiring an ID to exist yet.


🧱 Bootstrapping Descriptors Before Descriptor Logic Exists

Many MAP behaviors β€” including validation, inverse relationship population, and declarative key generation β€” depend on descriptors like PropertyType, RelationshipType, or HolonType.

But you can’t run logic that depends on descriptors until descriptors are present.

By requiring materialized key fields in the JSON of Keyed Holons, we can: - Import descriptors without requiring key generation logic - Reference them from other holons in the same import graph - Stage and introspect schemas and data prior to persistence

This makes it possible to: - Import the MAP Meta-Schema - Import domain-specific schema extensions - Import valid data instances ...all in a single, unified process.


πŸ” Associative Retrieval in Distributed Systems

In distributed architectures like Holochain, data is stored in Distributed Hash Tables (DHTs) β€” meaning:

  • You cannot β€œquery the whole database” as you would in a centralized store
  • You typically need a known hash or path to locate content efficiently

Materialized keys provide the critical link between semantic meaning and retrieval paths:

βœ… They support:

  • Associative lookup: finding content based on associated properties (e.g., type, relationship role)
  • Path-based indexing: storing holons under DHT paths that reflect their keys (e.g., path!(("HolonType", key)))
  • Declarative retrieval APIs: enabling callers to say β€œget me the [MentoredBy] relationship” without knowing its ID

Without keys:

  • Content is only retrievable via opaque identifiers
  • Queries become tightly coupled to global indexes or full scans (inefficient or unavailable in DHTs)
  • Schema introspection and semantic queries are significantly harder

🧠 Summary

Keys are not just syntactic sugar β€” they are critical infrastructure for:

  • Declarative, schema-linked imports
  • ID-free reference resolution across files
  • Bootstrapping descriptors before runtime logic is available
  • Efficient, semantic-based retrieval in distributed systems
  • Federated schema evolution and shared introspection

By embracing materialized, semantically meaningful keys, MAP achieves a powerful combination of:

  • Structural clarity
  • Introspectable relationships
  • Decentralized operability
  • Self-hosted schema evolution

This makes keys one of the most essential capabilities in the MAP Type System.


πŸ“ Layered Inheritance: The Value Type Stack

MetaValueType β€”[Describes]β†’ MapStringValueType β€”[Extends]β†’ StringValueConstraints

This gives us three clear layers:

  1. Meta Descriptor Level β€” defines what a value type must contain
  2. Descriptor Level β€” a value type like MapStringValueType or PropertyNameValueType
  3. Constraint Layer β€” reusable modular constraints via Extends
Layer Holon Purpose
Meta MetaValueType Describes value type descriptors
Type MapStringValueType Actual TypeDescriptor
Constraint StringValueConstraints Adds constraint properties

πŸ” Pattern Repeats for All Primitive Types

Here’s the same pattern across other type kinds:

ValueType DescribedBy ExtendedBy Constraints Provided
MapStringValueType MetaValueType StringValueConstraints min_length, max_length, etc.
PropertyNameValueType MetaValueType StringValueConstraints Custom limits, case_convention
MapIntegerValueType MetaValueType IntegerValueConstraints min_value, max_value
MapBytesValueType MetaValueType BytesValueConstraints length, encoding, format_hint
MapEnumValueType MetaValueType EnumValueConstraints Variants relationship
MapBooleanValueType MetaValueType (none needed) (no constraints required)

🧩 Are Meta Types Holons Too?

Yes β€” and this is where the architectural recursion becomes elegant.

Just as MapStringValueType is a holon and needs to be DescribedBy, so too does MetaValueType.

Let’s follow the thread:

MetaValueType         β€”[DescribedBy]β†’ MetaTypeDescriptor  
MetaIntegerValueType  β€”[DescribedBy]β†’ MetaValueType

So:
πŸ” Meta types themselves are holons
πŸ” They need to be described
πŸ” They participate in the same system they define


πŸ”„ Recursion Meets Structure: MetaTypeDescriptor Extends MetaHolonType

To avoid repeating the structural obligations of all holons (like needing DescribedBy and OwnedBy) across every Meta type…

We simply declare:

MetaTypeDescriptor β€”[Extends]β†’ MetaHolonType

Now, every Meta type (like MetaValueType, MetaPropertyType, etc.) that is an instance of MetaTypeDescriptor inherits from MetaHolonType, which defines the baseline expectations for all holon types.

βœ… Every Meta type becomes both a type descriptor and a holon
βœ… DRY design: MetaHolonType captures shared structural rules
βœ… Recursive closure: the system defines itself in clean, layered cycles


🧠 Summary of the Pattern

Concept Relationship Notes
ValueType DescribedBy β†’ MetaValueType Marks as a valid type holon
ValueType Extends β†’ ValueConstraints Adds constraints modularly
MetaValueType DescribedBy β†’ MetaTypeDescriptor Makes it a descriptor of type descriptors
MetaValueType Extends β†’ MetaHolonType Inherits holon-level expectations
Constraints (e.g. StringValueConstraints) (no type) Purely compositional constraint layer

🧰 Bonus: How You Might Use This in Validation or Import

When validating a PropertyType that refers to a ValueType:

  1. Confirm the target is a holon
  2. Confirm it’s DescribedBy MetaValueType
  3. Confirm it satisfies the constraints from any Extends facets

This lets you:

  • Reuse constraints
  • Compose constraint types
  • Keep descriptors clean and minimal
  • Keep validation DRY and generalizable