Functional Error Handling with Either
Implement Either monad for type-safe error handling with map, flatMap, and fold operations.
sealed class Either<out L, out R> {
data class Left<L>(val value: L) : Either<L, Nothing>()
data class Right<R>(val value: R) : Either<Nothing, R>()
fun <T> map(f: (R) -> T): Either<L, T> = when (this) {
is Left -> this
is Right -> Right(f(value))
}
fun <T> flatMap(f: (R) -> Either<L, T>): Either<L, T> = when (this) {
is Left -> this
is Right -> f(value)
}
fun <T> fold(onLeft: (L) -> T, onRight: (R) -> T): T = when (this) {
is Left -> onLeft(value)
is Right -> onRight(value)
}
}
sealed class AppError(val message: String) {
class NotFound(msg: String) : AppError(msg)
class Validation(msg: String) : AppError(msg)
}
data class User(val id: Int, val name: String, val email: String)
object UserService {
private val users = mapOf(1 to User(1, "Alice", "alice@test.com"))
fun findById(id: Int): Either<AppError, User> =
users[id]?.let { Either.Right(it) }
?: Either.Left(AppError.NotFound("User $id not found"))
fun validate(user: User): Either<AppError, User> =
if (user.email.contains("@")) Either.Right(user)
else Either.Left(AppError.Validation("Invalid email"))
}
fun main() {
val result = UserService.findById(1).flatMap { UserService.validate(it) }
println(result.fold({ it.message }, { it.name }))
}Use Cases
- Type-safe error handling without exceptions
- Railway-oriented programming
- Composable validation
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
Functional Error Handling with Either
Use Either and Option for type-safe error handling: Railway-oriented programming without exceptions.
Best for: Type-safe error handling without exceptions
Result Monad — Functional Error Handling
Handle errors functionally with Kotlin Result: map, recover, fold, and chaining fallible operations.
Best for: Type-safe error handling without exceptions
Kotlin Result API Functional Error Handling
Use Kotlin's built-in Result type for functional error handling: runCatching, map, recover, and fold.
Best for: Functional error handling without try-catch
Collections — map, filter, groupBy, and More
Master Kotlin collections: functional transformations, aggregations, grouping, and partition operations.
Best for: Data processing and transformation pipelines