Either: esensi, penerapan, dan prinsip kerja

Penulis: IT Sectr Diterbitkan: 2026-05-26 Waktu membaca: 8 mnt

Either — tipe fungsional yang mewakili nilai dari salah satu dari dua kemungkinan varian: kiri (Left) untuk kesalahan dan kanan (Right) untuk keberhasilan. Tidak seperti pengecualian, Either membuat penanganan kesalahan eksplisit di tingkat tipe dan tidak memerlukan blok try-catch. Menurut data Arrow, 2026, Either banyak digunakan dalam proyek Kotlin untuk komposisi operasi yang mungkin gagal, tanpa efek samping.

Poin Utama

  • Either — tipe data aljabar untuk merepresentasikan dua varian yang saling eksklusif: Left (kesalahan) dan Right (keberhasilan).
  • Left secara tradisional berisi informasi tentang kesalahan, Right — nilai yang benar.
  • Tipifikasi eksplisit — Either memaksa penanganan kedua varian pada tahap kompilasi, menghilangkan kegagalan tak terduga.
  • Komposisi — Either mendukung map, flatMap, dan fold untuk rantai transformasi tanpa pemeriksaan bersarang.
  • Perbedaan dari Result — Either dapat menyimpan tipe kesalahan arbitrer, bukan hanya Error atau Throwable.

Apa itu Either?

Either — adalah tipe data aljabar yang dipinjam dari pemrograman fungsional, yang mewakili nilai tepat dari salah satu dari dua tipe yang mungkin. Dalam konteks penanganan kesalahan, konvensi yang diterima adalah: tipe kiri (Left) berisi deskripsi masalah, dan kanan (Right) — hasil yang berhasil.

Konsep Either berasal dari bahasa Haskell dan kategori tipe Either a b, di mana a adalah tipe nilai kiri, b — kanan. Dalam pengembangan seluler, Either menjadi populer berkat pustaka Arrow untuk Kotlin dan pendekatan fungsional di Swift.

Keunggulan utama Either dibandingkan pengecualian — tidak adanya jalur eksekusi tersembunyi. Fungsi yang mengembalikan Either secara eksplisit menyatakan dalam tanda tangannya bahwa ia dapat berakhir dengan kesalahan. Kompilator memeriksa apakah kedua varian telah ditangani.

Tidak seperti melempar pengecualian, Either mempertahankan transparansi aliran data. Pemanggilan fungsi yang mengembalikan Either tidak memerlukan try-catch di sisi kode pemanggil — pattern-matching atau fold sudah cukup. Ini sangat penting dalam arsitektur dengan pendekatan reaktif, di mana setiap sumber data mengembalikan Either, dan rantai transformasi dibangun melalui map dan flatMap.

Bagaimana Either bekerja: struktur Left dan Right

Either terdiri dari dua subtipe: Left dan Right. Sebuah instance Either hanya dapat menjadi salah satunya pada setiap saat. Tanda tangan tipikal di Kotlin terlihat sebagai Either<E, A>, di mana E adalah tipe kesalahan, A — tipe nilai keberhasilan.

Tipe Left: wadah kesalahan

Left mewakili kasus kegagalan. Tidak seperti pengecualian, Left tidak mengganggu aliran eksekusi — ia hanya mengembalikan nilai yang perlu ditangani. Tipe kesalahan bisa apa saja: String, Int, sealed class kustom, atau model domain.

Tipe Right: wadah keberhasilan

Right berisi hasil operasi yang benar. Nama mencerminkan “kebenaran” — menurut konvensi Right berarti keberhasilan. Pada Right-lah transformasi map dan flatMap diterapkan, yang memungkinkan membangun rantai perhitungan tanpa memeriksa setiap langkah.

Komposisi Either melalui flatMap

flatMap — mekanisme utama komposisi Either. Jika nilai saat ini adalah Right, flatMap menerapkan fungsi yang diberikan dan mengembalikan Either baru. Jika Left — flatMap melewatkan transformasi dan meneruskan kesalahan. Perilaku ini disebut short-circuit evaluation.

Selain flatMap, Either mendukung mapLeft untuk transformasi kesalahan, fold untuk menangani kedua varian di satu tempat, dan getOrElse untuk mengekstrak nilai dengan default. Fungsi-fungsi ini mencakup semua skenario: dari ekstraksi sederhana hingga komposisi kompleks dengan panggilan asinkron di coroutine Kotlin atau Combine di Swift.

kotlin
fun parseInt(input: String): Either<String, Int> =
    input.toIntOrNull()?.let { Right(it) }
    ?: Left("Tidak dapat mengonversi: $input")

fun divide(a: Int, b: Int): Either<String, Int> =
    if (b == 0) Left("Pembagian dengan nol")
    else Right(a / b)

val result = parseInt("10")
    .flatMap { divide(it, 2) }

Either di Kotlin: penerapan praktis

Dalam ekosistem Kotlin, Either diimplementasikan di pustaka Arrow. Pustaka standar Kotlin menawarkan Result, tetapi Either memberikan fleksibilitas lebih: tipe kesalahan arbitrer, komposisi melalui flatMap, dan dukungan untuk pola fungsional.

Pustaka Arrow dan Either

Arrow — pustaka fungsional untuk Kotlin yang menambahkan Either, Option, Validated, dan tipe lainnya. Arrow.Either — sealed class dengan dua pewaris: ArrowCore.Left dan ArrowCore.Right. Pustaka juga menyediakan ekstensi untuk pekerjaan yang nyaman: .getOrElse(), .fold(), .mapLeft().

Contoh: Either dengan permintaan jaringan

Mari kita pertimbangkan skenario nyata — permintaan jaringan di aplikasi Android dengan kemungkinan kesalahan: tidak ada jaringan, kesalahan server, respons tidak valid. Either memungkinkan menggabungkan semua varian dalam satu tipe kembalian.

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 di Swift: perbedaan dari Result standar

Di Swift sejak versi 5.0, tipe bawaan Result telah muncul, yang secara konseptual mirip dengan Either, tetapi memiliki keterbatasan: kesalahan harus sesuai dengan protokol Error, dan nilai keberhasilan — satu tipe. Either di Swift diimplementasikan melalui enum dengan dua parameter generik.

Result standar versus Either

Result<Success, Failure> — tipe bawaan Swift, di mana Failure: Error. Either tidak membatasi tipe kesalahan, yang memungkinkan menyimpan String, struktur kustom, atau bahkan beberapa tipe kesalahan melalui enum bersarang.

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 }

Kapan menggunakan Either di aplikasi seluler

Either optimal untuk skenario yang memerlukan penanganan kesalahan eksplisit dan aman tipe tanpa pengecualian. Mari kita lihat kasus penggunaan utama dalam pengembangan seluler di Kotlin dan Swift.

  • Permintaan jaringan — setiap permintaan dapat mengembalikan kesalahan koneksi, server, atau parsing. Either mengumpulkan semua varian dalam satu tipe.
  • Validasi formulir — Either dengan tipe kesalahan kustom dengan mudah mewakili hasil pemeriksaan bidang input: email atau kata sandi tidak valid.
  • Repositori data — Either memungkinkan menggabungkan hasil dari berbagai sumber (cache, database, jaringan) dengan tipe kesalahan yang seragam.
  • Interpreter perintah — jika aplikasi mem-parsing input pengguna atau perintah, Either memberikan cara aman tipe untuk melaporkan kesalahan.

Jangan gunakan Either untuk operasi sederhana tanpa efek samping — nilai kembalian biasa lebih andal dan mudah dibaca. Either juga berlebihan ketika kegagalan adalah situasi luar biasa, bukan skenario yang diharapkan.

Either juga efektif saat bekerja dengan coroutine di Kotlin. Fungsi yang mengembalikan Either dapat dipanggil di dalam coroutine dengan penanganan kesalahan melalui fold atau mapLeft tanpa memblokir thread. Ini sangat berguna di aplikasi Android dengan arsitektur MVVM, di mana setiap repositori mengembalikan Either, dan ViewModel mengubah hasilnya menjadi UiState.

Kesalahan umum saat bekerja dengan Either

Pengembang yang baru pertama kali mengenal Either sering melakukan kesalahan serupa. Mari kita lihat yang paling umum dan cara menghindarinya.

  • Mengabaikan Left — memanggil .getOrElse() dengan nilai default tanpa menganalisis penyebab kesalahan menghilangkan makna penggunaan Either. Tangani kesalahan secara eksplisit.
  • Tipe kesalahan global — menggunakan String atau Exception sebagai tipe umum untuk semua Either dalam proyek mengurangi keamanan tipe. Buat sealed class domain.
  • Either bersarang — Either berulang di dalam Right (Either<E, Either<E, A>>) mempersulit pembacaan. Gunakan flatMap untuk meratakan.
  • Mencampur dengan pengecualian — fungsi mengembalikan Either, tetapi di dalamnya melempar pengecualian. Ini bertentangan dengan ide penanganan kesalahan eksplisit.

Pertanyaan yang Sering Diajukan

Apa perbedaan Either dengan Optional?

Optional mewakili ada atau tidaknya nilai (Some/None), tetapi tidak menyampaikan penyebab ketiadaan. Either memberikan dua tipe konkret — kiri untuk kesalahan dan kanan untuk keberhasilan, yang memungkinkan menyampaikan konteks kegagalan.

Bisakah Either digunakan di Java?

Di Java tidak ada Either bawaan, tetapi pustaka Vavr dan functionaljava menyediakan implementasi. Dalam pengembangan Android, Either dari Vavr adalah alternatif populer untuk gaya fungsional dengan lambda.

Kapan lebih baik menggunakan sealed class daripada Either?

Sealed class di Kotlin lebih nyaman ketika varian lebih dari dua atau memiliki struktur berbeda. Untuk hasil biner (kesalahan/keberhasilan) Either lebih ringkas dan menyediakan kombinator fungsional siap pakai.

Apakah Either mendukung multi-threading?

Either bersifat immutabel dan aman untuk thread secara default. Di Kotlin dengan coroutine, Either dapat dikombinasikan dengan baik: flatMap bekerja di dalam coroutine scope, dan penanganan kesalahan tidak memerlukan penguncian.

Haruskah Either digunakan untuk semua fungsi dalam proyek?

Tidak. Either cocok untuk operasi dengan kegagalan yang diharapkan (jaringan, validasi, logika bisnis). Untuk getter sederhana dan perhitungan tanpa efek samping, tipe biasa lebih mudah dibaca dan tidak menambah kompleksitas yang tidak perlu.

Kesimpulan

  • Either — tipe fungsional untuk merepresentasikan dua varian: Left (kesalahan) dan Right (keberhasilan), membuat penanganan kegagalan eksplisit di tingkat tipe.
  • Left dapat berisi tipe kesalahan arbitrer — dari String hingga sealed class domain, tidak seperti Result standar.
  • flatMap memastikan komposisi Either tanpa pemeriksaan bersarang: kesalahan secara otomatis merambat melalui seluruh rantai.
  • Arrow — pustaka Either utama untuk Kotlin dengan dukungan bawaan untuk coroutine dan ekstensi.
  • Swift menggunakan Result bawaan, tetapi Either diimplementasikan melalui enum dengan dua parameter generik untuk fleksibilitas penuh.
  • Terapkan Either untuk permintaan jaringan, validasi formulir, dan repositori — skenario dengan kesalahan yang diharapkan.
  • Hindari tipe kesalahan global, mengabaikan Left, dan Either bersarang — ini mengurangi manfaat keamanan tipe.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga