Sunghyun Hwang
April 22, 2018
1.2k

# Practical FP in Kotlin

[Droid Knights 2018](https://droidknights.github.io/2018/) 에서 발표한 [Practical FP in Kotlin] 발표 자료 입니다.

April 22, 2018

## Transcript

4. ### •Language Features (that aid) • Immutable Data • First Class

Function • Tail Call Optimization •Programming Techniques (to write) • Map • Reduce • Recursion • Currying •Advantages (of Functional Program) • Parallelization • Lazy Evaluation • Determinism •Language Features (that aid) • Immutable Data • First Class Function • Tail Call Optimization •Programming Techniques (to write) • Map • Reduce • Recursion • Currying •Advantages (of Functional Program) • Parallelization • Lazy Evaluation • Determinism When “FP” is told
5. ### When “FP” is told fun someFancyFunc(f: (Int) -> Int): Int

{ val immutable = random() tailrec fun fancy(n: Int, acc: Int): Int = if (n > 1) { fancy(n - 1, acc + f(n)) } else { acc } return fancy(immutable, 0) }
6. ### fun someFancyFunc(f: (Int) -> Int): Int { val immutable =

random() tailrec fun fancy(n: Int, acc: Int): Int = if (n > 1) { fancy(n - 1, acc + f(n)) } else { acc } return fancy(immutable, 0) } fun someFancyFunc(f: (Int) -> Int): Int { val immutable = random() tailrec fun fancy(n: Int, acc: Int): Int = if (n > 1) { fancy(n - 1, acc + f(n)) } else { acc } return fancy(immutable, 0) } When “FP” is told
7. ### fun someFancyFunc(f: (Int) -> Int): Int { val immutable =

random() tailrec fun fancy(n: Int, acc: Int): Int = if (n > 1) { fancy(n - 1, acc + f(n)) } else { acc } return fancy(immutable, 0) } fun someFancyFunc(f: (Int) -> Int): Int { val immutable = random() tailrec fun fancy(n: Int, acc: Int): Int = if (n > 1) { fancy(n - 1, acc + f(n)) } else { acc } return fancy(immutable, 0) } When “FP” is told
8. ### fun someFancyFunc(f: (Int) -> Int): Int { val immutable =

random() tailrec fun fancy(n: Int, acc: Int): Int = if (n > 1) { fancy(n - 1, acc + f(n)) } else { acc } return fancy(immutable, 0) } fun someFancyFunc(f: (Int) -> Int): Int { val immutable = random() tailrec fun fancy(n: Int, acc: Int): Int = if (n > 1) { fancy(n - 1, acc + f(n)) } else { acc } return fancy(immutable, 0) } When “FP” is told
9. ### fun someFancyFunc(f: (Int) -> Int): Int { val immutable =

random() tailrec fun fancy(n: Int, acc: Int): Int = if (n > 1) { fancy(n - 1, acc + f(n)) } else { acc } return fancy(immutable, 0) } fun someFancyFunc(f: (Int) -> Int): Int { val immutable = random() tailrec fun fancy(n: Int, acc: Int): Int = if (n > 1) { fancy(n - 1, acc + f(n)) } else { acc } return fancy(immutable, 0) } When “FP” is told
10. ### fun main(args : Array<String>) { val f: (Int) -> Int

= { i -> i * 2 } someFancyFunc(f) // 130 someFancyFunc(f) // 340 someFancyFunc(f) // 88 } fun main(args : Array<String>) { val f: (Int) -> Int = { i -> i * 2 } someFancyFunc(f) // 130 someFancyFunc(f) // 340 someFancyFunc(f) // 88 } When “FP” is told
11. ### fun main(args : Array<String>) { val f: (Int) -> Int

= { i -> i * 2 } someFancyFunc(f) // 130 someFancyFunc(f) // 340 someFancyFunc(f) // 88 } fun main(args : Array<String>) { val f: (Int) -> Int = { i -> i * 2 } someFancyFunc(f) // 130 someFancyFunc(f) // 340 someFancyFunc(f) // 88 } When “FP” is told
12. ### fun main(args : Array<String>) { val f: (Int) -> Int

= { i -> i * 2 } someFancyFunc(f) // 130 someFancyFunc(f) // 340 someFancyFunc(f) // 88 } fun main(args : Array<String>) { val f: (Int) -> Int = { i -> i * 2 } someFancyFunc(f) // 130 someFancyFunc(f) // 340 someFancyFunc(f) // 88 } When “FP” is told
13. ### fun main(args : Array<String>) { val f: (Int) -> Int

= { i -> i * 2 } someFancyFunc(f) // 130 someFancyFunc(f) // 340 someFancyFunc(f) // 88 } When “FP” is told
14. ### Functional Code Functional code is characterized by one thing: the

absence of side eﬀects. It (a pure function) doesn’t rely on data outside the current function, and it doesn’t change data that exists outside the current function. [1]

16. ### fun fibonacci(n: Int): Int { if (n <= 2) {

return 1 } var a = 1 var b = 1 for (i in 2 until n) { val c = a + b a = b b = c } return b } Imperative Programming
17. ### fun fibonacci(n: Int): Int { if (n <= 2) {

return 1 } var a = 1 var b = 1 for (i in 2 until n) { val c = a + b a = b b = c } return b } fun fibonacci(n: Int): Int { if (n <= 2) { return 1 } var a = 1 var b = 1 for (i in 2 until n) { val c = a + b a = b b = c } return b } Imperative Programming
18. ### fun fibonacci(n: Int): Int { if (n < 2) {

return 1 } var a = 1 var b = 1 for (i in 2 until n) { val c = a + b a = b b = c } return b } fun fibonacci(n: Int): Int { if (n <= 2) { return 1 } var a = 1 var b = 1 for (i in 2 until n) { val c = a + b a = b b = c } return b } Imperative Programming
19. ### Imperative programming is a programming paradigm that uses statements that

change a program’s state. It consists of a series of commands for the computer to perform. It focuses on describing the details of how a program operates. [2]

21. ### fun fibonacci(n: Int): Int { return if (n <= 2)

{ 1 } else { fibonacci(n-1) + fibonacci(n - 2) } } Declarative Programming
22. ### Declarative programming is a programming paradigm that expresses the logic

of a computation without describing its control ﬂow. [3]
23. ### Functional programming is a programming paradigm that treats computation as

the evaluation of mathematical functions and avoids changing-state and mutable data. [4]
24. ### •Language Features (that aid) • Immutable Data • First Class

Function • Tail Call Optimization •Programming Techniques (to write) • Map • Reduce • Recursion • Currying •Advantages (of Functional Program) • Parallelization • Lazy Evaluation • Determinism •Language Features (that aid) • Immutable Data • First Class Function • Tail Call Optimization •Programming Techniques (to write) • Map • Reduce • Recursion • Currying •Advantages (of Functional Program) • Parallelization • Lazy Evaluation • Determinism When “FP” is told
25. ### •Language Features (that aid) • Immutable Data • First Class

Function • Tail Call Optimization •Programming Techniques (to write) • Map • Reduce • Recursion • Currying •Advantages (of Functional Program) • Parallelization • Lazy Evaluation • Determinism •Language Features (that aid) • Immutable Data • First Class Function • Tail Call Optimization •Programming Techniques (to write) • Map • Reduce • Recursion • Currying •Advantages (of Functional Program) • Parallelization • Lazy Evaluation • Determinism When “FP” is told
26. ### Disclaimer •Practical Approaches for FP •Category Theory (ex. Functor, Monad,

…) •Currying, Closure, …
27. ### Disclaimer •Practical Approaches for FP •Category Theory (ex. Functor, Monad,

…) •Currying, Closure, …
28. ### Disclaimer •Practical Approaches for FP •Category Theory (ex. Functor, Monad,

…) •Currying, Closure, …

31. ### 1. Writing pure functions is easy, but combining them into

a complete application is where things get hard. (…) 4. Because you can’t mutate existing data, you instead use a pattern that I call, “Update as you copy.” 5. Pure functions and I/O don’t really mix. (…) [5] 1. Writing pure functions is easy, but combining them into a complete application is where things get hard. (…) 4. Because you can’t mutate existing data, you instead use a pattern that I call, “Update as you copy.” 5. Pure functions and I/O don’t really mix. (…) [5]

34. ### interface PizzaView : PizzaRepository { fun getPizza(): Pizza = pizzas()[0]

} interface PizzaView { val r: PizzaRepository fun getPizza(): Pizza = r.pizzas()[0] }
35. ### interface PizzaView : PizzaRepository { fun getPizza(): Pizza = pizzas()[0]

} interface PizzaView { val r: PizzaRepository fun getPizza(): Pizza = r.pizzas()[0] }
36. ### interface PizzaRepositoryImpl : PizzaRepository { override fun pizzas(): List<Pizza> =

listOf( Pizza("Cheese Pizza"), Pizza("Some Pizza") ) }
37. ### val obj = object : PizzaView, PizzaRepositoryImpl {} val obj

= object : PizzaView, PizzaRepositoryImpl { override val repository: PizzaRepository get() = this }
38. ### val obj = object : PizzaView, PizzaRepositoryImpl {} val obj

= object : PizzaView, PizzaRepositoryImpl { override val repository: PizzaRepository get() = this }

}

42. ### 1. Writing pure functions is easy, but combining them into

a complete application is where things get hard. (…) 4. Because you can’t mutate existing data, you instead use a pattern that I call, “Update as you copy.” 5. Pure functions and I/O don’t really mix. (…) [5] 1. Writing pure functions is easy, but combining them into a complete application is where things get hard. (…) 4. Because you can’t mutate existing data, you instead use a pattern that I call, “Update as you copy.” 5. Pure functions and I/O don’t really mix. (…) [5]

)
44. ### 1. Writing pure functions is easy, but combining them into

a complete application is where things get hard. (…) 4. Because you can’t mutate existing data, you instead use a pattern that I call, “Update as you copy.” 5. Pure functions and I/O don’t really mix. (…) [5] 1. Writing pure functions is easy, but combining them into a complete application is where things get hard. (…) 4. Because you can’t mutate existing data, you instead use a pattern that I call, “Update as you copy.” 5. Pure functions and I/O don’t really mix. (…) [5]
45. ### "The I/O monad does not make a function pure. It

just makes it obvious that it’s impure.” — Martin Odersky

48. ### interface PizzaView : PizzaRepository { fun getPizzas(): IO<Pizza> = pizzas().map

{ p -> p.copy(name = p.name.reversed()) } }
49. ### data class PizzaViewModel( val displayName: String, val color: Color )

interface PizzaActivityLike : PizzaView { fun onGetPizzasButtonClicked( sth: Boolean ): IO<PizzaViewModel> = getPizzas().filter { /* sth */ }.map { p -> toPizzaViewModel(p) } }

}
51. ### interface PizzaRepositoryImpl : PizzaRepository { override fun pizza(): Pizza {

// What if no pizzas are available? return db.getPizzaFromDb() } }
52. ### interface PizzaRepositoryImpl : PizzaRepository { override fun pizza(): Pizza? {

return try { db.getPizzaFromDb() } catch (oop: OutOfPizzaException) { null } } }
53. ### interface PizzaRepositoryImpl : PizzaRepository { override fun pizza(): Either<Pizza, Exception>

{ return try { Left(db.getPizzaFromDb()) } catch (oop: OutOfPizzaException) { Right(oop) } } }
54. ### sealed class ShadowOfPizza data class RealPizza(val p: Pizza) : ShadowOfPizza()

object OutOfPizza : ShadowOfPizza() interface PizzaRepositoryImpl : PizzaRepository { override fun pizza(): ShadowOfPizza { return try { RealPizza(db.getPizzaFromDb()) } catch (oop: OutOfPizzaException) { OutOfPizza } } }
55. ### 1. Use interface always 2. Use only data class 3.

Let impure jobs happen only in impure layers 4. Let exception happen only in impure layers 1. Use interface always 2. Use only data class 3. Let impure jobs happen only in impure layers 4. Let exception happen only in impure layers .map( )
56. ### 1. Use interface always 2. Use only data class 3.

Let impure jobs happen only in impure layers 4. Let exception happen only in impure layers 1. Use interface always 2. Use only data class 3. Let impure jobs happen only in impure layers 4. Let exception happen only in impure layers .map( )
57. ### 1. Use interface always 2. Use only data class 3.

Let impure jobs happen only in impure layers 4. Let exception happen only in impure layers 1. Use interface always 2. Use only data class 3. Let impure jobs happen only in impure layers 4. Let exception happen only in impure layers .map( )
58. ### 1. Use interface always 2. Use only data class 3.

Let impure jobs happen only in impure layers 4. Let exception happen only in impure layers 1. Use interface always 2. Use only data class 3. Let impure jobs happen only in impure layers 4. Let exception happen only in impure layers .map( )
59. ### We are hiring! https://rainist.com/recruit/engineer • Back-end Engineer (Scala) • Data

Engineer • Data Scientist • Android Engineer (Kotlin) • iOS Engineer • QA Engineer • Security Engineer • … X Engineer

61. ### References (1) https://maryrosecook.com/blog/post/a-practical-introduction- to-functional-programming (2) https://en.wikipedia.org/wiki/Imperative_programming (3) https://en.wikipedia.org/wiki/Declarative_programming (4) https://en.wikipedia.org/wiki/Functional_programming

(5) Alvin Alexander, <Functional Programming, Simpliﬁed> p.101