Either — funkcionální typ, který reprezentuje hodnotu jedné ze dvou možných variant: levou (Left) pro chybu a pravou (Right) pro úspěch. Na rozdíl od výjimek činí Either zpracování chyb explicitní na úrovni typů a nevyžaduje bloky try-catch. Podle údajů Arrow, 2026 je Either široce používán v projektech Kotlin pro kompozici operací, které mohou selhat, bez vedlejších účinků.
Hlavní body
Either — je algebraický datový typ převzatý z funkcionálního programování, který reprezentuje hodnotu právě jednoho ze dvou možných typů. V kontextu zpracování chyb je konvence taková: levý typ (Left) obsahuje popis problému, pravý (Right) — úspěšný výsledek.
Koncept Either pochází z jazyka Haskell a kategorie typů Either a b, kde a je typ levé hodnoty, b — pravé. V mobilním vývoji si Either získal popularitu díky knihovně Arrow pro Kotlin a funkcionálním přístupům ve Swift.
Klíčovou výhodou Either oproti výjimkám je absence skrytých cest provádění. Funkce vracející Either explicitně deklaruje ve svém podpisu, že může skončit chybou. Kompilátor kontroluje, zda byly obě varianty zpracovány.
Na rozdíl od vyhazování výjimek si Either zachovává transparentnost toku dat. Volání funkce vracející Either nevyžaduje try-catch na straně volajícího kódu — stačí pattern-matching nebo fold. To je zvláště důležité v architekturách s reaktivním přístupem, kde každý zdroj dat vrací Either a řetězec transformací se buduje pomocí map a flatMap.
Either se skládá ze dvou podtypů: Left a Right. Instance Either může být v každém okamžiku pouze jedna z nich. Typický podpis v Kotlin vypadá jako Either<E, A>, kde E je typ chyby, A — typ úspěšné hodnoty.
Left představuje případ selhání. Na rozdíl od výjimek Left nepřerušuje tok provádění — jednoduše vrací hodnotu, kterou je třeba zpracovat. Typ chyby může být jakýkoli: String, Int, vlastní sealed class nebo doménový model.
Right obsahuje správný výsledek operace. Název odráží „správnost“ — podle konvence Right znamená úspěch. Právě na Right se aplikují transformace map a flatMap, což umožňuje budovat řetězce výpočtů bez kontroly každého kroku.
flatMap — hlavní mechanismus kompozice Either. Pokud je aktuální hodnota Right, flatMap aplikuje předanou funkci a vrátí nový Either. Pokud je Left — flatMap přeskočí transformaci a předá chybu dál. Toto chování se nazývá short-circuit evaluation.
Kromě flatMap podporuje Either mapLeft pro transformaci chyby, fold pro zpracování obou variant na jednom místě a getOrElse pro extrakci hodnoty s výchozí hodnotou. Tyto funkce pokrývají všechny scénáře: od jednoduché extrakce až po složitou kompozici s asynchronními voláními v korutinách Kotlin nebo Combine ve Swift.
fun parseInt(input: String): Either<String, Int> =
input.toIntOrNull()?.let { Right(it) }
?: Left("Nepodařilo se převést: $input")
fun divide(a: Int, b: Int): Either<String, Int> =
if (b == 0) Left("Dělení nulou")
else Right(a / b)
val result = parseInt("10")
.flatMap { divide(it, 2) }
V ekosystému Kotlin je Either implementován v knihovně Arrow. Standardní knihovna Kotlin nabízí Result, ale Either poskytuje větší flexibilitu: libovolný typ chyby, kompozici pomocí flatMap a podporu funkcionálních vzorů.
Arrow — funkcionální knihovna pro Kotlin, která přidává Either, Option, Validated a další typy. Arrow.Either — sealed class se dvěma dědici: ArrowCore.Left a ArrowCore.Right. Knihovna také poskytuje rozšíření pro pohodlnou práci: .getOrElse(), .fold(), .mapLeft().
Uvažujme reálný scénář — požadavek na síť v aplikaci Android s možnými chybami: žádná síť, chyba serveru, neplatná odpověď. Either umožňuje spojit všechny varianty do jednoho návratového typu.
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 ?: ""))
}
}
Ve Swift od verze 5.0 se objevil vestavěný typ Result, který je koncepčně podobný Either, ale má omezení: chyba musí odpovídat protokolu Error a úspěšná hodnota — jednomu typu. Either ve Swift se implementuje pomocí enum se dvěma generickými parametry.
Result<Success, Failure> — vestavěný typ Swift, kde Failure: Error. Either neklade omezení na typ chyby, což umožňuje ukládat String, vlastní struktury nebo dokonce několik typů chyb pomocí vnořených enumů.
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 je optimální pro scénáře, které vyžadují explicitní a typově bezpečné zpracování chyb bez výjimek. Podívejme se na hlavní případy použití v mobilním vývoji v Kotlin a Swift.
Nepoužívejte Either pro jednoduché operace bez vedlejších účinků — běžná návratová hodnota je spolehlivější a čitelnější. Either je také nadbytečný, když je selhání výjimečná situace, nikoli očekávaný scénář.
Either je také efektivní při práci s korutinami v Kotlin. Funkce vracející Either může být volána uvnitř korutiny se zpracováním chyby pomocí fold nebo mapLeft bez blokování vlákna. To je zvláště užitečné v aplikacích pro Android s architekturou MVVM, kde každé úložiště vrací Either a ViewModel transformuje výsledek na UiState.
Vývojáři, kteří se poprvé seznamují s Either, často dělají podobné chyby. Podívejme se na nejčastější z nich a způsoby, jak se jim vyhnout.
Často kladené otázky
Optional představuje přítomnost nebo nepřítomnost hodnoty (Some/None), ale nesděluje příčinu nepřítomnosti. Either dává dva konkrétní typy — levý pro chybu a pravý pro úspěch, což umožňuje předat kontext selhání.
V Java není vestavěný Either, ale knihovny Vavr a functionaljava poskytují implementaci. Ve vývoji pro Android je Either z Vavr populární alternativou pro funkcionální styl s lambdami.
Sealed class v Kotlin je pohodlnější, když je variant více než dvě nebo mají odlišnou strukturu. Pro binární výsledek (chyba/úspěch) je Either kompaktnější a poskytuje hotové funkcionální kombinátory.
Either je neměnný a standardně bezpečný pro vlákna. V Kotlin s korutinami se Either výborně kombinuje: flatMap funguje uvnitř coroutine scope a zpracování chyb nevyžaduje zámky.
Ne. Either je vhodný pro operace s očekávanými selháními (síť, validace, obchodní logika). Pro jednoduché gettery a výpočty bez vedlejších účinků je běžný typ čitelnější a nepřidává zbytečnou složitost.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také