Result<T, E> is the tool for failures: it is a first-class value that your functions return and your callers handle explicitly. Faults are not Result values; they terminate the current execution boundary and signal that the program reached a state it was not designed to handle. Keeping these two categories separate means your domain logic stays clean, your error paths are visible, and unexpected failures never silently masquerade as normal outcomes.
Result<T, E> — Construction
Result<T, E> is part of the Core prelude. You do not need to import it. Construct a successful outcome with Result.success() and a failed outcome with Result.failure().
E must be value-like — use an enum or a value type, not a raw Text or a numeric code. This ensures errors are structured, pattern-matchable, and self-documenting.
Inspecting a Result
A Result<T, E> exposes four members for inspection:
Canonical Inspection with match
The standard way to handle a Result is to match on its .isSuccess property. This makes both branches visible and forces you to handle each case explicitly.
if when only one branch needs action:
Designing Error Types
Error types communicate the full vocabulary of ways an operation can fail. Preferenum when the set of failure cases is closed and each case is self-contained:
value type when a failure case carries structured data that the caller needs to act on:
enum whose cases carry value payloads (where the language supports associated values in a future version). For v0.1, use separate value types for cases that carry data and enum for those that do not.
Faults
A fault is distinct from aResult failure. Where a failure is an expected outcome that your function deliberately returns, a fault is an unexpected invariant violation that Kairo detects at runtime and treats as an unrecoverable condition within the current execution boundary.
Faults occur when your code does something it should never have done — for example:
- Accessing
.valueon a failedResult - Accessing
.erroron a successfulResult - Violating a precondition the runtime enforces
Think of faults as the equivalent of null-pointer exceptions or index-out-of-bounds errors in other languages — they indicate that the program reached a state the developer did not account for.
Result is for states you anticipate; faults are for states you should have prevented.Full Example
Here is a complete example showing a function that validates a customer name, an errorenum, and a caller that handles both outcomes:
match to handle each case:
Summary
Result failure
An expected, domain-meaningful outcome. Return
Result.failure(error) to signal it. The caller inspects and handles it explicitly.Fault
An unexpected invariant violation. Not a
Result. Terminates the execution boundary. Fix the code that caused it — don’t try to catch it.Error type design
Use
enum for closed sets of failure cases. Use value when a case carries structured data. Never use raw Text or numbers.Canonical inspection
Match on
result.isSuccess. Access .value only when isSuccess is true. Access .error only when isSuccess is false.