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
#!ek9 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, generic, multi, multiple, pair, parameter, parameterized, parentheses, tuple, type, type-parameter