Home Android & Kotlin Books Functional Programming in Kotlin by Tutorials

B
Appendix B: Chapter 2 Exercise & Challenge Solutions Written by Massimo Carli

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

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

Exercise 2.1

Can you write an example of a function mapping distinct values in the domain to non-distinct values in the range, like f(b) and f(c) in Figure 2.2?

a’ b’ Domain Range f(b) f(a) f(c)
Figure 2.2: A function definition

Hint: Think of a possible way to group values you get as input. A very simple example is to return a Boolean that tells if the value in input is positive or not.

Exercise 2.1 solution

A simple example of a function mapping distinct values in the domain to non-distinct values in the range is:

fun isEven(x: Int): Boolean = x % 2 == 0
fun main() {
  println(isEven(2))
  println(isEven(-2))
  println(isEven(12))
  println(isEven(18))
  println(isEven(19))
  println(isEven(-3))
  println(isEven(1))
  println(isEven(-5))
}
true
true
true
true
false
false
false
false
typealias Predicate<A> = Fun<A, Boolean> // (A) -> Boolean

Exercise 2.2

Can you write the inverse function of twice? What are the domain and range for the inverse function?

fun twice(x: Int) = 2 * x

Exercise 2.2 solution

This exercise isn’t as easy as it looks. If twice has type Fun<Int, Int>, the inverse function should have the same type. This is because if a function has type Fun<A,B>, the inverse should have type Fun<B,A>. You get this by inverting the input type A with the output type B.

fun half(x: Int) = x / 2
half after twice == twice after half
half after twice == half(twice(x)) == (2 * x) / 2 == x
twice after half == twice(half(x)) == 2 * ( x / 2)
x = 0    2 * (x / 2) == 2 * (0 / 2) == 2 * 0 = 0 == x
x = 1    2 * (x / 2) == 2 * (1 / 2) == 2 * 0 = 0 != x
x = 2    2 * (x / 2) == 2 * (2 / 2) == 2 * 1 = 2 == x
x = 3    2 * (x / 2) == 2 * (2 / 2) == 2 * 1 = 2 != x
fun twice(x: Double): Double = 2 * x
fun half(x: Double): Double  = x / 2.0

Exercise 2.3

Can you prove that using Sets as objects and “is a subset of” as morphisms results in a category? In other words, a morphism from set A to set B would mean that A is a subset of B. In that case, what are the initial and terminal objects?

Exercise 2.3 solution

To prove some kinds of objects and morphisms define a category, you need to prove the three fundamental properties:

I Z P U T M
Woziso 4i.5: Noznexomauj ov dusn

I X K G
Nodexa 6o.8: Evfepoewekurz el gifs

Exercise 2.4

In this chapter, you defined after, which allows you to write expressions like:

val formatTwice = g after f
val formatTwice = f compose g

Exercise 2.4 solution

In this case, you need to consider f as the receiver of the function and write the following code:

inline infix fun <A, B, C> Fun<A, B>.compose(
  crossinline g: Fun<B, C>
): Fun<A, C> =
  { a: A ->
    g(this(a))
  }
fun main() {
  val f: Fun<Int, Int> = ::twice
  val g: Fun<Int, String> = ::format
  val formatTwice = f compose g // HERE
  println(formatTwice(37))
}

Exercise 2.5

Can you write an example of an isomorphic function f and its inverse g and prove they always compose to identity?

Exercise 2.5 solution

The following is an example of a function and its inverse:

fun addOne(x: Int) = x + 1

fun removeOne(x: Int) = x - 1
addOne after removeOne = removeOne after addOne = identity
(x - 1) + 1 = 1 + (x - 1) = x

Challenge 1: Functions and sets

How would you represent a specific Set using a function? For instance, how would you represent the set of even numbers with a function? After that, how would you print all the values in the set?

Challenge 1 solution

A Set is something more than a bunch of things because it has some structure. An object can be in the set or not. If an object is in the Set, it must be unique. You can’t have the same object in a Set twice.

typealias Predicate<A> = Fun<A, Boolean>
val evenIntSet: Predicate<Int> = { a: Int -> a % 2 == 0}
fun main() {
  println(" 0  is even?  ${evenIntSet(0)}")
  println(" 9  is even?  ${evenIntSet(-9)}")
  println(" 10 is even?  ${evenIntSet(10)}")
  println(" 3  is even?  ${evenIntSet(3)}")
}
 0  is even?  true
 9  is even?  false
 10 is even?  true
 3  is even?  false
  (Int.MIN_VALUE..Int.MAX_VALUE)
    .filter(evenIntSet)
    .forEach { println(it) }

Challenge 2: Functions and set again

How would you represent the intersection and union of two sets using functions? The intersection is the set of objects that belong to set A and set B, and the union is the set of all objects that belong to set A or set B.

Challenge 2 solution

Suppose you have the following functions for two different sets:

/** The set of all the odd Ints */
val oddIntSet: Predicate<Int> = { a: Int -> a % 2 != 0 }

/** The set of all multiples of 37 */
val multipleOf37: Predicate<Int> = { a: Int -> a % 37 == 0 }
/** The union of the two sets */
fun <A> union(
  set1: Predicate<A>,
  set2: Predicate<A>
): Predicate<A> = { a: A ->
  set1(a) || set2(a)
}
/** The intersection of the two sets */
fun <A> intersection(
  set1: Predicate<A>,
  set2: Predicate<A>
): Predicate<A> = { a: A ->
  set1(a) && set2(a)
}
val oddMultipleOf37Union =
    union(oddIntSet, multipleOf37)
val oddMultipleOf37Intersection =
  intersection(oddIntSet, multipleOf37)

println("1   is in union ${oddMultipleOf37Union(1)}")
println("37  is in union ${oddMultipleOf37Union(37)}")
println("74  is in union ${oddMultipleOf37Union(74)}")
println("100 is in union ${oddMultipleOf37Union(100)}")

println("1   is in intersection ${oddMultipleOf37Intersection(1)}")
println("37  is in intersection ${oddMultipleOf37Intersection(37)}")
println("74  is in intersection ${oddMultipleOf37Intersection(74)}")
println("100 is in intersection ${oddMultipleOf37Intersection(100)}")

Challenge 3: The right domain

Consider the following function:

fun oneOver(x: Int): Double = 1.0 / x

Challenge 3 solution

You probably know from your math in school that the function 1/x doesn’t exist for x = 0. This means that the domain of oneOver is the set represented by all the Int values without 0.

fun oneOver(x: NonZeroInt): Double = 1.0 / x
@JvmInline
value class NonZeroInt private constructor(val value: Int) {
  companion object {
    operator fun invoke(value: Int): NonZeroInt? {
      return when (value) {
        0 -> null
        else -> NonZeroInt(value)
      }
    }
  }
}
fun main() {
  println("1/3 = ${oneOver(NonZeroInt(3))}") // ERROR
}
2.16 - Type Mismatch. Required: NonZeroInt. Found: NonZeroInt?
3.59 - Ykla Nezwomwz. Qoweirah: TogSafuIrb. Xuozh: JepZacuAnx?

fun main() {
  println("1/3 = ${oneOver(NonZeroInt(3)!!)}") // COMPILES
}
@JvmInline
value class NonZeroInt(val value: Int) {
  init {
    require(value != 0) { "O is not a value for this type!" }
  }
}
println("1/3 = ${oneOver(NonZeroInt(3))}")
1/3 = 0.3333333333333333
println("1/3 = ${oneOver(NonZeroInt(0))}")
Exception in thread "main" java.lang.IllegalArgumentException: O is not a value for this type!

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.

© 2022 Razeware LLC

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.