How do I define generics with multiple type parameters in EK9?
← Generics · Ref: Q196
EK9 supports multiple type parameters using parentheses: 'of type (A, B)'. This enables types like Pair, Either, and mapper functions with distinct input/output types.
MULTIPLE TYPE PARAMETERS
Use parentheses for multiple parameters (a generic type needs both a default and an inferred-type constructor, E06040):
defines class Pair of type (A, B) first as A? second as B?
Pair() as pure first :=? A() second :=? B()
Pair() as pure -> a as A b as B first :=? a second :=? b
default operator ?
INSTANTIATION
Provide both types explicitly with empty parentheses (this creates an unset Pair):
pair <- Pair() of (String, Integer)
Or give the values and let EK9 infer the types:
pair <- Pair("hello", 42)
Giving values AND an 'of' clause together is error E06220: choose either empty parentheses with a type definition, or values with inferred types.
GENERIC FUNCTIONS WITH MULTIPLE PARAMETERS
Functions can also use multiple type parameters:
defines function mapper() of type (S, T) as abstract -> source as S <- target as T?
BUILT-IN EXAMPLES
Dict, Result, and DictEntry all use multiple type parameters:
counts <- Dict() of (String, Integer) outcome <- Result() of (String, Integer)
See Q194 for single-parameter generics. See Q195 for constraints. See Q46 for Dict.
See Q654 for parameter count validation. See Q655 for method overloading with generics.
Example
defines module qa.generics.multitype defines class Pair of type (A, B) first as A? second as B? Pair() as pure first :=? A() second :=? B() Pair() as pure -> a as A b as B first :=? a second :=? b getFirst() <- rtn as A: A() rtn :=? A(first) getSecond() <- rtn as B: B() rtn :=? B(second) default operator ? defines program MultiParamGenericDemo() stdout <- Stdout() // === INSTANTIATION WITH INFERENCE === pair <- Pair("hello", 42) stdout.println(`Pair is set: ${pair?}`) // === ACCESSING VALUES === first <- pair.getFirst() if first? stdout.println(`First: ${first}`) second <- pair.getSecond() if second? stdout.println(`Second: ${second}`) // === DIFFERENT TYPE COMBINATIONS === boolFloat <- Pair(true, 3.14) stdout.println(`Bool-Float pair set: ${boolFloat?}`)
Common mistakes
E06220 — A constructor call that supplies values cannot also carry an of type clause: choose either empty parentheses with a type definition, Pair() of (String, Integer), or values with inferred types, Pair("hello", 42). See ek9 -h E06220 for details.
Incorrect:
pair <- Pair("hello") of String
Correct:
pair <- Pair("hello", 42)
E06030 — A generic class constructor parameter count must match the number of type parameters. Pair of type (A, B) needs a constructor accepting both A and B. See ek9 -h E06030 for details.
Incorrect:
a as A
Correct:
a as A b as B
Other ways to ask this
- Can EK9 generics have more than one type parameter?
- How do I create a Pair type with two generic parameters?
- What is the syntax for multi-parameter generics in EK9?
Coming from another language?
Java: class Pair<A, B> with angle brackets. C++: template<typename A, typename B>. Rust: struct Pair<A, B>. Go: type Pair[A, B any]. Kotlin: class Pair<A, B>. EK9: 'Pair of type (A, B)' with parentheses for multiple parameters, reads as natural English.
Keywords: define, tuple, parameter, multiple, pair, parentheses, parameterized, type, generic, multi, type-parameter