0Pricing
Kotlin Academy · บทเรียน

Arrow Raise DSL: การประกอบข้อผิดพลาดแบบมีชนิด

ใช้บริบท Raise ของ Arrow และ raise() เพื่อประกอบลำดับการทำงานที่มีข้อผิดพลาดหลายรายการอย่างเป็นระเบียบ

Arrow Raise DSL: การประกอบข้อผิดพลาดแบบมีชนิด เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

ข้อจำกัดของการเชื่อม Either

การเชื่อม Either ด้วย flatMap จะสร้างแลมบ์ดาที่ซ้อนกันลึกเมื่อมีการดำเนินการต่อเนื่องหลายขั้นตอน Raise DSL ของ Arrow (เริ่มมีใน Arrow 1.2) จึงมีรูปแบบไวยากรณ์ที่สะอาดกว่าและคล้ายโครูทีน โดยใช้ context receiver หรือฟังก์ชันส่วนขยายของ Kotlin

Raise<E> คืออะไร

Raise เป็นบริบทที่สามารถ raise (หยุดการทำงานทันทีพร้อมส่งต่อ) ข้อผิดพลาดชนิด E ได้ ฟังก์ชันที่อาจล้มเหลวจะเรียก raise(error) เพื่อยกเลิกและส่งต่อข้อผิดพลาด ซึ่งคล้ายกับการโยนข้อยกเว้นแต่ไม่ใช้ข้อยกเว้น

ตัวสร้าง either { }

ตัวสร้าง either { } จะสร้าง Either จากบล็อกที่มี Raise อยู่ในขอบเขต ภายในบล็อก ให้เรียก raise(error) เมื่อล้มเหลว หรือคืนค่าโดยตรงเมื่อสำเร็จ:

import arrow.core.raise.either
import arrow.core.raise.Raise

fun validateAge(age: Int): Either<String, Int> = either {
    if (age < 0) raise("Age cannot be negative")
    if (age > 150) raise("Age too large")
    age
}

bind() — แกะค่า Either ภายใน either{}

ภายในบล็อก either { } ให้เรียก .bind() กับค่า Either ใด ๆ เพื่อแกะค่าออกมา หากค่านั้นเป็น Left bind() จะเรียก raise และหยุดบล็อกทันทีโดยอัตโนมัติ:

fun createUser(name: String, age: Int): Either<String, User> = either {
    val validName = validateName(name).bind()  // raises if Left
    val validAge  = validateAge(age).bind()    // raises if Left
    User(validName, validAge)                  // only reached if both succeed
}

ensure() — ตรวจสอบเงื่อนไขแบบแทรกในบรรทัด

ensure(condition) { error } เป็นรูปแบบย่อของ if (!condition) raise(error) ช่วยให้ตรรกะการตรวจสอบกระชับ:

fun validateEmail(email: String): Either<String, String> = either {
    ensure(email.contains("@")) { "Email must contain @" }
    ensure(email.length <= 255) { "Email too long" }
    email
}

ensureNotNull() — ตรวจสอบค่าว่างด้วย Raise

ensureNotNull(value) { error } จะแกะค่าที่อาจเป็นค่าว่างออกมา หรือเรียก raise หากค่านั้นเป็นค่าว่าง:

fun findUser(id: Long, repo: UserRepo): Either<UserError, User> = either {
    ensureNotNull(repo.findById(id)) { UserError.NotFound(id) }
}

Raise ด้วย Context Receiver (Arrow 1.2 ขึ้นไป)

คุณสามารถประกาศฟังก์ชันที่ต้องการบริบท Raise ได้โดยตรง โดยไม่ต้องห่อฟังก์ชันด้วย either { }:

context(Raise<String>)
fun requirePositive(n: Int): Int {
    ensure(n > 0) { "Must be positive" }
    return n
}

// Called inside either { }
val result = either { requirePositive(-1) }  // Left("Must be positive")

การสะสมข้อผิดพลาดด้วย zipOrAccumulate

ตามค่าเริ่มต้น Raise จะหยุดทำงานเมื่อพบข้อผิดพลาดแรก ใช้ zipOrAccumulate() เพื่อเรียกใช้การตรวจสอบหลายรายการและรวบรวมข้อผิดพลาดทั้งหมดไว้ใน NonEmptyList:

val result: Either<NonEmptyList<String>, User> = either {
    zipOrAccumulate(
        { validateName(name).bind() },
        { validateAge(age).bind() }
    ) { validName, validAge -> User(validName, validAge) }
}

recover { } — การจัดการข้อผิดพลาดเฉพาะรายการ

ใช้ recover { error -> ... } ภายใน either { } เพื่อจัดการข้อผิดพลาดที่ถูก raise เฉพาะรายการและกำหนดค่า fallback จากนั้นจึงทำการคำนวณต่อ:

val name: String = either {
    findUser(0L).bind().name
}.recover { error ->
    if (error == UserError.NotFound) "Guest" else raise(error)
}.getOrNull() ?: "Guest"

Raise เทียบกับการเชื่อม Either: ควรใช้แบบใด

ใช้ either { }.bind() สำหรับลำดับการทำงานเชิงเส้นที่มีหลายขั้นตอนต่อเนื่อง เพราะอ่านได้เหมือนโค้ดเชิงคำสั่งแต่ยังคงบริสุทธิ์ ใช้การเชื่อมด้วย flatMap สำหรับองค์ประกอบสั้น ๆ สองขั้นตอน หรือเมื่อต้องเชื่อมกับไลบรารีเชิงฟังก์ชันอื่น

การทดสอบฟังก์ชันที่ใช้ Raise

ทดสอบโดยเรียกฟังก์ชันภายใน either { } แล้วตรวจสอบผลลัพธ์ ตัวจับคู่ของ Kotest อย่าง shouldBeLeft() และ shouldBeRight() ใน Arrow ช่วยให้การตรวจสอบกระชับ:

import arrow.core.shouldBeLeft
import arrow.core.shouldBeRight

@Test
fun `negative age returns Left`() {
    validateAge(-1).shouldBeLeft()
}

@Test
fun `valid age returns Right`() {
    validateAge(25).shouldBeRight(25)
}

ตรวจสอบความเข้าใจ

ภายในบล็อก either { } การเรียก .bind() กับค่า Either.Left จะทำอะไร

สรุป: Arrow Raise DSL

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

  • either { } สร้าง Either จากบล็อกที่มี Raise อยู่ในขอบเขต
  • .bind() แกะค่า Either และหยุดการทำงานทันทีเมื่อพบ Left
  • ensure(condition) { error } และ ensureNotNull(value) { error } ใช้สำหรับการตรวจสอบแบบแทรกในบรรทัด
  • zipOrAccumulate() ใช้รวบรวมข้อผิดพลาดหลายรายการแทนการหยุดทำงานทันที
  • อ่านได้เหมือนโค้ดเชิงคำสั่ง แต่ยังคงเป็นฟังก์ชันบริสุทธิ์

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

บทเรียน “Arrow Raise DSL: การประกอบข้อผิดพลาดแบบมีชนิด” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “Arrow Raise DSL: การประกอบข้อผิดพลาดแบบมีชนิด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “Arrow Raise DSL: การประกอบข้อผิดพลาดแบบมีชนิด”

ใช้บริบท Raise ของ Arrow และ raise() เพื่อประกอบลำดับการทำงานที่มีข้อผิดพลาดหลายรายการอย่างเป็นระเบียบ คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “Arrow Raise DSL: การประกอบข้อผิดพลาดแบบมีชนิด” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม

ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. Either : การจัดการข้อผิดพลาดตามชนิดโดยไม่ใช้ Exception
  2. Arrow Raise DSL: การประกอบข้อผิดพลาดแบบมีชนิด
  3. Option และ Nullable: ควรใช้แต่ละแบบเมื่อใด
  4. การสร้างแบบจำลองโดเมนเชิงฟังก์ชันด้วยชนิดหลักของ Arrow
← กลับไปที่ Kotlin Academy