Computation        FunctorAPPLICATIVE        For loop        Traverse
Computation              K[T]A type of            A type of valuecomputation
ComputationsZero or one    Option[T]Zero or more   List[T]Later          Future[T]Depend on S    State[S, T]Ext. effects  ...
Create computations?Option[T]     Some(t)List[T]       List(t)Future[T]     future(t)State[S, T]   state(s => (s, t))IO[T]...
Pointed         K[T].point(t)Compute a value
Use computations?Option[T]     Some(2)List[T]       List(1, 2)Future[T]     future(calculate)State[S, T]   state(s => (s, ...
FunctorK[T] map f           Use the value
Functors mapOption[T]     modify the valueList[T]       modify the valuesFuture[T]     modify laterState[S, T]   modify ts...
ApplicativeBeforegetUser(props: Properties): StringgetPassword(props: Properties): StringgetConnection(user: String, pw: S...
ApplicativeAftergetUser(props: Properties): Option[String]getPassword(props: Properties): Option[String]getConnection(user...
Applicativef(a, b)How?f(K[a], K[b])
Use Pointedf(a:A, b:B): Cpointfk: K[A => B => C]
Applicative    K[A => B] <*> K[A]            ==           K[B]Apply the function
Applicative    K[A => B => C] <*>    K[A]           <*> K[B]                ==         K[B => C] <*> K[B]                 ...
ApplicativeK(f) <*> K(a) <*> K(b)Apply ‘f’ to ‘a’ and ‘b’ “inside” ‘K’
ApplicativeK(f) <*> K(a) <*> K(b)Apply ‘f’ to ‘a’ and ‘b’ “inside” ‘K’
Applicative           OptionSome(getConnection.curried) <*>user(p)                     <*>password(p)
Applicative            Option(user(p) <**> password(p))(mkConnection)mkConnection <$> user(p) <*> password(p)
Applicative           Futurefuture(discount(_,_))) <*>future(amount)         <*>future(rate): Future[Double]
Applicative             ListList(plus1) <*> List(1, 2, 3)List(2, 3, 4)
Applicative             ListList(plus1, plus2) <*> List(1, 2, 3)== List(2, 3, 4, 3, 4, 5)ratings <*> clients
Applicative            ZipListList(plus1, plus2, plus3) <*>List(1,     2,     3)== List(1, 4, 6)
Applicative Stateval add     = (i: Int) => (j: Int) => i+jval times   = (i: Int) => (j: Int) => i*j// 0 -> 1, 2, 3, 4val s...
Applicative State                             current state            +1=2   +1=3(add     <$> s1 <*> s1)(1) == (3, 5)    ...
Monad, remember?Unitdef unit[A](a: =>A): M[A]Binddef bind[A, B](ma: M[A])(f: A => M[B]): M[B]
Monad => ApplicativePointdef point(a: =>A) = Monad[M].unit(a)Applydef <*>[A, B](mf: M[A=>B])(ma: M[A]):M[B] =  Monad[M].bi...
The “for” loopval basket = Basket(orange, apple)var count = 0val juices = Basket[Juice]()                                 ...
Traverse                        Traversabledef traverse(f: A => F[B]): T[A] => F[T[B]]                Applicative         ...
Traverse a ListList(x, y, z): List[A]f: A => F[B]
Traverse a List       Apply ‘f’ to ‘z’F(::) <*> F(z) <*> F(Nil)“Rebuild” the list F(z :: Nil)
Traverse a ListF(::) <*> F(y) <*> F(z :: Nil) F(y :: z :: Nil)F(::) <*> F(x) <*> F(y::z::Nil) F(x :: y :: z :: Nil)
Traverse a            Binary Tree    f                x                    y       zx                                x    ...
`sequence`def sequence[F: Applicative]:  T[F[A]] => F[T[A]] =   traverse(identity)
`sequence`Execute concurrently?val examples: Seq[Example] =  Seq(e1, e2, e3)                         Sequence of promisesv...
Measure with              Monoidstrait Monoid[A] {  val zero: A; def append(a: A, b: A): A}def measure[T: Traversable, M :...
`measure`def measure[T: Traversable, M : Monoid]  (f: A => M) = traverse(a => f(a))
`Const`                  “Phantom “ typecase class Const[M, +A](value: M)new Applicative[Const[M, *]] {  def point(a: =>A)...
Applicative => MonadUnitdef unit[A](a: =>A) = Const(Monoid[M].zero)Binddef bind[A, B](ma: Const[M, A])              (f: A ...
`measure`Sum up all sizesdef sumSizes[A : Size](seq: Seq[A]) =  measure(a => Size[A].size(a))(seq)Collect all sizesdef col...
`contents`def contents[A](tree: Tree[A]): List[A] =  measure(a => List(a))(tree)   x                     =>        List(x,...
`shape`def shape[A](tree: Tree[A]): Tree[Unit] =  map(a => ())(tree)   x                     =>        .       y     z    ...
`decompose`def decompose[A](tree: Tree[A]) =  (contents(tree), shape(tree))                               List(x, y, z)   ...
Applicative productscase class Product[F1[_], F2[_], A](  first: F1[A], second: F2[A])F1: Applicative, F2: Applicativedef ...
`contents               ⊗   shape`F1 = Const[List[A], *]F2 = Ident[*]val contents = (a: A) => Const[List[A], Unit](List(a)...
Type indifference One parameter type constructortrait Apply[F[_]] {  def <*>[A, B](f: F[A => B]): F[A] => F[B]}List[Int]:...
Type indifference Anonymous type ({type l[a]=Const[List[Int], a]})#lType member({type l[a]=Const[List[Int], a]})#lType pr...
Type indifference Measuredef measure[M : Monoid](f: T => M): M =  traverse(t => Monoid[M].unit(f(t))).valueFor real…def m...
`collect`Accumulate and mapdef collect[F[_] : Applicative, A, B]  (f: A => F[Unit], g: A => B) = {    traverse { a: A =>  ...
`disperse`Label and mapdef disperse(F[_] : Applicative, A, B, C]  (f: F[B], g: A => B => C): T[A] => F[T[C]]val tree = Bin...
EIP `measure`Map and countdef measure[F[_] : Applicative, A, B]  (f: F[B], g: A => C): T[A] => F[C]val crosses = modify((s...
Traversals                                           mapped depend state depend on   function   map element   create state...
Quizzdef findMatches(divs: Seq[Int], nums: Seq[Int])findMatches(Seq(2, 3, 4), Seq(1, 6, 7, 8, 9))=> Seq((2, 6), (3, 9), (4...
Quizzdef findMatches(divs: Seq[Int], nums: Seq[Int]) = {    case class S(matches: Seq[(Int, Int)] = Seq[(Int, Int)](),    ...
Compositionval results = new ListBufferfor (a <- as) {  val currentSize = a.size  total += currentSize  results.add(total)...
`assemble`Shape + content => assembleddef assemble[F[_] : Applicative, A]:  (f: F[Unit], g: List[A]): T[A] => F[A]val shap...
`assemble`def takeHead: State[List[B], Option[B]] =  state { s: List[B] =>    s match {      case Nil     => (Nil, None)  ...
`assemble`def assemble[F[_] : Applicative, A]  (f: F[Unit], list: List[A]) = traverse(takeHead).apply(list)
Monadic compositionM : Monadval f: B => M[C]val g: A => M[B]val h: A => M[C] = f   • gFusion?traverse(f) • traverse(g) == ...
Monadic compositionYes if the Monad is commutative val xy = for {                   val yx = for {   x <- (mx: M[X])      ...
Applicative composition vs       Monadic compositionNot commutative functions => fusionSeq(1,2,3).traverse(times2 ⊙ plus1)...
Monadic composition:            conjectureCommutative functionsval plus1 = (a: A) => state((n: Int) => (n+1, a))val plus2 ...
Monadic composition:             conjecture Commutative functions => fusionSeq(1,2,3).traverse(plus2 ∎ plus1) == 10Seq(1,2...
The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern (pdf)
Upcoming SlideShare
Loading in...5
×

The Essence of the Iterator Pattern (pdf)

564

Published on

The Essence of the Iterator Pattern (pdf version)

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
564
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
23
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "The Essence of the Iterator Pattern (pdf)"

  1. 1. Computation FunctorAPPLICATIVE For loop Traverse
  2. 2. Computation K[T]A type of A type of valuecomputation
  3. 3. ComputationsZero or one Option[T]Zero or more List[T]Later Future[T]Depend on S State[S, T]Ext. effects IO[T]
  4. 4. Create computations?Option[T] Some(t)List[T] List(t)Future[T] future(t)State[S, T] state(s => (s, t))IO[T] IO(t)
  5. 5. Pointed K[T].point(t)Compute a value
  6. 6. Use computations?Option[T] Some(2)List[T] List(1, 2)Future[T] future(calculate)State[S, T] state(s => (s, s+1))IO[T] IO(println(“hello”))
  7. 7. FunctorK[T] map f Use the value
  8. 8. Functors mapOption[T] modify the valueList[T] modify the valuesFuture[T] modify laterState[S, T] modify tsIO[T] modify the action
  9. 9. ApplicativeBeforegetUser(props: Properties): StringgetPassword(props: Properties): StringgetConnection(user: String, pw: String):Connection = { if (user != null && pw != null) ....}getConnection(getUser(p), getPassword(p))
  10. 10. ApplicativeAftergetUser(props: Properties): Option[String]getPassword(props: Properties): Option[String]getConnection(user: String, pw: String):Connection = { if (user != null && pw != null) ....}getConnection(?, ?)
  11. 11. Applicativef(a, b)How?f(K[a], K[b])
  12. 12. Use Pointedf(a:A, b:B): Cpointfk: K[A => B => C]
  13. 13. Applicative K[A => B] <*> K[A] == K[B]Apply the function
  14. 14. Applicative K[A => B => C] <*> K[A] <*> K[B] == K[B => C] <*> K[B] ==Currying ftw! K[C]
  15. 15. ApplicativeK(f) <*> K(a) <*> K(b)Apply ‘f’ to ‘a’ and ‘b’ “inside” ‘K’
  16. 16. ApplicativeK(f) <*> K(a) <*> K(b)Apply ‘f’ to ‘a’ and ‘b’ “inside” ‘K’
  17. 17. Applicative OptionSome(getConnection.curried) <*>user(p) <*>password(p)
  18. 18. Applicative Option(user(p) <**> password(p))(mkConnection)mkConnection <$> user(p) <*> password(p)
  19. 19. Applicative Futurefuture(discount(_,_))) <*>future(amount) <*>future(rate): Future[Double]
  20. 20. Applicative ListList(plus1) <*> List(1, 2, 3)List(2, 3, 4)
  21. 21. Applicative ListList(plus1, plus2) <*> List(1, 2, 3)== List(2, 3, 4, 3, 4, 5)ratings <*> clients
  22. 22. Applicative ZipListList(plus1, plus2, plus3) <*>List(1, 2, 3)== List(1, 4, 6)
  23. 23. Applicative Stateval add = (i: Int) => (j: Int) => i+jval times = (i: Int) => (j: Int) => i*j// 0 -> 1, 2, 3, 4val s1 = modify((i: Int) => i+1)(add <$> s1 <*> s1)(1) == ?(times <$> s1 <*> s1)(1) == ?
  24. 24. Applicative State current state +1=2 +1=3(add <$> s1 <*> s1)(1) == (3, 5) add 2 previous states +1=2 +1=3(times <$> s1 <*> s1)(1) == (3, 6) multiply 2 previous states
  25. 25. Monad, remember?Unitdef unit[A](a: =>A): M[A]Binddef bind[A, B](ma: M[A])(f: A => M[B]): M[B]
  26. 26. Monad => ApplicativePointdef point(a: =>A) = Monad[M].unit(a)Applydef <*>[A, B](mf: M[A=>B])(ma: M[A]):M[B] = Monad[M].bind(mf) { f => Monad[M].bind(ma) { a => f(a) // M[B] } // M[B] } // M[B]
  27. 27. The “for” loopval basket = Basket(orange, apple)var count = 0val juices = Basket[Juice]() accumulationfor (fruit <- basket) { count = count + 1 juices.add(fruit.press) “mapping”} same container for the result
  28. 28. Traverse Traversabledef traverse(f: A => F[B]): T[A] => F[T[B]] Applicative Same structure
  29. 29. Traverse a ListList(x, y, z): List[A]f: A => F[B]
  30. 30. Traverse a List Apply ‘f’ to ‘z’F(::) <*> F(z) <*> F(Nil)“Rebuild” the list F(z :: Nil)
  31. 31. Traverse a ListF(::) <*> F(y) <*> F(z :: Nil) F(y :: z :: Nil)F(::) <*> F(x) <*> F(y::z::Nil) F(x :: y :: z :: Nil)
  32. 32. Traverse a Binary Tree f x y zx x y z y z y z
  33. 33. `sequence`def sequence[F: Applicative]: T[F[A]] => F[T[A]] = traverse(identity)
  34. 34. `sequence`Execute concurrently?val examples: Seq[Example] = Seq(e1, e2, e3) Sequence of promisesval executing: Seq[Promise[Result]] = examples.map(e => promise(e.execute))val results: Promise[Seq[Result]] = executing.sequence Promise of a sequence
  35. 35. Measure with Monoidstrait Monoid[A] { val zero: A; def append(a: A, b: A): A}def measure[T: Traversable, M : Monoid] (f: A => M): T[A] => MCount elements: Int MonoidAccumulate elements: List Monoid
  36. 36. `measure`def measure[T: Traversable, M : Monoid] (f: A => M) = traverse(a => f(a))
  37. 37. `Const` “Phantom “ typecase class Const[M, +A](value: M)new Applicative[Const[M, *]] { def point(a: =>A) = Const(Monoid[M].zero) def <*>(f: Const[M, A=>B], a: Const[M, A]) = Const(Monoid[M].append(f.value, a.value))}
  38. 38. Applicative => MonadUnitdef unit[A](a: =>A) = Const(Monoid[M].zero)Binddef bind[A, B](ma: Const[M, A]) (f: A => Const[M, B]) ==> but no value `a: A` to be found!
  39. 39. `measure`Sum up all sizesdef sumSizes[A : Size](seq: Seq[A]) = measure(a => Size[A].size(a))(seq)Collect all sizesdef collectSizes[A : Size](seq: Seq[A]) = measure(a => List(Size[A].size(a)))(seq)
  40. 40. `contents`def contents[A](tree: Tree[A]): List[A] = measure(a => List(a))(tree) x => List(x, y, z) y z
  41. 41. `shape`def shape[A](tree: Tree[A]): Tree[Unit] = map(a => ())(tree) x => . y z . .def map[A, B](f: A => B): T[A] => traverse(a => Ident(f(a))) Identity monad
  42. 42. `decompose`def decompose[A](tree: Tree[A]) = (contents(tree), shape(tree)) List(x, y, z) x => y z . . . Not very efficient…
  43. 43. Applicative productscase class Product[F1[_], F2[_], A]( first: F1[A], second: F2[A])F1: Applicative, F2: Applicativedef point[A, B](a: => A) = Product[F1, F2, B](Pointed[F1].point(a), Pointed[F2].point(a))def <*>[A, B](f: Product[F1, F2, A => B]) = (c: Product[F1, F2, A]) => Product[F1, F2, B](f.first <*> c.first, f.second <*> c.second)
  44. 44. `contents ⊗ shape`F1 = Const[List[A], *]F2 = Ident[*]val contents = (a: A) => Const[List[A], Unit](List(a))val shape = (a: A) => Ident(())val contentsAndShape: A => Product[Const[List[A], _], Ident[_], *] = contents ⊗ shapetree.traverse(contentsAndShape)
  45. 45. Type indifference One parameter type constructortrait Apply[F[_]] { def <*>[A, B](f: F[A => B]): F[A] => F[B]}List[Int]: Monoid Applicative => Const[List[Int], _]({type l[a]=Const[List[Int], a]})#l
  46. 46. Type indifference Anonymous type ({type l[a]=Const[List[Int], a]})#lType member({type l[a]=Const[List[Int], a]})#lType projection({type l[a]=Const[List[Int], a]})#ltype ApplicativeProduct =({type l[a]=Product[Const[List[A],_],Ident[_],a]})#l
  47. 47. Type indifference Measuredef measure[M : Monoid](f: T => M): M = traverse(t => Monoid[M].unit(f(t))).valueFor real…def measure[M : Monoid](f: A => M): M = traverse[(type l[a]=Const[M, a]})#l, A, Any] { t => Monoid[M].point(f(t)) }.value
  48. 48. `collect`Accumulate and mapdef collect[F[_] : Applicative, A, B] (f: A => F[Unit], g: A => B) = { traverse { a: A => Applicative[F].point((u: Unit) => g(a)) <*> f(a)) }}val count = (i: Int) => state((n: Int) => (n+1, ()))val map = (i: Int) => i.toStringtree.collect(count, map).apply(0)  (2, Bin(Leaf("1"), Leaf("2")))
  49. 49. `disperse`Label and mapdef disperse(F[_] : Applicative, A, B, C] (f: F[B], g: A => B => C): T[A] => F[T[C]]val tree = Bin(Leaf(1.1), Bin(Leaf(2.2), Leaf(3.3)))val label = modify((n:Int) => n+1)val name = (p1:Double) => (p2:Int) => p1+" node is "+p2tree.disperse(label, name).apply(0)._2 Bin(Leaf("1.1 node is 1"), Bin(Leaf("2.2 node is 2"), Leaf("3.3 node is 3")))
  50. 50. EIP `measure`Map and countdef measure[F[_] : Applicative, A, B] (f: F[B], g: A => C): T[A] => F[C]val crosses = modify((s: String) => s+"x")val map = (i: Int) => i.toStringtree.measure(crosses, map).apply("")("xxx", Bin(Leaf("1"), Bin(Leaf("2"), Leaf("3"))))
  51. 51. Traversals mapped depend state depend on function map element create state on state elementcollect X X Xdisperse X X Xmeasure X Xtraverse X X X Xreduce X XreduceConst Xmap X
  52. 52. Quizzdef findMatches(divs: Seq[Int], nums: Seq[Int])findMatches(Seq(2, 3, 4), Seq(1, 6, 7, 8, 9))=> Seq((2, 6), (3, 9), (4, 8))With Traverse?
  53. 53. Quizzdef findMatches(divs: Seq[Int], nums: Seq[Int]) = { case class S(matches: Seq[(Int, Int)] = Seq[(Int, Int)](), remaining: Seq[Int]) val initialState = S(remaining = nums) def find(div: Int) = modify { (s: S) => s.remaining.find(_ % div == 0).map { (n: Int) => S(s.matches :+ div -> n, s.remaining - n) }.getOrElse(s) } divs.traverse(find).exec(initialState).matches}
  54. 54. Compositionval results = new ListBufferfor (a <- as) { val currentSize = a.size total += currentSize results.add(total)}F1 (map) then F2 (sum) F2 [F1[_]] => Applicative?
  55. 55. `assemble`Shape + content => assembleddef assemble[F[_] : Applicative, A]: (f: F[Unit], g: List[A]): T[A] => F[A]val shape: BinaryTree[Unit] = Bin(Leaf(()), Leaf(()))shape.assemble(List(1, 2)) (List(), Some(Bin(Leaf(1), Leaf(2))))shape.assemble(List(1, 2, 3)) (List(3), Some(Bin(Leaf(1), Leaf(2))))shape.assemble(List(1)) (List(), None)
  56. 56. `assemble`def takeHead: State[List[B], Option[B]] = state { s: List[B] => s match { case Nil => (Nil, None) case x :: xs => (xs, Some(x)) } } F1: Option[_] An element to insertF2 :State[List[A], _] the rest of the listF2 [F1]: State[List[A], Option[_]] An applicative
  57. 57. `assemble`def assemble[F[_] : Applicative, A] (f: F[Unit], list: List[A]) = traverse(takeHead).apply(list)
  58. 58. Monadic compositionM : Monadval f: B => M[C]val g: A => M[B]val h: A => M[C] = f • gFusion?traverse(f) • traverse(g) == traverse(f • g)
  59. 59. Monadic compositionYes if the Monad is commutative val xy = for { val yx = for { x <- (mx: M[X]) y <- (my: M[Y]) xy == yx y <- (my: M[Y]) x <- (mx: M[X]) } yield (x, y) } yield (x, y)State is *not* commutativeval mx = state((n: Int) => (n+1, n+1))val my = state((n: Int) => (n+1, n+1))xy.apply(0) == (2, (1, 2))yx.apply(0) == (2, (2, 1))
  60. 60. Applicative composition vs Monadic compositionNot commutative functions => fusionSeq(1,2,3).traverse(times2 ⊙ plus1) == 4 State[Int, State[Int, Seq[Int]]]Seq(1,2,3).traverse(times2) ⊙Seq(1,2,3).traverse(plus1) == 4 State[Int, Seq[State[Int, Int]]
  61. 61. Monadic composition: conjectureCommutative functionsval plus1 = (a: A) => state((n: Int) => (n+1, a))val plus2 = (a: A) => state((n: Int) => (n+2, a))val times2 = (a: A) => state((n: Int) => (n*2, a))plus1 and plus2 are commutativeplus1 and times2 are not commutative:(0 + 1) * 2 != (0 * 2) + 1
  62. 62. Monadic composition: conjecture Commutative functions => fusionSeq(1,2,3).traverse(plus2 ∎ plus1) == 10Seq(1,2,3).traverse(plus2) ∎ Seq(1,2,3).traverse(plus1) == 10 Not commutative functions => no fusionSeq(1,2,3).traverse(times2 ∎ plus1) == 22Seq(1,2,3).traverse(times2) ∎ Seq(1,2,3).traverse(plus1) == 32
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×