Either — een functioneel type dat de waarde van een van twee mogelijke varianten vertegenwoordigt: links (Left) voor fout en rechts (Right) voor succes. In tegenstelling tot uitzonderingen maakt Either foutafhandeling expliciet op typeniveau en vereist geen try-catch-blokken. Volgens gegevens van Arrow, 2026, wordt Either veel gebruikt in Kotlin-projecten voor het samenstellen van bewerkingen die kunnen mislukken, zonder bijwerkingen.
Belangrijkste
Either — is een algebraïsch gegevenstype, ontleend aan functioneel programmeren, dat de waarde van precies een van twee mogelijke typen vertegenwoordigt. In de context van foutafhandeling is de conventie: het linkertype (Left) bevat de beschrijving van het probleem, en rechts (Right) — het succesvolle resultaat.
Het concept Either komt uit de taal Haskell en de categorie van typen Either a b, waarbij a het type van de linkerwaarde is, b — van de rechter. In mobiele ontwikkeling heeft Either populariteit gekregen dankzij de bibliotheek Arrow voor Kotlin en functionele benaderingen in Swift.
Het belangrijkste voordeel van Either boven uitzonderingen — geen verborgen uitvoeringspaden. Een functie die Either retourneert, verklaart expliciet in zijn handtekening dat deze kan eindigen in een fout. De compiler controleert of beide varianten zijn afgehandeld.
In tegenstelling tot het gooien van uitzonderingen behoudt Either transparantie van de gegevensstroom. Het aanroepen van een functie die Either retourneert, vereist geen try-catch aan de kant van de aanroepende code — pattern-matching of fold is voldoende. Dit is vooral belangrijk in architecturen met een reactieve benadering, waarbij elke gegevensbron Either retourneert en de transformatieketen wordt opgebouwd via map en flatMap.
Either bestaat uit twee subtypen: Left en Right. Een instantie van Either kan op elk moment slechts een van beide zijn. De typische handtekening in Kotlin ziet eruit als Either<E, A>, waarbij E het fouttype is, A — het type van de succeswaarde.
Left vertegenwoordigt het geval van een storing. In tegenstelling tot uitzonderingen onderbreekt Left de uitvoeringsstroom niet — het retourneert gewoon een waarde die moet worden afgehandeld. Het fouttype kan van alles zijn: String, Int, een aangepaste sealed class of een domeinmodel.
Right bevat het juiste resultaat van de bewerking. De naam weerspiegelt „correctheid“ — volgens conventie betekent Right succes. Op Right worden de transformaties map en flatMap toegepast, wat het mogelijk maakt berekeningsketens te bouwen zonder elke stap te controleren.
flatMap — het belangrijkste mechanisme voor compositie van Either. Als de huidige waarde Right is, past flatMap de doorgegeven functie toe en retourneert een nieuwe Either. Als het Left is — slaat flatMap de transformatie over en geeft de fout door. Dit gedrag wordt short-circuit evaluation genoemd.
Naast flatMap ondersteunt Either mapLeft voor transformatie van de fout, fold voor het afhandelen van beide varianten op een plaats en getOrElse voor het extraheren van de waarde met een standaardwaarde. Deze functies dekken alle scenario's: van eenvoudige extractie tot complexe compositie met asynchrone aanroepen in Kotlin-coroutines of Combine in Swift.
fun parseInt(input: String): Either<String, Int> =
input.toIntOrNull()?.let { Right(it) }
?: Left("Kon niet converteren: $input")
fun divide(a: Int, b: Int): Either<String, Int> =
if (b == 0) Left("Delen door nul")
else Right(a / b)
val result = parseInt("10")
.flatMap { divide(it, 2) }
In het Kotlin-ecosysteem is Either geïmplementeerd in de Arrow-bibliotheek. De standaardbibliotheek van Kotlin biedt Result, maar Either geeft meer flexibiliteit: een willekeurig fouttype, compositie via flatMap en ondersteuning voor functionele patronen.
Arrow — een functionele bibliotheek voor Kotlin die Either, Option, Validated en andere typen toevoegt. Arrow.Either — een sealed class met twee subklassen: ArrowCore.Left en ArrowCore.Right. De bibliotheek biedt ook extensies voor gemakkelijk werk: .getOrElse(), .fold(), .mapLeft().
Laten we een realistisch scenario bekijken — een netwerkverzoek in een Android-app met mogelijke fouten: geen netwerk, serverfout, onjuist antwoord. Either maakt het mogelijk alle varianten in een retourtype te combineren.
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 is vanaf versie 5.0 het ingebouwde type Result verschenen, dat conceptueel lijkt op Either, maar beperkingen heeft: de fout moet voldoen aan het protocol Error en de succeswaarde — aan een type. Either in Swift wordt geïmplementeerd via een enum met twee generieke parameters.
Result<Success, Failure> — het ingebouwde type van Swift, waarbij Failure: Error. Either legt geen beperkingen op aan het fouttype, wat het mogelijk maakt een String, aangepaste structuren of zelfs meerdere fouttypen via geneste enums op te slaan.
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 is optimaal voor scenario's die expliciete en typeveilige foutafhandeling zonder uitzonderingen vereisen. Laten we de belangrijkste toepassingsgevallen in mobiele ontwikkeling in Kotlin en Swift bekijken.
Gebruik Either niet voor eenvoudige bewerkingen zonder bijwerkingen — een gewone retourwaarde is betrouwbaarder en leesbaarder. Either is ook overbodig wanneer een storing een uitzonderlijke situatie is en geen verwacht scenario.
Either is ook effectief bij het werken met coroutines in Kotlin. Een functie die Either retourneert, kan binnen een coroutine worden aangeroepen met foutafhandeling via fold of mapLeft zonder de thread te blokkeren. Dit is vooral nuttig in Android-apps met MVVM-architectuur, waarbij elke repository Either retourneert en de ViewModel het resultaat transformeert naar UiState.
Ontwikkelaars die voor het eerst kennismaken met Either maken vaak vergelijkbare fouten. Laten we de meest voorkomende bekijken en manieren om ze te vermijden.
Veelgestelde vragen
Optional vertegenwoordigt de aan- of afwezigheid van een waarde (Some/None), maar geeft de oorzaak van afwezigheid niet aan. Either geeft twee concrete typen — links voor fout en rechts voor succes, wat het mogelijk maakt de context van de storing door te geven.
In Java is er geen ingebouwde Either, maar de bibliotheken Vavr en functionaljava bieden een implementatie. In Android-ontwikkeling is Either van Vavr een populair alternatief voor functionele stijl met lambda's.
Sealed class in Kotlin is handiger wanneer er meer dan twee varianten zijn of ze een verschillende structuur hebben. Voor een binaire uitkomst (fout/succes) is Either compacter en biedt kant-en-klare functionele combinatoren.
Either is onveranderlijk en standaard thread-safe. In Kotlin met coroutines combineert Either uitstekend: flatMap werkt binnen de coroutine scope en foutafhandeling vereist geen vergrendelingen.
Nee. Either is geschikt voor bewerkingen met verwachte storingen (netwerk, validatie, bedrijfslogica). Voor eenvoudige getters en berekeningen zonder bijwerkingen is het gewone type leesbaarder en voegt het geen onnodige complexiteit toe.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook