Functional companion to Kotlin's Standard Library
import arrow.core.Either
import arrow.core.Either.Left
import arrow.core.Either.Right
import arrow.core.computations.either
object Lettuce
object Knife
object Salad
sealed class CookingException {
object LettuceIsRotten: CookingException()
object KnifeNeedsSharpening: CookingException()
data class InsufficientAmount(val quantityInGrams : Int): CookingException()
}
typealias NastyLettuce = CookingException.LettuceIsRotten
typealias KnifeIsDull = CookingException.KnifeNeedsSharpening
typealias InsufficientAmountOfLettuce = CookingException.InsufficientAmount
fun takeFoodFromRefrigerator(): Either<NastyLettuce, Lettuce> = Right(Lettuce)
fun getKnife(): Either<KnifeIsDull, Knife> = Right(Knife)
fun prepare(tool: Knife, ingredient: Lettuce): Either<InsufficientAmountOfLettuce, Salad> = Left(InsufficientAmountOfLettuce(5))
suspend fun main() {
//sampleStart
suspend fun prepareLunch(): Either<CookingException, Salad> =
either<CookingException, Salad> {
val lettuce = takeFoodFromRefrigerator().bind()
val knife = getKnife().bind()
val lunch = prepare(knife, lettuce).bind()
lunch
}
println(prepareLunch())
//sampleEnd
}
import arrow.fx.coroutines.parTraverse
import arrow.fx.coroutines.parZip
data class Street(val name: String)
data class Company(val name: String)
data class Employee(val name: String, val company: Company, val hired : Boolean = false)
/** An async non blocking service **/
suspend fun company(name: String): Company =
Company("$name on ${Thread.currentThread().name}")
/** An async non blocking service **/
suspend fun street(name: String): Street =
Street("$name on ${Thread.currentThread().name}")
/** An async non blocking service **/
suspend fun hire(employee: Employee): Employee =
employee.copy(hired = true)
fun employee(name: String, company: Company): Employee =
Employee(name, company)
suspend fun main() {
//sampleStart
//maps each function to `::employee` in parallel
val audrey = parZip({ "Audrey" }, { company("Arrow") }) { name, company -> Employee(name, company) }
val pepe = parZip({ "Pepe" }, { company("Arrow") }) { name, company -> Employee(name, company) }
val candidates = listOf(audrey, pepe)
val employees = candidates.parTraverse { hire(it) } //hires in parallel
//sampleEnd
println(employees)
}
import arrow.meta.CliPlugin
import arrow.meta.Meta
import arrow.meta.invoke
import arrow.meta.quotes.Transform
import arrow.meta.quotes.namedFunction
//sampleStart
val Meta.helloWorld: CliPlugin get() =
"Hello World" {
meta(
namedFunction(this, { element.name == "helloWorld" }) { (c, _) -> // <-- namedFunction(...) {...}
Transform.replace(
replacing = c,
newDeclaration = """|fun helloWorld(): Unit =
| println("Hello ΛRROW Meta!")
|""".function(descriptor).syntheticScope
)
}
)
}
//sampleEnd
package example
import arrow.core.*
import arrow.optics.*
data class Street(val number: Int, val name: String) {
companion object {
val name: Lens<Street, String> = Lens(Street::name)
{ street, name -> street.copy(name = name) }
}
}
data class Address(val city: String, val street: Street) {
companion object {
val street: Lens<Address, Street> = Lens(Address::street)
{ address, street -> address.copy(street = street) }
}
}
data class Company(val name: String, val address: Address) {
companion object {
val address: Lens<Company, Address> = Lens(Company::address)
{ company, address -> company.copy(address = address) }
}
}
data class Employee(val name: String, val company: Company?) {
companion object {
val company: Optional<Employee, Company> = Optional(
getOption = { it.company.toOption() },
set = { source, focus -> source.copy(company = focus) }
)
}
}
fun main() {
//sampleStart
val john =
Employee("Audrey Tang",
Company("Arrow",
Address("Functional city",
Street(42, "lambda street"))))
val modify = Employee.company.address.street.name
.modify(john, String::toUpperCase)
println(modify)
//sampleEnd
}
val <A> Optional<A, Company>.address: Optional<A, Address>
get() = this compose Company.address
val <A> Optional<A, Address>.street: Optional<A, Street>
get() = this compose Address.street
val <A> Optional<A, Street>.name: Optional<A, String>
get() = this compose Street.name