Either เป็นชนิดฟังก์ชันที่แสดงค่าหนึ่งในสองรูปแบบที่เป็นไปได้: Left สำหรับข้อผิดพลาด และ Right สำหรับความสำเร็จ แตกต่างจากข้อยกเว้น Either ทำให้การจัดการข้อผิดพลาดชัดเจนในระดับชนิด และไม่ต้องใช้บล็อก try-catch ตาม Arrow, 2026 Either ถูกใช้อย่างแพร่หลายในโปรเจกต์ Kotlin เพื่อประกอบการดำเนินการที่อาจล้มเหลว โดยไม่มีผลข้างเคียง
ประเด็นสำคัญ
Either เป็นชนิดข้อมูลเชิงพีชคณิต ที่ยืมมาจากการเขียนโปรแกรมเชิงฟังก์ชัน ซึ่งแสดงค่าหนึ่งในสองชนิดที่เป็นไปได้ ในบริบทของการจัดการข้อผิดพลาด ข้อตกลงคือ: ชนิด Left (Left) มีคำอธิบายปัญหา ในขณะที่ชนิด Right (Right) มีผลลัพธ์ที่สำเร็จ
แนวคิดของ Either มาจากภาษา Haskell และหมวดหมู่ชนิด Either a b โดยที่ a คือชนิดของค่าซ้าย และ b คือชนิดของค่าขวา ในการพัฒนาแอปมือถือ Either ได้รับความนิยมด้วยไลบรารี Arrow สำหรับ Kotlin และแนวทางเชิงฟังก์ชันใน Swift
ข้อได้เปรียบหลักของ Either เหนือข้อยกเว้นคือ ไม่มีเส้นทางการทำงานที่ซ่อนอยู่ ฟังก์ชันที่คืนค่า Either ประกาศอย่างชัดเจนในลายเซ็นว่าอาจล้มเหลว คอมไพเลอร์ตรวจสอบว่าทั้งสองรูปแบบได้รับการจัดการแล้ว
แตกต่างจากการโยนข้อยกเว้น Either รักษา ความโปร่งใสของโฟลว์ข้อมูล การเรียกฟังก์ชันที่คืนค่า Either ไม่ต้องใช้ try-catch ฝั่งผู้เรียก — pattern-matching หรือ fold ก็เพียงพอ ซึ่งสำคัญอย่างยิ่งในสถาปัตยกรรมที่มีแนวทางเชิงปฏิกิริยา ซึ่งแต่ละแหล่งข้อมูลคืนค่า Either และห่วงโซ่การแปลงถูกสร้างขึ้นผ่าน map และ flatMap
Either ประกอบด้วยชนิดย่อยสองชนิด: Left และ Right อินสแตนซ์ของ Either สามารถเป็นเพียงหนึ่งในนั้นในเวลาใดก็ตาม ลายเซ็นทั่วไปใน Kotlin คือ Either<E, A> โดยที่ E คือชนิดข้อผิดพลาด และ A คือชนิดค่าสำเร็จ
Left แสดงถึงกรณีความล้มเหลว 不同于ข้อยกเว้น Left ไม่ขัดจังหวะโฟลว์การทำงาน — มันเพียงคืนค่าที่ต้องจัดการ ชนิดข้อผิดพลาดสามารถเป็นอะไรก็ได้: String, Int, sealed class ที่กำหนดเอง หรือโมเดลโดเมน
Right มีผลลัพธ์ที่ถูกต้องของการดำเนินการ ชื่อสะท้อนถึงความถูกต้อง — ตามข้อตกลง Right หมายถึงความสำเร็จ การแปลงเช่น map และ flatMap ถูกใช้กับ Right ทำให้สามารถสร้างห่วงโซ่การคำนวณโดยไม่ต้องตรวจสอบแต่ละขั้นตอน
flatMap เป็นกลไกหลักขององค์ประกอบของ Either หากค่าปัจจุบันเป็น Right flatMap จะใช้ฟังก์ชันที่ส่งเข้าไปและคืนค่า Either ใหม่ หากเป็น Left flatMap จะข้ามการแปลงและส่งต่อข้อผิดพลาด พฤติกรรมนี้เรียกว่าการประเมินแบบลัดวงจร
นอกเหนือจาก flatMap แล้ว Either ยังรองรับ mapLeft สำหรับการแปลงข้อผิดพลาด fold สำหรับจัดการทั้งสองรูปแบบในที่เดียว และ getOrElse สำหรับดึงค่าด้วยค่าเริ่มต้น ฟังก์ชันเหล่านี้ครอบคลุมทุกสถานการณ์: ตั้งแต่การดึงค่าอย่างง่ายไปจนถึงองค์ประกอบที่ซับซ้อนด้วยการเรียกแบบอะซิงโครนัสในโครูทีน Kotlin หรือ Combine ใน Swift
fun parseInt(input: String): Either<String, Int> =
input.toIntOrNull()?.let { Right(it) }
?: Left("ไม่สามารถแปลง: $input")
fun divide(a: Int, b: Int): Either<String, Int> =
if (b == 0) Left("หารด้วยศูนย์")
else Right(a / b)
val result = parseInt("10")
.flatMap { divide(it, 2) }
ในระบบนิเวศ Kotlin Either ถูกนำไปใช้ในไลบรารี Arrow ไลบรารีมาตรฐานของ Kotlin มี Result แต่ Either ให้ความยืดหยุ่นมากกว่า: ชนิดข้อผิดพลาดตามอำเภอใจ องค์ประกอบผ่าน flatMap และการรองรับรูปแบบเชิงฟังก์ชัน
Arrow เป็นไลบรารีเชิงฟังก์ชันสำหรับ Kotlin ที่เพิ่ม Either, Option, Validated และชนิดอื่น ๆ Arrow.Either เป็น sealed class ที่มีคลาสย่อยสองคลาส: ArrowCore.Left และ ArrowCore.Right ไลบรารียังมีส่วนขยายที่สะดวก: .getOrElse(), .fold(), .mapLeft()
พิจารณาสถานการณ์จริง — คำขอเครือข่ายในแอป Android ที่อาจมีข้อผิดพลาด: ไม่มีเครือข่าย ข้อผิดพลาดเซิร์ฟเวอร์ การตอบสนองไม่ถูกต้อง Either ช่วยให้รวมทุกรูปแบบเป็นชนิดส่งคืนเดียว
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 ?: ""))
}
}
ใน Swift ตั้งแต่เวอร์ชัน 5.0 เป็นต้นมา มีชนิด Result ในตัว ซึ่งแนวคิดคล้ายกับ Either แต่มีข้อจำกัด: ข้อผิดพลาดต้องสอดคล้องกับโพรโทคอล Error และค่าสำเร็จต้องเป็นชนิดเดียว Either ใน Swift ถูกนำไปใช้ผ่าน enum ที่มีพารามิเตอร์เจนเนอริกสองตัว
Result<Success, Failure> เป็นชนิดในตัวของ Swift โดยที่ Failure: Error Either ไม่กำหนดข้อจำกัดเกี่ยวกับชนิดข้อผิดพลาด ทำให้สามารถเก็บ String โครงสร้างที่กำหนดเอง หรือแม้แต่ชนิดข้อผิดพลาดหลายชนิดผ่าน enum ที่ซ้อนกัน
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 เหมาะที่สุดสำหรับสถานการณ์ที่ต้องการจัดการข้อผิดพลาดอย่างชัดแจ้งและปลอดภัยชนิดโดยไม่มีข้อยกเว้น พิจารณากรณีการใช้งานหลักในการพัฒนาแอปมือถือด้วย Kotlin และ Swift
อย่าใช้ Either สำหรับการดำเนินการง่าย ๆ ที่ไม่มีผลข้างเคียง — ค่าส่งคืนปกติเชื่อถือได้มากกว่าและอ่านง่ายกว่า Either ยังมากเกินไปเมื่อความล้มเหลวเป็นสถานการณ์พิเศษ ไม่ใช่สถานการณ์ที่คาดหวัง
Either ยังมีประสิทธิภาพเมื่อทำงานกับโครูทีนใน Kotlin ฟังก์ชันที่คืนค่า Either สามารถเรียกภายในโครูทีนด้วยการจัดการข้อผิดพลาดผ่าน fold หรือ mapLeft โดยไม่บล็อกเธรด ซึ่งมีประโยชน์อย่างยิ่งในแอป Android ที่มีสถาปัตยกรรม MVVM ซึ่งแต่ละพื้นที่เก็บข้อมูลคืนค่า Either และ ViewModel แปลงผลลัพธ์เป็น UiState
นักพัฒนาที่เพิ่งรู้จักกับ Either มักทำข้อผิดพลาดคล้ายกัน มาดูข้อผิดพลาดที่พบบ่อยที่สุดและวิธีหลีกเลี่ยงกัน
คำถามที่พบบ่อย
Optional แสดงถึงการมีหรือไม่มีค่า (Some/None) แต่ไม่บอกสาเหตุของการไม่มี Either ให้ชนิดเฉพาะสองชนิด — ซ้ายสำหรับข้อผิดพลาดและขวาสำหรับความสำเร็จ — ซึ่งอนุญาตให้ส่งต่อบริบทของความล้มเหลว
ใน Java ไม่มี Either ในตัว แต่ไลบรารี Vavr และ functionaljava มีการนำไปใช้ ในการพัฒนา Android Either จาก Vavr เป็นทางเลือกยอดนิยมสำหรับสไตล์เชิงฟังก์ชันกับ lambda
Sealed class ใน Kotlin สะดวกกว่าเมื่อมีมากกว่าสองรูปแบบหรือมีโครงสร้างต่างกัน สำหรับผลลัพธ์แบบทวิภาค (ข้อผิดพลาด/ความสำเร็จ) Either กระทัดรัดกว่าและมีตัวรวมเชิงฟังก์ชันพร้อมใช้
Either ไม่เปลี่ยนรูปและปลอดภัยต่อเธรดโดยค่าเริ่มต้น ใน Kotlin กับโครูทีน Either รวมกันได้อย่างสมบูรณ์: flatMap ทำงานภายในขอบเขตโครูทีนและการจัดการข้อผิดพลาดไม่ต้องใช้ล็อค
ไม่ Either เหมาะสำหรับการดำเนินการที่มีความล้มเหลวที่คาดหวัง (เครือข่าย การตรวจสอบ ตรรกะธุรกิจ) สำหรับ getter ง่าย ๆ และการคำนวณที่ไม่มีผลข้างเคียง ชนิดปกติอ่านง่ายกว่าและไม่เพิ่มความซับซ้อนที่ไม่จำเป็น
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม