Reference ยท Functional Programming in Scala
Functional data structures
The compact reference for Lesson 03.
Standalone
These examples use a tiny immutable list and small values. No VPS, account, private repository, production data, network service, or CLI is required.
Optional Scala source for syntax comparison.
Two constructors
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
Nilis the empty case.Cons(head, tail)is the nonempty case.sealedmakes the set of cases closed to this file.- Immutable tails can be shared by multiple list versions.
Pattern matching
def sum(xs: List[Int]): Int = xs match {
case Nil => 0
case Cons(head, tail) => head + sum(tail)
}
Match the empty base case first, then expose the head and recurse over the tail.
Safe sharing
def tailOrEmpty[A](xs: List[A]): List[A] = xs match {
case Nil => Nil
case Cons(_, tail) => tail
}
def setHead[A](xs: List[A], value: A): List[A] = xs match {
case Nil => Cons(value, Nil)
case Cons(_, tail) => Cons(value, tail)
}
setHead allocates one new node and reuses the old tail. Immutability means the shared suffix cannot be changed behind another reference.
Fold and map
def foldRight[A, B](xs: List[A], zero: B)(f: (A, B) => B): B = xs match {
case Nil => zero
case Cons(head, tail) => f(head, foldRight(tail, zero)(f))
}
def map[A, B](xs: List[A])(f: A => B): List[B] =
foldRight(xs, Nil: List[B])((head, tail) => Cons(f(head), tail))
Nilbecomeszero.- Each
Consbecomes a call tof. mapinjects a transformation while rebuilding the list shape.
Design checklist
- List every constructor case.
- Choose the base result for the empty case.
- Make the recursive call on a smaller structural value.
- Return new nodes instead of mutating old ones.
- Share immutable suffixes when that preserves the desired shape.
Rust translation
Think of Nil/Cons as the Scala equivalent of Empty/Cons enum variants. The ownership and allocation details differ, but the case analysis and recursive structure transfer directly.