H Appendix H: Chapter 8 Exercise & Challenge Solutions Written by Massimo Carli

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Exercise 8.1

In this chapter, you implemented the generic `curry` function that basically maps a function of type `(A, B) -> C` in a function of type `(A) -> (B) -> C`. Can you now implement the `uncurry` function, which does the inverse? It’s a function that maps a function of type `(A) -> (B) -> C` in a function of type `(A, B) -> C`.

Exercise 8.1 solution

The implementation of the `uncurry` function is:

``````fun <A, B, C> ((A) -> (B) -> C).uncurry(): (A, B) -> C =
{ a: A, b: B ->
this(a)(b)
}
``````
``````fun main() {
val sum = { a: Int, b: Int -> a + b }
println(sum(2, 3))
val sum2 = sum.curry().uncurry()
println(sum2(2, 3))
}
``````
``````5
5
``````

Exercise 8.2

Implement a higher-order function `flip` that maps a function of type `(A, B) -> C` in the function `(B, A) -> C`, flipping the order of the input parameters.

Exercise 8.2 solution

The `flip` function is very interesting and useful. Given you already have `curry` and `uncurry`, you can implement `flip` like this:

``````fun <A, B, C> ((A, B) -> C).flip(): (B, A) -> C =
{ b: B, a: A ->
this(a, b)
}
``````
``````fun append(a: String, b: String): String = "\$a \$b"
``````
``````fun main() {
val flippedAppend = ::append.flip() // 1
println(append("First", "Second")) // 2
println(flippedAppend("First", "Second")) // 3
}
``````
``````First Second
Second First
``````
``````fun runDelayed(fn: () -> Unit, delay: Long) { // 1
sleep(delay) // 2
fn() // 3
}
``````
``````fun main() {
// ...
runDelayed({
println("Delayed")
}, 1000)
}
``````
``````fun main() {
// ...
val runDelayed1Second =
::runDelayed.flip() // 1
.curry() // 2
.invoke(1000L) // 3
runDelayed1Second { // 4
println("Delayed")
}
}
``````

Exercise 8.3

The `curry` function maps a function of type `Fun2<A, B, C>` to a function of type `(A) -> (B) -> C`. How would you define an overload of `curry` for functions of three, four, five or, in general, `n` parameters?

Exercise 8.3 solution

To make the code easier to read, start by writing a `typealias` for each function type with a specified number of parameters, from 3 until 5 like this:

``````typealias Fun3<I1, I2, I3, O> = (I1, I2, I3) -> O
typealias Fun4<I1, I2, I3, I4, O> = (I1, I2, I3, I4) -> O
typealias Fun5<I1, I2, I3, I4, I5, O> =
(I1, I2, I3, I4, I5) -> O
``````
``````typealias Chain3<I1, I2, I3, O> = (I1) -> (I2) -> (I3) -> O
typealias Chain4<I1, I2, I3, I4, O> =
(I1) -> (I2) -> (I3) -> (I4) -> O
typealias Chain5<I1, I2, I3, I4, I5, O> =
(I1) -> (I2) -> (I3) -> (I4) -> (I5) -> O
``````
``````fun <I1, I2, I3, O> Fun3<I1, I2, I3, O>.curry():
Chain3<I1, I2, I3, O> = { i1: I1, i2: I2 ->
{ i3: I3 ->
this(i1, i2, i3)
}
}.curry()
``````
``````(I1, I2, I3) -> O
``````
``````(I1, I2) -> ((I3) -> O)
``````
``````fun <I1, I2, I3, I4, O> Fun4<I1, I2, I3, I4, O>.curry():
Chain4<I1, I2, I3, I4, O> = { i1: I1, i2: I2, i3: I3 ->
{ i4: I4 ->
this(i1, i2, i3, i4)
}
}.curry()
``````
``````fun <I1, I2, I3, I4, I5, O>
Fun5<I1, I2, I3, I4, I5, O>.curry():
Chain5<I1, I2, I3, I4, I5, O> =
{ i1: I1, i2: I2, i3: I3, i4: I4 ->
{ i5: I5 ->
this(i1, i2, i3, i4, i5)
}
}.curry()
``````
``````fun main() {
val sum = { a: Int, b: Int, c: Int, d: Int, e: Int ->
a + b + c + d + e // 1
}
val curriedSum = sum.curry() // 2
println(curriedSum(1)(2)(3)(4)(5)) // 3
}
``````
``````15
``````
``````curriedSum(1)(2)(3)(4)(5)
``````
``````fun main() {
val sum = { a: Int, b: Int, c: Int, d: Int, e: Int ->
a + b + c + d + e
}
val curriedSum = sum.curry()
val result = 5 pipe 4 pipe 3 pipe 2 pipe 1 pipe curriedSum // HERE
println(result)
println(curriedSum(1)(2)(3)(4)(5))
}
``````
``````val result = 5 pipe (4 pipe (3 pipe (2 pipe (1 pipe curriedSum))))
``````
``````infix fun <A, B> Fun<A, B>.epip(a: A): B = this(a)
``````
``````fun main() {
val sum = { a: Int, b: Int, c: Int, d: Int, e: Int ->
a + b + c + d + e
}
val curriedSum = sum.curry()
val result = curriedSum epip 1 epip 2 epip 3 epip 4 epip 5 // HERE
println(result)
}
``````

Exercise 8.4

How would you apply the previous pattern for `Array<T>`? Basically, you need a way to compose functions of type:

`````` typealias ToArray<A, B> = (A) -> Array<B>
``````
``````val fun1: (A) -> Array<B>
val fun2: (C) -> Array<C>
``````
``````fun1 compose fun2
``````

Exercise 8.4 solution

First, you need to understand what composing functions of type `ToArray<A, B>` means. The first is a function receiving an input value of type `A` and returning an `Array<B>`. The second receives an input of type `B` and returns an `Array<C>`.

``````inline infix fun <A, B, reified C> ToArray<A, B>.compose(
crossinline g: ToArray<B, C> // 1
): ToArray<A, C> = { a: A -> // 2
val bArray = this(a) // 3
val cArray = mutableListOf<C>() // 4
for (bValue in bArray) {
}
cArray.toTypedArray() // 5
}
``````
``````val fibo = { n: Int -> // 1
tailrec fun fiboHelper(a: Int, b: Int, fiboN: Int): Int =
when (fiboN) {
0 -> a
1 -> b
else -> fiboHelper(b, a + b, fiboN - 1)
}
fiboHelper(1, 1, n)
}

fun main() {
val counter = { a: Int -> Array(a) { it } } // 2
val fiboLength = { n: Int -> Array(n) { fibo(it) } } // 3
val counterFibo = counter compose fiboLength // 4
counterFibo(5).forEach { print("\$it ") } // 5
}
``````
``````1 1 1 1 1 2 1 1 2 3
``````
``````inline infix fun <A, B, reified C> ToArray<A, B>.composeWithFold(
crossinline g: ToArray<B, C>
): ToArray<A, C> = { a: A ->
this(a).fold(mutableListOf<C>()) { acc, item ->
for (bValue in g(item)) { // HERE
}
acc
}.toTypedArray()
}
``````
``````fun main() {
// ...
val counterFiboWithFold = counter composeWithFold fiboLength
counterFiboWithFold(5).forEach { print("\$it ") }
}
``````
``````1 1 1 1 1 2 1 1 2 3
``````

Challenge 1: Callable stuff

In the chapter, you learned how to implement the `compose` function in different scenarios following a common pattern. Consider, now, the following function type:

``````typealias WithCallable<A, B> = Fun<A, Callable<B>>
``````
``````interface Callable<V> {
@Throws(Exception::class)
fun call(): V
}
``````

Challenge 1 solution

Following the same pattern you learned in the chapter, you can implement `compose` like this:

``````infix fun <A, B, C> WithCallable<A, B>.compose( // 1
g: WithCallable<B, C>
): WithCallable<A, C> = { a: A -> // 2
Callable<C> { // 3
g(this(a).call()).call() // 4
}
}
``````
``````fun main() {
val waitAndReturn = { a: Int -> // 1
Callable {
sleep(1000)
a
}
}
val comp = waitAndReturn compose waitAndReturn  // 2
chronoMs {
comp(2).call() // 3
} pipe ::println
}
``````
``````2053
``````

Challenge 2: Parameters or not parameters?

Suppose you have the following functions:

``````val three = { 3 } // 1

val unitToThree = { a: Unit -> 3 } // 2
``````
``````fun main() {
val double = { a: Int -> a * 2 } // 1
val comp2 = unitToThree compose double // 2  COMPILE
val comp1 = three compose double // 3  DOESN'T COMPILE
}
``````

Challenge 2 solution

The solution to this challenge is very simple. You just need to define the following functions:

``````fun <A> (() -> A).addUnit() = { unit: Unit -> this() }

fun <A> ((Unit) -> A).removeUnit() = { this(Unit) }
``````
``````fun main() {
val double = { a: Int -> a * 2 }
val comp2 = unitToThree compose double
val comp1 = three.withUnit() compose double // HERE
``````

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.