昨天簡述了 Functional Programming 的概念,今天我們來用幾個範例帶大家看一下 Kotlin 使用套件 arrow-kt (1.1.5) 版如何實踐 Functional Programming 的概念。
data class Person(val name: String, val age: Int)
sealed interface Error
data class NotFoundError(val msg: Int) : Error()
data class InvalidValueError(val age: Int) : Error()
object PersonIdMapping{
persons = mapOf(
1 to Person("Alice", 25),
2 to Person("Bob", 30),
3 to Person("Charlie", 22)
)
}
fun findPersonById(id: Int): Either<NotFoundError, Person> =
persons[id].toOption().toEither{
ifEmpty = { NotFoundError(id) }
}
fun isPersonEligible(person: Person): Either<InvalidValueError, Person> =
when ( person.age >= 18 ) {
ture -> person.right()
false -> InvalidValueError(person.age).left()
}
fun eligibilityMessage(personId: Int): Either<Error, Person> =
findPersonById(personId).flatMap { person ->
isPersonEligible(person)
}
fun main() {
val testPersonId = 1
eligibilityMessage(testPersonId).fold(
ifLeft = {println(it)},
ifRight = {println("Person not found or not eligible.")}
)
}
先稍微說明一下這份 code 的行為:
資料類別 Person
:
這段程式碼定義了一個 Person
資料類別,有兩個屬性:name
(字串)和 age
(整數)。資料類別用於表示簡單的資料結構。
物件 PersonIdMapping
:
在物件內部,有一個名為 persons
的屬性,它是一個將人員 ID對應到 Person
物件的映射。
函式 findPersonById
:
這個函式以一個整數 id
為參數,返回一個 Either<NotFoundError, Person>
。Either
是一種資料型別,可以表示兩種可能的值,通常稱為左值(NotFoundError
)或右值(Person
)。
函式 isPersonEligible
:
它檢查 Person
的年齡是否大於或等於 18,如果人員符合資格(true
),它將人員作為右值返回。如果人員不符合資格(false
), 創建 InvalidValueError
並將其作為左值返回。
函式 eligibilityMessage
:
它使用 findPersonById
函數按照 personId
查找一個人員。如果找到人員(右值),它使用 isPersonEligible
檢查他們的資格。
好,大致上了解各函式之後,我們講解一下 flatMap
跟 Either
在這裡扮演的角色:
在 eligibilityMessage
中 faltMap
串接了兩個 Either
,每一個 Either
(一種 monad) 代表此處回傳結果可能為左或右值,因為兩者的左值 (錯誤值) 都屬於 Error
介面所以可串接過程中會自動幫我們把它變成 Error
型別。