Either: o que é, como funciona e aplicação prática

Autor: IT Sectr Publicado: 2026-05-26 Tempo de leitura: 8 min

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 para representar duas variantes mutuamente exclusivas: Left (erro) e Right (sucesso).
  • Left tradicionalmente contém informação de erro, Right contém o valor correto.
  • Tipagem explícita — Either obriga o tratamento de ambas as variantes em tempo de compilação, eliminando falhas inesperadas.
  • Composição — Either suporta map, flatMap e fold para cadeias de transformações sem verificações aninhadas.
  • Diferença do Result — Either pode armazenar um tipo de erro arbitrário, não apenas Error ou Throwable.

O que é Either?

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.

Como Either funciona: estrutura Left e Right

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.

Tipo Left: contêiner de erro

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.

Tipo Right: contêiner de sucesso

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.

Composição de Either com flatMap

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.

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

Either em Kotlin: aplicação prática

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.

Biblioteca Arrow e Either

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

Exemplo: Either com requisição de rede

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.

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 em Swift: diferença do Result padrão

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 padrão vs. Either

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.

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 }

Quando usar Either em aplicativos mobile

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.

  • Requisições de rede — cada requisição pode retornar um erro de conexão, servidor ou parsing. Either agrupa todas as variantes em um único tipo.
  • Validação de formulários — Either com um tipo de erro personalizado representa convenientemente o resultado da validação de campos: e-mail ou senha inválidos.
  • Repositório de dados — Either permite combinar resultados de diferentes fontes (cache, BD, rede) com um tipo de erro unificado.
  • Interpretador de comandos — se o aplicativo analisa entrada do usuário ou comandos, Either fornece uma maneira type-safe de relatar erros.

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.

Erros comuns ao trabalhar com Either

Desenvolvedores iniciantes em Either frequentemente cometem erros semelhantes. Vamos examinar os mais comuns e como evitá-los.

  • Ignorar Left — chamar .getOrElse() com um valor padrão sem analisar a causa do erro perde o sentido de usar Either. Trate o erro explicitamente.
  • Tipo de erro global — usar String ou Exception como tipo comum para todos os Either em um projeto reduz a segurança de tipos. Crie classes seladas de domínio.
  • Either aninhados — um Either dentro de Right (Either<E, Either<E, A>>) dificulta a leitura. Use flatMap para achatar.
  • Mistura com exceções — uma função retorna Either mas internamente lança exceções. Isso contradiz a ideia de tratamento explícito de erros.

Perguntas frequentes

Qual a diferença entre Either e Optional?

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.

Pode-se usar Either em Java?

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.

Quando é melhor usar sealed class em vez de Either?

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 suporta multithreading?

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.

Devo usar Either para todas as funções no projeto?

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

  • Either é um tipo funcional para representar duas variantes: Left (erro) e Right (sucesso), tornando o tratamento de erros explícito no nível de tipos.
  • Left pode conter um tipo de erro arbitrário — de String a uma classe selada de domínio, ao contrário do Result padrão.
  • flatMap permite a composição de Either sem verificações aninhadas: o erro se propaga automaticamente por toda a cadeia.
  • Arrow é a principal biblioteca de Either para Kotlin com suporte embutido a corrotinas e extensões.
  • Swift usa o Result embutido, mas Either pode ser implementado via enum com dois parâmetros genéricos para máxima flexibilidade.
  • Use Either para requisições de rede, validação de formulários e repositórios — cenários com erros esperados.
  • Evite tipos de erro globais, ignorar Left e Either aninhados — isso reduz os benefícios da segurança de tipos.

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.

Discutir o projeto

Leia também