Type Sets

Felix allows you define a set of types:

typedef sints = typesetof (short,int,long);
typedef uints = typesetof (ushort,uint,ulong);

The list of elements of a type set can be either types or typesets:

typedef ints = typesetof (sints,uints, byte);

You can also calculate the union of two typesets with the TeX operator cup, the symbol ..math:cup, it also accepts types as an abuse of notation.

typeset ints = sints \cup uints \cup byte;

Membership of a typeset can be tested with the in operator:

long in ints

The result is a type, either void (0) for false and unit (1) for true. [This is a design fault, the result should of kind BOOL]

Typesets are used for constrained polymorphism, primarily with primitive bindings:

fun add[T where T in ints]) : T * T -> T = "$1+$2";
fun add[T in ints]) : T * T -> T = "$1+$2";
fun add[T:ints] : T * T -> T = "$1+$2";

The second and third forms are a shortcut versions of the first.

When a query is made of a typeset, it is expanded to a typematch:

// T in sints
typematch T with
| short => 1
| int => 1
| long => 1
| _ => 0
endmatch

This means the elements of a typeset can be parameterised by one or more type variables provided they’re in scope. For example:

typedef iorspair[S,U] = typesetof (S * S, U * U);
fun add[T,U,W where T in sints, U in uints, W in iorspair[S,U]) ...

where the last condition expands to

typematch W with
| S * S => 1
| U * U => 1
| _ => 0
endmatch