Failures are values — try propagates them
Expected failures live in the return type, not as exceptions that can tunnel invisibly up the stack. try unwraps the good case and continues; on failure it early-returns from the enclosing function — every propagation point visible in source, every signature honest. Adapting a foreign error is an explicit else clause, never silent.
type AppError = Read{ cause: IOError } | Parse{ cause: ParseError };fn loadNumber(path: String) -> Int orelse AppError { fix text = try readFile(path) else e -> AppError.Read{ cause: e }; fix n = try parseInt(text) else e -> AppError.Parse{ cause: e }; Ok{ value: n }}