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

Functional Programming from OO perspective (Sayeret Lambda lecture)

on

  • 1,075 views

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

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

Statistics

Views

Total Views
1,075
Views on SlideShare
953
Embed Views
122

Actions

Likes
2
Downloads
19
Comments
0

1 Embed 122

http://jujo00obo2o234ungd3t8qjfcjrs3o6k-a-sites-opensocial.googleusercontent.com 122

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Functional Programming from OO perspective (Sayeret Lambda lecture) Functional Programming from OO perspective (Sayeret Lambda lecture) Presentation Transcript

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