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.

Ragunath Jawahar

April 23, 2019
Tweet

More Decks by Ragunath Jawahar

Other Decks in Programming

Transcript

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

    array.indices) { if (array[i] == key) return i } return -1 }
  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): Index { for (i in

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

    array.indices) { if (array[i] == key) return i } return null } typealias Index = Int
  20. 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
  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 // absence // presence
  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
  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 <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
  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>, p: (A) -> Boolean): Option<Index> {

    for (i in array.indices) { if (p(array[i])) 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 // findFirst(people, { it.firstName == “Ajay” })
  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
  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 // findFirst(people) { it.firstName == “Ajay” }
  34. 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” }
  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
  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 } fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
  37. 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!
  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 add(a: Int, b: Int): Int = a + b

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

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

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

    val addRef: (Int, Int) -> Int = ::add val subtractLambda = { a: Int, b: Int -> a - b }
  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 } // (a: Int, b: Int) -> Int
  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 }
  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. 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
  73. 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
  74. 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”)
  75. 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>
  76. 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
  77. 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”)
  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 // <i>Hello</i>
  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 // boldItalic(“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><i>Hello</i></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 // italicBold(“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><b>Hello</b></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. 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
  87. 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
  88. 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
  89. 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
  90. 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
  91. 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
  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 // x2(10)
  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 // 20
  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
  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
  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 // x5(10)
  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 // 50
  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. 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 }
  106. 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 }
  107. 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 }
  108. 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 }
  109. 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 }
  110. 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 }
  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 } // findCat(animals)
  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 }
  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 } // findDog(animals)
  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. Logical Complement val onlyCats: (Animal) -> Boolean = { it

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

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

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

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

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

    is Cat } val allCats = filter(animals, onlyCats) val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
  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. 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)
  139. 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)
  140. 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)
  141. 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)
  142. 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)
  143. 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)
  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) // 100
  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)
  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) // 100
  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 (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)
  157. 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)
  158. 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)
  159. 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)
  160. 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)
  161. 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)
  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) // (height) -> (width)
  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) // (height, width)
  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) // (width, height)
  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)
  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)
  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) // 100
  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)
  169. More… • memoize() // FunctionN • firstOption() // Array, Sequence,

    and Iterable • flatten() - tail() - prependTo(List<T>) // List • plus(C) // TupleN • paired() - tripled() // FunctionN • pipe() // FunctionN
  170. 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.
  171. 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.
  172. 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.
  173. 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.
  174. 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.
  175. 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()
  176. 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()
  177. 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()
  178. 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()
  179. 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()
  180. 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()
  181. 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()
  182. Option (Extraction) val intOption: Option<Int> = Option(1) val nullableResult: Int?

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

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

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

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

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

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

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

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

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

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

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

    (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
  194. Option (map) val intOption: Option<Int> = Option(1) intOption.map { it

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    = None oneOption.flatMap { one -> twoOption.map { two -> one + two } } // None
  212. 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)
  213. 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)
  214. 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)
  215. 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)
  216. 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)
  217. 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)
  218. 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)
  219. 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)
  220. 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)
  221. 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
  222. 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
  223. 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
  224. 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)))
  225. 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)))
  226. 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)))
  227. 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)))
  228. 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)))
  229. 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)))
  230. 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)))
  231. 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)))
  232. 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)))
  233. 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)))
  234. 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)))
  235. 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
  236. 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
  237. 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
  238. 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.
  239. 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.
  240. 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.
  241. 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.
  242. 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.
  243. 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()
  244. 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()
  245. 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()
  246. 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()
  247. 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()
  248. 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()
  249. 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()
  250. Either (Extraction - when) sealed class DomainError { /* ...

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

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

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

    */ } val result: Either<DomainError, Int> = Right(1) when (result) { is Left -> 0 is Right -> result.b } // Right(1)
  254. 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
  255. Either (Extraction - when) sealed class DomainError { /* ...

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

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

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

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

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

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

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

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

    */ } val result: Either<DomainError, Int> = Right(1) result.fold( { 0 }, { it + 1 } ) // Right(2)
  264. 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)
  265. 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)
  266. 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)
  267. 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)
  268. 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)
  269. 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)
  270. 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)
  271. 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)
  272. 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)
  273. 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)
  274. 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)
  275. 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)
  276. 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)
  277. 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)
  278. 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)
  279. 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)
  280. 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)
  281. 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)
  282. 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)
  283. 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)
  284. 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)
  285. 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)
  286. 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)
  287. 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)
  288. 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)
  289. 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)
  290. 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)
  291. 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)
  292. 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)
  293. 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)
  294. 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)
  295. 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)))
  296. 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)))
  297. 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)))
  298. 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)))
  299. 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)))
  300. 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)))
  301. 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)))
  302. 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)))
  303. 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)))
  304. 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)))
  305. 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)))
  306. 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)
  307. 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)
  308. 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)
  309. More… • Try // Success - Failure • Validated //

    Valid - Invalid • Eval // Now - Always - Later - Defer • TupleN // Tuple2 - Tuple22
  310. 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.
  311. Show interface Show<in A> { fun A.show(): String } The

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

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

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

    Show typeclass abstracts the ability to obtain a String representation of any object.
  315. 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.
  316. 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.
  317. 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.
  318. 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.
  319. 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.
  320. 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.
  321. 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.
  322. 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.
  323. 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.
  324. 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.
  325. 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
  326. 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
  327. 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
  328. 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
  329. 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
  330. 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
  331. 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
  332. 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
  333. 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
  334. 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
  335. 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
  336. 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
  337. 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 }
  338. 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 }
  339. 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 }
  340. 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 }
  341. 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 }
  342. 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 }
  343. 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 }
  344. 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 }
  345. 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 }
  346. 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 }
  347. 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 }
  348. 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 }
  349. 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 }
  350. 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 }
  351. 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 }
  352. 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 }
  353. 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 }
  354. 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 }
  355. 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 }
  356. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
  357. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
  358. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
  359. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
  360. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
  361. Without Lens val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164")

    ) val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
  362. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  363. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  364. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  365. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  366. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  367. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  368. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  369. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  370. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  371. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  372. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  373. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  374. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  375. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  376. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  377. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile) // “[email protected]
  378. With Lens val profile = UserProfile( /* … */ )

    val emailLens: Lens<UserProfile, String> = UserProfile.contact.email val workEmail = "[email protected]" val updatedProfile = emailLens.modify(profile) { workEmail } val email = emailLens.get(profile)
  379. 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 }
  380. 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 }
  381. 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 }
  382. 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 }
  383. 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 }
  384. 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 }
  385. 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 }
  386. 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 }
  387. 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 }
  388. 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 }
  389. 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 }
  390. 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 }
  391. 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 }
  392. 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 }
  393. 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 }
  394. 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 }
  395. 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 }
  396. 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 }
  397. 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 }
  398. 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 }
  399. Optional (Get) val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Query Language • Generic • Integrations • Free • Recursion Schemes
  417. 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