Previous chapter: #6: Limited Types (Addition)

Dylan Design Notes: #7: Union Types (Addition)

Dylan Design Notes

#7: Union Types (Addition)

Version 1, March 1993

This design note introduces a new facility for creating a union type as a union of two other types. Union types are useful as slot specializers, and describe the return types of many common functions. For example, (union <integer> (singleton #f)) describes the return type of size.

Union types are not classes. See Dylan Design Note #5: Regularization of the Type System for a general description of types that are not classes.


Add a new facility for creating a type as a union of two other types.

union type1 type2 #key => type [Method]

Returns a type whose instances are each an instance of type1 or type2. No keyword arguments are accepted (the union method for sequences has a test: argument, hence the #key in the parameter list). This type is not instantiable.

For example:

The result of size is of type (union <integer> (singleton #f)).
The result of find-method is of type (union <method> (singleton #f)).
The first argument to union must be of type (union <sequence> 
<type>).
If x is an object, s1, ..., sm, t1, ..., tn are non-union types, and the notation (union* t1 ... tn) stands for any arrangement of nested calls of union, where none of the arguments is a subtype of any other, and none of the arguments form an exhaustive partition of any other type:
(union t1 t1) = t1

(union t1 t2) = (union t2 t1)

(union t1 (union t2 t3)) = (union (union t1 t2) t3)

(union t1 t2) = t2 when (subtype? t1 t2)

(union t1 t2) = t3 when t1 and t2 form an exhaustive partition of t3
e.g. (union <integer> <ratio>) = <rational>.

(instance? x (union* t1 ... tn)) 
         iff (or (instance? x t1) ... (instance? x tn))

(subtype? (union* t1 ... tn) s1) 
         iff (and (subtype? t1 s1) ... (subtype? tn s1))

(subtype? s1 (union* t1 ... tn)) 
         iff (or (subtype? s1 t1) ... (subtype? s1 tn))

(subtype? (union* s1 ... sm) (union* t1 ... tn))
  iff (and (or (subtype? s1 t1) ... (subtype? s1 tn))
             ...
             (or (subtype? sm t1) ... (subtype? sm tn)))

Notes:

The union, instance?, and subtype? methods for unions are straightforward to implement. Adding unions to the method dispatch mechanism simply makes a union-specialized method applicable to each type in the union.

Dispatching to a union-specialized method should be no slower than dispatching to separate methods applicable to each type in the union, and should take less space.

Next chapter: #8: Method Dispatch Ambiguity (Clarification)