Either é um tipo funcional que representa um valor de uma de duas variantes possíveis: Left para erros e Right para sucesso. Ao contrário das exceções, Either torna o tratamento de erros explícito no nível de tipos e não requer blocos try-catch. De acordo com Arrow, 2026, Either é amplamente utilizado em projetos Kotlin para compor operações que podem falhar, sem efeitos colaterais.
Principais pontos
Either é um tipo de dado algébrico, emprestado da programação funcional, que representa exatamente um de dois tipos possíveis. No contexto do tratamento de erros, a convenção é: o tipo Left (Left) contém uma descrição do problema, enquanto o tipo Right (Right) contém um resultado bem-sucedido.
O conceito de Either origina-se da linguagem Haskell e da categoria de tipos Either a b, onde a é o tipo do valor esquerdo e b é o tipo do direito. No desenvolvimento mobile, Either ganhou popularidade graças à biblioteca Arrow para Kotlin e abordagens funcionais em Swift.
A principal vantagem do Either sobre as exceções é a ausência de caminhos de execução ocultos. Uma função que retorna Either declara explicitamente em sua assinatura que pode falhar. O compilador garante que ambas as variantes sejam tratadas.
Ao contrário de lançar exceções, Either preserva a transparência do fluxo de dados. Chamar uma função que retorna Either não requer try-catch do lado do chamador — basta pattern-matching ou fold. Isso é especialmente importante em arquiteturas com abordagem reativa, onde cada fonte de dados retorna Either e cadeias de transformação são construídas com map e flatMap.
Either consiste em dois subtipos: Left e Right. Uma instância de Either pode ser apenas um deles em cada momento. A assinatura típica em Kotlin é Either<E, A>, onde E é o tipo de erro e A é o tipo de valor de sucesso.
Left representa o caso de falha. Ao contrário das exceções, Left não interrompe o fluxo de execução — ele simplesmente retorna um valor que precisa ser tratado. O tipo de erro pode ser qualquer coisa: String, Int, uma classe selada personalizada ou um modelo de domínio.
Right contém o resultado correto da operação. O nome reflete a correção — por convenção, Right significa sucesso. Transformações como map e flatMap são aplicadas ao Right, permitindo cadeias de cálculos sem verificar cada etapa.
flatMap é o principal mecanismo de composição do Either. Se o valor atual for Right, flatMap aplica a função recebida e retorna um novo Either. Se for Left, flatMap pula a transformação e propaga o erro. Esse comportamento é chamado de avaliação de curto-circuito.
Além de flatMap, Either suporta mapLeft para transformação de erro, fold para tratar ambas as variantes em um só lugar e getOrElse para extrair um valor com um padrão. Essas funções cobrem todos os cenários: desde a extração simples até a composição complexa com chamadas assíncronas em corrotinas Kotlin ou Combine em Swift.
fun parseInt(input: String): Either<String, Int> =
input.toIntOrNull()?.let { Right(it) }
?: Left("Falha ao converter: $input")
fun divide(a: Int, b: Int): Either<String, Int> =
if (b == 0) Left("Divisão por zero")
else Right(a / b)
val result = parseInt("10")
.flatMap { divide(it, 2) }
No ecossistema Kotlin, Either é implementado na biblioteca Arrow. A biblioteca padrão do Kotlin oferece Result, mas Either proporciona mais flexibilidade: tipo de erro arbitrário, composição via flatMap e suporte a padrões funcionais.
Arrow é uma biblioteca funcional para Kotlin que adiciona Either, Option, Validated e outros tipos. Arrow.Either é uma classe selada com duas subclasses: ArrowCore.Left e ArrowCore.Right. A biblioteca também fornece extensões convenientes: .getOrElse(), .fold(), .mapLeft().
Considere um cenário real — uma requisição de rede em um aplicativo Android com possíveis erros: falta de rede, erro de servidor, resposta inválida. Either permite combinar todas as variantes em um único tipo de retorno.
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 ?: ""))
}
}
Em Swift, a partir da versão 5.0, o tipo integrado Result está disponível, conceitualmente semelhante ao Either, mas com limitações: o erro deve estar em conformidade com o protocolo Error e o valor de sucesso deve ser de um único tipo. Either em Swift é implementado usando um enum com dois parâmetros genéricos.
Result<Success, Failure> é o tipo integrado do Swift, onde Failure: Error. Either não impõe restrições ao tipo de erro, permitindo armazenar String, estruturas personalizadas ou até múltiplos tipos de erro por meio de enums aninhados.
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 é ideal para cenários que exigem tratamento de erros explícito e type-safe sem exceções. Considere os principais casos de uso no desenvolvimento mobile com Kotlin e Swift.
Não use Either para operações simples sem efeitos colaterais — um valor de retorno normal é mais confiável e fácil de ler. Either também é excessivo quando a falha é uma situação excepcional e não um cenário esperado.
Either também é eficaz ao trabalhar com corrotinas em Kotlin. Uma função que retorna Either pode ser chamada dentro de uma corrotina com tratamento de erro via fold ou mapLeft sem bloquear a thread. Isso é especialmente útil em aplicativos Android com arquitetura MVVM, onde cada repositório retorna Either e a ViewModel transforma o resultado em UiState.
Desenvolvedores iniciantes em Either frequentemente cometem erros semelhantes. Vamos examinar os mais comuns e como evitá-los.
Perguntas frequentes
Optional representa a presença ou ausência de um valor (Some/None), mas não informa a causa da ausência. Either fornece dois tipos concretos — esquerdo para erro e direito para sucesso — permitindo transmitir o contexto da falha.
Em Java não há Either embutido, mas as bibliotecas Vavr e functionaljava fornecem implementações. No desenvolvimento Android, Either do Vavr é uma alternativa popular para estilo funcional com lambdas.
Sealed class em Kotlin é mais conveniente quando há mais de duas variantes ou elas têm estruturas diferentes. Para um resultado binário (erro/sucesso), Either é mais compacto e fornece combinadores funcionais prontos para uso.
Either é imutável e thread-safe por padrão. Em Kotlin com corrotinas, Either combina perfeitamente: flatMap funciona dentro de um escopo de corrotina e o tratamento de erros não requer bloqueios.
Não. Either é adequado para operações com falhas esperadas (rede, validação, lógica de negócios). Para getters simples e cálculos sem efeitos colaterais, um tipo normal é mais fácil de ler e não adiciona complexidade desnecessária.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também