Functional companion to Kotlin's Standard Library
// function with pre- and post-condition
fun increment(x: Int): Int {
pre(x > 0) { "value must be positive" }
return (x + 1).post({ it > 0 }) { "result is positive" }
}
class Positive(val value: Int) {
init { require(value > 0) } // type invariant
fun add(other: Positive) =
Positive(this.value + other.value)
}
suspend fun prepareLunch(): Either<CookingException, Salad> =
// with the 'either' computation block
// we follow a "fail fast" strategy
either<CookingException, Salad> {
val lettuce = takeFoodFromRefrigerator().bind()
val knife = getKnife().bind()
val lunch = prepare(knife, lettuce).bind()
lunch
}
suspend fun process(): List<Employee> {
// maps to 'Employee' in parallel using 'parZip'
val audrey = parZip({ "Audrey" }, { company("Arrow") }) {
name, company -> Employee(name, company)
}
val pepe = parZip({ "Pepe" }, { company("Arrow") }) {
name, company -> Employee(name, company)
}
// hires in parallel using 'parTraverse'
return listOf(audrey, pepe).parTraverse { hire(it) }
}
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
)
}
)
}
val john =
Employee("Audrey Tang",
Company("Arrow",
Address("Functional City",
Street(42, "Lambda St."))))
// an optic is a reference to a piece of information
val optic = Employee.company.address.street.name
// which we then use to query or modify immutable data
val modified = optic.modify(john, String::toUpperCase)