terni
I wanna thank Brene Brown for her work.
Ternary error handling for Rust. Because computation is not binary.
eh
The type. Three states instead of two.
use ;
let perfect: = Success;
let lossy = Partial;
let failed: = Failure;
let costly_failure: = Failure;
assert!;
assert!;
assert!;
// Failure carries accumulated loss — the cost of getting here:
assert_eq!;
Failure(E, L) carries the accumulated loss from before the failure. The loss tells you what it cost to arrive here. If you need to distinguish "failed immediately" from "failed after expensive work," the carried loss is that information.
Loss measures what didn't survive. It's a monoid: zero() identity, combine associative, total() absorbing.
Three loss types ship with the crate:
ConvergenceLoss— distance to crystal. Combine: max.ApertureLoss— dark dimensions. Combine: union.RoutingLoss— decision entropy. Combine: max entropy, min gap.
Migration from Result
| Result | terni | |
|---|---|---|
Ok(v) |
Imperfect::Success(v) |
same |
Err(e) |
Imperfect::Failure(e, l) |
same |
Imperfect::Partial(v, l) |
new | |
Imperfect::Failure(e, l) |
honest |
The two empty cells on the left are the argument. Result doesn't have a row for partial success or honest failure. That's why terni exists.
Loss types in depth → · Full migration guide →
eh!
The bind. Chain operations, accumulate loss.
use ;
let result = Success
.eh
.eh;
assert_eq!;
assert!;
Recovery from failure carries the cost:
use ;
let result = Success
.eh
.eh
.recover;
// Recovery from Failure always produces Partial — the failure was real
assert!;
assert_eq!;
For explicit context with loss accumulation:
use ;
let mut eh = new;
let a = eh.eh.unwrap;
let b = eh.eh.unwrap;
let result: = eh.finish;
assert!;
.imp() and .tri() are aliases for .eh() — same bind, different name. Use whichever reads best in your code.
Pipeline guide → · Context guide →
eh?
The question. Coming in a future release.
Block macro for implicit loss accumulation — eh! { } will do what Eh does without the boilerplate.
More
- Loss types — the
Losstrait, shipped types, custom implementations - Pipeline —
.eh()bind in depth, loss accumulation rules - Context —
Ehstruct, mixingImperfectandResult - Terni-functor — the math behind
.eh() - Migration — moving from
Result<T, E>toImperfect<T, E, L>
License
Apache-2.0