
Lightweight, zero-overhead Result type offering type-safe failures, enforced handling, functional composition, concise operator syntax, exception-to-failure mapping, map/recover operators and debugging support.
Superposition is a lightweight, high-performance Result type for Kotlin. It leverages Kotlin's value class to
minimize object allocation overhead while providing a robust, functional approach to strictly typed error handling.
@JvmInline value class.Throwable.map and recover.dependencies {
implementation("io.github.diareuse:superposition-core:<latest-version>")
}The core type is Superposition<Success, Failure>. To access the Success value, you must use handle. The
onFailure block returns Nothing, guaranteeing flow interruption on error.
fun processData(result: Superposition<String, ApiError>): String {
// Access is only possible via handle
val value = result.handle { error ->
// Must return Nothing (throw, return, etc.)
println("Error: ${error.code}")
return "Early exit"
}
// 'value' is guaranteed to be String here
return value
}Wrap throwing code using the superposition builder and an Unwrap strategy to map exceptions to domain failures.
sealed interface MyDomainError {
data object DomainRuleBreak1 : MyDomainError
class Unknown(error: Throwable) : UnhandledException(error), MyDomainError
companion object : Superposition.Unwrap<MyDomainError> {
override fun map(error: Throwable) = when(error) {
is RuntimeException -> DomainRuleBreak1
else -> Unknown
}
}
}
val result: Superposition<String, MyDomainError> = superposition(MyDomainError) {
if (someCondition) throw RuntimeException("Boom")
"Success Data"
}The invoke operator
Shortcut for handle:
val value = result { error -> return "Failed" }Guaranteed Success
If the Failure type is Nothing, you can unwrap directly:
val successOnly: Superposition<String, Nothing> = ...
val value = successOnly() // No lambda requiredMap
Transform success values while preserving failure types:
val intResult = result.map { str -> str.length }Flat Map
Transform success values while preserving failure types:
val fooBar: (String) -> Superposition<Int, ...> = { ... }
val result = result.flatMap { str -> fooBar(str) }Recover
Provide a fallback value instead of interrupting flow:
val value = result.recover { failure -> "Fallback: ${failure.msg}" }Chain operations using the superposition scope.
Sequential unwrap
val result = superposition(MyDomainError) {
// Unwrap results sequentially
val user = getUser().handle { throw UserNotFound(it) }
val service = getLoadBalancedService().handle { throw ServiceUnavailable(it) }
getProfile(user, service) // Returns the final result
}Flattened unwrap
val result = flatSuperposition(MyDomainError) {
val user = getUser().handle { throw UserNotFound(it) }
getProfile(user) // assumes -> getProfile(): Superposition<??, MyDomainError>
}The library includes UnhandledException which prints stack traces to System.err for unhandled exceptions during
creation or mapping, aiding in development debugging.
Superposition is a lightweight, high-performance Result type for Kotlin. It leverages Kotlin's value class to
minimize object allocation overhead while providing a robust, functional approach to strictly typed error handling.
@JvmInline value class.Throwable.map and recover.dependencies {
implementation("io.github.diareuse:superposition-core:<latest-version>")
}The core type is Superposition<Success, Failure>. To access the Success value, you must use handle. The
onFailure block returns Nothing, guaranteeing flow interruption on error.
fun processData(result: Superposition<String, ApiError>): String {
// Access is only possible via handle
val value = result.handle { error ->
// Must return Nothing (throw, return, etc.)
println("Error: ${error.code}")
return "Early exit"
}
// 'value' is guaranteed to be String here
return value
}Wrap throwing code using the superposition builder and an Unwrap strategy to map exceptions to domain failures.
sealed interface MyDomainError {
data object DomainRuleBreak1 : MyDomainError
class Unknown(error: Throwable) : UnhandledException(error), MyDomainError
companion object : Superposition.Unwrap<MyDomainError> {
override fun map(error: Throwable) = when(error) {
is RuntimeException -> DomainRuleBreak1
else -> Unknown
}
}
}
val result: Superposition<String, MyDomainError> = superposition(MyDomainError) {
if (someCondition) throw RuntimeException("Boom")
"Success Data"
}The invoke operator
Shortcut for handle:
val value = result { error -> return "Failed" }Guaranteed Success
If the Failure type is Nothing, you can unwrap directly:
val successOnly: Superposition<String, Nothing> = ...
val value = successOnly() // No lambda requiredMap
Transform success values while preserving failure types:
val intResult = result.map { str -> str.length }Flat Map
Transform success values while preserving failure types:
val fooBar: (String) -> Superposition<Int, ...> = { ... }
val result = result.flatMap { str -> fooBar(str) }Recover
Provide a fallback value instead of interrupting flow:
val value = result.recover { failure -> "Fallback: ${failure.msg}" }Chain operations using the superposition scope.
Sequential unwrap
val result = superposition(MyDomainError) {
// Unwrap results sequentially
val user = getUser().handle { throw UserNotFound(it) }
val service = getLoadBalancedService().handle { throw ServiceUnavailable(it) }
getProfile(user, service) // Returns the final result
}Flattened unwrap
val result = flatSuperposition(MyDomainError) {
val user = getUser().handle { throw UserNotFound(it) }
getProfile(user) // assumes -> getProfile(): Superposition<??, MyDomainError>
}The library includes UnhandledException which prints stack traces to System.err for unhandled exceptions during
creation or mapping, aiding in development debugging.