Dylan Design Notes

#7: Union Types	(Addition)

Version 1, March 1993
Copyright (c) 1993-1994, Apple Computer

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 #7: 
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.

