Scala Type System
Use when scala's advanced type system including generics, variance, type bounds, implicit conversions, type classes, higher-kinded types, path-dependent types, and abstract type members for building type-safe, flexible APIs.
What this skill does
# Scala Type System
## Introduction
Scala features one of the most sophisticated type systems among mainstream
programming languages, combining object-oriented and functional programming
concepts. This advanced type system enables precise modeling of domain concepts,
compile-time verification of complex constraints, and highly reusable abstractions.
Key features include parametric polymorphism (generics), variance annotations,
type bounds, implicit conversions and parameters, type classes, higher-kinded
types, path-dependent types, and abstract type members. These features enable
expressive APIs while maintaining type safety.
This skill covers generics and variance, upper and lower type bounds, view and
context bounds, implicit conversions, type classes, higher-kinded types,
path-dependent types, and practical type-level programming patterns.
## Generics and Type Parameters
Type parameters enable writing reusable code that works with multiple types while
maintaining type safety.
```scala
// Basic generic class
class Box[T](val content: T) {
def get: T = content
def map[U](f: T => U): Box[U] = new Box(f(content))
}
val intBox = new Box(42)
val stringBox = new Box("hello")
// Generic methods
def identity[T](x: T): T = x
def swap[A, B](pair: (A, B)): (B, A) = (pair._2, pair._1)
// Multiple type parameters
class Pair[A, B](val first: A, val second: B) {
def swap: Pair[B, A] = new Pair(second, first)
}
// Generic collections
def first[T](list: List[T]): Option[T] = list.headOption
def last[T](list: List[T]): Option[T] = list.lastOption
// Type parameter constraints with type bounds
class NumberBox[T <: Number](val value: T) {
def doubleValue: Double = value.doubleValue()
}
// Generic trait
trait Container[T] {
def add(item: T): Container[T]
def get: T
def isEmpty: Boolean
}
class SimpleContainer[T](private var item: Option[T] = None)
extends Container[T] {
def add(newItem: T): Container[T] = {
item = Some(newItem)
this
}
def get: T = item.getOrElse(throw new NoSuchElementException)
def isEmpty: Boolean = item.isEmpty
}
// Generic companion object
object Container {
def empty[T]: Container[T] = new SimpleContainer[T]()
def of[T](item: T): Container[T] = new SimpleContainer[T](Some(item))
}
// Type parameter inference
val box1 = new Box(42) // Box[Int]
val box2 = new Box("hello") // Box[String]
val list1 = List(1, 2, 3) // List[Int]
// Explicit type parameters when needed
val box3 = new Box[Any](42)
val emptyList = List.empty[String]
// Generic functions with multiple constraints
def max[T](a: T, b: T)(implicit ord: Ordering[T]): T =
if (ord.gt(a, b)) a else b
println(max(5, 10)) // 10
println(max("apple", "banana")) // banana
// Type aliases for complex generic types
type StringMap[V] = Map[String, V]
type IntPair = (Int, Int)
val userAges: StringMap[Int] = Map("Alice" -> 30, "Bob" -> 25)
val point: IntPair = (10, 20)
```
Generics enable writing code once and reusing it with multiple types while
maintaining compile-time type safety.
## Variance Annotations
Variance controls how parameterized types relate to each other based on their
type parameters' subtyping relationships.
```scala
// Covariance (+T): if A <: B, then Container[A] <: Container[B]
class CovariantBox[+T](val content: T) {
def get: T = content
// Can't have T in contravariant position (method parameters)
// def set(item: T): Unit = ??? // Won't compile
}
class Animal
class Dog extends Animal
class Cat extends Animal
val dogBox: CovariantBox[Dog] = new CovariantBox(new Dog)
val animalBox: CovariantBox[Animal] = dogBox // Valid due to covariance
// Contravariance (-T): if A <: B, then Container[B] <: Container[A]
trait Printer[-T] {
def print(item: T): Unit
}
class AnimalPrinter extends Printer[Animal] {
def print(animal: Animal): Unit = println("Animal")
}
val animalPrinter: Printer[Animal] = new AnimalPrinter
val dogPrinter: Printer[Dog] = animalPrinter // Valid due to contravariance
// Invariance (T): no subtyping relationship
class InvariantBox[T](private var content: T) {
def get: T = content
def set(item: T): Unit = { content = item }
}
// Practical variance example: Function1
trait Function1[-T, +R] {
def apply(v: T): R
}
val animalToString: Function1[Animal, String] = animal => "Animal"
val dogToAny: Function1[Dog, Any] = animalToString // Valid
// Collections variance
val dogs: List[Dog] = List(new Dog, new Dog)
val animals: List[Animal] = dogs // List is covariant
// Mutable collections are invariant
val dogArray: Array[Dog] = Array(new Dog)
// val animalArray: Array[Animal] = dogArray // Won't compile
// Option is covariant
val someDog: Option[Dog] = Some(new Dog)
val someAnimal: Option[Animal] = someDog // Valid
// Variance with multiple type parameters
class Function2[-T1, -T2, +R] {
def apply(v1: T1, v2: T2): R = ???
}
// Variance bounds in definition
class Box[+T](val content: T) {
// Use lower bound to allow contravariant position
def set[U >: T](item: U): Box[U] = new Box(item)
}
// Either is covariant in both parameters
sealed trait Either[+A, +B]
case class Left[A](value: A) extends Either[A, Nothing]
case class Right[B](value: B) extends Either[Nothing, B]
val rightInt: Either[String, Int] = Right(42)
val rightAny: Either[String, Any] = rightInt // Valid
```
Variance annotations make parameterized types more flexible while maintaining
type safety, especially for immutable containers.
## Type Bounds
Type bounds constrain type parameters to specific type hierarchies, enabling
type-safe operations on generic types.
```scala
// Upper type bound (T <: Upper)
def findMax[T <: Ordered[T]](list: List[T]): Option[T] = {
if (list.isEmpty) None
else Some(list.reduce((a, b) => if (a > b) a else b))
}
// Lower type bound (T >: Lower)
class Animal
class Dog extends Animal
class Container[+T] {
def add[U >: T](item: U): Container[U] = ???
}
// Using both bounds together
def cloneAndReset[T >: Null <: Cloneable](obj: T): T = {
val cloned = obj.clone().asInstanceOf[T]
cloned
}
// Complex type bounds
trait Comparable[T] {
def compareTo(that: T): Int
}
def sort[T <: Comparable[T]](list: List[T]): List[T] =
list.sortWith(_.compareTo(_) < 0)
// Multiple bounds with 'with'
trait Loggable {
def log(): Unit
}
trait Serializable {
def serialize(): String
}
def process[T <: Loggable with Serializable](item: T): String = {
item.log()
item.serialize()
}
// Recursive type bounds (F-bounded polymorphism)
trait Comparable2[T <: Comparable2[T]] { self: T =>
def compare(that: T): Int
}
class Person(val name: String, val age: Int) extends Comparable2[Person] {
def compare(that: Person): Int = this.age - that.age
}
// View bounds (deprecated but useful to understand)
// def sum[T <% Ordered[T]](list: List[T]): T = ???
// Context bounds (modern approach)
def sum[T: Numeric](list: List[T]): T = {
val numeric = implicitly[Numeric[T]]
list.foldLeft(numeric.zero)(numeric.plus)
}
println(sum(List(1, 2, 3))) // 6
println(sum(List(1.5, 2.5, 3.0))) // 7.0
// Multiple context bounds
def print[T: Ordering: Numeric](list: List[T]): Unit = {
val ord = implicitly[Ordering[T]]
val num = implicitly[Numeric[T]]
println(s"Max: ${list.max(ord)}, Sum: ${sum(list)}")
}
// Abstract type members with bounds
trait Container2 {
type Content <: AnyRef
def get: Content
}
class StringContainer extends Container2 {
type Content = String
def get: String = "hello"
}
// Type bounds with variance
class Box[+T] {
def put[U >: T](item: U): Box[U] = new Box[U]
}
// Existential types (less common)
def processAnyBox(box: Box[_]): Unit = {
println("Processing box")
}
// Type bounds for type classes
trait Show[T] {
def show(value: T): String
}
def display[T: Show](value: T): String = {
val shower = implicitly[Show[T]]
shower.show(value)
}
implicit val intShow: Show[Int] = (value: Int) => value.toString
impliRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.