SlideShare una empresa de Scribd logo
1 de 64
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
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

Más contenido relacionado

La actualidad más candente

Monoids, Monoids, Monoids - ScalaLove 2020
Monoids, Monoids, Monoids - ScalaLove 2020Monoids, Monoids, Monoids - ScalaLove 2020
Monoids, Monoids, Monoids - ScalaLove 2020Luka Jacobowitz
 
Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)stasimus
 
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov Vyacheslav
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov VyacheslavSeminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov Vyacheslav
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov VyacheslavVyacheslav Arbuzov
 
Programs in array using SWIFT
Programs in array using SWIFTPrograms in array using SWIFT
Programs in array using SWIFTvikram mahendra
 
하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3Kwang Yul Seo
 
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
Send + More = Money – Let’s mash 2 monads to solve a simple CSPSend + More = Money – Let’s mash 2 monads to solve a simple CSP
Send + More = Money – Let’s mash 2 monads to solve a simple CSPFilippo Vitale
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monadskenbot
 
하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4Kwang Yul Seo
 
Why The Free Monad isn't Free
Why The Free Monad isn't FreeWhy The Free Monad isn't Free
Why The Free Monad isn't FreeKelley Robinson
 
The Ring programming language version 1.5.4 book - Part 22 of 185
The Ring programming language version 1.5.4 book - Part 22 of 185The Ring programming language version 1.5.4 book - Part 22 of 185
The Ring programming language version 1.5.4 book - Part 22 of 185Mahmoud Samir Fayed
 

La actualidad más candente (17)

Monoids, Monoids, Monoids - ScalaLove 2020
Monoids, Monoids, Monoids - ScalaLove 2020Monoids, Monoids, Monoids - ScalaLove 2020
Monoids, Monoids, Monoids - ScalaLove 2020
 
Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)
 
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov Vyacheslav
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov VyacheslavSeminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov Vyacheslav
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov Vyacheslav
 
Functor Laws
Functor LawsFunctor Laws
Functor Laws
 
02 arrays
02 arrays02 arrays
02 arrays
 
Programs in array using SWIFT
Programs in array using SWIFTPrograms in array using SWIFT
Programs in array using SWIFT
 
Data import-cheatsheet
Data import-cheatsheetData import-cheatsheet
Data import-cheatsheet
 
Perm winter school 2014.01.31
Perm winter school 2014.01.31Perm winter school 2014.01.31
Perm winter school 2014.01.31
 
하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3
 
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
Send + More = Money – Let’s mash 2 monads to solve a simple CSPSend + More = Money – Let’s mash 2 monads to solve a simple CSP
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monads
 
하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4
 
Seminar PSU 10.10.2014 mme
Seminar PSU 10.10.2014 mmeSeminar PSU 10.10.2014 mme
Seminar PSU 10.10.2014 mme
 
Why The Free Monad isn't Free
Why The Free Monad isn't FreeWhy The Free Monad isn't Free
Why The Free Monad isn't Free
 
The Ring programming language version 1.5.4 book - Part 22 of 185
The Ring programming language version 1.5.4 book - Part 22 of 185The Ring programming language version 1.5.4 book - Part 22 of 185
The Ring programming language version 1.5.4 book - Part 22 of 185
 
20090622 Bp Study#22
20090622 Bp Study#2220090622 Bp Study#22
20090622 Bp Study#22
 
Seminar psu 20.10.2013
Seminar psu 20.10.2013Seminar psu 20.10.2013
Seminar psu 20.10.2013
 

Destacado

Destacado (7)

Iterator Pattern
Iterator PatternIterator Pattern
Iterator Pattern
 
C# Strings
C# StringsC# Strings
C# Strings
 
Iterator - a powerful but underappreciated design pattern
Iterator - a powerful but underappreciated design patternIterator - a powerful but underappreciated design pattern
Iterator - a powerful but underappreciated design pattern
 
Iterator
IteratorIterator
Iterator
 
Iterator Design Pattern
Iterator Design PatternIterator Design Pattern
Iterator Design Pattern
 
Programming in c#
Programming in c#Programming in c#
Programming in c#
 
C# Tutorial
C# Tutorial C# Tutorial
C# Tutorial
 

Similar a Here is how I would implement findMatches using traverse:def findMatchesF_: Applicative(divs: SeqInt, nums: SeqInt): FSeq(Int, Int) = { traverse(div => nums.traverse(n => if(n % div == 0) ApplicativeF.pure((div, n)) else ApplicativeF.pure(None))) (divs).map(_.flatten)}// Usage:findMatches(Seq(2,3,4), Seq(1,6,7,8,9))This traverses the divs, mapping each to a traverse of nums to find matches

Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adtsHang Zhao
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2Hang Zhao
 
Monads and friends demystified
Monads and friends demystifiedMonads and friends demystified
Monads and friends demystifiedAlessandro Lacava
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systemsleague
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2Hang Zhao
 
Monadologie
MonadologieMonadologie
Monadologieleague
 
Functions, Types, Programs and Effects
Functions, Types, Programs and EffectsFunctions, Types, Programs and Effects
Functions, Types, Programs and EffectsRaymond Roestenburg
 
Generic Functional Programming with Type Classes
Generic Functional Programming with Type ClassesGeneric Functional Programming with Type Classes
Generic Functional Programming with Type ClassesTapio Rautonen
 
Drinking the free kool-aid
Drinking the free kool-aidDrinking the free kool-aid
Drinking the free kool-aidDavid Hoyt
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed worldDebasish Ghosh
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsJohn De Goes
 
An Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using HaskellAn Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using HaskellMichel Rijnders
 
Will it Blend? - ScalaSyd February 2015
Will it Blend? - ScalaSyd February 2015Will it Blend? - ScalaSyd February 2015
Will it Blend? - ScalaSyd February 2015Filippo Vitale
 

Similar a Here is how I would implement findMatches using traverse:def findMatchesF_: Applicative(divs: SeqInt, nums: SeqInt): FSeq(Int, Int) = { traverse(div => nums.traverse(n => if(n % div == 0) ApplicativeF.pure((div, n)) else ApplicativeF.pure(None))) (divs).map(_.flatten)}// Usage:findMatches(Seq(2,3,4), Seq(1,6,7,8,9))This traverses the divs, mapping each to a traverse of nums to find matches (20)

Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adts
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2
 
Thesis PPT
Thesis PPTThesis PPT
Thesis PPT
 
Thesis
ThesisThesis
Thesis
 
Functional programming in scala
Functional programming in scalaFunctional programming in scala
Functional programming in scala
 
Monads and friends demystified
Monads and friends demystifiedMonads and friends demystified
Monads and friends demystified
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systems
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2
 
Monadologie
MonadologieMonadologie
Monadologie
 
Functions, Types, Programs and Effects
Functions, Types, Programs and EffectsFunctions, Types, Programs and Effects
Functions, Types, Programs and Effects
 
Generic Functional Programming with Type Classes
Generic Functional Programming with Type ClassesGeneric Functional Programming with Type Classes
Generic Functional Programming with Type Classes
 
Drinking the free kool-aid
Drinking the free kool-aidDrinking the free kool-aid
Drinking the free kool-aid
 
purrr.pdf
purrr.pdfpurrr.pdf
purrr.pdf
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed world
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
 
An Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using HaskellAn Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using Haskell
 
Monad Fact #4
Monad Fact #4Monad Fact #4
Monad Fact #4
 
Scala best practices
Scala best practicesScala best practices
Scala best practices
 
Map, Reduce and Filter in Swift
Map, Reduce and Filter in SwiftMap, Reduce and Filter in Swift
Map, Reduce and Filter in Swift
 
Will it Blend? - ScalaSyd February 2015
Will it Blend? - ScalaSyd February 2015Will it Blend? - ScalaSyd February 2015
Will it Blend? - ScalaSyd February 2015
 

Más de Eric Torreborre

wire-all-the-things-lambda-days-2023.pdf
wire-all-the-things-lambda-days-2023.pdfwire-all-the-things-lambda-days-2023.pdf
wire-all-the-things-lambda-days-2023.pdfEric Torreborre
 
The many faces of modularity
The many faces of modularityThe many faces of modularity
The many faces of modularityEric Torreborre
 
What haskell taught us when we were not looking
What haskell taught us when we were not lookingWhat haskell taught us when we were not looking
What haskell taught us when we were not lookingEric Torreborre
 
Wire once, rewire twice! (Haskell exchange-2018)
Wire once, rewire twice! (Haskell exchange-2018)Wire once, rewire twice! (Haskell exchange-2018)
Wire once, rewire twice! (Haskell exchange-2018)Eric Torreborre
 
Pratical eff-functional-conf
Pratical eff-functional-confPratical eff-functional-conf
Pratical eff-functional-confEric Torreborre
 
Specs2, from starters to dessert and... a look in the kitchen
Specs2, from starters to dessert and... a look in the kitchenSpecs2, from starters to dessert and... a look in the kitchen
Specs2, from starters to dessert and... a look in the kitchenEric Torreborre
 
Streaming, effects and beautiful folds: a winning trilogy
Streaming, effects and beautiful folds: a winning trilogyStreaming, effects and beautiful folds: a winning trilogy
Streaming, effects and beautiful folds: a winning trilogyEric Torreborre
 
Pratical eff-scalaitaly-2017
Pratical eff-scalaitaly-2017Pratical eff-scalaitaly-2017
Pratical eff-scalaitaly-2017Eric Torreborre
 
Pratical eff monad at Scaladays Chicago
Pratical eff monad at Scaladays ChicagoPratical eff monad at Scaladays Chicago
Pratical eff monad at Scaladays ChicagoEric Torreborre
 
The Eff monad, one monad to rule them all
The Eff monad, one monad to rule them allThe Eff monad, one monad to rule them all
The Eff monad, one monad to rule them allEric Torreborre
 
Data generation, the hard parts
Data generation, the hard partsData generation, the hard parts
Data generation, the hard partsEric Torreborre
 
Origami, a monadic fold library for Scala
Origami, a monadic fold library for ScalaOrigami, a monadic fold library for Scala
Origami, a monadic fold library for ScalaEric Torreborre
 
Datatypes for the real world
Datatypes for the real worldDatatypes for the real world
Datatypes for the real worldEric Torreborre
 
Specs2 whirlwind tour at Scaladays 2014
Specs2 whirlwind tour at Scaladays 2014Specs2 whirlwind tour at Scaladays 2014
Specs2 whirlwind tour at Scaladays 2014Eric Torreborre
 
Epic success \/ failure, refactoring to *real* FP
Epic success \/ failure, refactoring to *real* FPEpic success \/ failure, refactoring to *real* FP
Epic success \/ failure, refactoring to *real* FPEric Torreborre
 

Más de Eric Torreborre (20)

wire-all-the-things-lambda-days-2023.pdf
wire-all-the-things-lambda-days-2023.pdfwire-all-the-things-lambda-days-2023.pdf
wire-all-the-things-lambda-days-2023.pdf
 
The many faces of modularity
The many faces of modularityThe many faces of modularity
The many faces of modularity
 
What haskell taught us when we were not looking
What haskell taught us when we were not lookingWhat haskell taught us when we were not looking
What haskell taught us when we were not looking
 
Wire once, rewire twice! (Haskell exchange-2018)
Wire once, rewire twice! (Haskell exchange-2018)Wire once, rewire twice! (Haskell exchange-2018)
Wire once, rewire twice! (Haskell exchange-2018)
 
Pratical eff-functional-conf
Pratical eff-functional-confPratical eff-functional-conf
Pratical eff-functional-conf
 
Specs2, from starters to dessert and... a look in the kitchen
Specs2, from starters to dessert and... a look in the kitchenSpecs2, from starters to dessert and... a look in the kitchen
Specs2, from starters to dessert and... a look in the kitchen
 
Streaming, effects and beautiful folds: a winning trilogy
Streaming, effects and beautiful folds: a winning trilogyStreaming, effects and beautiful folds: a winning trilogy
Streaming, effects and beautiful folds: a winning trilogy
 
Pratical eff-scalaitaly-2017
Pratical eff-scalaitaly-2017Pratical eff-scalaitaly-2017
Pratical eff-scalaitaly-2017
 
Pratical eff monad at Scaladays Chicago
Pratical eff monad at Scaladays ChicagoPratical eff monad at Scaladays Chicago
Pratical eff monad at Scaladays Chicago
 
Pratical eff
Pratical effPratical eff
Pratical eff
 
The Eff monad, one monad to rule them all
The Eff monad, one monad to rule them allThe Eff monad, one monad to rule them all
The Eff monad, one monad to rule them all
 
Easy di-slideshare
Easy di-slideshareEasy di-slideshare
Easy di-slideshare
 
Data generation, the hard parts
Data generation, the hard partsData generation, the hard parts
Data generation, the hard parts
 
Origami, a monadic fold library for Scala
Origami, a monadic fold library for ScalaOrigami, a monadic fold library for Scala
Origami, a monadic fold library for Scala
 
Datatypes for the real world
Datatypes for the real worldDatatypes for the real world
Datatypes for the real world
 
Specs2 3.4
Specs2 3.4Specs2 3.4
Specs2 3.4
 
DSLs with fold algebras
DSLs with fold algebrasDSLs with fold algebras
DSLs with fold algebras
 
Specs2 whirlwind tour at Scaladays 2014
Specs2 whirlwind tour at Scaladays 2014Specs2 whirlwind tour at Scaladays 2014
Specs2 whirlwind tour at Scaladays 2014
 
Epic success \/ failure, refactoring to *real* FP
Epic success \/ failure, refactoring to *real* FPEpic success \/ failure, refactoring to *real* FP
Epic success \/ failure, refactoring to *real* FP
 
Vampire methods
Vampire methodsVampire methods
Vampire methods
 

Último

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 

Último (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 

Here is how I would implement findMatches using traverse:def findMatchesF_: Applicative(divs: SeqInt, nums: SeqInt): FSeq(Int, Int) = { traverse(div => nums.traverse(n => if(n % div == 0) ApplicativeF.pure((div, n)) else ApplicativeF.pure(None))) (divs).map(_.flatten)}// Usage:findMatches(Seq(2,3,4), Seq(1,6,7,8,9))This traverses the divs, mapping each to a traverse of nums to find matches

  • 1.
  • 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
  • 29.
  • 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