The Type Hierarchy & Type Inference
Local type inference: parameter types of methods must be declared.
10.1 Unified type hierarchy
Any: supertype of everything (equals, hashCode, toString).
AnyVal: value types (unboxed where possible).
AnyRef: reference types.
Nothing: subtype of everything; type of throw and non-terminating expressions.
Null: type of null. With -Yexplicit-nulls, reference types are non-nullable and you write String | Null.
Unit: single value ().
Any
/ \
AnyVal AnyRef (java.lang.Object)
Int Double Boolean String, List, your classes...
Char Unit Long ... |
\ Null (only with explicit-nulls off)
\ /
Nothingval things: List[Any] = List(1, "two", 3.0, 'c', true, () => 5)
def fail(msg: String): Nothing = throw RuntimeException(msg)10.2 Type inference
Local type inference: parameter types of methods must be declared.
val x = 42 // Int
val xs = List(1, 2, 3) // List[Int]
val mixed = List(1, "a") // List[Int | String] in Scala 3 (Any in Scala 2)
def sq(x: Int) = x * x // return type inferred: Int10.3 Type aliases
type UserId = Long
type Callback[A] = A => Unit10.4 Tuples
val t = (1, "Ann", true) // (Int, String, Boolean)
t._1, t._2 // 1, "Ann"
t(0) // 1 (Scala 3 index access)
val (id, name, active) = t // destructuring
t.toList, t.size, t ++ (4.0, 'x'), t.head, t.tail
// Named tuples (Scala 3.7+)
val p = (name = "Ann", age = 30)
p.name🧪 Part I Exercises
Write @main def fizzbuzz(n: Int) using match on (i % 3, i % 5).
Write a tail-recursive power(base: Double, exp: Int): Double.
Write isPalindrome(s: String): Boolean ignoring case and non-letters.
Create a Vec class with +, -, * (scalar), dot, and unary -.
Write compose(fs: List[Int => Int]): Int => Int.
Write a method retry[A](times: Int)(block: => A): A using by-name parameters.
Write collatz(n: Int): List[Int].
Using for/yield, generate all Pythagorean triples with sides ≤ 30.
Write countWords(text: String): Map[String, Int].
Convert temperatures with default and named parameters: convert(value, from = "C", to = "F").