Home Android & Kotlin Books Functional Programming in Kotlin by Tutorials

K
Appendix K: Chapter 12 Exercise 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 12.1

Can you find an example of a monoid whose operation isn’t commutative?

Exercise 12.1 solution

A typical example of a monoid in programming that isn’t commutative is:

a + (b + c) = (a + b) + c
a + b != b + a
fun main() {
  val str1 = "Hello"
  val str2 = " World!"

  println(str1 + str2)
  println(str2 + str1)
}
Hello World!
 World!Hello
fun main() {
  // ...
  val unit = ""
  println(str1 + unit)
  println(unit + str1)
}
Hello
Hello

Exercise 12.2

Can you prove that the set of integer values and multiplication define a monoid? In this case, what would the unit element be?

Exercise 12.2 solution

To prove that the set of integer values and multiplication form a monoid, you have to prove that:

a * (b * c) = (a * b) * c
a * 1 = a
1 * a = a
fun main() {
  val a = 3
  val b = 7
  val c = 13
  val res1 = a * (b * c)
  val res2 = (a * b) * c

  println(res1)
  println(res2)

  val unit = 1
  val res3 = a * unit
  val res4 = unit * a

  println(res3)
  println(res4)
}
273
273
3
3

Exercise 12.3

How would you implement the monoid MonoidIntMult for Int and multiplication?

Exercise 12.3 solution

The implementation of MonoidIntMult is simple because it’s similar to MonoidIntAdd, which you saw in the chapter. Follow that pattern, and you can implement MonoidIntMult like this:

object MonoidIntMult : Monoid<Int> { // 1
  override val unit: Int
    get() = 1 // 2
  override val combine: Int.(Int) -> Int
    get() = Int::times // 3
}

Exercise 12.4

How would you implement the monoid MonoidStringConcat for String and String concatenation?

Exercise 12.4 solution

As mentioned in the chapter, String concatenation is an example of a monoid with an operation that isn’t commutative. The implementation of MonoidStringConcat isn’t so different from MonoidIntAdd. A possible implementation is:

object MonoidStringConcat : Monoid<String> { // 1
  override val unit: String
    get() = "" // 2
  override val combine: String.(String) -> String
    get() = String::plus // 3
}

Exercise 12.5

In the chapter, you proved that addition is different from multiplication using op(op(a, 1), 1) and op(a, 2). The two expressions are equal for any Int a if op is addition, but the same isn’t true if op is multiplication. Can you implement a Property<Int> implementation for this rule and use it to create a new test?

Exercise 12.5 solution

Following the pattern you used previously in the chapter, a possible implementation is the following:

class DoubleIncrementProperty : Property<Int> { // 1
  override fun invoke(
    gen: Generator<Int>,
    fn: (List<Int>) -> Int
  ): Boolean { // 2
    val randomValue = gen.generate(1)[0] // 3
    val res1 = fn(listOf(fn(listOf(randomValue, 1)), 1)) // 4
    val res2 = fn(listOf(randomValue, 2)) // 5
    return res1 == res2 // 6
  }
}
class PropertyTestTest {

  @Test
  fun `Exercise 5 solution`() {
    100.times {
      val additionProp =
        CommutativeProperty<Int>() and
            DoubleIncrementProperty() and
            IdentityProperty(0)
      val evaluation = additionProp(IntGenerator) {
        sum(it[0], it[1])
      }
      Truth.assertThat(evaluation).isTrue()
    }
  }
}

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.