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 — 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.
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.
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.
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.
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.
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) }
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.
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().
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.
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 ?: ""))
}
}
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<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.
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 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.
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.
Pengembang yang baru pertama kali mengenal Either sering melakukan kesalahan serupa. Mari kita lihat yang paling umum dan cara menghindarinya.
Pertanyaan yang Sering Diajukan
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.
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.
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.
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.
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
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.
Baca juga