Scala Generics and Type System for Python Developers
SkillDev toolsTranslating Python generic types, variance, and type bounds to Scala 2.13
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Scala Generics and Type System for Python Developers skill
What this skill tells your AI
The instructions your AI receives, as published by cxcscmu/skilllearnbench in skills/b1-one-shot-claude-haiku-4-5/python-scala-translation/scala-generics/SKILL.md and read by ahel’s review.
Core Concepts
Variance (Key Difference from Python)
Python has no explicit variance system. Scala requires explicit declarations:
Covariance (+T) - "out" position, can return subtypes:
class Container[+T](items: Seq[T]) {
def get: T = items.head // OK - returning subtype
// def set(t: T): Unit // ERROR - would be contravariant
}
Contravariance (-T) - "in" position, can accept supertypes:
class Consumer[-T] {
def consume(t: T): Unit // OK - accepting supertype
// def produce: T // ERROR - would be covariant
}
Invariance (T) - exact type, no variance:
class Handler[T] {
def get: T
def set(t: T): Unit // Both OK - invariant
}
Translation Pattern
| Python | Scala | Notes |
|---|---|---|
TypeVar("T") | [T] | Invariant by default |
TypeVar("T_co", covariant=True) | [+T] | Covariant, out-position only |
TypeVar("T_contra", contravariant=True) | [-T] | Contravariant, in-position only |
TypeVar("T", int, float) | [T <: Int | Float] | Upper bound (Scala 3) or sealed trait |
Generic[T] | [T] | Class definition |
Union[A, B] | A | B (Scala 3) or sealed trait | Use sealed traits for compatibility |
Type Bounds
// Upper bound - T must be subtype of Ordered
class Comparable[T <: Ordered[T]]
// Lower bound - T must be supertype of String
class Container[T >: String]
// Context bound (implicit evidence)
class Serializable[T: Format]
Higher-Kinded Types (Scala's advantage)
Python's TypeVar("F") for type constructors cannot express true HKTs.
Scala can use type lambdas:
// Scala 2.13 with kind-projector
type Functor[F[_]] = {
def map[A, B](fa: F[A], f: A => B): F[B]
}
// Or in Scala 3
def map[F[_], A, B](fa: F[A], f: A => B): F[B]
Translation Examples
Generic Container (Python)
class TokenContainer(Generic[T_co]):
def __init__(self, items: Sequence[T_co]) -> None:
self._items: tuple[T_co, ...] = tuple(items)
def get_all(self) -> tuple[T_co, ...]:
return self._items
Generic Container (Scala 2.13)
class TokenContainer[+T](items: Seq[T]) {
private val _items: Vector[T] = items.toVector
def getAll: Vector[T] = _items
def size: Int = _items.size
}
Collections Generics
Python uses Sequence[T], Iterable[T], etc. Scala equivalents:
| Python | Scala |
|---|---|
Sequence[T] | Seq[T] (immutable) |
Iterable[T] | Iterable[T] |
Iterator[T] | Iterator[T] |
list[T] | scala.collection.mutable.ListBuffer[T] or List[T] (immutable) |
tuple[T, ...] | Vector[T] or (T, T, ...) for fixed size |
dict[K, V] | Map[K, V] |
Best Practices for Scala 2.13
- Prefer immutable by default - use
Vector,List,Map - Generics in method position - use
[T]not just at class level - Variance where appropriate - adds flexibility but keep simple
- Use sealed traits for union types - more powerful than Python's Union
- Type classes for ad-hoc polymorphism - replaces duck typing
Working with Circe JSON Types
Circe provides Json type which is immutable and generic:
import io.circe._
// Json is essentially: Json = JNull | JBoolean | JNumber | JString | JArray | JObject
val json: Json = Json.fromString("hello")
val jsonObj: Json = Json.obj("key" -> Json.fromString("value"))
Signals
- GitHub stars
- 83
- Forks
- 5
- Last commit
- Jul 2026
Advanced
- Catalog kind
- skill
- Gateway key
scala-generics- Source
- github.com/cxcscmu/skilllearnbench