Tour: Structural Types

By mixing text content with commands, we create a concatenation. By adding empty lines, we create paragraphs, which can in turn be concatenations. Both are syntactic constructs that produce typed expressions.

A concatenation can be heterogeneous, i.e. contain expressions of different types. For example, if you want to write text and have some of that text be rendered with a bold font, you would define a Record named Bold that has textual content. You can then write a concatenation which contains both text and \Bold values.

Nyarna allows this structure by supporting type intersections. The concatenation of \Text expressions and \Bold expressions will thus be of type \Concat(\Intersection(\Text, \Bold)).

A concatenation whose content is a pure scalar type will have a textual type because concatenation is an operation on textual types. If the inner concatenation type is an enumeration or numeric type, the resulting type will be \Text because you can't concatenate numbers or enumeration values.

Similarly, there is a prototype \Sequence for paragraphs content. \Sequence types carry the semantics of having separated inner items. The separators (i.e. empty lines) are part of the values. Unlike with \Concat, you can have a \Sequence(\Text) because the text items are separated.

You may think, if syntactic paragraphs have a \Sequence(\Text) type, why can we write multiple paragraphs in the input that expects the type \Text? That is because an implicit conversion exists from \Sequence(\Text) to \Text, which merges the paragraphs with the separators.

Details

When two expressions are both contributing to an inferred type, for example by being part of the same concatenation, or by being the then and else branch of an \if expression, their types get intersected to calculate the return type. Intersection is an operation on two types a and b whose result is c with a ≤ c ∧ b ≤ c.

An \Intersection type contains at least two types of which at most one may be a scalar type, the others must be record types. It is the result of intersecting its contained types. The semantics of an expression having an intersection type is that it may evaluate to a value of either of the contained types.

If you have an expression that has an intersection type, you can use \match or \matcher to branch on its actual type at runtime. We will see an example of this shortly.

Intersections between \Void (a type usually created by missing expressions, such as a missing else branch) and another type will create an \Optional type whose inner type is the non-void type. An expression of \Optional type will contribute its inner type to the calculated type of a concatenation a paragraphs expression. For example, a concatenation of \Bold and \Optional(\Text) will have the type \Concat(\Intersection(\Bold, \Text)).