Type
Introduction¶
The RIDDL language allows users to define types of data, or information. RIDDL's type system is fairly rich, for a specification language, providing abstractions for many concretely common information structures. This is done to make it easier for domain engineers and experts to understand the models they are creating.
A type defines the shape of some information. There are many kinds of type definitions allowed, so we have grouped them into categories:
Predefined Types¶
RIDDL supports several predefined types that just "exist" because they are: * applicable to nearly all fields of study or knowledge domains * fundamental in nature, covering the SI base units * fundamental in business, covering basic financial quantities such as currency * easily represented in any computing environment
RIDDL inherently knows about these predefined types so to use them you just use their name, no further definition is required. Here are the simple predefined types:
Simple Predefined Types¶
| Name | Description |
|---|---|
| Anything | An unspecified, arbitrary type, compatible with any other type |
| Nothing | A type that cannot hold any value, commonly used as a placeholder |
| Boolean | A Boolean value, with values true or false |
| Current | An SI unit of electric current, measured in Amperes |
| Date | A date value comprising a day, month and year |
| DateTime | A combination of Date and Time |
| Duration | An amount of time, measured in SI units of seconds |
| Length | An SI unit of distance measured in meters |
| Luminosity | An SI unit of luminous intensity, measured in candelas |
| Mass | An SI unit of mass measured in kilograms |
| Mole | An SI unit of an amount of substance, measured in mol |
| Number | An arbitrary number, integer, decimal or floating point |
| String | A sequence of Unicode characters |
| Temperature | An SI unit of thermodynamic temperature, measured in Kelvin |
| Time | A time value comprising an hour, minute, second and millisecond |
| TimeStamp | A fixed point in time |
| UUID | A randomly unique identifier with low likeliness of collision |
Anything and Nothing are duals: Anything is assignment-compatible with
every type in both directions, while Nothing holds no value at all. A
port typed Anything is compatible with any port it is connected
to, which is what lets the standard module's universal
terminators accept every stream.
Abstract was renamed to Anything in RIDDL 2.0
The old spelling still parses to the same node and emits a
[deprecated] message, so existing models keep working. Prettified output
emits Anything.
Parameterized Predefined Types¶
Some predefined types take parameters to customize their content, we call these parameterized predefined types.
| Name | Parameters | Description |
|---|---|---|
| String | (min,max, enc) |
A String, as above, of a specific length range and encoding. |
| Id | (entity) |
A unique identifier for a kind of entity given by entity |
| URL | (scheme) |
A URL for a specific URL scheme (e.g. http) |
| Range | (min,max) |
A integer from min to max |
| LatLong | (lat, long) |
A location based on latitude and longitude |
| Currency | (country-code) |
The currency of a nation using ISO 3166 country codes |
| Pattern | (regex) |
A string value that conforms to a regular expression, regex |
Compounds¶
Compound types add structure around the predefined types and require further definition in RIDDL.
Enumeration¶
An enumeration defines a type that may take the value of one identifier from a
closed set of constant identifiers using the any of keywords and the set of
identifiers enclosed in curly braces, like this:
Alternation¶
An alternation must offer a real choice
| Alternatives | Result |
|---|---|
zero — one of { } |
Error |
one — one of { A } |
[deprecated] — it names no alternative |
| two or more | clean |
one of { ??? } |
fine — undecided is not the same as empty |
A one-armed alternation still parses, so no model breaks today.
A type can be defined as any one type chosen from a set of other type names
using the one of keywords followed by type names in curly braces, like this:
There must be at least two types in an alternation.
Aggregation¶
A type can be defined as an aggregate of a group of values of types. DDD calls this a "value object". Aggregations can be nested, even recursively. Each value in the aggregation has an identifier (name) and a type separated by a colon. For example, here is the type definition for a rectangle located on a Cartesian coordinate system at point (x,y) with a given height and width:
Key/Value Mapping¶
A type can be defined as a mapping from one type (the key) to another type (the value). For example, here is a dictionary definition that maps a word (lower case letters) to a type named DictionaryEntry that presumably contains all the things one would find in a dictionary entry.
Aggregate Use Cases¶
An aggregate type (value object in DDD) can be declared with a keyword that
says what kind of thing it is. Eight are available: type, command,
query, event, result, record, graph and table.
Four of them — command, query, event and result — are the
messages, and only those four can be sent, told, yielded or
handled. A record is data: it types an entity state and supplies
the payload of a morph, but can never be sent. graph and table model
graph-structured and tabular data respectively.
command JustDoIt is { id: Id(AnEntity), encouragement: String, swoosh: URL }
record OrderData is { id: OrderId, total: Currency(USD) }
The yields Clause¶
A command or query may declare the response it produces, between the
identifier and the body:
command PlaceOrder yields event OrderPlaced is { cartId is CartId }
query GetOrder yields result OrderInfo is { orderId is OrderId }
A command's yields must resolve to an event and a query's to a result;
anything else is an Error, as is yields on a type that is neither. See
Messages for the conformance rules.
Cardinality¶
You can use a cardinality suffix or prefix with any of the type expressions defined above to transform that type expression into the element type of a collection.
Suffixes¶
The suffixes allowed are adopted from regular expression syntax with the following meanings:
| Suffix | Meaning |
|---|---|
|
Required: exactly 1 instance of the preceding type |
? |
Optional: either 0 or 1 instances of the preceding type |
* |
Zero or more instances of the preceding type |
+ |
One or more instances of the preceding type |
... |
One or more instances of the preceding type |
...? |
Zero or more instances of the preceding type |
Note the empty first item in the table; without the suffix, the cardinality of a type expression is "required" (exactly one). For example, in this:
theMyType type is an aggregate that contains one or more Id values
in the ids field and an optional string value in name
Prefixes¶
The prefixes allowed have a similar meaning to the suffixes:
| Prefix | Meaning |
|---|---|
| required | Required: exactly 1 instance of the following type |
| optional | Optional: either 0 or 1 instances of the following type |
| many | Zero or more instances of the following type |
| many required | One or more instances of the following type |
Occurs In¶
Contains¶
- Fields (in aggregations only)