scalaadvanced
Type-Level Programming with Tuples
Work with heterogeneous collections: named tuples, type-safe access, and compile-time operations.
scalaPress ⌘/Ctrl + Shift + C to copy
import scala.compiletime.*
import scala.deriving.Mirror
// Scala 3 named tuples / labeled types
type Person = (name: String, age: Int, email: String)
// Type-safe heterogeneous list using tuples
val record: Person = (name = "Alice", age = 30, email = "alice@test.com")
// Generic programming with Mirrors
inline def fieldNames[T](using m: Mirror.ProductOf[T]): List[String] =
fieldNamesHelper[m.MirroredElemLabels]
inline def fieldNamesHelper[T <: Tuple]: List[String] =
inline erasedValue[T] match
case _: EmptyTuple => Nil
case _: (head *: tail) =>
constValue[head].toString :: fieldNamesHelper[tail]
// Product to Map
def toMap(product: Product): Map[String, Any] =
product.productElementNames.zip(product.productIterator).toMap
// Case class derivation
case class User(name: String, age: Int, active: Boolean)
case class Config(host: String, port: Int, debug: Boolean, maxRetries: Int)
// Type-safe builder pattern
sealed trait HasName
sealed trait HasAge
sealed trait HasEmail
class PersonBuilder[State]:
private var _name: String = ""
private var _age: Int = 0
private var _email: String = ""
def name(n: String): PersonBuilder[State & HasName] =
_name = n
this.asInstanceOf[PersonBuilder[State & HasName]]
def age(a: Int): PersonBuilder[State & HasAge] =
_age = a
this.asInstanceOf[PersonBuilder[State & HasAge]]
def email(e: String): PersonBuilder[State & HasEmail] =
_email = e
this.asInstanceOf[PersonBuilder[State & HasEmail]]
// Only available when all fields are set
def build(using ev: State =:= (HasName & HasAge & HasEmail)): User =
User(_name, _age, _email == "active")
// Tuple operations
def tupleOps(): Unit =
val t1 = (1, "hello", true)
val t2 = (3.14, 'c')
// Concatenation
val combined = t1 ++ t2
println(s"Combined: $combined")
// Map
val mapped = t1.map[[X] =>> String] {
[T] => (t: T) => t.toString
}
println(s"Mapped: $mapped")
// Size
println(s"Size: ${t1.size}")
// toList (if homogeneous after map)
val list = t1.toList
println(s"ToList: $list")
// Zip
val names = ("Alice", "Bob", "Carol")
val ages = (30, 25, 35)
val zipped = names.zip(ages)
println(s"Zipped: $zipped")
@main def run(): Unit =
// Named tuple access
println(s"Name: ${record.name}")
println(s"Age: ${record.age}")
println(s"Email: ${record.email}")
// Field names via Mirror
println(s"\nUser fields: ${fieldNames[User]}")
println(s"Config fields: ${fieldNames[Config]}")
// Product to map
val user = User("Bob", 25, true)
println(s"\nAs map: ${toMap(user)}")
val config = Config("localhost", 8080, true, 3)
println(s"Config map: ${toMap(config)}")
// Tuple operations
println()
tupleOps()
// Type-safe builder
// PersonBuilder().build // Won't compile! Missing fields
// PersonBuilder().name("A").build // Won't compile!
// PersonBuilder().name("A").age(30).email("a@b").build // Compiles!
println(s"\nBuilder works type-safely at compile time")Use Cases
- Generic programming with Mirrors
- Type-safe builder APIs
- Heterogeneous data handling
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
scalaadvanced
Type-Level Programming Basics
Explore Scala 3 type-level programming: match types, singleton types, and type lambdas.
Best for: Type-safe library APIs
#scala#type-level
scalabeginner
Tuples and Product Types
Work with Scala 3 tuples: named tuples, tuple operations, conversions, and generic programming.
Best for: Returning multiple values from functions
#scala#tuples
scalaadvanced
Type Class Derivation with Mirrors
Derive type class instances automatically using Scala 3 Mirrors and inline metaprogramming.
Best for: Automatic codec generation
#scala#derivation
scalaadvanced
Inline and Compile-Time Metaprogramming
Use Scala 3 inline, transparent inline, and compiletime for compile-time computation and code generation.
Best for: Compile-time computation
#scala#inline