Version 1 defines 24 DataCanon Types (DCTs). A DataCanon Instance (DCI) is an instance of one DCT. Instances of different DCTs are never equal. Each DCT specifies its information and validity rules; canonical bytes encode that identity independently of textual presentation.
Named mathematical constants
Constant stores the name pi or e, identifying the exact mathematical
constant without a decimal approximation. Shorthand uses Pi and E;
longhand uses constant("pi") and constant("e"). A Constant DCI is distinct
from every Float approximation and is permitted as a Numerical DCI.
Conventional types and DCT implementations
A conventional type is a type used directly for data and computation in a programming language, including built-in, library-provided, and user-defined types. Conversion interfaces connect DCIs with instances of conventional types.
DCTs and conventional types have their own rules. For example, Python’s
ListDC class implements the List DCT. A ListDC instance and a conventional
list instance are Python objects of different types. Conversion connects the
types without changing programming languages. A conventional Fraction or
Sum may simplify its contents, while Fraction and Sum DCIs retain their
prescribed structure.
The Conventional Types guide introduces the relationships and operations. Exact conversion directions and limitations belong to the Python API. The optional Conventional Types specification defines the common behavioral contract for independent language implementations. Its arithmetic and comparison requirements do not alter the DCT identity rules summarized below.
Primitive types
Primitive DCTs specify their information directly, without constituent DCIs. This includes Fraction’s two prescribed integer fields.
| DCT | Information | Example Shorthand |
|---|---|---|
| Null | One value | null |
| Boolean | False or true | true |
| Integer | Arbitrary-precision mathematical integer | 42 |
| Float | Finite binary64 value, with bit identity | 1.0 |
| String | Unicode scalar sequence, without normalization | "hello" |
| Bytes | Opaque finite byte sequence | bytes("00ff80") |
| Constant | Exact named mathematical constant | Pi or E |
| Fraction | Integer numerator and positive integer denominator | 1/3 or fraction(1, 3) |
Positive and negative Float zero are distinct. Nonfinite floating-point values are excluded. Fraction pairs are retained without reduction in the DCI model.
Numerical DCIs
A Numerical DCI is a scalar numerical structure, an Array, a Sum, or an OrderedProduct. A Scalar Numerical DCI is Integer, Float, Fraction, Constant, Product, Power, Quotient, or a Sum/OrderedProduct whose every operand is recursively scalar. Arrays, including rank-zero Arrays, are not scalar in this classification. Boolean and Complex DCIs are outside these categories.
Classification is structural, without evaluation or shape inference. Sum and OrderedProduct accept Numerical DCIs; Product, Power bases, Quotient operands, and Complex components require Scalar Numerical DCIs.
Atomic types
Atomic types have a fixed set of named fields and at least one constituent DCI.
| DCT | Information | Example Shorthand |
|---|---|---|
| Power | Scalar Numerical base DCI; positive integer exponent numerator and denominator | 5**(1/3) or power(5, 1, 3) |
| Quotient | Scalar Numerical numerator and denominator DCIs | quotient(1, sqrt(3) + sqrt(2)) |
| Complex | Real and imaginary Scalar Numerical DCIs | complex(1/2, sqrt(3)) |
Power’s exponent defaults to denominator one in its two-argument constructor.
Fraction bases require explicit power(...) syntax. sqrt(base) is the Power
spelling with exponent fields 1 and 2. Exponent fields remain unreduced in DCIs.
Quotient has no mathematical nonzero-denominator invariant in the current Core
draft. Converting a Quotient DCI to a conventional Quotient object can fail
for a recognized zero denominator; explicit numerical evaluation can fail for
other undefined expressions.
Composite types
| DCT | Structure and identity | Example Shorthand |
|---|---|---|
| List | Ordered DCIs | [1, 2] or list(1, 2) |
| Tuple | Ordered DCIs, distinct from List | (1, 2) or tuple(1, 2) |
| Set | Unordered distinct DCIs | {1, 2} or set(1, 2) |
| Multiset | Unordered DCI occurrences, retaining multiplicity | multiset(1, 1, 2) |
| Sum | Unordered Numerical DCI occurrences | 1 + 2 or sum(1, 2) |
| Product | Unordered Scalar Numerical DCI occurrences | 2 * sqrt(3) or product(2, sqrt(3)) |
| OrderedProduct | Ordered Numerical DCI occurrences, including Arrays | ordered_product(2, array([[1, 0], [0, 1]])) |
| Mapping | Ordered entries with distinct DCI keys | {"a": 1} or mapping("a": 1) |
| UnorderedMapping | Unordered entries with distinct DCI keys | umapping("a": 1) |
| Record | Unicode name and ordered uniquely named DCI fields | record("Point", "x": 1.0) |
| Array | Portable machine type, shape, and elements | array([1.0, 2.0]) |
| ExternalFile | Relative path and content digest | external_file("x.bin", "DIGEST") |
| ExternalArray | Relative path, Array type, shape, and content digest | external_array("x.bin", "float64", (2), "DIGEST") |
DIGEST is a placeholder for 64 hexadecimal characters, not valid literal
metadata. Resource availability does not change an external DCI’s identity.
Empty Sets use set(); empty Mappings use {} or mapping(). A singleton
Tuple is (1) or tuple(1). Empty and singleton Sums and Products retain their
constructors. Numerical nesting and multiplicity participate in identity.
Numerical structure and presentation
Sum and Product identity ignores operand order but retains repeated operands
and nesting. A flat sum(1, 2, 3) and a nested sum(1, sum(2, 3)) therefore
represent different DCIs. Quotient and Fraction are distinct DCTs even when
their mathematical interpretations agree.
The Python DCT implementations retain supplied operand order for Shorthand presentation. Canonical encoding sorts complete operand encodings for unordered DCTs. Canonical decoding may recover a different presentation order without changing DCI identity. The numerical conventional types have separate construction and simplification rules.
Strict Shorthand parentheses construct Tuples rather than grouped arithmetic
expressions. Constructors preserve explicit nesting, as in
product(2, sum(3, 4)); binary subtraction is not part of strict Shorthand.
Direct information and constituent DCIs
Fixed-domain information is prescribed directly: Fraction integers, Power exponent integers, Record and field names, relative-path components, Array metadata, and digests. Their domains do not vary by field value.
A Power base, Complex component, Quotient operand, collection member, or Record field value is a DCI. Its DCT participates in the containing value’s identity. Record names do not identify another DCT or instruct an application to create a class.
Canonical encoding reuses shared payload rules for fixed information and full DCI encodings for constituent DCIs. Array elements use specialized machine representations rather than individual DCI encodings.
Portable Array types
| Category | Types |
|---|---|
| Boolean | bool |
| Signed integers | int8, int16, int32, int64 |
| Unsigned integers | uint8, uint16, uint32, uint64 |
| Floating point | float16, float32, float64 |
| Complex | complex64, complex128 |
Array type, rank, shape, and corresponding element identities all matter. A rank-zero Array contains one element. Any zero dimension gives zero elements. Elements are canonically encoded in logical C order, with the rightmost index varying fastest and multibyte numerical values in big-endian order.
Array construction and dtype promotion in the Python interface follow the supported NumPy behavior. Explicit dtype conversion can round values; the resulting Array must satisfy its DCT’s validity rules.
Shorthand, longhand, and preprocessing
Longhand uses explicit constructors for structured values and ordinary literals
for Null, Boolean, Integer, Float, and String. The distinction concerns syntax,
not the Core type classification: Fraction uses fraction(...) despite being
primitive. Bytes keeps bytes(...), and Array elements retain their specialized
syntax. sum(1, 1.0, fraction(1, 2)) is longhand without extra literal wrappers.
The parser accepts both
and any mixture; render_shorthand(..., longhand=True) selects longhand.
Default rendering uses shorter forms with identity-preserving fallbacks.
Layout styles are independent of that choice.
The Python renderer separates layout (standard, semi-compact, compact,
or inline) from column align, structural indent (default 2), and same-line
padding (default 1). Use custom_layout for per-type overrides. Compact
continuation items align with their first item; indentation controls nested
blocks on new lines. Padding also applies to flat collections. An inline
value forces its entire subtree onto one line, overriding child layouts and
ignoring alignment and indentation there. The
Python API defines the options.
Optional preprocessing expands compact Lists, substitutes names, and evaluates
explicit scalar eval(...) expressions before strict parsing. It is not
implicitly used by YAML airlocks or persistence reads.
Representations
| Representation | Role |
|---|---|
Canonical bytes / .dcb | Unique binary identity encoding |
Shorthand / .dcs | Readable strict text, including longhand |
| YAML interchange | Native YAML plus $ strict Shorthand |
HDF5 / .h5 | Native numerical datasets, structured DCIs, and embedded external payloads |
SHA-256 of canonical bytes is the DCI fingerprint. It is not a hash of Shorthand, YAML, or HDF5 file bytes. SHA-256 content digests also identify external payloads; those payloads require separate retrieval and verification.
For normative rules and conformance vectors, use the Specifications.