Expand description
I wanna thank Brené Brown for her work.
Result extended with partial success. Three states:
Success(T)— the transformation preserved everything. Zero loss.Partial(T, L)— a value came through, but something was lost getting here. The loss is measured and carried forward.Failure(E, L)— no value survived, but the cost of getting here is measured. The accumulated loss tells you what it cost to arrive at this failure.
The middle state is the point. Most real transformations are not perfect
and not failed. They are partial: a value exists, and it cost something.
Collapsing that into Ok or Err destroys the information about what
was lost.
Loss is the trait that measures what didn’t survive. Each domain
carries its own loss type: ConvergenceLoss for iterative refinement,
ApertureLoss for partial observation, RoutingLoss for decision
uncertainty.
§Constructors
use terni::{Imperfect, ConvergenceLoss};
// The four ways to construct an Imperfect:
let perfect: Imperfect<i32, String, ConvergenceLoss> = Imperfect::Success(42);
let lossy: Imperfect<i32, String, ConvergenceLoss> = Imperfect::Partial(42, ConvergenceLoss::new(3));
let failed: Imperfect<i32, String, ConvergenceLoss> = Imperfect::Failure("gone".into(), ConvergenceLoss::new(0));
let failed_with_cost: Imperfect<i32, String, ConvergenceLoss> = Imperfect::Failure("gone".into(), ConvergenceLoss::new(5));
assert!(perfect.is_ok());
assert!(lossy.is_partial());
assert!(failed.is_err());
// Failure carries accumulated loss — the cost of getting here:
assert_eq!(failed_with_cost.loss().steps(), 5);§The Terni-Functor
Imperfect is a terni-functor — a three-state composition that accumulates
loss through the middle state. The bind operator comes in three flavors:
.eh()— the shrug. For engineers who get it..imp()— the name. For the mischievous ones..tri()— the math. For engineers who know what a terni-functor is.
§Pipeline
use terni::{Imperfect, ConvergenceLoss};
let result = Imperfect::<i32, String, ConvergenceLoss>::Success(1)
.eh(|x| Imperfect::Success(x * 2))
.eh(|x| Imperfect::Partial(x + 1, ConvergenceLoss::new(3)));
assert!(result.is_partial());
assert_eq!(result.ok(), Some(3));§Recovery
use terni::{Imperfect, ConvergenceLoss};
// Recovery from failure always produces Partial — the failure happened,
// and that cost is carried forward.
let failed: Imperfect<i32, String, ConvergenceLoss> =
Imperfect::Failure("gone".into(), ConvergenceLoss::new(3));
let recovered = failed.recover(|_e| Imperfect::Success(0));
assert!(recovered.is_partial()); // never Success — the failure was real
assert_eq!(recovered.loss().steps(), 3); // cost survives
assert_eq!(recovered.ok(), Some(0));§Explicit Context
use terni::{Imperfect, Eh, ConvergenceLoss};
let mut eh = Eh::new();
let a = eh.imp(Imperfect::<i32, String, ConvergenceLoss>::Success(1)).unwrap();
let b = eh.imp(Imperfect::<_, String, _>::Partial(a + 1, ConvergenceLoss::new(5))).unwrap();
let result: Imperfect<i32, String, ConvergenceLoss> = eh.finish(b);
assert!(result.is_partial());Structs§
- Aperture
Loss - Which dimensions were dark during observation. Zero means all observed. Combine takes the union of dark dims. Total is represented by aperture = 1.0.
- Convergence
Loss - Distance to crystal. Zero means crystallized. Combine takes the max (the furthest from crystal dominates).
- Eh
- Terni-functor composition context.
- Routing
Loss - Decision uncertainty at a routing point. Zero means one model at 100%. Combine takes max entropy (most uncertain dominates).
Enums§
- Imperfect
- Result extended with partial success.
Traits§
- Loss
- A measure of what didn’t survive a transformation.