With function composition, we take two functions to create the third function; with partial application, we create a new function by passing a parameter to an existing function.
Arrow comes with two flavours of partial application—explicit and implicit.
The explicit style uses a series of extension functions called partially1, partially2, all the way up to partially22. The implicit style takes a series of extensions, overloading the invoke operator:
package com.packtpub.functionalkotlin.chapter11
import arrow.syntax.function.invoke
import arrow.syntax.function.partially3
fun main(args: Array<String>) {
val strong: (String, String, String) -> String = { body, id, style -> "<strong id="$id" style="$style">$body</strong>" }
val redStrong: (String, String) -> String = strong.partially3("font: red") //Explicit
val blueStrong: (String, String) -> String = strong(p3 = "font: blue") //Implicit
println(redStrong("Red Sonja", "movie1"))
println(blueStrong("Deep Blue Sea", "movie2"))
}
Both styles can be chained as follows:
fun partialSplitter(billAndOrder: Pair<Bill, PickingOrder>?, warehouse: (PickingOrder) -> Unit, accounting: (Bill) -> Unit) {
if (billAndOrder != null) {
warehouse(billAndOrder.second)
accounting(billAndOrder.first)
}
}
fun main(args: Array<String>) {
val splitter: (billAndOrder: Pair<Bill, PickingOrder>?) -> Unit = ::partialSplitter.partially2 { order -> println("TESTING $order") }(p2 = ::accounting)
val salesSystem: (quote: Quote) -> Unit = ::calculatePrice andThen ::filterBills forwardCompose splitter
salesSystem(Quote(20.0, "Foo", "Shoes", 1))
salesSystem(Quote(20.0, "Bar", "Shoes", 200))
salesSystem(Quote(2000.0, "Foo", "Motorbike", 1))
}
Our original splitter function was not very flexible as it directly invoked warehouse and accounting functions. The partialSplitter function resolves this problem by taking warehouse and accounting as parameters; however a (Pair<Bill, PickingOrder>?, (PickingOrder) -> Unit, (Bill) -> Unit) function can't be used in composition. Then, we partially apply two functions—a lambda and a reference.