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
This document discusses different types of computations in functional programming such as Option, List, Future, State, and IO. It explains how to create computations of these types by wrapping values, and how to use computations by mapping and applying functions to the wrapped values. It also covers applicative functors and how they allow applying functions to multiple arguments wrapped in computations. Some examples of applicative operations on Option, List, Future, State and IO are given. Finally, it briefly discusses traversals, which allow transforming data structures of type F[A] to F[B] by applying a function A => F[B] to each element.
Semelhante 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
Semelhante 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)
UiPath Community: Communication Mining from Zero to Hero
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]
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
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
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)
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
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?
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
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))