Без заголовка
Ну, пишешь разборный тип или типаж, а потом case-ом его разбираешь по вариантам:
// !scala
trait Expr
case class Number(n: Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
// ...
def eval(e: Expr): Int = e match {
case Number(n) => n
case Sum(e1, e2) => eval(e1) + eval(e2)
}
match здесь обобщает и распространяет на интроспекцию switch, как можно понять.
Можешь глянуть мой конспектик недописанный (не факт, что более внятные тексты по-русски существуют).
Я просто поймал себя на том, что когда решал простые задачки, несколько раз писал файл с определением типа и кучей данных, вместо того, чтобы организовывать нормальное чтение данных из файла.