1 / 64

The Essence of the Iterator Pattern

( eip ). The Essence of the Iterator Pattern. Functor. Computation. For loop. APPLICATIVE. Traverse. Computation. K [T ]. A type of computation. A type of value. Computations. Option[T]. Zero or one. List[T]. Zero or more. Future[T]. Later. State[S, T]. Depend on S. IO[T].

goro
Download Presentation

The Essence of the Iterator Pattern

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. (eip) The Essence of the IteratorPattern

  2. Functor Computation For loop APPLICATIVE Traverse

  3. Computation K[T] A type of computation A type of value

  4. Computations Option[T] Zero or one List[T] Zero or more Future[T] Later State[S, T] Depend on S IO[T] Ext. effects

  5. 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)

  6. Pointed K[T].point(t) Compute a value

  7. 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”))

  8. Functor K[T] map f Use the value

  9. Functors map Option[T] modify the value List[T] modify the values Future[T] modify later State[S, T] modify ts IO[T] modify the action

  10. Applicative Before getUser(props: Properties): String getPassword(props: Properties): String getConnection(user: String, pw: String): Connection = { if (user != null && pw != null) .... } getConnection(getUser(p), getPassword(p))

  11. Applicative After getUser(props: Properties): Option[String] getPassword(props: Properties): Option[String] getConnection(user: String, pw: String): Connection = { if (user != null && pw != null) .... } getConnection(?, ?)

  12. Applicative f(a, b) How? f(K[a], K[b])

  13. Use Pointed f(a:A, b:B): C point fk: K[A => B => C]

  14. Applicative K[A => B] <*> K[A] == K[B] Apply the function

  15. Applicative K[A => B => C] <*> K[A] <*> K[B] == K[B => C] <*> K[B] == K[C] Currying ftw!

  16. Applicative K(f) <*> K(a) <*> K(b) Apply ‘f’ to ‘a’ and ‘b’ “inside” ‘K’

  17. Applicative K(f) <*> K(a) <*> K(b) Apply ‘f’ to ‘a’ and ‘b’ “inside” ‘K’

  18. Applicative Option Some(getConnection.curried) <*> user(p) <*> password(p)

  19. Applicative Option (user(p) <**> password(p))(mkConnection) mkConnection <$> user(p) <*> password(p)

  20. Applicative Future future(discount(_,_))) <*> future(amount) <*> future(rate) : Future[Double]

  21. Applicative List List(plus1) <*> List(1, 2, 3) List(2, 3, 4)

  22. Applicative List List(plus1, plus2) <*> List(1, 2, 3) == List(2, 3, 4, 3, 4, 5) • ratings <*> clients

  23. Applicative ZipList List(plus1, plus2, plus3) <*> List(1, 2, 3) == List(1, 4, 6)

  24. Applicative State val add = (i: Int) => (j: Int) => i+j val times = (i: Int) => (j: Int) => i*j // 0 -> 1, 2, 3, 4 val s1 = modify((i: Int) => i+1) (add <$> s1 <*> s1)(1) == ? (times <$> s1 <*> s1)(1) == ?

  25. 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

  26. Monad, remember? Unit def unit[A](a: =>A): M[A] Bind defbind[A, B](ma: M[A])(f: A => M[B]): M[B]

  27. Monad => Applicative Point defpoint(a: =>A) = Monad[M].unit(a) Apply def<*>[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]

  28. The “for” loop val basket =Basket(orange, apple)var count =0val juices =Basket[Juice]() for(fruit <- basket){ count = count +1juices.add(fruit.press)} accumulation “mapping” same container for the result

  29. Traverse Traversable def traverse(f: A => F[B]): T[A]=> F[T[B]] Applicative Same structure

  30. Traverse a List List(x, y, z): List[A] f: A => F[B]

  31. Traverse a List Apply ‘f’ to ‘z’ F(::) <*> F(z) <*> F(Nil) “Rebuild” the list • F(z :: Nil)

  32. Traverse a List • F(::) <*> F(y) <*> F(z :: Nil) • F(y :: z :: Nil) • F(::) <*> F(x) <*> F(y::z::Nil) • F(x:: y:: z :: Nil)

  33. Traverse a Binary Tree • f x y z x x y z y z y z

  34. `sequence` def sequence[F: Applicative]: T[F[A]]=> F[T[A]] = • traverse(identity)

  35. `sequence` Execute concurrently? • val examples: Seq[Example] = • Seq(e1, e2, e3) Sequence of promises • val executing: Seq[Promise[Result]] = • examples.map(e => promise(e.execute)) • val results: Promise[Seq[Result]] = executing.sequence Promise of a sequence

  36. Measure with Monoids traitMonoid[A] { val zero: A; def append(a: A, b: A): A } def measure[T: Traversable, M : Monoid] (f: A => M): T[A] => M Count elements: IntMonoid Accumulate elements: List Monoid

  37. `measure` def measure[T: Traversable, M : Monoid] (f: A => M) = traverse(a => f(a))

  38. `Const` “Phantom “ type case 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)) • }

  39. Applicative => Monad Unit def unit[A](a: =>A) = Const(Monoid[M].zero) Bind defbind[A, B](ma: Const[M, A]) (f: A => Const[M, B]) = => but no value `a: A` to be found!

  40. `measure` Sum up all sizes defsumSizes[A : Size](seq: Seq[A]) = measure(a => Size[A].size(a))(seq) Collect all sizes defcollectSizes[A : Size](seq: Seq[A]) = measure(a => List(Size[A].size(a)))(seq)

  41. `contents` def contents[A](tree: Tree[A]): List[A] = • measure(a => List(a))(tree) => x List(x, y, z) y z

  42. `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

  43. `decompose` def decompose[A](tree: Tree[A]) = (contents(tree), shape(tree)) List(x, y, z) => x . y z . . Not very efficient…

  44. Applicative products case classProduct[F1[_], F2[_], A]( first: F1[A], second: F2[A]) F1: Applicative, F2: Applicative • def 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)

  45. `contents ⊗shape` F1 = Const[List[A], *] F2 = Ident[*] • val contents =(a: A)=>Const[List[A],Unit](List(a)) val shape =(a: A)=>Ident(())valcontentsAndShape: • A => Product[Const[List[A], _], Ident[_], *] = • contents ⊗ shape • tree.traverse(contentsAndShape)

  46. Type indifference  One parameter type constructor • trait Apply[F[_]]{def <*>[A, B](f: F[A => B]): F[A]=> F[B]} List[Int]: MonoidApplicative => Const[List[Int], _] • ({type l[a]=Const[List[Int], a]})#l

  47. Type indifference  Anonymous type • ({type l[a]=Const[List[Int], a]})#l Type member • ({type l[a]=Const[List[Int], a]})#l Type projection • ({type l[a]=Const[List[Int], a]})#l • type ApplicativeProduct = • ({type l[a]=Product[Const[List[A],_],Ident[_],a]})#l

  48. Type indifference  Measure • def measure[M : Monoid](f: T => M): M = • traverse(t => Monoid[M].unit(f(t))).value For 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

  49. `collect` Accumulate and map def 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")))

More Related