Why can't I use a function type to parameterize a generic that calls constructors?
← Generics · Ref: Q833
EK9 generics discover implicit requirements from their bodies. If a generic uses 'T()' (constructor) or 'arg0 <=> arg1' (comparator), those become requirements on the parameterizing type. Functions cannot satisfy constructor or comparator requirements, so parameterizing such generics with a function triggers E06110.
IMPLICIT CONTRACT DISCOVERY
When you write:
Holder of type T createNew() <- rtn as T: T() // Requires T has a constructor compare() <- rtn as Integer: a <=> b // Requires T has <=>
The compiler discovers that T must have a constructor and a comparator.
FUNCTION LIMITATIONS
Functions cannot be constructed with 'T()' — they are not classes. Functions cannot be compared with '<=>'. So a function can only parameterize generics that use minimal capabilities like '?' (isSet).
CONTAINER-STYLE GENERICS WORK
A generic that only checks 'arg0?' and 'arg1?' works with functions — like List or Optional. These are container-style generics that just hold values.
THIS EXAMPLE
Shows a container-style generic (SafeHolder) that works with both classes and functions, alongside a concrete class (Counter) that satisfies constructor requirements.
See Q646 for type inference limits. See Q707 for Consumer/Acceptor. See Q58 for generic functions.
Example
defines module qa.generics.function.in.generic defines function <?- Abstract function type for use as a delegate/generic parameter. -?> CheckFn as abstract -> arg0 as Integer <- rtn as Boolean? IsPositive() is CheckFn -> arg0 as Integer <- rtn as Boolean: arg0 > 0 defines class Counter count <- 0 default Counter() Counter() -> initial as Integer count :=: initial increment() count += 1 value() <- rtn as Integer: Integer(count) default operator ? <?- A container-style generic — only uses '?' operator. This works with BOTH classes AND functions. -?> SafeHolder of type T default SafeHolder() default SafeHolder() -> arg0 as T check() -> arg0 as T arg1 as T <- rtn as Boolean: arg0? and arg1? <?- Generic that uses T() constructor — NOT safe for functions. -?> ConstructingHolder of type T default ConstructingHolder() default ConstructingHolder() -> arg0 as T check() -> arg0 as T arg1 as T <- rtn as Boolean: arg0? and arg1? createNew() <- rtn as T: T() <?- Generic that uses <=> comparator — NOT safe for functions. -?> ComparingHolder of type T default ComparingHolder() default ComparingHolder() -> arg0 as T check() -> arg0 as T arg1 as T <- rtn as Boolean: arg0? and arg1? compare() -> arg0 as T arg1 as T <- rtn as Integer: arg0 <=> arg1 defines program GenericFunctionDemo() stdout <- Stdout() //Functions work with container-style generics holder <- SafeHolder() of CheckFn result <- holder.check(IsPositive, IsPositive) stdout.println(`Function holder check: ${result}`) //Classes work with any generic counterHolder <- SafeHolder() of Counter classResult <- counterHolder.check(Counter(), Counter(5)) stdout.println(`Counter holder check: ${classResult}`)
Common mistakes
E06110 — ConstructingHolder uses 'T()' in its body, requiring a constructor. Functions cannot be constructed. Use a container-style generic that only uses '?' (isSet) with functions. See ek9 -h E06110 for details.
Incorrect:
holder <- ConstructingHolder() of CheckFn
Correct:
holder <- SafeHolder() of CheckFn
E06120 — ComparingHolder uses 'arg0 <=> arg1' in its body. Functions cannot be compared. Use a generic that only checks isSet with functions. See ek9 -h E06120 for details.
Incorrect:
holder <- ComparingHolder() of CheckFn
Correct:
holder <- SafeHolder() of CheckFn
Other ways to ask this
- What is E06110 CONSTRUCTOR_WITH_FUNCTION_IN_GENERIC?
- Why does EK9 reject my generic when I parameterize it with a function?
- What are the limitations of using functions with generic types?
Coming from another language?
Java: type erasure means generic constraint violations appear as ClassCastExceptions at runtime. C++: templates check at instantiation with poor diagnostics. Rust: requires explicit trait bounds ('T: Ord'). EK9: discovers implicit requirements from generic body and validates at parameterization site with specific error codes.
Keywords: container, comparator, constructor, isSet, constraint, E06110, generic, implicit, function, parameterize