Arrow Typed Errors (Kotlin)
Quick start
- Classify the failure first: logical failure (typed error) vs exceptional failure (exception).
- Pick the surface type:
Raise<E>+ builder (either {}/option {}/nullable {}) for composable logic.- Wrapper type (
Either/Option/Ior/Result/nullable) for API boundaries.
- Read
references/typed-errors.mdfor API details and patterns before coding if unsure.
Workflow
- Model errors as sealed types.
- Implement happy-path logic with Raise DSL (prefer
either {}ornullable {}depending on output). - Guard invariants with
ensure/ensureNotNull. - Interop with external code:
- Use
catch/Either.catchOrThrowto convert expected exceptions into typed errors.
- Use
- Compose with
.bind()and transform errors withwithErrororrecover. - For validation across fields or lists, use accumulation (
zipOrAccumulate,mapOrAccumulate, oraccumulate). - Expose wrapper types at module boundaries; keep Raise internally when possible.
Patterns to apply
- Smart constructors (parse, don't validate): make constructors private; expose
invokereturningEither. - Validation accumulation: use
EitherNelandzipOrAccumulate/mapOrAccumulate. - Wrapper choice:
- Prefer nullable for optional values unless nested nullability issues exist; then use
Option. - Use
Eitherfor disjoint success/failure;Ioronly when success + warning is meaningful. - Use
Resultonly when errors areThrowableand interop with stdlib APIs is required.
- Prefer nullable for optional values unless nested nullability issues exist; then use
- Error translation across layers: use
withErrorto map inner errors to outer domain errors. - Drop error types explicitly: wrap
bindwithignoreErrorswhen moving from informative error types toOption/nullable flows. - Avoid sealed-on-sealed inheritance: model error hierarchies with composition (wrapper data classes), not sealed inheritance chains.
References
- Load
references/typed-errors.mdfor API details, error accumulation, wrapper-specific guidance, and sample snippets.