Generic function values
A higher-order function can use a type parameter inside its callable signature. The compiler infers the type from the function value and the other arguments:
def increment(value: u8) -> Result[u8, OverflowError[u8]]:
Ok(value + 1)
def apply[T, U](operation: Callable[[T], U], value: T) -> U:
operation(value)
def main() -> Result[(), IoError | OverflowError[u8]]:
print(apply(increment, 41u8)?)?
Ok(())
42
Here T is u8. Passing 41i64 would conflict with increment’s signature.
To choose a generic function’s own type arguments, use brackets without calling it:
def identity[T](value: T) -> T:
value
def main() -> Result[(), IoError]:
keep = identity[u8]
print(keep(42))?
Ok(())
42
identity[u8] is a function value; identity[u8](42) calls that specialization.
A concrete callable annotation can also supply those type arguments:
def identity[T](value: T) -> T:
value
def main() -> Result[(), IoError]:
keep: Callable[[u8], u8] = identity
print(keep(42))?
Ok(())
42
This also works when a parameter or return type supplies the concrete signature.
Without that context, use explicit brackets such as identity[u8].