รู้จักกับ Arrow Types ของ Arrow-kt ที่ใช้งานบ่อยๆกับ Kotlin
สำหรับ Kotlin แฟนแล้ว หลายคนอาจจะรู้กับ Arrow หรือ Arrow-kt กันมาบ้างแล้ว ซึ้ง Arrow เป็น functional programming library สำหรับภาษา kotlin ซึ่งเกิดมาจากการ fusion ระหว่าง functional programming library สำหรับ Kotlin 2 ตัว คือ funKTionale และ funKTionale
ถึงแม้ Kotlin จะไม่ใช่ pure functional programming language เราก็สามารถใช้ Arrow ในการเพิ่มความสามารถและ features ต่างๆ ที่ช่วยให้เราเขียน code ให้มีความเป็น functional ได้ง่ายมากยิ่งขึ้น และยังช่วยให้ code สามารถทำความเข้าใจและ maintain ได้ง่ายมากยิ่งขึ้นด้วย สำหรับบทความนี้เราจะมาทำความรู้จักกับพื้นฐาน data types ที่ใช้งานบ่อยๆ สำหรับใช้งานกับ functional programming ซึ่งจะอยู่ใน arrow-core นั้นเองครับ
Basic Setup
สำหรับการ setup ของ Arrow นั้นก็แสนจะง่ายดาย เพียงแค่เราทำการเพิ่ม dependencies เข้าไปใน project ก็สามารถใช้งาน Arrow ได้ทันที
— gradle
compile ("io.arrow-kt:arrow-core:0.9.0")
— maven
<dependency>
<groupId>io.arrow-kt</groupId>
<artifactId>arrow-core</artifactId>
<version>0.9.0</version>
</dependency>
Option
Option เป็น Algebraic Data Typs เป็น type พิเศษที่ใช้แทน data types อื่นๆที่เป็น subtypes โดยปกติแล้วเราจะใช้ Option แสดงถึงการไม่มีอยู่ (absence) ของ value เช่น ในตอนที่เรา query ข้อมูลจาก database การจะได้ค่า return ที่เป็น null หรือได้ throw NotFound exception อะไรสักอย่าง ด้วย Option เราสามารถ return None แทนการไม่มีอยู่ของข้อมูลแทนและใช้ Some(value) แทนการมีอยู่ของข้อมูล
Option data type ของ Arrow มีรูปแบบเหมือนกันกับที่ภาษา Scala, Haskell และ Java ที่ใช้ในการจัดการกับ Optional values
สำหรับรูปแบบในการสร้าง Option นั้น สามารถทำได้หลากหลายวิธี เช่น
รูปแบบในการ extract value ของ Option นั้น ก็สามารถทำได้หลากหลายวิธี เช่น
Extract โดยใช้ when
เรายังสามารถใช้ operation fold ในการ extract value ได้ด้วย
นอกจากนั้น ใน Option เรายังสามารถใช้งาน operation map ในการ map inner value เป็น type อื่นๆได้อีกด้วย ในกรณีที่ Option เป็น present (การมีอยู่ของข้อมูล)
operation flatmap
Tips
ใช้ Option เมื่อ value สามารถที่จะเป็นได้ทั้ง present หรือ absent โดยไม่สนใจสาเหตุของการ absent ของข้อมูล โดยปกติแล้ว จะใช้กับการดึงข้อมูลหรือการทำ validation
Either
Either เป็น Algebraic Data Types อีกตัวนึงที่ design มาเพื่อใช้ในการหุ้ม left value หรือ right value โดยจะไม่สามารถมีทั้ง left value และ right value ในเวลาเดียวกัน ในการใช้งาน Option การจัดการกับ failure นั้นก็สะดวกมากๆ แต่ในการณีที่เราต้องการข้อมูลเพิ่มเติมเกี่ยวกับ failure นั้น การใช้งาน Option ดูจะไม่เพียงพอ ในกรณีนี้ Either สามารถใช้งานแทนได้ โดยปกติแล้ว เราจะใช้ Either กับ code ที่มีการ return ประเภท exception หรือ result ของ function โดยตามหลักทั่วไปของ functional convention นั้น ฝั่ง left ของ Either จะเป็น exception หรือ error (ถ้ามี exception เกิดขึ้น) และฝั่ง right ของ Either จะเป็น successful result
ในการสร้าง Either นั้น สามารถทำได้หลายวิธี เช่น
การ extract Either ก็สามารถทำได้หลายวิธี เช่น
Extract โดยใช้ when
Extract โดยใช้ operation fold
ยังสามารถใช้งาน operation map ได้ด้วย
operation flatmap
Tips
ใช้ Either ใน use case ที่เหมือนกันกับ Option แต่ว่าเราสนใจ information เกี่ยวกับ error ที่เกิดขึ้นด้วย
Try
จากที่เราได้รู้จัก Option ที่ใช้งานการจัดการกับการขาดหายของข้อมูล และมี Either ที่ใช้ในการจัดการกับ return ของ successful result หรือ failed result
ถึงตอนนี้เราก็มี Try data type อีกตัวที่เหมือนกับ Either ที่มี 2 รูปแบบเหมือนกัน คือ Success[T] สำหรับกรณี successful และ Failure[T] ในกรณีที่เกิด failure แต่สิ่งที่ Either และ Try มีความแตกต่างกันคือ Try จะใช้ในการณีที่ computation มี successful result หรือเกิด exception ในกรณีที่เกิด failure และในกรณี failure นั้น จะสามารถเป็นได้แค่ type Throwable เท่านั้น โดยปกติแล้ว เราจะใช้ Try แทนการใช้งาน try/catch block ก็คือเอาไว้ใช้ในการทำ Exception Handling นั้นเองครับ
จาก function ด้านบน วิธีในการ control ในกรณีที่ parse String เป็น Int นั้น เราจะใช้ try/catch block ในการ control เช่น
แต่ด้วย Try แล้ว เราสามารถเรียก function ที่อาจจะเกิด error ด้วยวิธีที่ clean กว่า เช่น
เราสามารถ extract Try ได้หลายวิธี ด้วย getOrDefault เราสามารถให้ default value สำหรับ return ได้
หรือเราสามารถใช้ failure ในการกำหนด default value ได้ด้วย getOrElse
นอกจากนี้ Try ยังมี functions อื่นๆให้เรียกใช้งานอีกมากมาย เช่น filter, exists, fold, getOrDefault, getOrElse, isFailure, isSuccess, map, flatMap, onFailure, onSuccess, orElse, recover, recoverWith, toEither, และ toOption เป็นต้น
Tips
ใช้ Try เมื่อ เรียกใช้งาน function ที่อาจจะเกิด error ที่เราไม่สามารถ handle ได้ เราสามารถใช้ Try ช่วยในการ handle error ที่อาจจะเกิดขึ้น
Conclusion
Arrow-kt เป็น library ช่วยให้เราใช้งาน functional features ได้อย่างสะดวก ด้วย Arrow data types ใน arrow-core แล้ว เราสามารถใช้งาน functional features ใน Kotlin ได้ง่าย เราสามารถใช้ Option, Either, Try และอื่นๆ เราสามารถ functional style control และ error handling อย่างสะดวก ในบทความนี้กล่าวถึง Arrow data types ที่ใช้งานบ่อยๆเพียง 3 แบบเท่านั้น ยังมี data types อื่นๆให้เราเลือกใช้งานอีกหลายแบบ เช่น Id, Validated, Eval และ Ior เป็นต้น สำหรับผู้ที่สนใจศึกษาเพิ่มเติม สามารถหาอ่านได้ที่ https://arrow-kt.io/ หรือ github