Generics ​
Generics let you write types and functions that work with any type, providing flexibility without sacrificing type safety.
Generic Types ​
Generic Records ​
Create records that work with any type:
type Box[T] = record
value: T
end record
type Pair[A, B] = record
first: A
second: B
end recordUsing generic records:
-- Specify the type parameter when constructing
int_box: Box[Int] = Box[Int](value = 42)
str_box: Box[String] = Box[String](value = "hello")
pair: Pair[Int, String] = Pair[Int, String](first = 1, second = "one")Generic Variants ​
Variants can also be generic:
type Maybe[T] = variant
Just(value: T)
Nothing
end variantThe built-in Option[T] and Result[T, E] are generic variants:
type Option[T] = variant
Some(value: T)
None
end variant
type Result[T, E] = variant
Ok(value: T)
Err(error: E)
end variantWorking with Generic Types ​
fn unwrap_or_default(box: Box[Int], default: Int) -> Int
box.value
end fn
fn map_maybe(m: Maybe[Int], f: Fn(Int) -> Int) -> Maybe[Int]
match m
Just(v) -> Just(f(v))
Nothing -> Nothing
end match
end fnConst Generics ​
Const generics allow compile-time integer parameters in types. This is useful for fixed-size data structures.
Defining Const Generic Types ​
Use N: Int syntax to declare a const parameter:
type Vector[N: Int] = record
data: List[Float]
end record
type Matrix[M: Int, N: Int] = record
rows: Int
cols: Int
data: List[Float]
end recordMixing Type and Const Parameters ​
You can combine regular type parameters with const parameters:
type SizedArray[T, N: Int] = record
elements: List[T]
capacity: Int
end recordUsing Const Generics ​
-- Integer literals in type positions
v3: Vector[3] = Vector[3](data = [1.0, 2.0, 3.0])
v4: Vector[4] = Vector[4](data = [1.0, 2.0, 3.0, 4.0])
m: Matrix[2, 3] = Matrix[2, 3](rows = 2, cols = 3, data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0])Type Safety with Const Generics ​
Different const values create different types:
v3: Vector[3] = Vector[3](data = [1.0, 2.0, 3.0])
v4: Vector[4] = Vector[4](data = [1.0, 2.0, 3.0, 4.0])
-- This would be a type error:
-- v3 = v4 -- ERROR: Vector[3] and Vector[4] are different typesThis catches size mismatches at compile time.
Generic Functions ​
Functions can have type parameters:
fn identity[T](x: T) -> T
x
end fn
fn swap[A, B](pair: Tuple[A, B]) -> Tuple[B, A]
(a, b) = pair
(b, a)
end fn
fn main() -> Unit using file_io
-- Type inferred from context
n: Int = identity(42)
s: String = identity("hello")
-- Works with any types
swapped: Tuple[String, Int] = swap((1, "one"))
print(to_string(n))
print(s)
end fnType parameters are inferred from usage context. You cannot explicitly specify type parameters at call sites (e.g., identity[Int](42) is not supported).
See also Effect Polymorphism for functions that work with any effect.
Next Steps ​
- Functional Programming — Higher-order functions and pipelines
- Effects System — Effect polymorphism for generic effectful code
- Linear Types — How generics interact with linear types