SlideShare a Scribd company logo
The Essence of the Iterator Pattern
Computati     Functo
    on           r

APPLICATIVE        For loop
        Traverse
Computation

              K[T]
A type of            A type of value
computation
Computations
Zero or one    Option[T]
Zero or more   List[T]
Later          Future[T]
Depend on S    State[S, T]
Ext. effects   IO[T]
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)
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, s+1))

IO[T]         IO(println(“hello”))
Functor

K[T] map f

           Use the value
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
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))
Applicative
After
getUser(props: Properties): Option[String]
getPassword(props: Properties): Option[String]

getConnection(user: String, pw: String):
Connection = {
  if (user != null && pw != null)
    ....
}


getConnection(?, ?)
Applicative

f(a, b)
How?

f(K[a], K[b])
Use Pointed

f(a:A, b:B): C
point

fk: 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]
                 ==

Currying ftw!
                K[C]
Applicative

K(f) <*> K(a) <*> K(b)



Apply „f‟ to „a‟ and „b‟ “inside” „K‟
Applicative

K(f) <*> K(a) <*> K(b)



Apply „f‟ to „a‟ and „b‟ “inside” „K‟
Applicative
           Option

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

(user(p) <**> password(p))(mkConnection)

mkConnection <$> user(p) <*> password(p)
Applicative
           Future

future(discount(_,_))) <*>
future(amount)         <*>
future(rate)

: Future[Double]
Applicative
              List
List(plus1) <*> List(1, 2, 3)




List(2, 3, 4)
Applicative
              List

List(plus1, plus2) <*> List(1, 2, 3)



== List(2, 3, 4, 3, 4, 5)

ratings <*> clients
Applicative
            ZipList

List(plus1, plus2, plus3) <*>

List(1,    2,      3)


== List(1, 4, 6)
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) == ?
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
Monad, remember?
Unit
def unit[A](a: =>A): M[A]


Bind
def bind[A, B](ma: M[A])(f: A => M[B]): M[B]
Monad => Applicative
Point
def point(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]
The “for” loop
val basket = Basket(orange, apple)
var count = 0

val juices = Basket[Juice]()
                                 accumulation
for (fruit <- basket) {
  count = count + 1
  juices.add(fruit.press)              “mapping”
}

 same container for the result
The Essence of the Iterator Pattern
Traverse
                        Traversable
def traverse(f: A => F[B]): T[A] => F[T[B]]


                Applicative             Same
                                      structure
Traverse a List

List(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 List

F(::) <*> 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       z

x
                                x
        y   z   y       z
                                    y   z
`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 promises
val executing: Seq[Promise[Result]] =
  examples.map(e => promise(e.execute))

val results: Promise[Seq[Result]] =
  executing.sequence

                        Promise of a sequence
Measure with
              Monoids
trait Monoid[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:        Int Monoid
Accumulate elements:   List Monoid
`measure`

def measure[T: Traversable, M : Monoid]
  (f: A => M) =

 traverse(a => f(a))
`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))
}
Applicative => Monad

Unit
def unit[A](a: =>A) = Const(Monoid[M].zero)


Bind
def bind[A, B](ma: Const[M, A])
              (f: A => Const[M, B]) =
=> but no value `a: A` to be found!
`measure`
Sum up all sizes
def sumSizes[A : Size](seq: Seq[A]) =
  measure(a => Size[A].size(a))(seq)


Collect all sizes
def collectSizes[A : Size](seq: Seq[A]) =
  measure(a => List(Size[A].size(a)))(seq)
`contents`
def contents[A](tree: Tree[A]): List[A] =
  measure(a => List(a))(tree)




   x
                     =>        List(x, y, z)

       y     z
`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
`decompose`
def decompose[A](tree: Tree[A]) =
  (contents(tree), shape(tree))


                               List(x, y, z)

   x
                     =>
       y     z                 .

                                    .     .



                              Not very efficient…
Applicative products
case class Product[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)
`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 ⊗ shape


tree.traverse(contentsAndShape)
Type indifference 
One parameter type constructor
trait 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
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
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
`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.toString

tree.collect(count, map).apply(0)
  (2, Bin(Leaf("1"), Leaf("2")))
`disperse`
Label and map
def 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 "+p2

tree.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")))
EIP `measure`
Map and count
def 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.toString

tree.measure(crosses, map).apply("")
("xxx", Bin(Leaf("1"), Bin(Leaf("2"),
                             Leaf("3"))))
Traversals

                                           mapped depend state depend on
   function   map element   create state
                                              on state       element

collect           X              X                              X
disperse          X              X               X
measure           X              X
traverse          X              X               X              X
reduce                           X                              X
reduceConst                      X
map               X
Quizz
def 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?
Quizz
def 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
}
Composition
val results = new ListBuffer

for (a <- as) {
  val currentSize = a.size
  total += currentSize
  results.add(total)
}

F1 (map) then F2 (sum)
     F2 [F1[_]] => Applicative?
`assemble`
Shape + content => assembled
def 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)
`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 insert

F2 :State[List[A], _]           the rest of the list

F2 [F1]: State[List[A], Option[_]]     An applicative
`assemble`
def assemble[F[_] : Applicative, A]
  (f: F[Unit], list: List[A]) =

 traverse(takeHead).apply(list)
Monadic composition
M : Monad
val f: B => M[C]
val g: A => M[B]

val h: A => M[C] = f   • g


Fusion?
traverse(f) • traverse(g) == traverse(f • g)
Monadic composition
Yes 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* commutative
val 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))
Applicative composition vs
      Monadic composition
Not commutative functions => fusion
Seq(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]]
Monadic composition:
            conjecture
Commutative functions
val 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 commutative
plus1 and times2 are not commutative:

(0 + 1) * 2 != (0 * 2) + 1
Monadic composition:
             conjecture
 Commutative functions => fusion
Seq(1,2,3).traverse(plus2 ∎ plus1) == 10
Seq(1,2,3).traverse(plus2) ∎
  Seq(1,2,3).traverse(plus1) == 10



 Not commutative functions => no fusion
Seq(1,2,3).traverse(times2 ∎ plus1) == 22
Seq(1,2,3).traverse(times2) ∎
  Seq(1,2,3).traverse(plus1) == 32

More Related Content

PDF
The Essence of the Iterator Pattern (pdf)
Eric Torreborre
 
PDF
Oh, All the things you'll traverse
Luka Jacobowitz
 
PDF
Monoids, monoids, monoids
Luka Jacobowitz
 
PDF
Testing in the World of Functional Programming
Luka Jacobowitz
 
PDF
Principled Error Handling with FP
Luka Jacobowitz
 
PPTX
(2015 06-16) Three Approaches to Monads
Lawrence Evans
 
PDF
Scala Functional Patterns
league
 
PDF
Traversals for all ocasions
Luka Jacobowitz
 
The Essence of the Iterator Pattern (pdf)
Eric Torreborre
 
Oh, All the things you'll traverse
Luka Jacobowitz
 
Monoids, monoids, monoids
Luka Jacobowitz
 
Testing in the World of Functional Programming
Luka Jacobowitz
 
Principled Error Handling with FP
Luka Jacobowitz
 
(2015 06-16) Three Approaches to Monads
Lawrence Evans
 
Scala Functional Patterns
league
 
Traversals for all ocasions
Luka Jacobowitz
 

What's hot (17)

PDF
Monoids, Monoids, Monoids - ScalaLove 2020
Luka Jacobowitz
 
PPTX
Introduction to Monads in Scala (1)
stasimus
 
PPTX
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov Vyacheslav
Vyacheslav Arbuzov
 
PDF
Functor Laws
Philip Schwarz
 
PDF
02 arrays
Rajan Gautam
 
PDF
Programs in array using SWIFT
vikram mahendra
 
PDF
Data import-cheatsheet
Dieudonne Nahigombeye
 
PDF
Perm winter school 2014.01.31
Vyacheslav Arbuzov
 
PPTX
하스켈 프로그래밍 입문 3
Kwang Yul Seo
 
PDF
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
Filippo Vitale
 
PPTX
Running Free with the Monads
kenbot
 
PPTX
하스켈 프로그래밍 입문 4
Kwang Yul Seo
 
PPTX
Seminar PSU 10.10.2014 mme
Vyacheslav Arbuzov
 
PDF
Why The Free Monad isn't Free
Kelley Robinson
 
PDF
The Ring programming language version 1.5.4 book - Part 22 of 185
Mahmoud Samir Fayed
 
PDF
20090622 Bp Study#22
Tomohito Ozaki
 
PPTX
Seminar psu 20.10.2013
Vyacheslav Arbuzov
 
Monoids, Monoids, Monoids - ScalaLove 2020
Luka Jacobowitz
 
Introduction to Monads in Scala (1)
stasimus
 
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov Vyacheslav
Vyacheslav Arbuzov
 
Functor Laws
Philip Schwarz
 
02 arrays
Rajan Gautam
 
Programs in array using SWIFT
vikram mahendra
 
Data import-cheatsheet
Dieudonne Nahigombeye
 
Perm winter school 2014.01.31
Vyacheslav Arbuzov
 
하스켈 프로그래밍 입문 3
Kwang Yul Seo
 
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
Filippo Vitale
 
Running Free with the Monads
kenbot
 
하스켈 프로그래밍 입문 4
Kwang Yul Seo
 
Seminar PSU 10.10.2014 mme
Vyacheslav Arbuzov
 
Why The Free Monad isn't Free
Kelley Robinson
 
The Ring programming language version 1.5.4 book - Part 22 of 185
Mahmoud Samir Fayed
 
20090622 Bp Study#22
Tomohito Ozaki
 
Seminar psu 20.10.2013
Vyacheslav Arbuzov
 
Ad

Viewers also liked (7)

PDF
Iterator Pattern
melbournepatterns
 
PPTX
C# Strings
Hock Leng PUAH
 
PPTX
Iterator - a powerful but underappreciated design pattern
Nitin Bhide
 
PDF
Iterator
melbournepatterns
 
PPT
Iterator Design Pattern
Varun Arora
 
PPT
Programming in c#
Shehrevar Davierwala
 
PPTX
C# Tutorial
Jm Ramos
 
Iterator Pattern
melbournepatterns
 
C# Strings
Hock Leng PUAH
 
Iterator - a powerful but underappreciated design pattern
Nitin Bhide
 
Iterator Design Pattern
Varun Arora
 
Programming in c#
Shehrevar Davierwala
 
C# Tutorial
Jm Ramos
 
Ad

Similar to The Essence of the Iterator Pattern (20)

PDF
Monad Transformers In The Wild
StackMob Inc
 
PDF
High Wizardry in the Land of Scala
djspiewak
 
PDF
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
PROIDEA
 
PPT
Functional programming in scala
Siarhiej Siemianchuk
 
PDF
Essence of the iterator pattern
Markus Klink
 
PDF
Fp in scala with adts
Hang Zhao
 
PDF
Monads and Monoids by Oleksiy Dyagilev
JavaDayUA
 
PDF
A bit about Scala
Vladimir Parfinenko
 
PDF
Scala-对Java的修正和超越
Caoyuan Deng
 
PPTX
Introduction to Monads in Scala (2)
stasimus
 
PDF
Monadologie
league
 
PDF
ハイブリッド言語Scalaを使う
bpstudy
 
PDF
Demystifying functional programming with Scala
Denis
 
PPT
An introduction to scala
Mohsen Zainalpour
 
PDF
Event Sourcing and Functional Programming
GlobalLogic Ukraine
 
PDF
Functional Programming & Event Sourcing - a pair made in heaven
Pawel Szulc
 
PDF
Ti1220 Lecture 7: Polymorphism
Eelco Visser
 
PPTX
Practically Functional
djspiewak
 
PDF
110617 lt
yamadamasaki
 
PDF
Fp in scala with adts part 2
Hang Zhao
 
Monad Transformers In The Wild
StackMob Inc
 
High Wizardry in the Land of Scala
djspiewak
 
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
PROIDEA
 
Functional programming in scala
Siarhiej Siemianchuk
 
Essence of the iterator pattern
Markus Klink
 
Fp in scala with adts
Hang Zhao
 
Monads and Monoids by Oleksiy Dyagilev
JavaDayUA
 
A bit about Scala
Vladimir Parfinenko
 
Scala-对Java的修正和超越
Caoyuan Deng
 
Introduction to Monads in Scala (2)
stasimus
 
Monadologie
league
 
ハイブリッド言語Scalaを使う
bpstudy
 
Demystifying functional programming with Scala
Denis
 
An introduction to scala
Mohsen Zainalpour
 
Event Sourcing and Functional Programming
GlobalLogic Ukraine
 
Functional Programming & Event Sourcing - a pair made in heaven
Pawel Szulc
 
Ti1220 Lecture 7: Polymorphism
Eelco Visser
 
Practically Functional
djspiewak
 
110617 lt
yamadamasaki
 
Fp in scala with adts part 2
Hang Zhao
 

More from Eric Torreborre (20)

PDF
Shoehorning dependency injection into a FP language
Eric Torreborre
 
PDF
Shoehorning dependency injection into a FP language, what does it take?
Eric Torreborre
 
PDF
Boost your command line applications with potions!
Eric Torreborre
 
PDF
wire-all-the-things-lambda-days-2023.pdf
Eric Torreborre
 
PDF
The many faces of modularity
Eric Torreborre
 
PDF
What haskell taught us when we were not looking
Eric Torreborre
 
PDF
Wire once, rewire twice! (Haskell exchange-2018)
Eric Torreborre
 
PDF
Pratical eff-functional-conf
Eric Torreborre
 
PDF
Specs2, from starters to dessert and... a look in the kitchen
Eric Torreborre
 
PDF
Streaming, effects and beautiful folds: a winning trilogy
Eric Torreborre
 
PPTX
Pratical eff-scalaitaly-2017
Eric Torreborre
 
PDF
Pratical eff monad at Scaladays Chicago
Eric Torreborre
 
PDF
Pratical eff
Eric Torreborre
 
PPT
The Eff monad, one monad to rule them all
Eric Torreborre
 
PPT
Easy di-slideshare
Eric Torreborre
 
PPT
Data generation, the hard parts
Eric Torreborre
 
PPT
Origami, a monadic fold library for Scala
Eric Torreborre
 
PPT
Datatypes for the real world
Eric Torreborre
 
PPT
Specs2 3.4
Eric Torreborre
 
PPTX
DSLs with fold algebras
Eric Torreborre
 
Shoehorning dependency injection into a FP language
Eric Torreborre
 
Shoehorning dependency injection into a FP language, what does it take?
Eric Torreborre
 
Boost your command line applications with potions!
Eric Torreborre
 
wire-all-the-things-lambda-days-2023.pdf
Eric Torreborre
 
The many faces of modularity
Eric Torreborre
 
What haskell taught us when we were not looking
Eric Torreborre
 
Wire once, rewire twice! (Haskell exchange-2018)
Eric Torreborre
 
Pratical eff-functional-conf
Eric Torreborre
 
Specs2, from starters to dessert and... a look in the kitchen
Eric Torreborre
 
Streaming, effects and beautiful folds: a winning trilogy
Eric Torreborre
 
Pratical eff-scalaitaly-2017
Eric Torreborre
 
Pratical eff monad at Scaladays Chicago
Eric Torreborre
 
Pratical eff
Eric Torreborre
 
The Eff monad, one monad to rule them all
Eric Torreborre
 
Easy di-slideshare
Eric Torreborre
 
Data generation, the hard parts
Eric Torreborre
 
Origami, a monadic fold library for Scala
Eric Torreborre
 
Datatypes for the real world
Eric Torreborre
 
Specs2 3.4
Eric Torreborre
 
DSLs with fold algebras
Eric Torreborre
 

Recently uploaded (20)

PDF
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
PPTX
Introduction to Flutter by Ayush Desai.pptx
ayushdesai204
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PPTX
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
PDF
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
PPTX
Dev Dives: Automate, test, and deploy in one place—with Unified Developer Exp...
AndreeaTom
 
PPTX
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
PDF
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
PDF
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
PDF
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
PDF
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
PDF
Brief History of Internet - Early Days of Internet
sutharharshit158
 
PDF
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 
PDF
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
PDF
The Future of Artificial Intelligence (AI)
Mukul
 
PDF
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
PDF
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
PDF
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
PDF
Get More from Fiori Automation - What’s New, What Works, and What’s Next.pdf
Precisely
 
PPTX
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
Introduction to Flutter by Ayush Desai.pptx
ayushdesai204
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
Dev Dives: Automate, test, and deploy in one place—with Unified Developer Exp...
AndreeaTom
 
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
Brief History of Internet - Early Days of Internet
sutharharshit158
 
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
The Future of Artificial Intelligence (AI)
Mukul
 
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
Get More from Fiori Automation - What’s New, What Works, and What’s Next.pdf
Precisely
 
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 

The Essence of the Iterator Pattern

  • 2. Computati Functo on r APPLICATIVE For loop Traverse
  • 3. Computation K[T] A type of A type of value computation
  • 4. Computations Zero or one Option[T] Zero or more List[T] Later Future[T] Depend on S State[S, T] Ext. effects IO[T]
  • 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(?, ?)
  • 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] == Currying ftw! K[C]
  • 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 def bind[A, B](ma: M[A])(f: A => M[B]): M[B]
  • 27. Monad => Applicative Point def point(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 = 0 val juices = Basket[Juice]() accumulation for (fruit <- basket) { count = count + 1 juices.add(fruit.press) “mapping” } same container for the result
  • 30. Traverse Traversable def traverse(f: A => F[B]): T[A] => F[T[B]] Applicative Same structure
  • 31. Traverse a List List(x, y, z): List[A] f: A => F[B]
  • 32. Traverse a List Apply „f‟ to „z‟ F(::) <*> F(z) <*> F(Nil) “Rebuild” the list F(z :: Nil)
  • 33. 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)
  • 34. Traverse a Binary Tree f x y z x x y z y z y z
  • 35. `sequence` def sequence[F: Applicative]: T[F[A]] => F[T[A]] = traverse(identity)
  • 36. `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
  • 37. Measure with Monoids trait Monoid[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: Int Monoid Accumulate elements: List Monoid
  • 38. `measure` def measure[T: Traversable, M : Monoid] (f: A => M) = traverse(a => f(a))
  • 39. `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)) }
  • 40. Applicative => Monad Unit def unit[A](a: =>A) = Const(Monoid[M].zero) Bind def bind[A, B](ma: Const[M, A]) (f: A => Const[M, B]) = => but no value `a: A` to be found!
  • 41. `measure` Sum up all sizes def sumSizes[A : Size](seq: Seq[A]) = measure(a => Size[A].size(a))(seq) Collect all sizes def collectSizes[A : Size](seq: Seq[A]) = measure(a => List(Size[A].size(a)))(seq)
  • 42. `contents` def contents[A](tree: Tree[A]): List[A] = measure(a => List(a))(tree) x => List(x, y, z) y z
  • 43. `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
  • 44. `decompose` def decompose[A](tree: Tree[A]) = (contents(tree), shape(tree)) List(x, y, z) x => y z . . . Not very efficient…
  • 45. Applicative products case class Product[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)
  • 46. `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 ⊗ shape tree.traverse(contentsAndShape)
  • 47. Type indifference  One parameter type constructor trait 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
  • 48. 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
  • 49. 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
  • 50. `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.toString tree.collect(count, map).apply(0)  (2, Bin(Leaf("1"), Leaf("2")))
  • 51. `disperse` Label and map def 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 "+p2 tree.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")))
  • 52. EIP `measure` Map and count def 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.toString tree.measure(crosses, map).apply("") ("xxx", Bin(Leaf("1"), Bin(Leaf("2"), Leaf("3"))))
  • 53. Traversals mapped depend state depend on function map element create state on state element collect X X X disperse X X X measure X X traverse X X X X reduce X X reduceConst X map X
  • 54. Quizz def 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?
  • 55. Quizz def 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 }
  • 56. Composition val results = new ListBuffer for (a <- as) { val currentSize = a.size total += currentSize results.add(total) } F1 (map) then F2 (sum) F2 [F1[_]] => Applicative?
  • 57. `assemble` Shape + content => assembled def 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)
  • 58. `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 insert F2 :State[List[A], _] the rest of the list F2 [F1]: State[List[A], Option[_]] An applicative
  • 59. `assemble` def assemble[F[_] : Applicative, A] (f: F[Unit], list: List[A]) = traverse(takeHead).apply(list)
  • 60. Monadic composition M : Monad val f: B => M[C] val g: A => M[B] val h: A => M[C] = f • g Fusion? traverse(f) • traverse(g) == traverse(f • g)
  • 61. Monadic composition Yes 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* commutative val 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))
  • 62. Applicative composition vs Monadic composition Not commutative functions => fusion Seq(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]]
  • 63. Monadic composition: conjecture Commutative functions val 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 commutative plus1 and times2 are not commutative: (0 + 1) * 2 != (0 * 2) + 1
  • 64. Monadic composition: conjecture Commutative functions => fusion Seq(1,2,3).traverse(plus2 ∎ plus1) == 10 Seq(1,2,3).traverse(plus2) ∎ Seq(1,2,3).traverse(plus1) == 10 Not commutative functions => no fusion Seq(1,2,3).traverse(times2 ∎ plus1) == 22 Seq(1,2,3).traverse(times2) ∎ Seq(1,2,3).traverse(plus1) == 32