Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Programming with Arrow in Kotlin

Functional Programming with Arrow in Kotlin

GIDS 2019: https://www.developermarch.com/developersummit/session.html?insert=Raghunath

With a rising trend in programming languages adding more and more functional capabilities, developers are working at a much higher level of abstraction. The declarative style of programming allows us to write readable and maintainable code that focuses on "what" (larger picture) rather than "how" (nuts and bolts). Functional programming also promotes immutability by default which makes dealing with concurrency an easy and a fun affair. Kotlin already supports some of these features like functions as first-class citizens, lambdas, anonymous functions, immutability, persistent collections, explicit nullable and non-nullable types, declarative constructs, etc., However, these features lack capabilities offered by purely functional languages.

Arrow is a Kotlin library that pushes the envelope further by introducing typeclasses, functional data types, optics, etc., It achieves this by clever usage of Kotlin language features and by generating code using annotation processors.

This talk will walk you through several ideas and code examples that will help you get started with functional programming using Arrow.

Audience will be able to:
- Use functional data types from the Arrow library.
- Use functional programming patterns.
- Solve problems using functional ideas and gradually move away from imperative programming.
- Deal with immutability and use optics to modify deeply nested data structures efficiently.

A8ee6ea52b89dfa1388b592a260c60a6?s=128

Ragunath Jawahar

April 23, 2019
Tweet

More Decks by Ragunath Jawahar

Other Decks in Programming

Transcript

  1. Functional Programming with Arrow in Kotlin @ragunathjawahar • Obvious (previously,

    Uncommon Bangalore)
  2. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  3. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  4. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  5. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  6. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  7. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  8. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  9. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  10. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  11. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  12. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  13. fun findFirst(array: Array<Char>, key: Char): Int { for (i in

    array.indices) { if (array[i] == key) return i } return -1 }
  14. fun findFirst(array: Array<Char>, key: Char): Index { for (i in

    array.indices) { if (array[i] == key) return i } return -1 } typealias Index = Int
  15. fun findFirst(array: Array<Char>, key: Char): Index { for (i in

    array.indices) { if (array[i] == key) return i } return -1 } typealias Index = Int
  16. fun findFirst(array: Array<Char>, key: Char): Index { for (i in

    array.indices) { if (array[i] == key) return i } return -1 } typealias Index = Int
  17. fun findFirst(array: Array<Char>, key: Char): Index { for (i in

    array.indices) { if (array[i] == key) return i } return -1 } typealias Index = Int // findFirst(chars, ‘e’) != -1
  18. fun findFirst(array: Array<Char>, key: Char): Index { for (i in

    array.indices) { if (array[i] == key) return i } return -1 } typealias Index = Int // findFirst(chars, ‘e’) != -1
  19. fun findFirst(array: Array<Char>, key: Char): Index { for (i in

    array.indices) { if (array[i] == key) return i } return -1 } typealias Index = Int
  20. fun findFirst(array: Array<Char>, key: Char): Index? { for (i in

    array.indices) { if (array[i] == key) return i } return null } typealias Index = Int
  21. fun findFirst(array: Array<Char>, key: Char): Option<Index> { for (i in

    array.indices) { if (array[i] == key) return Some(i) } return None } typealias Index = Int
  22. fun findFirst(array: Array<Char>, key: Char): Option<Index> { for (i in

    array.indices) { if (array[i] == key) return Some(i) } return None } typealias Index = Int // absence // presence
  23. fun findFirst(array: Array<Char>, key: Char): Option<Index> { for (i in

    array.indices) { if (array[i] == key) return Some(i) } return None } typealias Index = Int
  24. fun findFirst(array: Array<Char>, key: Char): Option<Index> { for (i in

    array.indices) { if (array[i] == key) return Some(i) } return None } typealias Index = Int
  25. fun findFirst(array: Array<Char>, key: Char): Option<Index> { for (i in

    array.indices) { if (array[i] == key) return Some(i) } return None } typealias Index = Int
  26. fun <A> findFirst(array: Array<A>, key: A): Option<Index> { for (i

    in array.indices) { if (array[i] == key) return Some(i) } return None } typealias Index = Int
  27. fun <A> findFirst(array: Array<A>, key: A): Option<Index> { for (i

    in array.indices) { if (array[i] == key) return Some(i) } return None } typealias Index = Int
  28. fun <A> findFirst(array: Array<A>, key: A): Option<Index> { for (i

    in array.indices) { if (array[i] == key) return Some(i) } return None } typealias Index = Int
  29. fun <A> findFirst(array: Array<A>, p: (A) -> Boolean): Option<Index> {

    for (i in array.indices) { if (p(array[i])) return Some(i) } return None } typealias Index = Int
  30. fun <A> findFirst(array: Array<A>, p: (A) -> Boolean): Option<Index> {

    for (i in array.indices) { if (p(array[i])) return Some(i) } return None } typealias Index = Int // findFirst(people, { it.firstName == “Ajay” })
  31. fun <A> findFirst(array: Array<A>, p: (A) -> Boolean): Option<Index> {

    for (i in array.indices) { if (p(array[i])) return Some(i) } return None } typealias Index = Int // findFirst(people) { it.firstName == “Ajay” }
  32. fun <A> findFirst(array: Array<A>, p: (A) -> Boolean): Option<Index> {

    for (i in array.indices) { if (p(array[i])) return Some(i) } return None } typealias Index = Int
  33. fun <A> findFirst(array: Array<A>, p: (A) -> Boolean): Option<Index> {

    for (i in array.indices) { if (p(array[i])) return Some(i) } return None } typealias Index = Int
  34. fun <A> findFirst(array: Array<A>, p: (A) -> Boolean): Option<Index> {

    for (i in array.indices) { if (p(array[i])) return Some(i) } return None } typealias Index = Int // findFirst(people) { it.firstName == “Ajay” }
  35. fun <A> Array<A>.findFirst(p:,(A) -> Boolean): Option<Index> { for (i in

    this.indices) { if (p(this[i])) return Some(i) } return None } typealias Index = Int // people.findFirst { it.firstName == “Ajay” }
  36. fun <A> Array<A>.findFirst(p:,(A) -> Boolean): Option<Index> { for (i in

    this.indices) { if (p(this[i])) return Some(i) } return None } typealias Index = Int
  37. fun <A> Array<A>.findFirst(p:,(A) -> Boolean): Option<Index> { for (i in

    this.indices) { if (p(this[i])) return Some(i) } return None } fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
  38. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  39. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  40. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  41. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  42. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  43. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  44. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  45. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  46. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  47. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  48. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  49. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  50. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  51. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  52. fun <A> findFirst(array: Array<A>, p:,(A) -> Boolean): Option<Index> { tailrec

    fun go(array: Array<A>, index: Index): Option<Index> { return when { index == array.size -> None p(array[index]) -> Some(index) else -> go(array, index + 1) } } return go(array, 0) } But!
  53. Core Ideas

  54. Core Ideas • Purity • Referential Transparency • Immutability •

    Lazy Evaluation
  55. Notations

  56. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  57. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  58. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  59. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  60. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  61. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  62. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  63. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  64. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  65. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  66. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  67. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  68. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b } // (a: Int, b: Int) -> Int
  69. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  70. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  71. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  72. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  73. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  74. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  75. fun add(a: Int, b: Int): Int = a + b

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  76. val addRef: (Int, Int) -> Int = ::add addRef.invoke(4, 5)

    addRef(4, 5)
  77. Arrow Syntax compile "io.arrow-kt:arrow-syntax:$arrow_version"

  78. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition
  79. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition
  80. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition // bold(“Hello”)
  81. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition // <b>Hello</b>
  82. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition
  83. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition // italic(“Hello”)
  84. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition // <i>Hello</i>
  85. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition
  86. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition // boldItalic(“Hello”)
  87. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition // <b><i>Hello</i></b>
  88. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition
  89. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition // italicBold(“Hello”)
  90. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition // <i><b>Hello</b></i>
  91. val bold: (String) -> String = { "<b>$it</b>" } val

    italic: (String) -> String = { "<i>$it</i>" } val boldItalic = bold compose italic val italicBold = bold forwardCompose italic Composition
  92. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  93. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  94. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  95. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  96. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  97. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  98. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  99. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  100. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application // x2(10)
  101. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application // 20
  102. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  103. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  104. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  105. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  106. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  107. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  108. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application // x5(10)
  109. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application // 50
  110. fun multiply(a: Int, b: Int): Int = a * b

    val x2: (Int) -> Int = ::multiply.partially1(2) val x5: (Int) -> Int = ::multiply.partially1(5) Partial Application
  111. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  112. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  113. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  114. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  115. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  116. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  117. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  118. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  119. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  120. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  121. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  122. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  123. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  124. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  125. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  126. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog } // findCat(animals)
  127. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  128. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  129. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  130. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  131. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  132. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  133. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog } // findDog(animals)
  134. Reverse fun findFirst( animals: List<Animal>, predicate: (Animal) -> Boolean ):

    Option<Animal> { /* … */ } val findCat: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Cat } val findDog: (List<Animal>) -> Option<Animal> = ::findFirst.reverse().partially1 { it is Dog }
  135. Logical Complement val onlyCats: (Animal) -> Boolean = { it

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  136. Logical Complement val onlyCats: (Animal) -> Boolean = { it

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  137. Logical Complement val onlyCats: (Animal) -> Boolean = { it

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  138. Logical Complement val onlyCats: (Animal) -> Boolean = { it

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  139. Logical Complement val onlyCats: (Animal) -> Boolean = { it

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  140. Logical Complement val onlyCats: (Animal) -> Boolean = { it

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  141. Logical Complement val onlyCats: (Animal) -> Boolean = { it

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  142. Logical Complement val onlyCats: (Animal) -> Boolean = { it

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  143. Logical Complement val onlyCats: (Animal) -> Boolean = { it

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  144. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  145. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  146. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  147. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  148. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  149. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  150. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  151. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1) // 100
  152. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  153. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  154. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  155. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  156. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  157. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  158. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  159. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  160. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1) // 100
  161. Currying (1/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length volume(10, 10, 1) val curriedVolume: (width: Int) -> (height: Int) -> (length: Int) -> Int = ::volume.curried() curriedVolume(10)(10)(1)
  162. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10)
  163. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10)
  164. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10)
  165. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10) // (width, height, length)
  166. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10) // (length, height, width)
  167. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10) // (length) -> (height) -> (width)
  168. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10) // (height) -> (width)
  169. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10) // (height, width)
  170. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10) // (width, height)
  171. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10)
  172. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10)
  173. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10) // 100
  174. Currying (2/2) fun volume(width: Int, height: Int, length: Int): Int

    = width * height * length val area = ::volume .reverse().curried()(1) .uncurried().reverse() area(10, 10)
  175. More… • memoize() // FunctionN • firstOption() // Array, Sequence,

    and Iterable • flatten() - tail() - prependTo(List<T>) // List • plus(C) // TupleN • paired() - tripled() // FunctionN • pipe() // FunctionN
  176. Data Types compile “io.arrow-kt:arrow-core-data:$arrow_version”

  177. Data Types • Option • Either • Try • Validated

    • Eval
  178. Option sealed class Option<out A> { object None : Option<Nothing>()

    data class Some<out T>(val t: T) : Option<T>() } Option is an Algebraic Data Type that is used to model the absence of value. In Kotlin they are encoded with sealed class hierarchies.
  179. Option sealed class Option<out A> { object None : Option<Nothing>()

    data class Some<out T>(val t: T) : Option<T>() } Option is an Algebraic Data Type that is used to model the absence of value. In Kotlin they are encoded with sealed class hierarchies.
  180. Option sealed class Option<out A> { object None : Option<Nothing>()

    data class Some<out T>(val t: T) : Option<T>() } Option is an Algebraic Data Type that is used to model the absence of value. In Kotlin they are encoded with sealed class hierarchies.
  181. Option sealed class Option<out A> { object None : Option<Nothing>()

    data class Some<out T>(val t: T) : Option<T>() } Option is an Algebraic Data Type that is used to model the absence of value. In Kotlin they are encoded with sealed class hierarchies.
  182. Option sealed class Option<out A> { object None : Option<Nothing>()

    data class Some<out T>(val t: T) : Option<T>() } Option is an Algebraic Data Type that is used to model the absence of value. In Kotlin they are encoded with sealed class hierarchies.
  183. Option (Construction) val intOption: Option<Int> = Option(1) val intOption: Option<Int>

    = None val intOption: Option<Int> = Option.fromNullable(a) // a: Int? val intOption: Option<Int> = 1.some() val intOption: Option<Int> = none()
  184. Option (Construction) val intOption: Option<Int> = Option(1) val intOption: Option<Int>

    = None val intOption: Option<Int> = Option.fromNullable(a) // a: Int? val intOption: Option<Int> = 1.some() val intOption: Option<Int> = none()
  185. Option (Construction) val intOption: Option<Int> = Option(1) val intOption: Option<Int>

    = None val intOption: Option<Int> = Option.fromNullable(a) // a: Int? val intOption: Option<Int> = 1.some() val intOption: Option<Int> = none()
  186. Option (Construction) val intOption: Option<Int> = Option(1) val intOption: Option<Int>

    = None val intOption: Option<Int> = Option.fromNullable(a) // a: Int? val intOption: Option<Int> = 1.some() val intOption: Option<Int> = none()
  187. Option (Construction) val intOption: Option<Int> = Option(1) val intOption: Option<Int>

    = None val intOption: Option<Int> = Option.fromNullable(a) // a: Int? val intOption: Option<Int> = 1.some() val intOption: Option<Int> = none()
  188. Option (Construction) val intOption: Option<Int> = Option(1) val intOption: Option<Int>

    = None val intOption: Option<Int> = Option.fromNullable(a) // a: Int? val intOption: Option<Int> = 1.some() val intOption: Option<Int> = none()
  189. Option (Construction) val intOption: Option<Int> = Option(1) val intOption: Option<Int>

    = None val intOption: Option<Int> = Option.fromNullable(a) // a: Int? val intOption: Option<Int> = 1.some() val intOption: Option<Int> = none()
  190. Option (Extraction) val intOption: Option<Int> = Option(1) val nullableResult: Int?

    = intOption.orNull() val result: Int = intOption.getOrElse { 0 }
  191. Option (Extraction) val intOption: Option<Int> = Option(1) val nullableResult: Int?

    = intOption.orNull() val result: Int = intOption.getOrElse { 0 }
  192. Option (Extraction) val intOption: Option<Int> = Option(1) val nullableResult: Int?

    = intOption.orNull() val result: Int = intOption.getOrElse { 0 }
  193. Option (Extraction) val intOption: Option<Int> = Option(1) val nullableResult: Int?

    = intOption.orNull() val result: Int = intOption.getOrElse { 0 }
  194. Option (Extraction) val intOption: Option<Int> = Option(1) val nullableResult: Int?

    = intOption.orNull() val result: Int = intOption.getOrElse { 0 }
  195. Option (Extraction - when) val intOption: Option<Int> = Option(1) when

    (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
  196. Option (Extraction - when) val intOption: Option<Int> = Option(1) when

    (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
  197. Option (Extraction - when) val intOption: Option<Int> = Option(1) when

    (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
  198. Option (Extraction - when) val intOption: Option<Int> = Option(1) when

    (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
  199. Option (Extraction - when) val intOption: Option<Int> = Option(1) when

    (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
  200. Option (Extraction - when) val intOption: Option<Int> = Option(1) when

    (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
  201. Option (Extraction - when) val intOption: Option<Int> = Option(1) when

    (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
  202. Option (Extraction - fold) val intOption: Option<Int> = Option(1) intOption.fold(

    { 0 }, { it + 1 } ) // Some(2)
  203. Option (Extraction - fold) val intOption: Option<Int> = Option(1) intOption.fold(

    { 0 }, { it + 1 } ) // Some(2)
  204. Option (Extraction - fold) val intOption: Option<Int> = Option(1) intOption.fold(

    { 0 }, { it + 1 } ) // Some(2)
  205. Option (Extraction - fold) val intOption: Option<Int> = Option(1) intOption.fold(

    { 0 }, { it + 1 } ) // Some(2)
  206. Option (Extraction - fold) val intOption: Option<Int> = Option(1) intOption.fold(

    { 0 }, { it + 1 } ) // Some(2)
  207. Option (Extraction - fold) val intOption: Option<Int> = Option(1) intOption.fold(

    { 0 }, { it + 1 } ) // Some(2)
  208. Option (Extraction - fold) val intOption: Option<Int> = Option(1) intOption.fold(

    { 0 }, { it + 1 } ) // Some(2)
  209. Option (map) val intOption: Option<Int> = Option(1) intOption.map { it

    * 2 } // Some(2) val intOption: Option<Int> = None intOption.map { it * 2 } // None
  210. Option (map) val intOption: Option<Int> = Option(1) intOption.map { it

    * 2 } // Some(2) val intOption: Option<Int> = None intOption.map { it * 2 } // None
  211. Option (map) val intOption: Option<Int> = Option(1) intOption.map { it

    * 2 } // Some(2) val intOption: Option<Int> = None intOption.map { it * 2 } // None
  212. Option (map) val intOption: Option<Int> = Option(1) intOption.map { it

    * 2 } // Some(2) val intOption: Option<Int> = None intOption.map { it * 2 } // None
  213. Option (map) val intOption: Option<Int> = Option(1) intOption.map { it

    * 2 } // Some(2) val intOption: Option<Int> = None intOption.map { it * 2 } // None
  214. Option (map) val intOption: Option<Int> = Option(1) intOption.map { it

    * 2 } // Some(2) val intOption: Option<Int> = None intOption.map { it * 2 } // None
  215. Option (map) val intOption: Option<Int> = Option(1) intOption.map { it

    * 2 } // Some(2) val intOption: Option<Int> = None intOption.map { it * 2 } // None
  216. Option (map) val intOption: Option<Int> = Option(1) intOption.map { it

    * 2 } // Some(2) val intOption: Option<Int> = None intOption.map { it * 2 } // None
  217. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = Option(2) oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
  218. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = Option(2) oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
  219. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = Option(2) oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
  220. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = Option(2) oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
  221. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = Option(2) oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
  222. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = Option(2) oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
  223. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = Option(2) oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
  224. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = None oneOption.flatMap { one -> twoOption.map { two -> one + two } } // None
  225. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = None oneOption.flatMap { one -> twoOption.map { two -> one + two } } // None
  226. Option (flatMap) val oneOption: Option<Int> = Option(1) val twoOption: Option<Int>

    = None oneOption.flatMap { one -> twoOption.map { two -> one + two } } // None
  227. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = Option(2) Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // Some(3)
  228. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = Option(2) Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // Some(3)
  229. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = Option(2) Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // Some(3)
  230. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = Option(2) Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // Some(3)
  231. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = Option(2) Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // Some(3)
  232. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = Option(2) Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // Some(3)
  233. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = Option(2) Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // Some(3)
  234. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = Option(2) Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // Some(3)
  235. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = Option(2) Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // Some(3)
  236. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = None Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // None
  237. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = None Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // None
  238. Option (Monad Binding) val oneOption: Option<Int> = Option(1) val twoOption:

    Option<Int> = None Option.monad().binding { val one = oneOption.bind() val two = twoOption.bind() one + two }.fix() // None
  239. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  240. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  241. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  242. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  243. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  244. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  245. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  246. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  247. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  248. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  249. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = Option(Foam(0.3)) Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // Some(Cappuccino(espresso=Espresso(%=0.3), milk=Milk(%=0.3), // foam=Foam(%=0.3)))
  250. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = None Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // None
  251. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = None Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // None
  252. Option (Applicative Builder) val maybeEspresso: Option<Espresso> = Option(Espresso(0.3)) val maybeMilkOption:

    Option<Milk> = Option(Milk(0.3)) val foamOption: Option<Foam> = None Option.applicative() .map(maybeEspresso, maybeMilk, maybeFoam) { (espresso, milk, foam) -> Cappuccino(espresso, milk, foam) }.fix() // None
  253. Either sealed class Either<out A, out B> { data class

    Left<out A, out B>(val a: A) : Either<A, B>() data class Right<out A, out B>(val b: B) : Either<A, B>() } Either is an Algebraic Data Type that is used to model a return type that may return one of two possible values.
  254. Either sealed class Either<out A, out B> { data class

    Left<out A, out B>(val a: A) : Either<A, B>() data class Right<out A, out B>(val b: B) : Either<A, B>() } Either is an Algebraic Data Type that is used to model a return type that may return one of two possible values.
  255. Either sealed class Either<out A, out B> { data class

    Left<out A, out B>(val a: A) : Either<A, B>() data class Right<out A, out B>(val b: B) : Either<A, B>() } Either is an Algebraic Data Type that is used to model a return type that may return one of two possible values.
  256. Either sealed class Either<out A, out B> { data class

    Left<out A, out B>(val a: A) : Either<A, B>() data class Right<out A, out B>(val b: B) : Either<A, B>() } Either is an Algebraic Data Type that is used to model a return type that may return one of two possible values.
  257. Either sealed class Either<out A, out B> { data class

    Left<out A, out B>(val a: A) : Either<A, B>() data class Right<out A, out B>(val b: B) : Either<A, B>() } Either is an Algebraic Data Type that is used to model a return type that may return one of two possible values.
  258. Either (Construction) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) val result: Either<DomainError, Int> = Left(UnknownUser) val result: Either<DomainError, Int> = 1.right() val result: Either<DomainError, Int> = UnknownUser.left()
  259. Either (Construction) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) val result: Either<DomainError, Int> = Left(UnknownUser) val result: Either<DomainError, Int> = 1.right() val result: Either<DomainError, Int> = UnknownUser.left()
  260. Either (Construction) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) val result: Either<DomainError, Int> = Left(UnknownUser) val result: Either<DomainError, Int> = 1.right() val result: Either<DomainError, Int> = UnknownUser.left()
  261. Either (Construction) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) val result: Either<DomainError, Int> = Left(UnknownUser) val result: Either<DomainError, Int> = 1.right() val result: Either<DomainError, Int> = UnknownUser.left()
  262. Either (Construction) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) val result: Either<DomainError, Int> = Left(UnknownUser) val result: Either<DomainError, Int> = 1.right() val result: Either<DomainError, Int> = UnknownUser.left()
  263. Either (Construction) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) val result: Either<DomainError, Int> = Left(UnknownUser) val result: Either<DomainError, Int> = 1.right() val result: Either<DomainError, Int> = UnknownUser.left()
  264. Either (Construction) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) val result: Either<DomainError, Int> = Left(UnknownUser) val result: Either<DomainError, Int> = 1.right() val result: Either<DomainError, Int> = UnknownUser.left()
  265. Either (Extraction - when) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) when (result) { is Left -> 0 is Right -> result.b } // Right(1)
  266. Either (Extraction - when) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) when (result) { is Left -> 0 is Right -> result.b } // Right(1)
  267. Either (Extraction - when) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) when (result) { is Left -> 0 is Right -> result.b } // Right(1)
  268. Either (Extraction - when) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) when (result) { is Left -> 0 is Right -> result.b } // Right(1)
  269. Either (Extraction - when) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) when (result) { is Left -> 0 is Right -> result.b } // Right(1) F
  270. Either (Extraction - when) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) when (result) { is Left -> 0 is Right -> result.b } // Right(1)
  271. Either (Extraction - when) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) when (result) { is Left -> 0 is Right -> result.b } // Right(1)
  272. Either (Extraction - fold) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) result.fold( { 0 }, { it + 1 } ) // Right(2)
  273. Either (Extraction - fold) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) result.fold( { 0 }, { it + 1 } ) // Right(2)
  274. Either (Extraction - fold) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) result.fold( { 0 }, { it + 1 } ) // Right(2)
  275. Either (Extraction - fold) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) result.fold( { 0 }, { it + 1 } ) // Right(2)
  276. Either (Extraction - fold) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) result.fold( { 0 }, { it + 1 } ) // Right(2)
  277. Either (Extraction - fold) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) result.fold( { 0 }, { it + 1 } ) // Right(2)
  278. Either (Extraction - fold) sealed class DomainError { /* ...

    */ } val result: Either<DomainError, Int> = Right(1) result.fold( { 0 }, { it + 1 } ) // Right(2)
  279. Either (map) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) result.map { it * 2 } // Right(2) val result: Either<DomainError, Int> = Left(UnknownUser) result.map { it * 2 } // Left(UnknownUser)
  280. Either (map) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) result.map { it * 2 } // Right(2) val result: Either<DomainError, Int> = Left(UnknownUser) result.map { it * 2 } // Left(UnknownUser)
  281. Either (map) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) result.map { it * 2 } // Right(2) val result: Either<DomainError, Int> = Left(UnknownUser) result.map { it * 2 } // Left(UnknownUser)
  282. Either (map) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) result.map { it * 2 } // Right(2) val result: Either<DomainError, Int> = Left(UnknownUser) result.map { it * 2 } // Left(UnknownUser)
  283. Either (map) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) result.map { it * 2 } // Right(2) val result: Either<DomainError, Int> = Left(UnknownUser) result.map { it * 2 } // Left(UnknownUser)
  284. Either (map) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) result.map { it * 2 } // Right(2) val result: Either<DomainError, Int> = Left(UnknownUser) result.map { it * 2 } // Left(UnknownUser)
  285. Either (map) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) result.map { it * 2 } // Right(2) val result: Either<DomainError, Int> = Left(UnknownUser) result.map { it * 2 } // Left(UnknownUser)
  286. Either (map) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) result.map { it * 2 } // Right(2) val result: Either<DomainError, Int> = Left(UnknownUser) result.map { it * 2 } // Left(UnknownUser)
  287. Either (map) sealed class DomainError { /* ... */ }

    val result: Either<DomainError, Int> = Right(1) result.map { it * 2 } // Right(2) val result: Either<DomainError, Int> = Left(UnknownUser) result.map { it * 2 } // Left(UnknownUser)
  288. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) result1.flatMap { one -> result2.map { two -> one + two } } // Right(3)
  289. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) result1.flatMap { one -> result2.map { two -> one + two } } // Right(3)
  290. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) result1.flatMap { one -> result2.map { two -> one + two } } // Right(3)
  291. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) result1.flatMap { one -> result2.map { two -> one + two } } // Right(3)
  292. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) result1.flatMap { one -> result2.map { two -> one + two } } // Right(3)
  293. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) result1.flatMap { one -> result2.map { two -> one + two } } // Right(3)
  294. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) result1.flatMap { one -> result2.map { two -> one + two } } // Right(3)
  295. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Left(UnknownUser) result1.flatMap { one -> result2.map { two -> one + two } } // Left(UnknownUser)
  296. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Left(UnknownUser) result1.flatMap { one -> result2.map { two -> one + two } } // Left(UnknownUser)
  297. Either (flatMap) sealed class DomainError { /* ... */ }

    val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Left(UnknownUser) result1.flatMap { one -> result2.map { two -> one + two } } // Left(UnknownUser)
  298. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Right(3)
  299. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Right(3)
  300. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Right(3)
  301. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Right(3)
  302. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Right(3)
  303. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Right(3)
  304. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Right(3)
  305. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Right(3)
  306. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Right(2) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Right(3)
  307. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Left(UnknownUser) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Left(UnknownUser)
  308. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Left(UnknownUser) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Left(UnknownUser)
  309. Either (Monad Binding) sealed class DomainError { /* ... */

    } val result1: Either<DomainError, Int> = Right(1) val result2: Either<DomainError, Int> = Left(UnknownUser) Either.monad<DomainError>.binding { val one = result1.bind() val two = result2.bind() one + two }.fix() // Left(UnknownUser)
  310. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  311. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  312. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  313. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  314. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  315. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  316. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  317. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  318. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  319. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  320. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Right(Water(0.6)) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Right(Americano(espresso=Espresso(%=0.4), water=Water(%=0.6)))
  321. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Left(RefillWater) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Left(RefillWater)
  322. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Left(RefillWater) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Left(RefillWater)
  323. Either (Applicative Builder) sealed class CoffeeMakerError { /* ... */

    } val espressoResult: Either<CoffeeMakerError, Espresso> = Right(Espresso(0.4)) val waterResult: Either<CoffeeMakerError, Water> = Left(RefillWater) Either.applicative<CoffeeMakerError>() .map(espressoResult, waterResult) { (espresso, water) -> Americano(espresso, water) }.fix() // Left(RefillWater)
  324. More… • Try // Success - Failure • Validated //

    Valid - Invalid • Eval // Now - Always - Later - Defer • TupleN // Tuple2 - Tuple22
  325. Typeclasses compile “io.arrow-kt:arrow-typeclasses:$arrow_version” kapt “io.arrow-kt:arrow-meta:$arrow_version”

  326. Typeclasses • Polymorphism in functional programming. • Separates data from

    behaviour. • Maybe governed by algebraic / category theoretic laws. • Implemented as interfaces in Kotlin. • One Typeclass instance per type.
  327. Typeclasses • Show • Eq • Semigroup • Functor •

    Monad • …
  328. Show interface Show<in A> { fun A.show(): String } The

    Show typeclass abstracts the ability to obtain a String representation of any object.
  329. Show interface Show<in A> { fun A.show(): String } The

    Show typeclass abstracts the ability to obtain a String representation of any object.
  330. Show interface Show<in A> { fun A.show(): String } The

    Show typeclass abstracts the ability to obtain a String representation of any object.
  331. Show interface Show<in A> { fun A.show(): String } The

    Show typeclass abstracts the ability to obtain a String representation of any object.
  332. Eq interface Eq<in F> { fun F.eqv(b: F): Boolean fun

    F.neqv(b: F): Boolean = !eqv(b) } The Eq typeclass abstracts the ability to compare two instances of any object. It can be compared to the typeclass equivalent of Java’s Object#equals.
  333. Eq interface Eq<in F> { fun F.eqv(b: F): Boolean fun

    F.neqv(b: F): Boolean = !eqv(b) } The Eq typeclass abstracts the ability to compare two instances of any object. It can be compared to the typeclass equivalent of Java’s Object#equals.
  334. Eq interface Eq<in F> { fun F.eqv(b: F): Boolean fun

    F.neqv(b: F): Boolean = !eqv(b) } The Eq typeclass abstracts the ability to compare two instances of any object. It can be compared to the typeclass equivalent of Java’s Object#equals.
  335. Eq interface Eq<in F> { fun F.eqv(b: F): Boolean fun

    F.neqv(b: F): Boolean = !eqv(b) } The Eq typeclass abstracts the ability to compare two instances of any object. It can be compared to the typeclass equivalent of Java’s Object#equals.
  336. Eq interface Eq<in F> { fun F.eqv(b: F): Boolean fun

    F.neqv(b: F): Boolean = !eqv(b) } The Eq typeclass abstracts the ability to compare two instances of any object. It can be compared to the typeclass equivalent of Java’s Object#equals.
  337. Semigroup interface Semigroup<A> { fun A.combine(b: A): A operator fun

    A.plus(b: A): A = this.combine(b) } The Semigroup for some given type A has a single operation combine which takes two values of type A, and returns a value of type A. This operation must be associative.
  338. Semigroup interface Semigroup<A> { fun A.combine(b: A): A operator fun

    A.plus(b: A): A = this.combine(b) } The Semigroup for some given type A has a single operation combine which takes two values of type A, and returns a value of type A. This operation must be associative.
  339. Semigroup interface Semigroup<A> { fun A.combine(b: A): A operator fun

    A.plus(b: A): A = this.combine(b) } The Semigroup for some given type A has a single operation combine which takes two values of type A, and returns a value of type A. This operation must be associative.
  340. Semigroup interface Semigroup<A> { fun A.combine(b: A): A operator fun

    A.plus(b: A): A = this.combine(b) } The Semigroup for some given type A has a single operation combine which takes two values of type A, and returns a value of type A. This operation must be associative.
  341. Semigroup interface Semigroup<A> { fun A.combine(b: A): A operator fun

    A.plus(b: A): A = this.combine(b) } The Semigroup for some given type A has a single operation combine which takes two values of type A, and returns a value of type A. This operation must be associative.
  342. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  343. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  344. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  345. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  346. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  347. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  348. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  349. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  350. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  351. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  352. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  353. Creating Instances data class Person(val firstName: String, val lastName: String)

    { companion object } @extension interface PersonShow : Show<Person> { override fun Person.show(): String = "$firstName $lastName" } val john = Person("John", "Doe") Person.show().run { john.show() } // John Doe
  354. More… • Hash • Order • Traverse • Applicative •

    And many more…
  355. Optics compile “io.arrow-kt:arrow-optics:$arrow_version” kapt “io.arrow-kt:arrow-meta:$arrow_version”

  356. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  357. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  358. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  359. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  360. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  361. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  362. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  363. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  364. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  365. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  366. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  367. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  368. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  369. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  370. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  371. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  372. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  373. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  374. Lens @optics data class UserProfile( val name: Name, /* Not

    shown for brevity */ val contact: Contact ) { companion object } @optics data class Contact( val email: String, val phone: String ) { companion object }
  375. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("john.doe@personal.com", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "john.doe@work.com" ) )
  376. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("john.doe@personal.com", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "john.doe@work.com" ) )
  377. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("john.doe@personal.com", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "john.doe@work.com" ) )
  378. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("john.doe@personal.com", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "john.doe@work.com" ) )
  379. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("john.doe@personal.com", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "john.doe@work.com" ) )
  380. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("john.doe@personal.com", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "john.doe@work.com" ) )
  381. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  382. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  383. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  384. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  385. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  386. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  387. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  388. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  389. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  390. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  391. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  392. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  393. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  394. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  395. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  396. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile) // “john.doe@work.com”
  397. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "john.doe@work.com" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  398. Optional @optics data class ShoppingCart( val id: String, val cartItems:

    ListK<CartItem> ) { companion object } @optics data class CartItem( val product: Product, /* Not shown for brevity */ val quantity: Int ) { companion object }
  399. Optional @optics data class ShoppingCart( val id: String, val cartItems:

    ListK<CartItem> ) { companion object } @optics data class CartItem( val product: Product, /* Not shown for brevity */ val quantity: Int ) { companion object }
  400. Optional @optics data class ShoppingCart( val id: String, val cartItems:

    ListK<CartItem> ) { companion object } @optics data class CartItem( val product: Product, /* Not shown for brevity */ val quantity: Int ) { companion object }
  401. Optional @optics data class ShoppingCart( val id: String, val cartItems:

    ListK<CartItem> ) { companion object } @optics data class CartItem( val product: Product, /* Not shown for brevity */ val quantity: Int ) { companion object }
  402. Optional @optics data class ShoppingCart( val id: String, val cartItems:

    ListK<CartItem> ) { companion object } @optics data class CartItem( val product: Product, /* Not shown for brevity */ val quantity: Int ) { companion object }
  403. Optional @optics data class ShoppingCart( val id: String, val cartItems:

    ListK<CartItem> ) { companion object } @optics data class CartItem( val product: Product, /* Not shown for brevity */ val quantity: Int ) { companion object }
  404. Optional @optics data class ShoppingCart( val id: String, val cartItems:

    ListK<CartItem> ) { companion object } @optics data class CartItem( val product: Product, /* Not shown for brevity */ val quantity: Int ) { companion object }
  405. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  406. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  407. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  408. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  409. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  410. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  411. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  412. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  413. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  414. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  415. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  416. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  417. Optional (Set) val shoppingCart = ShoppingCart("CRT19321", cartItems) val quantityOptional: Optional<ShoppingCart,

    Int> = ShoppingCart .cartItems .index(ListK.index(), productIndex) .quantity val updatedCart = quantityOptional.modify(shoppingCart) { it + 1 }
  418. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  419. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  420. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  421. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  422. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  423. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  424. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  425. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  426. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  427. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  428. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  429. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  430. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  431. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  432. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  433. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

    val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
  434. More… • Iso • Prism • Getter / Setter •

    Fold • Each • And others …
  435. That’s not it… • Arrow Fx • Effects • Arrow

    Query Language • Generic • Integrations • Free • Recursion Schemes
  436. Resources • https://arrow-kt.io/docs/ • http://learnyouahaskell.com/ • https://caster.io/courses/functional-programming-in-kotlin-with-arrow • https://github.com/hemanth/functional-programming-jargon#function •

    https://wiki.haskell.org/Typeclassopedia • http://nealford.com/functionalthinking.html • https://prod.packtpub.com/in/application-development/functional-kotlin
  437. end; @ragunathjawahar Twitter / Medium / GitHub