Either: สาระสำคัญ การใช้งาน และหลักการทำงาน

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-26 เวลาอ่าน: 8 นาที

Either เป็นชนิดฟังก์ชันที่แสดงค่าหนึ่งในสองรูปแบบที่เป็นไปได้: Left สำหรับข้อผิดพลาด และ Right สำหรับความสำเร็จ แตกต่างจากข้อยกเว้น Either ทำให้การจัดการข้อผิดพลาดชัดเจนในระดับชนิด และไม่ต้องใช้บล็อก try-catch ตาม Arrow, 2026 Either ถูกใช้อย่างแพร่หลายในโปรเจกต์ Kotlin เพื่อประกอบการดำเนินการที่อาจล้มเหลว โดยไม่มีผลข้างเคียง

ประเด็นสำคัญ

  • Either เป็นชนิดข้อมูลเชิงพีชคณิตสำหรับแสดงสองรูปแบบที่ไม่สามารถเกิดร่วมกันได้: Left (ข้อผิดพลาด) และ Right (ความสำเร็จ)
  • Left โดยทั่วไปมีข้อมูลข้อผิดพลาด Right มีค่าที่ถูกต้อง
  • การกำหนดชนิดอย่างชัดแจ้ง — Either บังคับให้จัดการทั้งสองรูปแบบในเวลาคอมไพล์ ลบความล้มเหลวที่ไม่คาดคิด
  • องค์ประกอบ — Either รองรับ map, flatMap และ fold สำหรับห่วงโซ่การแปลงโดยไม่ต้องตรวจสอบแบบซ้อน
  • ความแตกต่างจาก Result — Either สามารถเก็บชนิดข้อผิดพลาดตามอำเภอใจ ไม่ใช่แค่ Error หรือ Throwable

Either คืออะไร?

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 ประกอบด้วยชนิดย่อยสองชนิด: Left และ Right อินสแตนซ์ของ Either สามารถเป็นเพียงหนึ่งในนั้นในเวลาใดก็ตาม ลายเซ็นทั่วไปใน Kotlin คือ Either<E, A> โดยที่ E คือชนิดข้อผิดพลาด และ A คือชนิดค่าสำเร็จ

ชนิด Left: ตัวเก็บข้อผิดพลาด

Left แสดงถึงกรณีความล้มเหลว 不同于ข้อยกเว้น Left ไม่ขัดจังหวะโฟลว์การทำงาน — มันเพียงคืนค่าที่ต้องจัดการ ชนิดข้อผิดพลาดสามารถเป็นอะไรก็ได้: String, Int, sealed class ที่กำหนดเอง หรือโมเดลโดเมน

ชนิด Right: ตัวเก็บความสำเร็จ

Right มีผลลัพธ์ที่ถูกต้องของการดำเนินการ ชื่อสะท้อนถึงความถูกต้อง — ตามข้อตกลง Right หมายถึงความสำเร็จ การแปลงเช่น map และ flatMap ถูกใช้กับ Right ทำให้สามารถสร้างห่วงโซ่การคำนวณโดยไม่ต้องตรวจสอบแต่ละขั้นตอน

องค์ประกอบของ Either ด้วย flatMap

flatMap เป็นกลไกหลักขององค์ประกอบของ Either หากค่าปัจจุบันเป็น Right flatMap จะใช้ฟังก์ชันที่ส่งเข้าไปและคืนค่า Either ใหม่ หากเป็น Left flatMap จะข้ามการแปลงและส่งต่อข้อผิดพลาด พฤติกรรมนี้เรียกว่าการประเมินแบบลัดวงจร

นอกเหนือจาก flatMap แล้ว Either ยังรองรับ mapLeft สำหรับการแปลงข้อผิดพลาด fold สำหรับจัดการทั้งสองรูปแบบในที่เดียว และ getOrElse สำหรับดึงค่าด้วยค่าเริ่มต้น ฟังก์ชันเหล่านี้ครอบคลุมทุกสถานการณ์: ตั้งแต่การดึงค่าอย่างง่ายไปจนถึงองค์ประกอบที่ซับซ้อนด้วยการเรียกแบบอะซิงโครนัสในโครูทีน Kotlin หรือ Combine ใน Swift

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

Either ใน Kotlin: การประยุกต์ใช้ในทางปฏิบัติ

ในระบบนิเวศ Kotlin Either ถูกนำไปใช้ในไลบรารี Arrow ไลบรารีมาตรฐานของ Kotlin มี Result แต่ Either ให้ความยืดหยุ่นมากกว่า: ชนิดข้อผิดพลาดตามอำเภอใจ องค์ประกอบผ่าน flatMap และการรองรับรูปแบบเชิงฟังก์ชัน

ไลบรารี Arrow และ Either

Arrow เป็นไลบรารีเชิงฟังก์ชันสำหรับ Kotlin ที่เพิ่ม Either, Option, Validated และชนิดอื่น ๆ Arrow.Either เป็น sealed class ที่มีคลาสย่อยสองคลาส: ArrowCore.Left และ ArrowCore.Right ไลบรารียังมีส่วนขยายที่สะดวก: .getOrElse(), .fold(), .mapLeft()

ตัวอย่าง: Either กับคำขอเครือข่าย

พิจารณาสถานการณ์จริง — คำขอเครือข่ายในแอป Android ที่อาจมีข้อผิดพลาด: ไม่มีเครือข่าย ข้อผิดพลาดเซิร์ฟเวอร์ การตอบสนองไม่ถูกต้อง Either ช่วยให้รวมทุกรูปแบบเป็นชนิดส่งคืนเดียว

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 ใน Swift: ความแตกต่างจาก Result มาตรฐาน

ใน Swift ตั้งแต่เวอร์ชัน 5.0 เป็นต้นมา มีชนิด Result ในตัว ซึ่งแนวคิดคล้ายกับ Either แต่มีข้อจำกัด: ข้อผิดพลาดต้องสอดคล้องกับโพรโทคอล Error และค่าสำเร็จต้องเป็นชนิดเดียว Either ใน Swift ถูกนำไปใช้ผ่าน enum ที่มีพารามิเตอร์เจนเนอริกสองตัว

Result มาตรฐานเทียบกับ Either

Result<Success, Failure> เป็นชนิดในตัวของ Swift โดยที่ Failure: Error Either ไม่กำหนดข้อจำกัดเกี่ยวกับชนิดข้อผิดพลาด ทำให้สามารถเก็บ String โครงสร้างที่กำหนดเอง หรือแม้แต่ชนิดข้อผิดพลาดหลายชนิดผ่าน enum ที่ซ้อนกัน

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 }

เมื่อใดควรใช้ Either ในแอปมือถือ

Either เหมาะที่สุดสำหรับสถานการณ์ที่ต้องการจัดการข้อผิดพลาดอย่างชัดแจ้งและปลอดภัยชนิดโดยไม่มีข้อยกเว้น พิจารณากรณีการใช้งานหลักในการพัฒนาแอปมือถือด้วย Kotlin และ Swift

  • คำขอเครือข่าย — แต่ละคำขออาจคืนค่าข้อผิดพลาดการเชื่อมต่อ เซิร์ฟเวอร์ หรือการแยกวิเคราะห์ Either รวบรวมทุกรูปแบบเป็นชนิดเดียว
  • การตรวจสอบฟอร์ม — Either ที่มีชนิดข้อผิดพลาดแบบกำหนดเองแสดงผลลัพธ์การตรวจสอบฟิลด์อินพุตได้สะดวก: อีเมลหรือรหัสผ่านไม่ถูกต้อง
  • พื้นที่เก็บข้อมูล — Either ช่วยให้รวมผลลัพธ์จากแหล่งต่าง ๆ (แคช, DB, เครือข่าย) ด้วยชนิดข้อผิดพลาดแบบรวม
  • ตัวแปลคำสั่ง — หากแอปแยกวิเคราะห์อินพุตหรือคำสั่งผู้ใช้ Either ให้วิธีที่ปลอดภัยชนิดในการรายงานข้อผิดพลาด

อย่าใช้ Either สำหรับการดำเนินการง่าย ๆ ที่ไม่มีผลข้างเคียง — ค่าส่งคืนปกติเชื่อถือได้มากกว่าและอ่านง่ายกว่า Either ยังมากเกินไปเมื่อความล้มเหลวเป็นสถานการณ์พิเศษ ไม่ใช่สถานการณ์ที่คาดหวัง

Either ยังมีประสิทธิภาพเมื่อทำงานกับโครูทีนใน Kotlin ฟังก์ชันที่คืนค่า Either สามารถเรียกภายในโครูทีนด้วยการจัดการข้อผิดพลาดผ่าน fold หรือ mapLeft โดยไม่บล็อกเธรด ซึ่งมีประโยชน์อย่างยิ่งในแอป Android ที่มีสถาปัตยกรรม MVVM ซึ่งแต่ละพื้นที่เก็บข้อมูลคืนค่า Either และ ViewModel แปลงผลลัพธ์เป็น UiState

ข้อผิดพลาดทั่วไปเมื่อทำงานกับ Either

นักพัฒนาที่เพิ่งรู้จักกับ Either มักทำข้อผิดพลาดคล้ายกัน มาดูข้อผิดพลาดที่พบบ่อยที่สุดและวิธีหลีกเลี่ยงกัน

  • การละเลย Left — การเรียก .getOrElse() ด้วยค่าเริ่มต้นโดยไม่วิเคราะห์สาเหตุของข้อผิดพลาดทำให้การใช้ Either ไร้ความหมาย จัดการข้อผิดพลาดอย่างชัดแจ้ง
  • ชนิดข้อผิดพลาดทั่วโลก — การใช้ String หรือ Exception เป็นชนิดร่วมสำหรับ Either ทั้งหมดในโปรเจกต์ลดความปลอดภัยของชนิด สร้าง sealed class โดเมน
  • Either ซ้อนกัน — Either ภายใน Right (Either<E, Either<E, A>>) ทำให้การอ่านซับซ้อน ใช้ flatMap เพื่อทำให้ราบเรียบ
  • การผสมกับข้อยกเว้น — ฟังก์ชันคืนค่า Either แต่ภายในโยนข้อยกเว้น ซึ่งขัดแย้งกับแนวคิดการจัดการข้อผิดพลาดอย่างชัดแจ้ง

คำถามที่พบบ่อย

Either แตกต่างจาก Optional อย่างไร?

Optional แสดงถึงการมีหรือไม่มีค่า (Some/None) แต่ไม่บอกสาเหตุของการไม่มี Either ให้ชนิดเฉพาะสองชนิด — ซ้ายสำหรับข้อผิดพลาดและขวาสำหรับความสำเร็จ — ซึ่งอนุญาตให้ส่งต่อบริบทของความล้มเหลว

สามารถใช้ Either ใน Java ได้หรือไม่?

ใน Java ไม่มี Either ในตัว แต่ไลบรารี Vavr และ functionaljava มีการนำไปใช้ ในการพัฒนา Android Either จาก Vavr เป็นทางเลือกยอดนิยมสำหรับสไตล์เชิงฟังก์ชันกับ lambda

เมื่อใดควรใช้ sealed class แทน Either?

Sealed class ใน Kotlin สะดวกกว่าเมื่อมีมากกว่าสองรูปแบบหรือมีโครงสร้างต่างกัน สำหรับผลลัพธ์แบบทวิภาค (ข้อผิดพลาด/ความสำเร็จ) Either กระทัดรัดกว่าและมีตัวรวมเชิงฟังก์ชันพร้อมใช้

Either รองรับมัลติเธรดดิ้งหรือไม่?

Either ไม่เปลี่ยนรูปและปลอดภัยต่อเธรดโดยค่าเริ่มต้น ใน Kotlin กับโครูทีน Either รวมกันได้อย่างสมบูรณ์: flatMap ทำงานภายในขอบเขตโครูทีนและการจัดการข้อผิดพลาดไม่ต้องใช้ล็อค

ควรใช้ Either สำหรับทุกฟังก์ชันในโปรเจกต์หรือไม่?

ไม่ Either เหมาะสำหรับการดำเนินการที่มีความล้มเหลวที่คาดหวัง (เครือข่าย การตรวจสอบ ตรรกะธุรกิจ) สำหรับ getter ง่าย ๆ และการคำนวณที่ไม่มีผลข้างเคียง ชนิดปกติอ่านง่ายกว่าและไม่เพิ่มความซับซ้อนที่ไม่จำเป็น

สรุป

  • Either เป็นชนิดฟังก์ชันสำหรับแสดงสองรูปแบบ: Left (ข้อผิดพลาด) และ Right (ความสำเร็จ) ทำให้การจัดการข้อผิดพลาดชัดเจนในระดับชนิด
  • Left สามารถเก็บชนิดข้อผิดพลาดตามอำเภอใจ — ตั้งแต่ String ถึง sealed class โดเมน แตกต่างจาก Result มาตรฐาน
  • flatMap ทำให้องค์ประกอบของ Either เป็นไปได้โดยไม่ต้องตรวจสอบแบบซ้อน: ข้อผิดพลาดกระจายโดยอัตโนมัติผ่านห่วงโซ่ทั้งหมด
  • Arrow เป็นไลบรารี Either หลักสำหรับ Kotlin ที่มีรองรับโครูทีนในตัวและส่วนขยาย
  • Swift ใช้ Result ในตัว แต่ Either สามารถนำไปใช้ผ่าน enum ที่มีพารามิเตอร์เจนเนอริกสองตัวเพื่อความยืดหยุ่นเต็มที่
  • ใช้ Either สำหรับ คำขอเครือข่าย การตรวจสอบฟอร์ม และพื้นที่เก็บข้อมูล — สถานการณ์ที่มีข้อผิดพลาดที่คาดหวัง
  • หลีกเลี่ยง ชนิดข้อผิดพลาดทั่วโลก การละเลย Left และ Either ซ้อนกัน — สิ่งนี้ลดข้อดีของความปลอดภัยของชนิด

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม