Sum Types, Type Aliases and Smart Casting

17.1 Sum Types (Tagged Unions)

Sum types can include primitives: type Value = int | string | f64 | bool | []Value | map[string]Value (a recursive JSON-like value).

match on a sum type must be exhaustive.

struct Circle { radius f64 }
struct Square { side f64 }
struct Triangle { base f64  height f64 }

type Shape = Circle | Square | Triangle

fn area(s Shape) f64 {
	return match s {
		Circle { 3.14159 * s.radius * s.radius }   // s is smart-cast to Circle
		Square { s.side * s.side }
		Triangle { 0.5 * s.base * s.height }
	}
}

fn main() {
	shapes := [Shape(Circle{2}), Square{3}, Triangle{4, 5}]
	for s in shapes {
		println('${s.type_name()}: ${area(s)}')
	}
	c := shapes[0]
	if c is Circle {
		println(c.radius)          // smart cast
	}
	sq := shapes[1] as Square      // explicit cast (panics on mismatch)
	_ = sq
}

17.2 Recursive Sum Types (ASTs)

struct BinOp {
	op    string
	left  Expr
	right Expr
}
type Expr = int | BinOp

fn eval(e Expr) int {
	return match e {
		int { e }
		BinOp {
			l := eval(e.left)
			r := eval(e.right)
			match e.op { '+' { l + r } '*' { l * r } else { 0 } }
		}
	}
}

17.3 Type Aliases (Distinct Types)

Aliases let you add methods to primitive-based types and improve type safety.

type UserId = int              // a new named type based on int
type Celsius = f64

fn (c Celsius) to_f() f64 { return f64(c) * 9 / 5 + 32 }

id := UserId(42)
temp := Celsius(36.6)
println(temp.to_f())

17.4 Smart Casting Rules

After if x is T or inside match x { T { ... } }, x is treated as T.

For mutable variables, use if mut x is T to get a mutable smart cast.

Smart casting works on sum types and interfaces (and on struct fields of those types).