func first(v: T[]): Result<T, Bool> {
if len(v) > 0 {
return Result.Ok(v[0])
}
return Result.Error(false)
}
proc main(): void {
a := first([1, 2, 3]) // first_Int
b := first(["x", "y"]) // first_Str, a separate copy
echo "{a} {b}"
}type Box {
items: T[dyn]
label: Str
}
type Either {
Left { left: A }
Right { right: B }
}
proc main(): void {
Box<Str> people = Box(["ada", "grace"], "people")
Box<Int> counts = Box([1, 2, 3], "counts")
Either<Str, Int> answer = Either.Right(42)
echo "{people.label}: {people.items}"
echo "{counts.label}: {counts.items}"
if answer is Either.Right(n) { echo n }
}A name in a signature that is neither a builtin type nor a declared one is a type variable, and it makes the callable generic. A variable is pinned down by where it appears among the parameters — including inside a parameter's own function type. Nothing about it is dynamic: every call is resolved when the program compiles, and one concrete copy is written per distinct set of type arguments — first_Str, first_Int — with no boxing and no dispatch. A type may take variables the same way, and is written with them filled in: Box<Str>, Either<Str, Int>.
Worth knowing:
func greet(u: Usr): Str is generic, and accepts anything. Check the spelling when a function takes more than it should.broken_Int.Either<Str, Int> answer = Either.Right(42) — since the variant alone does not say what the other side holds.