fn add(a: Int, b: Int): Int is pure = a + b

fn subtract(a: Int, b: Int): Int is pure = a - b

fn multiply(a: Int, b: Int): Int is commutative = a * b

fn sum(a: Int, b: Int): Int is commutative = a + b

fn abs(x: Int): Int is idempotent = if x < 0 then 0 - x else x

fn identity(x: Int): Int is idempotent = x

fn factorial(n: Int): Int is deterministic = if n <= 1 then 1 else n * factorial(n - 1)

fn fib(n: Int): Int is deterministic = if n <= 1 then n else fib(n - 1) + fib(n - 2)

fn sumTo(n: Int): Int is total = if n <= 0 then 0 else n + sumTo(n - 1)

fn power(base: Int, exp: Int): Int is total = if exp <= 0 then 1 else base * power(base, exp - 1)

fn main(): Unit with {Console} = {
    Console.print("=== Behavioral Types Demo ===")
    Console.print("")
    Console.print("Part 1: Pure functions")
    Console.print("  add(5, 3) = " + toString(add(5, 3)))
    Console.print("  subtract(10, 4) = " + toString(subtract(10, 4)))
    Console.print("")
    Console.print("Part 2: Commutative functions")
    Console.print("  multiply(7, 6) = " + toString(multiply(7, 6)))
    Console.print("  sum(10, 20) = " + toString(sum(10, 20)))
    Console.print("")
    Console.print("Part 3: Idempotent functions")
    Console.print("  abs(-42) = " + toString(abs(0 - 42)))
    Console.print("  identity(100) = " + toString(identity(100)))
    Console.print("")
    Console.print("Part 4: Deterministic functions")
    Console.print("  factorial(5) = " + toString(factorial(5)))
    Console.print("  fib(10) = " + toString(fib(10)))
    Console.print("")
    Console.print("Part 5: Total functions")
    Console.print("  sumTo(10) = " + toString(sumTo(10)))
    Console.print("  power(2, 8) = " + toString(power(2, 8)))
}

let output = run main() with {}
