48 Type expressions

A type expression is an expression that denotes a type. Types can be nominal, structural, or formed from other types by type expressions such as Set<T>, subtype T where p, union { ... }, and intersection { ... }. Also, types can be types of values or types of entities.

A type name is a type expression. For example, the following type expressions denote value types:

  • Boolean
  • Integer
  • Float64
  • String
  • Color
  • Geometry.Point

The full list of built-in types is given in 46 Built-in Types.

The following type expressions denote nominal entity types:

  • Supplier
  • Part
  • Shipment
  • ShipmentsSystem
  • Iso.Author
  • Iso.ISBN
  • Iso.Book

The following type expressions denote structural types:

  • { Real x; Real y; Real z; }
  • { Point centre; Real radius; }
  • { Supplier supplier*; Part part*; Shipment shipment*; }

Structural type identity, aliases, nesting, and structural values are described in 47 Structural types.

The following type expressions are formed from other types:

  • Set<String>
  • Point<Float64, 3>
  • subtype Real where this > 0
  • subtype Person where age ≥ 18
  • Set<(subtype Real where this > 0)>
  • subtype (intersection { Shape, Renderable }) where visible
  • union { EmailContact, PhoneContact }
  • union { Shape, Circle }
  • intersection { Shape, Texture }

Grouping with parentheses

Parentheses may be used to group type expressions and control precedence. Parentheses do not change the denoted type except by making the intended parse explicit. They are especially useful when a refinement type expression appears as a type argument or when a refinement is applied to a compound type expression:


type PositiveRealSet = Set<(subtype Real where this > 0)>;
type VisibleRenderableShape = subtype (intersection { Shape, Renderable }) where visible;
type Contact = subtype (union { EmailContact, PhoneContact }) where verified;

When type expressions denote the same type

Two type expressions denote the same type if:

  • They name the same predefined type.
  • They resolve to the same nominal type declaration.
  • They are aliases of the same type.
  • They denote structural types with the same ordered sequence of attribute names, cardinality qualifiers, and attribute types.
  • They denote the same canonical non-nominal type expression, such as a refinement, union, or intersection with the same canonical form.

For structural types, equality uses the structural identity rule from 47 Structural types. For example, { Real x; String y; } and { String y; Real x; } denote different structural types.

The set of values or entities of a type is called its domain. For example, Integer has domain ℤ.

The following is a type definition:


value Point 
{
    Real x;
    Real y;
}

This construct defines the type Point. The definition itself does not denote a type; only the type expression Point denotes the type that has been defined.

Point is called a nominal type. A nominal type introduces a name whose identity is distinct from any structural coincidence. Thus Point and { Real x; Real y; } denote different types even though they share structure.