Your SlideShare is downloading. ×
Functional Programming from OO perspective (Sayeret Lambda lecture)
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Functional Programming from OO perspective (Sayeret Lambda lecture)

829
views

Published on

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

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

Published in: Technology, Business

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
829
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
20
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Ittay Dror ittayd@tikalk.com @ittayd http://www.tikalk.com/blogs/ittayd Functional Programming From OOP perspective26-Oct-11
  • 2. What is FP? 2 WWW.TIKALK.COM
  • 3. “a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data” 3 WWW.TIKALK.COM
  • 4. • Functions as values• Immutable data structures• Mathematical models• Referential transparency 4 WWW.TIKALK.COM
  • 5. Why Should We Care? 5 WWW.TIKALK.COM
  • 6. Not everything is an object 6 WWW.TIKALK.COM
  • 7. May Forget Nothing toservice.init return?val data = service.getservice.close May forget / call twiceprintln(data) 7 WWW.TIKALK.COM
  • 8. IOC 8 WWW.TIKALK.COM
  • 9. class Service { def withData[T](f: Data => T) { init if (thereIsData) f(getData) close }}service.witData(println) 9 WWW.TIKALK.COM
  • 10. Simplification 10 WWW.TIKALK.COM
  • 11. In OOP: trait DataConsumer[T] { def withData(data: Data): T {In FP: Data => T 11 WWW.TIKALK.COM
  • 12. Factories are partially applied functions 12 WWW.TIKALK.COM
  • 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. Security 14 WWW.TIKALK.COM
  • 15. Immutable data is sharable 15 WWW.TIKALK.COM
  • 16. Instead of modifying, create new 16 WWW.TIKALK.COM
  • 17. Abstraction 17 WWW.TIKALK.COM
  • 18. Functors, Applicatives, Monads 18 WWW.TIKALK.COM
  • 19. Usual way of describing: WTF?? 19 WWW.TIKALK.COM
  • 20. OO way: Design Patterns 20 WWW.TIKALK.COM
  • 21. Values in a context 21 WWW.TIKALK.COM
  • 22. Option[X]List[X]Future[X] 22 WWW.TIKALK.COM
  • 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. trait Future[A] { def onReady(f: A => Unit) }val future = findUser(userName)future.onReady{user => println(user)} 24 WWW.TIKALK.COM
  • 25. Functor 25 WWW.TIKALK.COM
  • 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. 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
  • 28. class ComputeTask extends RecursiveTask { def compute = // split and callinvokeAll...{val pool = new ForkJoinPool()val task = new ComputeTask()pool.invoke(task) Vs.list.par.map(compute) 28 WWW.TIKALK.COM
  • 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. 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. Future[Family] User => Familyjoe.map{joe => jane.map{jane => marry(joe, jane)}} User => Future[Family] Future[Future[Family]] 31 WWW.TIKALK.COM
  • 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. It is easier to work withsingle argument functions 33 WWW.TIKALK.COM
  • 34. Curried Functionsval func: Int => Int => Int = a => b => a + b (marry _).curried 34 WWW.TIKALK.COM
  • 35. Attempt IItrait Future[A] { ... def apply[B](f: Future[A => B]): Future[B]{ 35 WWW.TIKALK.COM
  • 36. Future[User => Family] User => User => Familyjoe.apply(jane.map((marry _).curried)) User => Future[Family] 36 WWW.TIKALK.COM
  • 37. We can do better 37 WWW.TIKALK.COM
  • 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. Applicative Functors 39 WWW.TIKALK.COM
  • 40. • Put value in context• Apply function in a context to value ina context 40 WWW.TIKALK.COM
  • 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. 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. Composing Functions thatReturn Value in a Context 43 WWW.TIKALK.COM
  • 44. Composing Special Functionsdef findUser(name: String): Future[User]def findProfile(user: User): Future[Profile]findProfile(findUser("joe")) 44 WWW.TIKALK.COM
  • 45. Monads 45 WWW.TIKALK.COM
  • 46. trait Future[A] { ... def flatMap[B](f: A => Future[B]): Future[B]}findUser("joe").flatMap(findProfile) 46 WWW.TIKALK.COM
  • 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. 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. Laws 49 WWW.TIKALK.COM
  • 50. Idiomatic “interface” for context classes 50 WWW.TIKALK.COM
  • 51. Monoid• For type A to be (have) a Monoid: • Binary operation „•„: (A, A) => A • Identity element „∅‟: A 51 WWW.TIKALK.COM
  • 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. • 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. Monoids generalize folds 54 WWW.TIKALK.COM
  • 55. Folds: reduce values to one• List(x,y,z) => ∅ • x • y • z• Option(x) => if Some ∅ • x else ∅ 55 WWW.TIKALK.COM
  • 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. Since many things aremonoids, we can havemany generic algorithms 57 WWW.TIKALK.COM
  • 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. Typeclass• Define an API• Create instance for each class thatcan conform to the API 59 WWW.TIKALK.COM
  • 60. Java example: Comparator 60 WWW.TIKALK.COM
  • 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. def age(name: String) (implicit functor: Functor[Future]) { functor.map(findUser(name), {u: User => u.age})} 62 WWW.TIKALK.COM
  • 63. def age[F[_] : Functor](name: String) { functor.map(findUser(name), {u: User => u.age})} 63 WWW.TIKALK.COM
  • 64. Generic Programming 64 WWW.TIKALK.COM
  • 65. def sequence[A, AP[_] : Applicative] (apas: List[AP[A]]): AP[List[A]]val futureOfList = sequence(listOfFutures) 65 WWW.TIKALK.COM
  • 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. It is NOT important if youdon’t understand the next slide 67 WWW.TIKALK.COM
  • 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. Beyond 69 WWW.TIKALK.COM
  • 70. val m = Map[Int, Int]()m.map{case (k, v) => k + v} 70 WWW.TIKALK.COM
  • 71. def map[B, That](f: A => B) (implicit bf: CanBuildFrom[Repr, B, That]) : That 71 WWW.TIKALK.COM
  • 72. ?72 WWW.TIKALK.COM