Generics

Aria uses square brackets [T] for type parameters instead of angle brackets <T>. This eliminates the "turbofish" problem and all parsing ambiguity — a < b is always a comparison, never a generic.

Generic Functions

fn identity[T](x: T) -> T = x

fn first[T](items: [T]) -> T? {
    if items.len() == 0 { None } else { Some(items[0]) }
}

fn map[T, U](list: [T], f: fn(T) -> U) -> [U] =
    [f(x) for x in list]

fn zip[A, B](a: [A], b: [B]) -> [(A, B)] {
    ...
}

Generic Types

type Pair[A, B] {
    first: A
    second: B
}

type Stack[T] {
    items: [T]
}

// Built-in generic types
type Option[T] = Some(T) | None
type Result[T, E] = Ok(T) | Err(E)

Trait Bounds

Constrain what types can be used:

// T must implement Ord
fn largest[T: Ord](items: [T]) -> T? {
    ...
}

// Multiple bounds with +
fn sortAndPrint[T: Ord + Display](items: [T]) {
    sorted := items.sort()
    for item in sorted {
        println(item.display())
    }
}

// Where clause for readability
fn merge[K, V]
    where K: Eq + Hash, V: Clone {
    ...
}

Generic Trait Implementations

impl[T: Display] Display for Stack[T] {
    fn display(self) -> str {
        items := self.items
            .map(fn(x) => x.display())
            .join(", ")
        "Stack[{items}]"
    }
}

impl[T: Display] Display for Option[T] {
    fn display(self) -> str = match self {
        Some(v) => "Some({v.display()})"
        None => "None"
    }
}

Why Square Brackets?

In C++, Rust, and Java, angle brackets create parsing ambiguity:

// Is this a comparison or a generic?
a < b > c

// Rust needs the "turbofish" workaround
Vec::<i32>::new()

// C++ needs the "template" keyword in dependent contexts
typename Container<T>::iterator

In Aria, there is zero ambiguity:

a < b        // always a comparison
Stack[i64]   // always a generic type
map[str, i64] // always a generic with two params

For AI code generation, this eliminates an entire class of parsing errors.

Monomorphization

Generics are compiled via monomorphization — the compiler generates specialized code for each concrete type used. This means zero runtime overhead (no boxing, no vtables for generics).

Next Steps