[Next] [Previous] [Up] [Top] [Contents] [Index]

4.1 Explicit Parameterization

4.1.1 Parameterized Declarations and Formal Type Parameters

The syntax of type, object, predicate object, method, field, and signature declarations is extended to allow explicit parameterization as follows:

tp_decl 	::=	"type" name [formal_params] {type_relation} ";"
object_decl 	::=	rep_role rep_kind name [formal_params]
		    {relation} [field_inits] ";"
predicate_decl 	::=	"predicate" name [formal_params]
		    {relation} [field_inits] ["when" expr] ";"
method_name	::=	msg_name [formal_params] | op_name
formal_params	::=	"[" formal_param { "," formal_param } "]"
formal_param	::=	["'"] name [ "<=" type ]
The number of formal type parameters is considered part of the "name" of the declared entity. For example, multiple objects can be declared with the same name, as long as they are declared with different numbers of formal type parameters.[14]

The formal type parameter of the form 'name <= type is quantified over all types that are subtypes of type; the leading back-quote symbol is optional. If the <= type upper bound is omitted, then <= any is assumed. Similar facilities appear under the name of bounded quantification [Cardelli & Wegner 85] and constrained genericity [Meyer 86].[15]

Type parameters are scoped over the whole declaration; type parameters must have distinct names. Within its scope, a type parameter may be used in a type declaration or as an instantiating type for some other parameterized type or method; a type parameter cannot be used in a subtypes clause, as this context requires a statically-known type. Cycles are not allowed in the dependency graph of formal type parameters and their upper bound types (e.g., ['A <= B, 'B <= A] is illegal), but no other orderings are required. For example, ['A <= B, 'B <= int] is legal, with the first occurrence of B referring to the instantiating type of the second type parameter.

A parameterized declaration can be typechecked in isolation, independently of any instantiating clients. This is in contrast with languages such as C++ and Modula-3 where typechecking of a parameterized class or module must in general be deferred and repeated for each instantiation. When typechecking the body of a parameterized method or the initialization expression of a parameterized field, all that can be assumed of a variable whose type is declared to some formal type parameter is that the variable is some subtype of the upper bound of the type parameter. For most purposes, this is equivalent to assuming the variable conforms to the upper bound type itself.


[14] This feature does not interact well with mixed dynamic and static typing, since the number of parameters affects the execution behavior of the program, violating the principle that static types do not affect the execution semantics. In the future, the number of parameters may be removed from the "name" of an object or method, so that parameters are confined to the (optional) static type system. Omitted type parameters would default to dynamic, in keeping with the default for omitted type declarations.
[15] Lower bounds on type parameters can also be useful, for example to model the case where a more specific closure type is required to have at least as general argument types.
The Cecil Language: Specification and Rationale, Version 2.1 - 25 MARCH 1997
[Next] [Previous] [Up] [Top] [Contents] [Index]

Generated with Harlequin WebMaker