Either — en funktionell typ som representerar värdet av en av två möjliga varianter: vänster (Left) för fel och höger (Right) för framgång. Till skillnad från undantag gör Either felhanteringen explicit på typnivå och kräver inga try-catch-block. Enligt data från Arrow, 2026 används Either i stor utsträckning i Kotlin-projekt för sammansättning av operationer som kan misslyckas, utan bieffekter.
Huvudpunkter
Either — är en algebraisk datatyp lånad från funktionell programmering som representerar värdet av exakt en av två möjliga typer. I sammanhanget av felhantering är konventionen: den vänstra typen (Left) innehåller beskrivningen av problemet, och den högra (Right) — det framgångsrika resultatet.
Konceptet Either härstammar från språket Haskell och typkategorin Either a b, där a är typen av det vänstra värdet, b — det högra. Inom mobilutveckling har Either blivit populär tack vare biblioteket Arrow för Kotlin och funktionella angreppssätt i Swift.
Den främsta fördelen med Either jämfört med undantag — inga dolda exekveringsvägar. En funktion som returnerar Either deklarerar explicit i sin signatur att den kan sluta med fel. Kompilatorn kontrollerar om båda varianterna har hanterats.
Till skillnad från att kasta undantag bevarar Either transparens i dataflödet. Att anropa en funktion som returnerar Either kräver ingen try-catch på den anropande kodsidan — pattern-matching eller fold är tillräckligt. Detta är särskilt viktigt i arkitekturer med reaktiv ansats, där varje datakälla returnerar Either och transformationskedjan byggs upp via map och flatMap.
Either består av två subtyper: Left och Right. En instans av Either kan bara vara en av dem vid varje given tidpunkt. Den typiska signaturen i Kotlin ser ut som Either<E, A>, där E är feltypen, A — typen av framgångsrikt värde.
Left representerar fallet med ett misslyckande. Till skillnad från undantag avbryter Left inte exekveringsflödet — den returnerar helt enkelt ett värde som måste hanteras. Feltypen kan vara vad som helst: String, Int, en anpassad sealed class eller en domänmodell.
Right innehåller det korrekta resultatet av operationen. Namnet återspeglar “korrekthet” — enligt konvention betyder Right framgång. Det är på Right som transformationerna map och flatMap tillämpas, vilket gör det möjligt att bygga beräkningskedjor utan att kontrollera varje steg.
flatMap — den huvudsakliga mekanismen för sammansättning av Either. Om det aktuella värdet är Right, tillämpar flatMap den överförda funktionen och returnerar en ny Either. Om det är Left — hoppar flatMap över transformationen och skickar felet vidare. Detta beteende kallas short-circuit evaluation.
Förutom flatMap stöder Either mapLeft för transformation av fel, fold för hantering av båda varianterna på ett ställe och getOrElse för att extrahera värdet med ett standardvärde. Dessa funktioner täcker alla scenarier: från enkel extraktion till komplex sammansättning med asynkrona anrop i Kotlin-korutiner eller Combine i Swift.
fun parseInt(input: String): Either<String, Int> =
input.toIntOrNull()?.let { Right(it) }
?: Left("Kunde inte konvertera: $input")
fun divide(a: Int, b: Int): Either<String, Int> =
if (b == 0) Left("Division med noll")
else Right(a / b)
val result = parseInt("10")
.flatMap { divide(it, 2) }
I Kotlin-ekosystemet är Either implementerat i Arrow-biblioteket. Kotlins standardbibliotek erbjuder Result, men Either ger mer flexibilitet: godtycklig feltyp, sammansättning via flatMap och stöd för funktionella mönster.
Arrow — ett funktionellt bibliotek för Kotlin som lägger till Either, Option, Validated och andra typer. Arrow.Either — sealed class med två arvtagare: ArrowCore.Left och ArrowCore.Right. Biblioteket tillhandahåller också tillägg för bekvämt arbete: .getOrElse(), .fold(), .mapLeft().
Låt oss betrakta ett verkligt scenario — en nätverksförfrågan i en Android-app med möjliga fel: inget nätverk, serverfel, ogiltigt svar. Either gör det möjligt att kombinera alla varianter i en returtyp.
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 ?: ""))
}
}
I Swift från version 5.0 har den inbyggda typen Result dykt upp, som konceptuellt liknar Either men har begränsningar: felet måste följa protokollet Error och det framgångsrika värdet — en typ. Either i Swift implementeras via en enum med två generiska parametrar.
Result<Success, Failure> — Swifts inbyggda typ, där Failure: Error. Either lägger inga begränsningar på feltypen, vilket gör det möjligt att lagra String, anpassade strukturer eller till och med flera feltyper via nästlade enums.
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 är optimalt för scenarier som kräver explicit och typsäker felhantering utan undantag. Låt oss titta på de viktigaste användningsfallen inom mobilutveckling i Kotlin och Swift.
Använd inte Either för enkla operationer utan bieffekter — ett vanligt returvärde är mer tillförlitligt och lättare att läsa. Either är också överflödigt när ett misslyckande är en exceptionell situation, inte ett förväntat scenario.
Either är också effektivt vid arbete med korutiner i Kotlin. En funktion som returnerar Either kan anropas inuti en korutin med felhantering via fold eller mapLeft utan att blockera tråden. Detta är särskilt användbart i Android-appar med MVVM-arkitektur, där varje repository returnerar Either och ViewModel transformerar resultatet till UiState.
Utvecklare som för första gången bekantar sig med Either gör ofta liknande misstag. Låt oss titta på de vanligaste och sätten att undvika dem.
Vanliga frågor
Optional representerar närvaro eller frånvaro av ett värde (Some/None), men anger inte orsaken till frånvaron. Either ger två konkreta typer — vänster för fel och höger för framgång, vilket gör det möjligt att överföra sammanhanget för misslyckandet.
I Java finns ingen inbyggd Either, men biblioteken Vavr och functionaljava tillhandahåller en implementation. Inom Android-utveckling är Either från Vavr ett populärt alternativ för funktionell stil med lambdas.
Sealed class i Kotlin är bekvämare när varianterna är fler än två eller har olika struktur. För ett binärt utfall (fel/framgång) är Either mer kompakt och erbjuder färdiga funktionella kombinatorer.
Either är oföränderlig och trådsäker som standard. I Kotlin med korutiner kombineras Either utmärkt: flatMap fungerar inom coroutine scope och felhantering kräver inga låsningar.
Nej. Either är lämplig för operationer med förväntade misslyckanden (nätverk, validering, affärslogik). För enkla getters och beräkningar utan bieffekter är den vanliga typen mer läsbar och tillför inte onödig komplexitet.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också