Collections of utils to support your functional programming kotlin. This library uses awesome Kotlin Arrow as its base functional proramming library. This library is multiplatform purposes.
It works with standard library such scope functions, standard monads, etc. This library won't add any new things to learn, just basic things with extra and easier accessibilities.
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.SingularityIndonesia:Func-It:1.0.0-alpha1-20230910'
}
The alters are bunch of infix functions that can operate with the value within the standard monads, such: Options, Either etc.
Click to see more
val a = none<Int>()
// these operations (in b) are lazy, means that these operations won't be executed, unless the input is type of Some
val b = a + 1 + 2 + 3
// these operations (in b) are lazy, means that these operations won't be executed, unless the input is type of Right
val a: Either<ErrorMessage, Int> = 1.right()
val b = a + 2 + 3 + 4
Working with monad of list is always awful, so i present monad's list alters with altMap
.
val stepOne: (Int) -> String = { inp ->
return "$inp step1"
}
val stepTwo: (String) -> String = { inp ->
return "$inp step2"
}
val a = (1, 2, 3).toList().some()
val b = a altMap stepOne altMap stepTwo // return Some<List<String>> of ["1 step1 step2", "2 step1 step2", .. ]
The purpose of transformers is to transform one object to another.
Click to see more
val stringToInt: (String) -> Option<Int> = { inp ->
return runCatching {
inp.toInt()
.some()
}.getOrElse {
none()
}
}
val a = "some string"
val b = a let stringToInt // result is none
// easy chain transformation
val c = a let stepOne let stepTwo let stepThree let ...
This is very useful infix to immediately escape from error in standard monads.
Note: Just remember that escaper is not associative.
Click to see more
Escaping from left:
val a: Either<String, Int> = "error".left()
val b = a orElse 5
Escaping to another monad
// get user from db return error
val getUserFromDB: () -> Result<User> = ...
// get user from internet return User
val getUserFromInternet: () -> Result<User> = ...
// try to get user from db, should return left
val a = getUserFromDB()
// try to get user from db or from internet
val b = (a orElse getUserFromInternet.invoke()) orElse User("dummy")
// the result in 'b' will be User object from internet.
Many useful infix functions in it.
Click to see more
You can alter list inside monad. You can do many things, such appending to list, get elem by index. etc.val a = (1..5).toList().some()
val b = a + 6 // result = Some([1,2,3,4,5,6])
val c = a[0] // result = Some(1)
val d = a[10] // result = None
Compose functions like butter.
Click to see more
I introduce you the composer infix ``o``. You can use pure math composition style to compose your functions.@JvmInline
value class Token(val value: String)
@JvmInline
value class UserID(val value: String)
@JvmInline
value class UserName(val value: String)
@JvmInline
value class Email(val value: String)
data class UserProfile(
val id: UserID,
val name: UserName,
val email: Email
)
data class UserProfileDisplayable(
val userProfile: UserProfile,
val enabled: Boolean,
val selected: Boolean
)
fun userIDOf(token: Token) =
UserID(
"Some ID"
).some()
fun userProfileOf(userID: Option<UserID>) =
userID.map {
UserProfile(
id = it,
name = UserName("Some Name"),
email = Email("Some Email")
)
}
fun displayableUserProfileOf(userProfile: Option<UserProfile>) =
userProfile.map {
UserProfileDisplayable(
userProfile = it,
enabled = true,
selected = false
)
}
@Test
fun testComposeUserDisplayableFromToken() {
val userToken: Token = Token("some Token")
val displayableUserProfile = ::displayableUserProfileOf o ::userProfileOf o ::userIDOf o userToken
assert(displayableUserProfile.isSome())
}
If you have some cool idea that I could put in it, please tell me, I would love to.