type-set Comparable >= {Int, Float, Character}
The type set Comparable is specified to denote a superset of the set {Int,Float,Character}. As such, it may be "extended" in other modules by relating it with other sets or other types through so called relate-declarations:
relate String in Comparable
where the relation "in" is used to specify that type String is an element of Comparable.
Additionally, sets of subprograms may be defined. Their application
to a range of arguments selects one of the included subprograms and then
applies this subprogram to the arguments. The selection process is based
on the actual (or dynamic) types of all arguments as well as the
(static) context of the call and is thus dynamic in general. This mechanism
is known as multi-methods or multi dispatching and is a generalization
of the single dispatching mechanism known from most object-oriented languages
like Eiffel, Java, or C++. However, there are several cases, when the subprogram
can be chosen at compile time, which is well-known as overloading
from languages like Ada. To achieve deterministic behavior and to avoid
type errors at run-time, the type-checker has to be able to statically
guarantee, that there is exactly one matching subprogram in the set to
be chosen. Therefore, two conditions must be satisfied when applying a
subprogram set: completeness and non-ambiguity. Completeness states that
there is at least one matching subprogram for the given arguments
and context, non-ambiguity requires that there is at most one. The
selection process is further determined by subprogram specificity, which
is a relation between two subprograms that informally holds if one subprogram
can be applied in less situations than the other.
For example, if we specified a subprogram set to
implement a comparison operation between various types as follows:
function LT_Int(Int; Int) return (Bool) is ...
-- similar for
LT_Float, LT_Char, LT_String
subprog-set "<" >= {LT_Int, LT_Float, LT_Char, LT_String}
Dependencies between polymorphic parameters or results of a subprogram can be specified in a very general manner using so called generic subprograms. A generic subprogram has some type variables in its signature (prefixed by a question mark) that may be constrained by type sets or other type variables. A generic Min-function can be written in Hoopla as follows:
function
Min(L: ?T; R: ?U) return (T+U) where T in
Comparable, U <= T
is
begin
if L < R then return L else return R end
if
end Min
The infix application of "<" selects then the appropriate implementation,
depending on the actual types of the arguments. For example:
I1,I2: Int
...
I1 := Min(I1,I2);
The application of subprogram set "<" in the body of Min would select the LT_Int function because the argument types (and context) match.
Finally, Hoopla has parametrized types. A parametrized stack type can be written as
type Stack[T <= Any] is ...
and then used by various stack operations:
procedure
Push(Stack[?T]; ?U) where T <= Any, U <= T
function
Top(Stack[?T]) return (T) where T <= Any
This example shows that type parameters can also be provided by type variables.
Hoopla is currently implemented in a preversion. A full version is expected end 1998.