Primitive Types
Soufflé provides two primitive types that form the foundation of every relation attribute definition.
Symbol type
The symbol type represents string values. Internally, symbols are stored in a global symbol table and referenced by ordinal numbers, making comparisons and joins efficient. Symbol literals are written in double quotes.
Number type
The number type represents signed 32-bit integer values. Numeric literals are written as standard integers and support arithmetic operations within rules.
Primitive type usage
When declaring a relation, each attribute is assigned a type. The following example declares a relation with two symbol attributes and one number attribute:
| Relation | Attribute | Type |
|---|---|---|
my_rel | first | symbol |
my_rel | second | symbol |
my_rel | third | number |
Beyond Primitive Types
Soufflé supports richer type constructs that go beyond primitives, enabling more expressive and reusable type definitions.
Base Type
A base type defines a new named type that is semantically distinct from its underlying primitive. For example, declaring .type Person <: symbol creates a type Person that is a subtype of symbol. This allows the type checker to distinguish a Person from a plain symbol, preventing accidental mixing of semantically different values.
Union Types
Union types combine multiple base types into a single type that can hold any of the member values. They are declared with the | operator. For instance, .type Identifier = Person | Company defines Identifier as a type that accepts either a Person or a Company value. Union types are especially useful when a relation attribute needs to reference entities from different domains.
Domains
A domain type restricts the set of valid values using a companion relation. Values that appear in the domain's defining relation are considered valid members of the type. This provides a lightweight form of value-set constraint that is checked at runtime.
Sub-typing
Soufflé's type system supports a sub-typing hierarchy. A base type declared with <: is a subtype of its parent. Sub-types inherit the properties of their parent while remaining distinct for type-checking purposes. This hierarchy enables precise modelling of program entities in static analysis, such as distinguishing different categories of variables or heap objects.