Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
Próximos SlideShares
Carregando em…5
×

# Functional Programming from OO perspective (Sayeret Lambda lecture)

1.215 visualizações

A lecture about some FP concepts from an (impure) OO perspective.

• Full Name
Comment goes here.

Are you sure you want to Yes No
• Seja o primeiro a comentar

### Functional Programming from OO perspective (Sayeret Lambda lecture)

1. 1. Ittay Dror ittayd@tikalk.com @ittayd http://www.tikalk.com/blogs/ittayd Functional Programming From OOP perspective26-Oct-11
2. 2. What is FP? 2 WWW.TIKALK.COM
3. 3. “a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data” 3 WWW.TIKALK.COM
4. 4. • Functions as values• Immutable data structures• Mathematical models• Referential transparency 4 WWW.TIKALK.COM
5. 5. Why Should We Care? 5 WWW.TIKALK.COM
6. 6. Not everything is an object 6 WWW.TIKALK.COM
7. 7. May Forget Nothing toservice.init return?val data = service.getservice.close May forget / call twiceprintln(data) 7 WWW.TIKALK.COM
8. 8. IOC 8 WWW.TIKALK.COM
9. 9. class Service { def withData[T](f: Data => T) { init if (thereIsData) f(getData) close }}service.witData(println) 9 WWW.TIKALK.COM
10. 10. Simplification 10 WWW.TIKALK.COM
11. 11. In OOP: trait DataConsumer[T] { def withData(data: Data): T {In FP: Data => T 11 WWW.TIKALK.COM
12. 12. Factories are partially applied functions 12 WWW.TIKALK.COM
13. 13. val factory_: File => String => User = file => name => readFromFile(name)val factory: String => User = factory_(usersFile) Look ma, no interfaces 13 WWW.TIKALK.COM
14. 14. Security 14 WWW.TIKALK.COM
15. 15. Immutable data is sharable 15 WWW.TIKALK.COM
16. 16. Instead of modifying, create new 16 WWW.TIKALK.COM
17. 17. Abstraction 17 WWW.TIKALK.COM
18. 18. Functors, Applicatives, Monads 18 WWW.TIKALK.COM
19. 19. Usual way of describing: WTF?? 19 WWW.TIKALK.COM
20. 20. OO way: Design Patterns 20 WWW.TIKALK.COM
21. 21. Values in a context 21 WWW.TIKALK.COM
22. 22. Option[X]List[X]Future[X] 22 WWW.TIKALK.COM
23. 23. trait Future[A] { def get: A {def findUser(name: String): Future[User] = ……val future = findUser(userName)val user = future.getprintln(user) 23 WWW.TIKALK.COM
24. 24. trait Future[A] { def onReady(f: A => Unit) }val future = findUser(userName)future.onReady{user => println(user)} 24 WWW.TIKALK.COM
25. 25. Functor 25 WWW.TIKALK.COM
26. 26. trait Future[A] { def map[B](f: A => B): Future[B]{val user = findUser(userName)val age: Future[Int] = user.map{user => user.age} 26 WWW.TIKALK.COM
27. 27. val result = new ArrayList(list.size)for (i <- 0 to (list.size - 1)) { result += compute(list(i))}result Vs.list.map(compute) 27 WWW.TIKALK.COM
29. 29. trait Future[A] { def get: A def map[B](f: A => B) = new Future[B] { def get = f(Future.this.get) {{ 29 WWW.TIKALK.COM
30. 30. def marry(man: User, woman: User): Family = ⠄⠄⠄val joe = findUser("joe")val jane = findUser("jane") Get Joe and Jane married 30 WWW.TIKALK.COM
31. 31. Future[Family] User => Familyjoe.map{joe => jane.map{jane => marry(joe, jane)}} User => Future[Family] Future[Future[Family]] 31 WWW.TIKALK.COM
32. 32. Attempt Itrait Future[A] { def apply[B, C](other: Future[B], f: (A, B) =>C): Future[C]} joe.apply(jane, marry) 32 WWW.TIKALK.COM
33. 33. It is easier to work withsingle argument functions 33 WWW.TIKALK.COM
34. 34. Curried Functionsval func: Int => Int => Int = a => b => a + b (marry _).curried 34 WWW.TIKALK.COM
35. 35. Attempt IItrait Future[A] { ... def apply[B](f: Future[A => B]): Future[B]{ 35 WWW.TIKALK.COM
36. 36. Future[User => Family] User => User => Familyjoe.apply(jane.map((marry _).curried)) User => Future[Family] 36 WWW.TIKALK.COM
37. 37. We can do better 37 WWW.TIKALK.COM
38. 38. val marry: Future[User => User => Family] = Future(marry)val partial: Future[User => Family] = futureMarry.apply(joe)val family: Future[Family] = partial.apply(jane)Future(marry).apply(joe).apply(jane)Future(marry)(joe)(jane) Using apply compiles iff A is a function 38 WWW.TIKALK.COM
39. 39. Applicative Functors 39 WWW.TIKALK.COM
40. 40. • Put value in context• Apply function in a context to value ina context 40 WWW.TIKALK.COM
41. 41. trait Future[A] { def apply[B, C](b: Future[B]) (implicit ev: A <:< (B => C)) : Future[C]{object Future { def apply[A](a: A): Future[A]} Future((marry _).curried)(joe)(jane) 41 WWW.TIKALK.COM
42. 42. trait Future[A] { def apply[B, C](b: Future[B]) (implicit ev: A <:< (B => C)) = new Future[C] { def get = Future.this.get(b.get) {{object Future { def apply[A](a: A) = new Future[A] { def get = a } }} 42 WWW.TIKALK.COM
43. 43. Composing Functions thatReturn Value in a Context 43 WWW.TIKALK.COM
44. 44. Composing Special Functionsdef findUser(name: String): Future[User]def findProfile(user: User): Future[Profile]findProfile(findUser("joe")) 44 WWW.TIKALK.COM
46. 46. trait Future[A] { ... def flatMap[B](f: A => Future[B]): Future[B]}findUser("joe").flatMap(findProfile) 46 WWW.TIKALK.COM
47. 47. trait Future[A] { ... def flatMap[B](f: A => Future[B]): Future[B] = new Future[B] { def get = f(Future.this.get).get } }} 47 WWW.TIKALK.COM
48. 48. All Togethertrait Context[A] { def map[B](f: A => B): Context[B] def apply[B, C](b: Context[B]) (implicit ev: A <:< (B => C)): Context[C] def flatMap[B](f: A => Context[B]): Context[B]} 48 WWW.TIKALK.COM
49. 49. Laws 49 WWW.TIKALK.COM
50. 50. Idiomatic “interface” for context classes 50 WWW.TIKALK.COM
51. 51. Monoid• For type A to be (have) a Monoid: • Binary operation „•„: (A, A) => A • Identity element „∅‟: A 51 WWW.TIKALK.COM
52. 52. • String is a Monoid (2 ways): • Binary operation: append or prepend • Identity element: “”• Int is a Monoid (2 ways): • Binary operation: + or * • Identity element: 0 or 1 52 WWW.TIKALK.COM
53. 53. • Future[A] is a monoid, if A is a monoid • Binary operation: Future(A#•) • (Future as applicative) • Identity element: Future(A#identity) 53 WWW.TIKALK.COM
54. 54. Monoids generalize folds 54 WWW.TIKALK.COM
55. 55. Folds: reduce values to one• List(x,y,z) => ∅ • x • y • z• Option(x) => if Some ∅ • x else ∅ 55 WWW.TIKALK.COM
56. 56. Unfolds: Create values from initial value and function• 1, if (a < 3) Some(a, a+1) else None • Some(1, 2), Some(2, 3), None • ∅•1•2•3 • If our monoid is a List: • Nil ++ List(1) ++ List(2) ++ List(3) • List(1,2,3) 56 WWW.TIKALK.COM
57. 57. Since many things aremonoids, we can havemany generic algorithms 57 WWW.TIKALK.COM
58. 58. Problems with subtyping: • Namespace pollution • Need to control the class • Describes behavior, not „is-a‟ • Sometimes ability is conditional: • Future is a monoid if A is a monoid • Sometimes there are different definitions • E.g., 2 monoids for integers • Maybe a class has several facets • E.g. context of 2 values 58 WWW.TIKALK.COM
59. 59. Typeclass• Define an API• Create instance for each class thatcan conform to the API 59 WWW.TIKALK.COM
60. 60. Java example: Comparator 60 WWW.TIKALK.COM
61. 61. trait Functor[F[_]] { def map[A, B](fa: F[A], f: A => B): F[B]{implicit object FutureHasFunctor extends Functor[Future] { def map[A, B](t: Future[A], f: A => B) = new Future[B] { def get = f(t.get) } }{def age(name: String) = { val functor = implicitly[Functor[Future]] functor.map(findUser(name), {u: User => u.age})} 61 WWW.TIKALK.COM
62. 62. def age(name: String) (implicit functor: Functor[Future]) { functor.map(findUser(name), {u: User => u.age})} 62 WWW.TIKALK.COM
63. 63. def age[F[_] : Functor](name: String) { functor.map(findUser(name), {u: User => u.age})} 63 WWW.TIKALK.COM
64. 64. Generic Programming 64 WWW.TIKALK.COM
65. 65. def sequence[A, AP[_] : Applicative] (apas: List[AP[A]]): AP[List[A]]val futureOfList = sequence(listOfFutures) 65 WWW.TIKALK.COM
66. 66. trait Applicative[AP[_]] { def pure[A](a: A) : AP[A] def apply[A, B](ap: AP[A => B], a: AP[A]): AP[B]{ 66 WWW.TIKALK.COM
67. 67. It is NOT important if youdon’t understand the next slide 67 WWW.TIKALK.COM
68. 68. def sequence[A, AP[_] : Applicative](apas: List[AP[A]]): AP[List[A]] = { val applicative = implicitly[Applicative[AP]] import applicative._ val cons = pure{x: A => xs: List[A] => x :: xs} apas match { case Nil => pure(Nil) case apa :: apas => val recursion = sequence(apas) // AP[List[A]] val partial = apply(cons, apa) // AP[List[A]=>List[A]] apply(partial, recursion) }} 68 WWW.TIKALK.COM
69. 69. Beyond 69 WWW.TIKALK.COM
70. 70. val m = Map[Int, Int]()m.map{case (k, v) => k + v} 70 WWW.TIKALK.COM
71. 71. def map[B, That](f: A => B) (implicit bf: CanBuildFrom[Repr, B, That]) : That 71 WWW.TIKALK.COM
72. 72. ?72 WWW.TIKALK.COM