Functional Programming with Arrow in Kotlin@ragunathjawahar • Obvious (previously, Uncommon Bangalore)
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Int { for (i in array.indices) { if (array[i] == key) return i } return -1 }
fun findFirst(array: Array<Char>, key: Char): Index { for (i in array.indices) { if (array[i] == key) return i } return -1 }
typealias Index = Int
fun findFirst(array: Array<Char>, key: Char): Index { for (i in array.indices) { if (array[i] == key) return i } return -1 }
typealias Index = Int
fun findFirst(array: Array<Char>, key: Char): Index { for (i in array.indices) { if (array[i] == key) return i } return -1 }
typealias Index = Int
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
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
fun findFirst(array: Array<Char>, key: Char): Index { for (i in array.indices) { if (array[i] == key) return i } return -1 }
typealias Index = Int
fun findFirst(array: Array<Char>, key: Char): Index? { for (i in array.indices) { if (array[i] == key) return i } return null }
typealias Index = Int
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
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
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
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
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
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
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
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
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
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” })
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” }
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
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
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” }
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” }
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
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 }
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!
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!
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!
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!
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!
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!
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!
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!
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!
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!
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!
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!
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!
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!
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!
Core Ideas
Core Ideas
• Purity
• Referential Transparency
• Immutability
• Lazy Evaluation
Notations
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
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
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
fun add(a: Int, b: Int): Int = a + b
val addRef: (Int, Int) -> Int = ::add
val subtractLambda = { a: Int, b: Int -> a - b }
val addRef: (Int, Int) -> Int = ::add
addRef.invoke(4, 5)
addRef(4, 5)
Arrow Syntaxcompile "io.arrow-kt:arrow-syntax:$arrow_version"
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
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
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”)
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>
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
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”)
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>
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
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”)
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>
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
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”)
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>
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
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
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
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
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
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
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
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
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
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)
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
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
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
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
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
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
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
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)
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
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
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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)
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 }
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 }
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 }
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 }
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 }
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 }
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)
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 }
Logical Complement
val onlyCats: (Animal) -> Boolean = { it is Cat } val allCats = filter(animals, onlyCats)
val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
Logical Complement
val onlyCats: (Animal) -> Boolean = { it is Cat } val allCats = filter(animals, onlyCats)
val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
Logical Complement
val onlyCats: (Animal) -> Boolean = { it is Cat } val allCats = filter(animals, onlyCats)
val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
Logical Complement
val onlyCats: (Animal) -> Boolean = { it is Cat } val allCats = filter(animals, onlyCats)
val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
Logical Complement
val onlyCats: (Animal) -> Boolean = { it is Cat } val allCats = filter(animals, onlyCats)
val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
Logical Complement
val onlyCats: (Animal) -> Boolean = { it is Cat } val allCats = filter(animals, onlyCats)
val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
Logical Complement
val onlyCats: (Animal) -> Boolean = { it is Cat } val allCats = filter(animals, onlyCats)
val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
Logical Complement
val onlyCats: (Animal) -> Boolean = { it is Cat } val allCats = filter(animals, onlyCats)
val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
Logical Complement
val onlyCats: (Animal) -> Boolean = { it is Cat } val allCats = filter(animals, onlyCats)
val noCats = onlyCats.complement() val allExceptCats = filter(animals, noCats)
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)
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)
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)
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)
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)
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)
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)
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
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
More…
• memoize() // FunctionN
• firstOption() // Array, Sequence, and Iterable
• flatten() - tail() - prependTo(List<T>) // List
• plus(C) // TupleN
• paired() - tripled() // FunctionN
• pipe() // FunctionN
Data Typescompile “io.arrow-kt:arrow-core-data:$arrow_version”
Data Types
• Option
• Either
• Try
• Validated
• Eval
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.
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.
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.
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.
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.
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()
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()
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()
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()
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()
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()
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()
Option (Extraction)
val intOption: Option<Int> = Option(1)
val nullableResult: Int? = intOption.orNull()
val result: Int = intOption.getOrElse { 0 }
Option (Extraction)
val intOption: Option<Int> = Option(1)
val nullableResult: Int? = intOption.orNull()
val result: Int = intOption.getOrElse { 0 }
Option (Extraction)
val intOption: Option<Int> = Option(1)
val nullableResult: Int? = intOption.orNull()
val result: Int = intOption.getOrElse { 0 }
Option (Extraction)
val intOption: Option<Int> = Option(1)
val nullableResult: Int? = intOption.orNull()
val result: Int = intOption.getOrElse { 0 }
Option (Extraction)
val intOption: Option<Int> = Option(1)
val nullableResult: Int? = intOption.orNull()
val result: Int = intOption.getOrElse { 0 }
Option (Extraction - when)
val intOption: Option<Int> = Option(1)
when (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
Option (Extraction - when)
val intOption: Option<Int> = Option(1)
when (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
Option (Extraction - when)
val intOption: Option<Int> = Option(1)
when (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
Option (Extraction - when)
val intOption: Option<Int> = Option(1)
when (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
Option (Extraction - when)
val intOption: Option<Int> = Option(1)
when (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
Option (Extraction - when)
val intOption: Option<Int> = Option(1)
when (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
Option (Extraction - when)
val intOption: Option<Int> = Option(1)
when (intOption) { is None -> 0 is Some -> intOption.t } // Some(1)
Option (Extraction - fold)
val intOption: Option<Int> = Option(1)
intOption.fold( { 0 }, { it + 1 } ) // Some(2)
Option (Extraction - fold)
val intOption: Option<Int> = Option(1)
intOption.fold( { 0 }, { it + 1 } ) // Some(2)
Option (Extraction - fold)
val intOption: Option<Int> = Option(1)
intOption.fold( { 0 }, { it + 1 } ) // Some(2)
Option (Extraction - fold)
val intOption: Option<Int> = Option(1)
intOption.fold( { 0 }, { it + 1 } ) // Some(2)
Option (Extraction - fold)
val intOption: Option<Int> = Option(1)
intOption.fold( { 0 }, { it + 1 } ) // Some(2)
Option (Extraction - fold)
val intOption: Option<Int> = Option(1)
intOption.fold( { 0 }, { it + 1 } ) // Some(2)
Option (Extraction - fold)
val intOption: Option<Int> = Option(1)
intOption.fold( { 0 }, { it + 1 } ) // Some(2)
Option (map)
val intOption: Option<Int> = Option(1) intOption.map { it * 2 } // Some(2)
val intOption: Option<Int> = None intOption.map { it * 2 } // None
Option (map)
val intOption: Option<Int> = Option(1) intOption.map { it * 2 } // Some(2)
val intOption: Option<Int> = None intOption.map { it * 2 } // None
Option (map)
val intOption: Option<Int> = Option(1) intOption.map { it * 2 } // Some(2)
val intOption: Option<Int> = None intOption.map { it * 2 } // None
Option (map)
val intOption: Option<Int> = Option(1) intOption.map { it * 2 } // Some(2)
val intOption: Option<Int> = None intOption.map { it * 2 } // None
Option (map)
val intOption: Option<Int> = Option(1) intOption.map { it * 2 } // Some(2)
val intOption: Option<Int> = None intOption.map { it * 2 } // None
Option (map)
val intOption: Option<Int> = Option(1) intOption.map { it * 2 } // Some(2)
val intOption: Option<Int> = None intOption.map { it * 2 } // None
Option (map)
val intOption: Option<Int> = Option(1) intOption.map { it * 2 } // Some(2)
val intOption: Option<Int> = None intOption.map { it * 2 } // None
Option (map)
val intOption: Option<Int> = Option(1) intOption.map { it * 2 } // Some(2)
val intOption: Option<Int> = None intOption.map { it * 2 } // None
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = Option(2)
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = Option(2)
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = Option(2)
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = Option(2)
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = Option(2)
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = Option(2)
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = Option(2)
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // Some(3)
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = None
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // None
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = None
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // None
Option (flatMap)
val oneOption: Option<Int> = Option(1) val twoOption: Option<Int> = None
oneOption.flatMap { one -> twoOption.map { two -> one + two } } // None
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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
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
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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
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
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
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.
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.
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.
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.
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.
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()
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()
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()
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()
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()
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()
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()
Either (Extraction - when)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
when (result) { is Left -> 0 is Right -> result.b } // Right(1)
Either (Extraction - when)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
when (result) { is Left -> 0 is Right -> result.b } // Right(1)
Either (Extraction - when)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
when (result) { is Left -> 0 is Right -> result.b } // Right(1)
Either (Extraction - when)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
when (result) { is Left -> 0 is Right -> result.b } // Right(1)
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
Either (Extraction - when)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
when (result) { is Left -> 0 is Right -> result.b } // Right(1)
Either (Extraction - when)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
when (result) { is Left -> 0 is Right -> result.b } // Right(1)
Either (Extraction - fold)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
result.fold( { 0 }, { it + 1 } ) // Right(2)
Either (Extraction - fold)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
result.fold( { 0 }, { it + 1 } ) // Right(2)
Either (Extraction - fold)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
result.fold( { 0 }, { it + 1 } ) // Right(2)
Either (Extraction - fold)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
result.fold( { 0 }, { it + 1 } ) // Right(2)
Either (Extraction - fold)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
result.fold( { 0 }, { it + 1 } ) // Right(2)
Either (Extraction - fold)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
result.fold( { 0 }, { it + 1 } ) // Right(2)
Either (Extraction - fold)
sealed class DomainError { /* ... */ }
val result: Either<DomainError, Int> = Right(1)
result.fold( { 0 }, { it + 1 } ) // Right(2)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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)))
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)
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)
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)
More…
• Try // Success - Failure
• Validated // Valid - Invalid
• Eval // Now - Always - Later - Defer
• TupleN // Tuple2 - Tuple22
Typeclassescompile “io.arrow-kt:arrow-typeclasses:$arrow_version” kapt “io.arrow-kt:arrow-meta:$arrow_version”
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.
Typeclasses
• Show
• Eq
• Semigroup
• Functor
• Monad
• …
Show
interface Show<in A> { fun A.show(): String }
The Show typeclass abstracts the ability to obtain a String representation of any object.
Show
interface Show<in A> { fun A.show(): String }
The Show typeclass abstracts the ability to obtain a String representation of any object.
Show
interface Show<in A> { fun A.show(): String }
The Show typeclass abstracts the ability to obtain a String representation of any object.
Show
interface Show<in A> { fun A.show(): String }
The Show typeclass abstracts the ability to obtain a String representation of any object.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
Creating Instancesdata 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
More…
• Hash
• Order
• Traverse
• Applicative
• And many more…
Opticscompile “io.arrow-kt:arrow-optics:$arrow_version” kapt “io.arrow-kt:arrow-meta:$arrow_version”
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
Without Lens
val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164") )
val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
Without Lens
val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164") )
val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
Without Lens
val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164") )
val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
Without Lens
val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164") )
val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
Without Lens
val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164") )
val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
Without Lens
val profile = UserProfile( Name("John", "Doe"), Contact("[email protected]", "6483920164") )
val updatedProfile = profile.copy( contact = profile.contact.copy( email = "[email protected]" ) )
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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]”
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)
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
Optional (Get)
val cartItemOption = ShoppingCart .cartItems .index(ListK.index(), productIndex) .getOption(shoppingCart)
val sameCartItemOption = ListK.index<CartItem>().run { ShoppingCart.cartItems[productIndex].getOption(shoppingCart) }
More…
• Iso
• Prism
• Getter / Setter
• Fold
• Each
• And others …
That’s not it…
• Arrow Fx
• Effects
• Arrow Query Language
• Generic
• Integrations
• Free
• Recursion Schemes
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
end;@ragunathjawaharTwitter / Medium / GitHub