| name | generics-implementation |
| description | Expert skill for implementing parametric polymorphism including type parameter bounds, monomorphization, type erasure, variance, higher-kinded types, and associated types. |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
| graph | {"domains":["domain:software-engineering"],"specializations":["specialization:programming-languages"],"skillAreas":["skill-area:compiler-implementation","skill-area:typescript-generic-programming"],"roles":["role:backend-engineer"]} |
Generics Implementation Skill
Implement parametric polymorphism for programming languages including generics, type bounds, and compilation strategies.
Capabilities
- Design generic syntax and type parameter bounds
- Implement monomorphization (Rust-style)
- Implement type erasure (Java-style)
- Handle variance in generic types
- Implement higher-kinded types (if applicable)
- Design trait/interface bounds
- Handle associated types
- Implement generic method dispatch
Usage
Invoke this skill when you need to:
- Add generics to a language
- Implement monomorphization or type erasure
- Design trait bounds and constraints
- Handle variance and subtyping with generics
Inputs
| Parameter | Type | Required | Description |
|---|
| compilationStrategy | string | Yes | Strategy (monomorphization, erasure, dictionary) |
| features | array | No | Features to implement |
| varianceModel | string | No | Variance handling (explicit, inferred, none) |
| boundsSystem | object | No | Bounds system configuration |
Compilation Strategies
{
"compilationStrategy": "monomorphization",
"compilationStrategy": "erasure",
"compilationStrategy": "dictionary"
}
Feature Options
{
"features": [
"type-parameters",
"trait-bounds",
"associated-types",
"variance",
"higher-kinded-types",
"default-type-parameters",
"const-generics",
"where-clauses",
"specialization"
]
}
Output Structure
generics/
├── syntax/
│ ├── type-params.grammar # Type parameter syntax
│ ├── bounds.grammar # Bounds and constraints
│ └── where-clause.grammar # Where clause syntax
├── typing/
│ ├── generic-types.ts # Generic type representation
│ ├── bounds-checking.ts # Bounds verification
│ ├── variance.ts # Variance checking
│ └── instantiation.ts # Type instantiation
├── compilation/
│ ├── monomorphization.ts # Monomorphization
│ ├── erasure.ts # Type erasure
│ └── dictionary.ts # Dictionary passing
├── inference/
│ ├── type-inference.ts # Generic type inference
│ └── constraint-solving.ts # Constraint resolution
└── tests/
├── bounds.test.ts
├── variance.test.ts
└── compilation.test.ts
Generic Type System
Type Parameter Syntax
struct Vec<T> {
data: T[],
len: usize
}
struct HashMap<K, V> {
buckets: Array<(K, V)>
}
fn sort<T: Ord>(arr: &mut [T]) { ... }
fn process<T, U>(t: T, u: U) -> bool
where
T: Clone + Debug,
U: AsRef<T>
{ ... }
struct Container<T = i32> {
value: T
}
struct Array<T, const N: usize> {
data: [T; N]
}
Generic Type Representation
interface GenericType {
name: string;
typeParams: TypeParameter[];
body: Type;
}
interface TypeParameter {
name: string;
bounds: TypeBound[];
variance: Variance;
default?: Type;
}
interface TypeBound {
trait: TraitRef;
}
type Variance = 'covariant' | 'contravariant' | 'invariant' | 'bivariant';
interface TypeApplication {
generic: GenericType;
args: Type[];
}
Monomorphization
interface MonomorphizationContext {
instantiations: Map<string, Type[]>[];
generatedCode: Map<string, GeneratedFunction>;
}
function monomorphize(
program: Program,
entryPoints: FunctionRef[]
): MonomorphizedProgram {
const ctx: MonomorphizationContext = {
instantiations: [],
generatedCode: new Map()
};
for (const entry of entryPoints) {
collectInstantiations(entry, ctx);
}
for (const [signature, typeArgs] of ctx.instantiations) {
const original = lookupGenericFunction(signature);
const specialized = specializeFunction(original, typeArgs);
ctx.generatedCode.set(mangleName(signature, typeArgs), specialized);
}
return buildMonomorphizedProgram(ctx);
}
(): {
substitution = (fn., typeArgs);
{
: (fn., typeArgs),
: fn..( (p., substitution)),
: (fn., substitution),
: (fn., substitution)
};
}
(): {
;
}
Type Erasure
function eraseGenericType(type: Type): Type {
if (type.kind === 'typeParam') {
return type.bounds.length > 0
? type.bounds[0]
: ObjectType;
}
if (type.kind === 'application') {
return eraseGenericType(type.generic);
}
if (type.kind === 'generic') {
return eraseGenericType(type.body);
}
return type;
}
function insertCasts(expr: Expr, expectedType: Type, actualType: Type): {
erasedExpected = (expectedType);
erasedActual = (actualType);
(!(erasedExpected, erasedActual)) {
{
: ,
: expr,
: erasedExpected
};
}
expr;
}
Variance
type Variance = 'covariant' | 'contravariant' | 'invariant' | 'bivariant';
interface VarianceChecker {
computeVariance(typeParam: TypeParameter, type: Type): Variance;
checkVariance(generic: GenericType): VarianceError[];
inferVariance(generic: GenericType): Map<TypeParameter, Variance>;
}
function computeVariance(param: TypeParameter, type: Type): Variance {
switch (type.kind) {
case 'typeParam':
return type.name === param.name ? 'covariant' : 'bivariant';
case 'function':
paramVariance = (
..( ((param, p)))
);
returnVariance = (param, .);
(paramVariance, returnVariance);
:
(
..( {
declaredVariance = ..[i].;
usageVariance = (param, arg);
(declaredVariance, usageVariance);
})
);
:
;
:
;
}
}
(): {
(sub. === && sup. === ) {
(sub. !== sup.) ;
sub..( {
supArg = sup.[i];
variance = sub..[i].;
(variance) {
:
(subArg, supArg);
:
(supArg, subArg);
:
(subArg, supArg);
:
;
}
});
}
}
Trait Bounds
interface BoundsChecker {
satisfiesBound(type: Type, bound: TypeBound): boolean;
resolveImpl(type: Type, trait: TraitRef): TraitImpl | null;
checkWhereClause(clause: WhereClause, env: TypeEnv): boolean;
}
function satisfiesBound(type: Type, bound: TypeBound): boolean {
const impl = findTraitImpl(type, bound.trait);
if (!impl) return false;
for (const [name, constraint] of bound.associatedTypes) {
const actualType = resolveAssociatedType(impl, name);
if (!typesEqual(actualType, constraint)) ;
}
;
}
{
: [];
}
{
: ;
: [];
}
Associated Types
trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
impl Iterator for Range {
type Item = i32;
fn next(&mut self) -> Option<i32> { ... }
}
interface AssociatedType {
name: string;
bounds: TypeBound[];
default?: Type;
}
interface TraitImpl {
trait: TraitRef;
forType: Type;
associatedTypes: Map<string, Type>;
methods: Map<string, Function>;
}
function resolveAssociatedType(
type: Type,
trait: TraitRef,
assocName: string
): Type {
const impl = findTraitImpl(, trait);
(!impl) ();
assocType = impl..(assocName);
(!assocType) ();
assocType;
}
Higher-Kinded Types
type Kind =
| { kind: 'type' }
| { kind: 'arrow'; from: Kind; to: Kind };
trait Functor<F: * -> *> {
fn map<A, B>(fa: F<A>, f: A -> B) -> F<B>;
}
interface HigherKindedType {
name: string;
kind: Kind;
}
function checkKind(type: Type, expectedKind: Kind): boolean {
const actualKind = inferKind(type);
return kindsEqual(actualKind, expectedKind);
}
function inferKind(type: Type): Kind {
if (type.kind === 'typeParam') {
return type.;
}
(. === ) {
fnKind = (.);
(fnKind. !== ) ();
(., fnKind.);
fnKind.;
}
}
Workflow
- Design generic syntax - Type parameters, bounds, where clauses
- Implement type system - Generic types, instantiation
- Add bounds checking - Verify trait bounds
- Implement variance - Covariance, contravariance
- Choose compilation - Monomorphization or erasure
- Add associated types - If using traits
- Consider HKT - For advanced use cases
- Generate tests - Bounds, variance, compilation
Best Practices Applied
- Clear separation of type checking and compilation
- Efficient monomorphization with deduplication
- Proper variance inference and checking
- Clear error messages for bound violations
- Support for type inference with generics
- Incremental compilation support
References
Target Processes
- generics-polymorphism.js
- type-system-implementation.js
- code-generation-llvm.js
- ir-design.js