Either: essens, tillämpning och funktionsprincip

Författare: IT Sectr Publicerad: 2026-05-26 Lästid: 8 min

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 — en algebraisk datatyp för att representera två ömsesidigt uteslutande varianter: Left (fel) och Right (framgång).
  • Left innehåller traditionellt information om felet, Right — det korrekta värdet.
  • Explicit typning — Either tvingar hantering av båda varianterna vid kompilering, vilket eliminerar oväntade fel.
  • Sammansättning — Either stöder map, flatMap och fold för transformationskedjor utan nästlade kontroller.
  • Skillnad från Result — Either kan lagra en godtycklig feltyp, inte bara Error eller Throwable.

Vad är Either?

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.

Hur fungerar Either: struktur av Left och Right

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.

Typen Left: felbehållare

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.

Typen Right: framgångsbehållare

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.

Sammansättning av Either via flatMap

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.

kotlin
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) }

Either i Kotlin: praktisk tillämpning

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-biblioteket och Either

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().

Exempel: Either med en nätverksförfrågan

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.

kotlin
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 ?: ""))
    }
}

Either i Swift: skillnad från standard Result

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.

Standard Result versus Either

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.

swift
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 }

När ska man använda Either i mobila appar

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.

  • Nätverksförfrågningar — varje förfrågan kan returnera ett anslutnings-, server- eller parsningsfel. Either samlar alla varianter i en typ.
  • Formulärvalidering — Either med en anpassad feltyp representerar bekvämt resultatet av kontroll av inmatningsfält: ogiltig e-post eller lösenord.
  • Datarepository — Either gör det möjligt att kombinera resultat från olika källor (cache, databas, nätverk) med en enhetlig feltyp.
  • Kommandotolk — om appen parserar användarinmatning eller kommandon, ger Either ett typsäkert sätt att rapportera fel.

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.

Vanliga misstag vid arbete med Either

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.

  • Ignorera Left — att anropa .getOrElse() med ett standardvärde utan att analysera orsaken till felet gör användningen av Either meningslös. Hantera felet explicit.
  • Global feltyp — att använda String eller Exception som gemensam typ för alla Either i projektet minskar typsäkerheten. Skapa domän-sealed classes.
  • Nästlade Either — upprepad Either inuti Right (Either<E, Either<E, A>>) försvårar läsning. Använd flatMap för utjämning.
  • Blandning med undantag — funktionen returnerar Either men kastar internt ett undantag. Detta strider mot idén om explicit felhantering.

Vanliga frågor

Vad skiljer Either från Optional?

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.

Kan Either användas i Java?

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.

När är det bättre att använda sealed class istället för Either?

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.

Stöder Either flertrådning?

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.

Bör Either användas för alla funktioner i projektet?

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

  • Either — funktionell typ för att representera två varianter: Left (fel) och Right (framgång), vilket gör felhantering explicit på typnivå.
  • Left kan innehålla en godtycklig feltyp — från String till domän-sealed class, till skillnad från standard Result.
  • flatMap säkerställer sammansättning av Either utan nästlade kontroller: felet sprids automatiskt genom hela kedjan.
  • Arrow — det huvudsakliga Either-biblioteket för Kotlin med inbyggt stöd för korutiner och tillägg.
  • Swift använder inbyggd Result, men Either implementeras via enum med två generiska parametrar för full flexibilitet.
  • Tillämpa Either för nätverksförfrågningar, formulärvalidering och repositories — scenarier med förväntade fel.
  • Undvik global feltyp, ignorering av Left och nästlade Either — detta minskar fördelarna med typsäkerhet.

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.

Diskutera projektet

Läs också