Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

Type Parameters

Type parameters make it possible for routines to be type polymorphic, i.e., to be applied to values of different types. This means that whenever a routine with type parameters is called, actual type parameters have to be provided in addition to the actual value arguments.

The declared routine is essentially just a template that will be replicated and specialized for all the actual type parameters it is used with. This means that there is not runtime cost for passing type parameters, actual type parameter values only exist at compilation time.

Type parameters always precede value arguments in the declaration of a routine as well as in a call.

Basic Type Parameters

The following example implements the arithmetic mean of two values of a numeric type that is provided as the type parameter N. The type parameter N is constraint with the type numeric, which means that the actual type parameters must inherit from the constraint type.

The mean function can then be called using any numeric types such as i32, f64 or num.complex f64:

Type parameters turn a feature into a template for all the variants given by the actual types provided by the callers. The compiler will create specialized versions of every combination of actual type parameters provided. In the previous example, the declaration of mean with type parameters is essentially short-hand for the declaration of three features operating on different types as shown here:

Type inference for Type Parameters

Type parameters that are used within types of value arguments do not have to be given explicitly in a call. Instead, these type parameters can be omitted and inferred from the actual value arguments.

Consequently, the actual type parameters in the previous example are not required, instead of mean f64 3.14 2.18, one can write mean 3.14 2.18, omitting the f64 that is derived from the float constants 3.14 and 2.18:

Note that for a call to a routine that expects several type parameters, either all type parameters have to given or all of them have to be omitted. It is not possible to omit only some type parameters.

Free Types

The declaration of type parameters can be omitted to obtain a more concise and readable feature declaration. If it is omitted, an undeclared type name like N will be converted into a type parameter automatically. If a constraint like : numeric is needed, that constraint must be added to the first occurrence of that type N : numeric, while later uses of that type N must not have a constraint. Such a type is called a free type.

Free types will be added to as type parameters in the order they occur in the feature's signature. It is possible to use both, declared type parameters and free types. In this case, the free types will be added as type parameters after the declared type parameters.

Here is the example from above using a free type N : numeric:

Type Place Holder _

Anonymous Free Types

In case a free type is required only once, it can be made anonymous suing _ as its name. In the previous example, this is possible if we omit the result type and infer it from the implementation as follows:

Note that _ is a place holder for any name, repeated uses of _ will be different types. Consequently, the following example using _ twice, as type of a and as type of b, will result in two different and incompatible anonymous type parameters. So the following code will result in an error:

Inference of Subset of Type Parameters

Another use of _ as a type place holder is to force inference of a subset of the type parameters.

The following example has two type parameters, A and B. We might want to specify the actual type for A explicitly, while the result type of the function argument can be inferred. We can achieve this by providing an actual type parameter u64 for A and leaving the type of B for type inference using _:

Note that not providing a type here will result in i32 being the inferred type which results in an overflow in the second call to apply.

last changed: 2025-12-17
next: Lazy Evaluation