Either ist ein funktionaler Typ, der einen Wert von zwei möglichen Varianten darstellt: Left für Fehler und Right für Erfolg. Im Gegensatz zu Ausnahmen macht Either die Fehlerbehandlung auf Typebene explizit und erfordert keine try-catch-Blöcke. Laut Arrow, 2026 wird Either in Kotlin-Projekten weit verbreitet eingesetzt, um Operationen zu komponieren, die ohne Nebenwirkungen fehlschlagen können.
Wichtige Punkte
Either ist ein algebraischer Datentyp, der aus der funktionalen Programmierung stammt und genau einen von zwei möglichen Typen darstellt. Im Kontext der Fehlerbehandlung gilt die Konvention: Der Left-Typ (Left) enthält eine Problembeschreibung, während der Right-Typ (Right) ein erfolgreiches Ergebnis enthält.
Das Konzept von Either stammt aus der Sprache Haskell und der Typkategorie Either a b, wobei a der Typ des linken Werts und b der Typ des rechten Werts ist. In der mobilen Entwicklung gewann Either durch die Arrow-Bibliothek für Kotlin und funktionale Ansätze in Swift an Popularität.
Der Hauptvorteil von Either gegenüber Ausnahmen ist das Fehlen versteckter Ausführungspfade. Eine Funktion, die Either zurückgibt, deklariert explizit in ihrer Signatur, dass sie fehlschlagen kann. Der Compiler stellt sicher, dass beide Varianten behandelt werden.
Im Gegensatz zum Werfen von Ausnahmen bewahrt Either die Transparenz des Datenflusses. Der Aufruf einer Funktion, die Either zurückgibt, erfordert auf der Aufruferseite kein try-catch — pattern-matching oder fold reichen aus. Dies ist besonders wichtig in Architekturen mit reaktivem Ansatz, bei denen jede Datenquelle Either zurückgibt und Transformationsketten über map und flatMap aufgebaut werden.
Either besteht aus zwei Subtypen: Left und Right. Eine Either-Instanz kann zu jedem Zeitpunkt nur einer von ihnen sein. Die typische Signatur in Kotlin ist Either<E, A>, wobei E der Fehlertyp und A der Typ des Erfolgswerts ist.
Left stellt den Fehlerfall dar. Anders als Ausnahmen unterbricht Left nicht den Ausführungsfluss — es gibt lediglich einen Wert zurück, der behandelt werden muss. Der Fehlertyp kann beliebig sein: String, Int, eine benutzerdefinierte versiegelte Klasse oder ein Domänenmodell.
Right enthält das korrekte Ergebnis der Operation. Der Name spiegelt die Korrektheit wider — per Konvention bedeutet Right Erfolg. Transformationen wie map und flatMap werden auf Right angewendet, was Berechnungsketten ohne Überprüfung jedes Schritts ermöglicht.
flatMap ist der Hauptmechanismus zur Komposition von Either. Wenn der aktuelle Wert Right ist, wendet flatMap die übergebene Funktion an und gibt ein neues Either zurück. Bei Left überspringt flatMap die Transformation und gibt den Fehler weiter. Dieses Verhalten wird als Kurzschlussauswertung bezeichnet.
Neben flatMap unterstützt Either mapLeft zur Fehlertransformation, fold zur Behandlung beider Varianten an einer Stelle und getOrElse zum Extrahieren eines Werts mit einem Standardwert. Diese Funktionen decken alle Szenarien ab: von der einfachen Extraktion bis zur komplexen Komposition mit asynchronen Aufrufen in Kotlin-Koroutinen oder Swift Combine.
fun parseInt(input: String): Either<String, Int> =
input.toIntOrNull()?.let { Right(it) }
?: Left("Konnte nicht konvertiert werden: $input")
fun divide(a: Int, b: Int): Either<String, Int> =
if (b == 0) Left("Division durch Null")
else Right(a / b)
val result = parseInt("10")
.flatMap { divide(it, 2) }
Im Kotlin-Ökosystem ist Either in der Arrow-Bibliothek implementiert. Die Kotlin-Standardbibliothek bietet Result, aber Either bietet mehr Flexibilität: beliebiger Fehlertyp, Komposition über flatMap und Unterstützung funktionaler Muster.
Arrow ist eine funktionale Bibliothek für Kotlin, die Either, Option, Validated und andere Typen hinzufügt. Arrow.Either ist eine versiegelte Klasse mit zwei Unterklassen: ArrowCore.Left und ArrowCore.Right. Die Bibliothek bietet auch praktische Erweiterungen: .getOrElse(), .fold(), .mapLeft().
Betrachten wir ein reales Szenario — eine Netzwerkanfrage in einer Android-App mit möglichen Fehlern: keine Netzwerkverbindung, Serverfehler, ungültige Antwort. Either ermöglicht es, alle Varianten in einem einzigen Rückgabetyp zu kombinieren.
sealed class NetworkError {
data class NoConnection(val message: String): NetworkError()
data class ServerError(val code: Int): NetworkError()
data class ParseError(val detail: String): NetworkError()
}
suspend fun fetchUser(id: String): Either<NetworkError, User> {
return try {
val response = api.getUser(id)
if (response.isSuccessful) {
Right(response.body()!!)
} else {
Left(NetworkError.ServerError(response.code()))
}
} catch (e: IOException) {
Left(NetworkError.NoConnection(e.message ?: ""))
}
}
In Swift ist ab Version 5.0 der integrierte Result-Typ verfügbar, der konzeptionell Either ähnelt, aber Einschränkungen hat: Der Fehler muss dem Error-Protokoll entsprechen, und der Erfolgswert muss von einem einzigen Typ sein. Either in Swift wird mit einem enum mit zwei generischen Parametern implementiert.
Result<Success, Failure> ist der integrierte Typ von Swift, wobei Failure: Error. Either erzwingt keine Einschränkungen für den Fehlertyp und kann String, benutzerdefinierte Strukturen oder sogar mehrere Fehlertypen über verschachtelte Enums speichern.
enum Either<E, A> {
case left(E)
case right(A)
func map<B>(_ transform: (A) -> B) -> Either<E, B> {
switch self {
case .left(let e): return .left(e)
case .right(let a): return .right(transform(a))
}
}
}
let result: Either<String, Int> = .right(42)
let mapped = result.map { $0 * 2 }
Either ist optimal für Szenarien, die eine explizite und typsichere Fehlerbehandlung ohne Ausnahmen erfordern. Betrachten wir die wichtigsten Anwendungsfälle in der mobilen Entwicklung mit Kotlin und Swift.
Verwenden Sie Either nicht für einfache Operationen ohne Nebenwirkungen — ein normaler Rückgabewert ist zuverlässiger und leichter lesbar. Either ist auch überflüssig, wenn ein Fehler eine Ausnahmesituation und kein erwartetes Szenario ist.
Either ist auch bei der Arbeit mit Koroutinen in Kotlin effektiv. Eine Funktion, die Either zurückgibt, kann innerhalb einer Koroutine mit Fehlerbehandlung über fold oder mapLeft aufgerufen werden, ohne den Thread zu blockieren. Dies ist besonders nützlich in Android-Apps mit MVVM-Architektur, bei denen jedes Repository Either zurückgibt und das ViewModel das Ergebnis in UiState umwandelt.
Entwickler, die zum ersten Mal mit Either arbeiten, machen oft ähnliche Fehler. Betrachten wir die häufigsten und wie man sie vermeidet.
Häufig gestellte Fragen
Optional repräsentiert das Vorhandensein oder Fehlen eines Werts (Some/None), gibt aber keinen Grund für das Fehlen an. Either bietet zwei konkrete Typen — links für Fehler und rechts für Erfolg — und ermöglicht so die Übergabe des Fehlerkontexts.
In Java gibt es kein integriertes Either, aber die Bibliotheken Vavr und functionaljava bieten Implementierungen. In der Android-Entwicklung ist Either von Vavr eine beliebte Alternative für einen funktionalen Stil mit Lambdas.
Sealed class in Kotlin ist praktischer, wenn es mehr als zwei Varianten gibt oder diese unterschiedliche Strukturen haben. Für ein binäres Ergebnis (Fehler/Erfolg) ist Either kompakter und bietet gebrauchsfertige funktionale Kombinatoren.
Either ist unveränderlich und standardmäßig threadsicher. In Kotlin mit Koroutinen lässt sich Either hervorragend kombinieren: flatMap funktioniert innerhalb eines Koroutinen-Scopes, und die Fehlerbehandlung erfordert keine Sperren.
Nein. Either eignet sich für Operationen mit erwarteten Fehlern (Netzwerk, Validierung, Geschäftslogik). Für einfache Getter und Berechnungen ohne Nebenwirkungen ist ein normaler Typ leichter lesbar und fügt keine unnötige Komplexität hinzu.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch