SlideShare a Scribd company logo
1 of 33
Download to read offline
Sequence	and	Traverse
Part	3
@philip_schwarzslides	by
Paul	ChiusanoRunar	Bjarnason
@pchiusano@runarorama
learn	about	the	sequence	and	traverse	functions	
through	the	work	of
FP in Scala
@fommil
Sam	Halliday
We now have instances of Traverse for List, Option, Map, and Tree . What does this generalized traverse /sequence
mean? Letā€™s just try plugging in some concrete type signatures for calls to sequence. We can speculate about what these functions
do, just based on their signatures:
ā€¢ List[Option[A]] => Option[List[A]] (a call to Traverse[List].sequence with Option as the
Applicative ) returns None if any of the input List is None; otherwise it returns the original List wrapped in Some.
ā€¢ Tree[Option[A]] => Option[Tree[A]] (a call to Traverse[Tree].sequence with Option as the
Applicative ) returns None if any of the input Tree is None; otherwise it returns the original Tree wrapped in Some.
ā€¢ Map[K, Par[A]] => Par[Map[K,A]] (a call to Traverse[Map[K,_]].sequence with Par as the
Applicative ) produces a parallel computation that evaluates all values of the map in parallel.
Functional Programming in Scala
(by	Paul	Chiusano	and	Runar	Bjarnason)
@pchiusano @runarorama
trait Traverse[F[_]] {
def traverse[M[_]:Applicative,A,B](fa: F[A])(f: A => M[B]): M[F[B]]
sequence(map(fa)(f))
def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] =
traverse(fma)(ma => ma)
}
For more details on Monoids, see this and this. For more details on
Foldable see slide 26 onwards of this (start from slide 16 for even
more of an introduction to folding).
In upcoming slides we are going to be referring to the Foldable trait
and the Monoid trait. The next four slides are a minimal introduction
to Monoids. The subsequent three slides are a minimal introduction to
Foldable.
https://www.slideshare.net/pjschwarz/monoids-with-examples-using-scalaz-and-cats-part-1
@philip_schwarz
https://www.slideshare.net/pjschwarz/monoids-with-examples-using-scalaz-and-cats-part-2
@philip_schwarz
What is a monoid?
Letā€™s consider the algebra of string concatenation. We can add "foo" +
"bar" to get "foobar", and the empty string is an identity element for
that operation. That is, if we say (s + "") or ("" + s), the result is
always s.
scala> val s = "foo" + "bar"
s: String = foobar
scala> assert( s == s + "" )
scala> assert( s == "" + s )
scala>
scala> val (r,s,t) = ("foo","bar","baz")
r: String = foo
s: String = bar
t: String = baz
scala> assert( ( ( r + s ) + t ) == ( r + ( s + t ) ) )
scala> assert( ( ( r + s ) + t ) == "foobarbaz" )
scala>
Furthermore, if we combine three strings by saying (r + s + t), the
operation is associative ā€”it doesnā€™t matter whether we parenthesize it: ((r
+ s) + t) or (r + (s + t)).
The exact same rules govern integer addition. Itā€™s associative, since (x +
y) + z is always equal to x + (y + z)
scala> val (x,y,z) = (1,2,3)
x: Int = 1
y: Int = 2
z: Int = 3
scala> assert( ( ( x + y ) + z ) == ( x + ( y + z ) ) )
scala> assert( ( ( x + y ) + z ) == 6 )
scala>
and it has an identity element, 0 , which ā€œdoes nothingā€ when added to
another integer
scala> val s = 3
s: Int = 3
scala> assert( s == s + 0)
scala> assert( s == 0 + s)
scala>
Ditto for integer multiplication
scala> val s = 3
s: Int = 3
scala> assert( s == s * 1)
scala> assert( s == 1 * s)
scala>
scala> val (x,y,z) = (2,3,4)
x: Int = 2
y: Int = 3
z: Int = 4
scala> assert(( ( x * y ) * z ) == ( x * ( y * z ) ))
scala> assert(( ( x * y ) * z ) == 24)
scala>
whose identity element is 1
The Boolean operators && and || are likewise associative
and they have identity elements true and false, respectively
scala> val (p,q,r) = (true,false,true)
p: Boolean = true
q: Boolean = false
r: Boolean = true
scala> assert(( ( p || q ) || r ) == ( p || ( q || r ) ))
scala> assert(( ( p || q ) || r ) == true )
scala> assert(( ( p && q ) && r ) == ( p && ( q && r ) ))
scala> assert(( ( p && q ) && r ) == false )
scala> val s = true
s: Boolean = true
scala> assert( s == ( s && true ) )
scala> assert( s == ( true && s ) )
scala> assert( s == ( s || false ) )
scala> assert( s == ( false || s ) )
These are just a few simple examples, but algebras like this are virtually everywhere. The term for this kind of algebra is monoid.
The laws of associativity and identity are collectively called the monoid laws.
A monoid consists of the following:
ā€¢ Some type A
ā€¢ An associative binary operation, op, that takes two values of type A and combines them into one: op(op(x,y), z) == op(x, op(y,z)) for any
choice of x: A, y: A, z: A
ā€¢ A value, zero: A, that is an identity for that operation: op(x, zero) == x and op(zero, x) == x for any x: A
trait Monoid[A] {
def op(a1: A, a2: A): A
def zero: A
}
val stringMonoid = new Monoid[String] {
def op(a1: String, a2: String) = a1 + a2
val zero = ""
}
An example instance of this trait is the String monoid:
def listMonoid[A] = new Monoid[List[A]] {
def op(a1: List[A], a2: List[A]) = a1 ++ a2
val zero = Nil
}
List concatenation also forms a monoid:
Functional Programming in Scala
(by	Paul	Chiusano	and	Runar	Bjarnason)
@pchiusano @runarorama
We can express this with a Scala trait:
List function returning a new list containing the elements from the left
hand operand followed by the elements from the right hand operand
String concatenation	function
Monoid instances for integer addition and multiplication as well as the Boolean operators
implicit val intAdditionMonoid = new Monoid[Int] {
def op(x: Int, y: Int) = x + y
val zero = 0
}
implicit val intMultiplicationMonoid = new Monoid[Int] {
def op(x: Int, y: Int) = x * y
val zero = 1
}
Just what is a monoid, then? Itā€™s simply a type A and an implementation of Monoid[A] that satisfies the laws.
Stated tersely, a monoid is a type together with a binary operation (op) over that type, satisfying associativity and having an
identity element (zero).
What does this buy us? Just like any abstraction, a monoid is useful to the extent that we can write useful generic code assuming
only the capabilities provided by the abstraction. Can we write any interesting programs, knowing nothing about a type other
than that it forms a monoid? Absolutely!
implicit val booleanOr = new Monoid[Boolean] {
def op(x: Boolean, y: Boolean) = x || y
val zero = false
}
implicit val booleanAnd = new Monoid[Boolean] {
def op(x: Boolean, y: Boolean) = x && y
val zero = true
}
Functional Programming in Scala
(by	Paul	Chiusano	and	Runar	Bjarnason)
@pchiusano @runarorama
(by	Runar	Bjarnason)
@runarorama
That was the minimal introduction to Monoid. Next, we
have three slides with a minimal introduction to Foldable.
@philip_schwarz
Foldable data structures
In chapter 3, we implemented the data structures List and Tree, both of which could be folded. In chapter 5, we wrote
Stream, a lazy structure that also can be folded much like a List can, and now weā€™ve just written a fold for IndexedSeq.
When weā€™re writing code that needs to process data contained in one of these structures, we often donā€™t care about the shape
of the structure (whether itā€™s a tree or a list), or whether itā€™s lazy or not, or provides efficient random access, and so forth.
For example, if we have a structure full of integers and want to calculate their sum, we can use foldRight:
ints.foldRight(0)(_ + _)
Looking at just this code snippet, we shouldnā€™t have to care about the type of ints. It could be a Vector, a Stream, or a
List, or anything at all with a foldRight method. We can capture this commonality in a trait:
Functional Programming in Scala
(by	Paul	Chiusano	and	Runar	Bjarnason)
@pchiusano @runarorama
trait Foldable[F[_]] {
def foldRight[A,B](as: F[A])(z: B)(f: (A,B) => B): B
def foldLeft[A,B](as: F[A])(z: B)(f: (B,A) => B): B
def foldMap[A,B](as: F[A])(f: A => B)(mb: Monoid[B]): B
def concatenate[A](as: F[A])(m: Monoid[A]): A =
foldLeft(as)(m.zero)(m.op)
}
Here weā€™re abstracting over a type constructor F, much like we did with the
Parser type in the previous chapter. We write it as F[_], where the
underscore indicates that F is not a type but a type constructor that takes
one type argument. Just like functions that take other functions as arguments
are called higher-order functions, something like Foldable is a higher-
order type constructor or a higher-kinded type .7
7 Just like values and functions have types, types and type constructors
have kinds. Scala uses kinds to track how many type arguments a type
constructor takes, whether itā€™s co- or contravariant in those arguments, and
what the kinds of those arguments are.
EXERCISE 10.12
Implement Foldable[List], Foldable[IndexedSeq], and Foldable[Stream]. Remember that foldRight, foldLeft,
and foldMap can all be implemented in terms of each other, but that might not be the most efficient implementation.
A Companion booklet to
FP in Scala
FP in Scala
trait Foldable[F[_]] {
def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B =
foldMap(as)(f.curried)(endoMonoid[B])(z)
def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B =
foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z)
def foldMap[A, B](as: F[A])(f: A => B)(mb: Monoid[B]): B =
foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b))
def concatenate[A](as: F[A])(m: Monoid[A]): A =
foldLeft(as)(m.zero)(m.op)
}
object ListFoldable extends Foldable[List] {
override def foldRight[A, B](as:List[A])(z:B)(f:(A,B)=>B) =
as.foldRight(z)(f)
override def foldLeft[A, B](as:List[A])(z:B)(f:(B,A)=>B) =
as.foldLeft(z)(f)
override def foldMap[A, B](as:List[A])(f:A=>B)(mb:Monoid[B]):B =
foldLeft(as)(mb.zero)((b, a) => mb.op(b, f(a)))
}
object IndexedSeqFoldable extends Foldable[IndexedSeq] {ā€¦}
object StreamFoldable extends Foldable[Stream] {
override def foldRight[A, B](as:Stream[A])(z:B)(f:(A,B)=>B) =
as.foldRight(z)(f)
override def foldLeft[A, B](as:Stream[A])(z:B)(f:(B,A)=>B) =
as.foldLeft(z)(f)
}
assert( ListFoldable.foldLeft(List(1,2,3))(0)(_+_) == 6)
assert( ListFoldable.foldRight(List(1,2,3))(0)(_+_) == 6)
assert( ListFoldable.concatenate(List(1,2,3))(intAdditionMonoid) == 6)
assert( ListFoldable.foldMap(List("1","2","3"))(_ toInt)(intAdditionMonoid) == 6)
assert( StreamFoldable.foldLeft(Stream(1,2,3))(0)(_+_) == 6)
assert( StreamFoldable.foldRight(Stream(1,2,3))(0)(_+_) == 6)
assert( StreamFoldable.concatenate(Stream(1,2,3))(intAdditionMonoid) == 6)
assert( StreamFoldable.foldMap(Stream("1","2","3"))(_ toInt)(intAdditionMonoid) == 6)
assert( ListFoldable.foldLeft(List("a","b","c"))("")(_+_) == "abc")
assert( ListFoldable.foldRight(List("a","b","c"))("")(_+_) == "abc")
assert( ListFoldable.concatenate(List("a","b","c"))(stringMonoid) == "abc")
assert( ListFoldable.foldMap(List(1,2,3))(_ toString)(stringMonoid) == "123")
assert( StreamFoldable.foldLeft(Stream("a","b","c"))("")(_+_) == "abc")
assert( StreamFoldable.foldRight(Stream("a","b","c"))("")(_+_) == "abc")
assert( StreamFoldable.concatenate(Stream("a","b","c"))(stringMonoid) == "abc")
assert( StreamFoldable.foldMap(Stream(1,2,3))(_ toString)(stringMonoid) == "123")
Using	the	methods	of	ListFoldable
and	StreamFoldable to	fold	
Lists/Streams	of	Ints	and	Strings.
If you are new to monoids, donā€™t worry about the
implementation of foldRight and foldLeft except for the
fact that it is possible to define them using foldMap.
Sam	Halliday
@fommil
Technically, Foldable is for data structures that can be walked to produce a summary value. However, this
undersells the fact that it is a one-typeclass army that can provide most of what youā€™d expect to see in a
Collections API.
You might recognise foldMap by its marketing buzzword name, MapReduce. Given an F[A], a function from A to
B, and a way to combine B (provided by the Monoid, along with a zero B), we can produce a summary value of
type B. There is no enforced operation order, allowing for parallel computation.
foldRight does not require its parameters to have a Monoid, meaning that it needs a starting value z and a
way to combine each element of the data structure with the summary value. The order for traversing the
elements is from right to left and therefore it cannot be parallelised.
foldLeft traverses elements from left to right. foldLeft can be implemented in terms of foldMap, but most
instances choose to implement it because it is such a basic operation. Since it is usually implemented with
tail recursion, there are no byname parameters.
The simplest thing to do with foldMap is to use the identity function, giving fold (the natural sum of the
monoidal elements), with left/right variants to allow choosing based on performance criteria:
@typeclass trait Foldable[F[_]] {
def foldMap[A, B: Monoid](fa: F[A])(f: A => B): B
def foldRight[A, B](fa: F[A], z: =>B)(f: (A, =>B) => B): B
def foldLeft[A, B](fa: F[A], z: B)(f: (B, A) => B): B = ...
def fold[A: Monoid](t: F[A]): A = ...
def sumr[A: Monoid](fa: F[A]): A = ...
def suml[A: Monoid](fa: F[A]): A = ...
ā€¦
In FPiS, fold is called
concatenate.
Sam	Halliday
Anything youā€™d expect to find in a collection library is
probably on Foldable and if it isnā€™t already, it probably
should be.
With that refresher on Monoid and Foldable out of the way, letā€™s first
compare Traverse.traverse with Foldable.foldMap and then see the
connection between Traverse.traverse and Functor.map.
@philip_schwarz
A traversal is similar to a fold in that both take some data structure and apply a function to the data within in order to produce a result.
The difference is that traverse preserves the original structure , whereas foldMap discards the structure and replaces it with
the operations of a monoid.
Look at the signature Tree[Option[A]] => Option[Tree[A]], for instance.
Weā€™re preserving the Tree structure, not merely collapsing the values using some monoid.
trait Traverse[F[_]] {
def traverse[M[_]:Applicative,A,B](as: F[A])(f: A => M[B]): M[F[B]]
def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] =
traverse(fma)(ma => ma)
}
trait Foldable[F[_]] {
def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B =
foldMap(as)(f.curried)(endoMonoid[B])(z)
def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B =
foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z)
def foldMap[A, B](as: F[A])(f: A => B)(mb: Monoid[B]): B =
foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b))
def concatenate[A](as: F[A])(m: Monoid[A]): A =
foldLeft(as)(m.zero)(m.op)
}
traverse(as: Tree[String])(f: String => Option[Int])(implicit G: Applicative[Option]): Option[Tree[Int]]
foldMap(as: Tree[String])(f: String => Int) (implicit mb: Monoid[Int]) : Int
// foldMap using integer addition monoid
//
// "2" --> 2 --> 6
// /  / 
// "1" "3" 1 3
// traverse
//
// "2" --> Some(2) --> Some( 2 )
// /  /  / 
// "1" "3" Some(1) Some(3) 1 3
To illustrate this difference between how traverse preserves the structure of
a Tree and foldMap collapses the structure using some monoid, we are
going to look at an example in which both traverse and foldMap convert the
elements of the Tree from String values to Int values, but while
traverse produces an Option[Tree[Int]], foldMap produces an Int.
FP in Scala
See the next
slide for the
full example.
@philip_schwarz
case class Tree[+A](head: A, tail: List[Tree[A]])
val tree = Tree("2",List(Tree("1", Nil), Tree("3", Nil)))
val toInt: String => Int = _.toInt
val folded = 6
assert( treeFoldable.foldMap(tree)(toInt)(intMonoid) == folded )
// treeFoldable.foldMap(tree)(toInt)(intMonoid)
//
// "2" --> 2 --> 6
// /  / 
// "1" "3" 1 3
// treeTraverse.traverse(tree)(parseInt)(optionApplicative)
//
// "2" --> Some(2) --> Some( 2 )
// /  /  / 
// "1" "3" Some(1) Some(3) 1 3
val listTraverse = new Traverse[List] {
override def traverse[M[_],A,B](as:List[A])(f: A=>M[B])(implicit M:Applicative[M]):M[List[B]] =
as.foldRight(M.unit(List[B]()))((a, fbs) => M.map2(f(a), fbs)(_ :: _))
}
val treeTraverse = new Traverse[Tree] {
override def traverse[G[_],A,B](ta:Tree[A])(f: A=>G[B])(implicit G:Applicative[G]):G[Tree[B]] =
G.map2(f(ta.head),
listTraverse.traverse(ta.tail)(a => traverse(a)(f)))(Tree(_, _))
}
implicit val optionApplicative = new Applicative[Option] {
def map2[A, B, C](fa: Option[A], fb: Option[B])(f: (A, B) => C): Option[C] =
(fa, fb) match {
case (Some(a), Some(b)) => Some(f(a,b))
case _ => None
}
def unit[A](a: => A): Option[A] = Some(a)
}
val treeFoldable = new Foldable[Tree] {
override def foldMap[A,B](as:Tree[A])(f:A=>B)(mb:Monoid[B]):B =
as match {
case Tree(head,Nil) =>
f(head)
case Tree(head,tree::rest) =>
mb.op(foldMap(Tree(head,rest))(f)(mb),
foldMap(tree)(f)(mb))
}
}
val parseInt: String => Option[Int] = x => Try{ x.toInt }.toOption
val traversed = Some(Tree(2,List(Tree(1,Nil), Tree(3,Nil))))
assert( treeTraverse.traverse(tree)(parseInt)(optionApplicative) == traversed ) ā€Ø
// "2"
// / 
// "1" "3"
implicit val intMonoid = new Monoid[Int]{
def op(a1: Int, a2: Int): Int = a1 + a2
def zero: Int = 0
}
In FPiS the Tree type that treeFoldable operates on is a bit different from the
one that treeTraverse operates on. Here I rewrote treeFoldable to operate on the
same Tree type as treeTraverse, so that I can show an example of traversing and
folding the same tree.
Traversing and folding
the same tree.
We were first introduced to the Traverse trait in Part 2
So at that time I suggested we think of Traverseā€˜s traverse method as not having a body, i.e. being abstract. I reckoned the body was just
there to point out that if Traverse did have a map function then it could be used to implement traverse.
All the traverse instances we have looked at so far implemented traverse without using a map function.
In the next two slides we are finally going to see the connection between Traverse and map.
trait Traverse[F[_]] {
def traverse[M[_]:Applicative,A,B](fa: F[A])(f: A => M[B]): M[F[B]]
sequence(map(fa)(f))
def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] =
traverse(fma)(ma => ma)
}
At that time we found it confusing that Traverseā€˜s
traverse function used a map function that was not
defined anywhere
We did however know, from Part 1, that just like flatMap is map and then flatten, traverse is map and then sequence.
def flatMap[A,B](ma: F[A])(f: A ā‡’ F[B]): F[B] = flatten(ma map f)
def flatten[A](mma: F[F[A]]): F[A] = flatMap(mma)(x ā‡’ x)
def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] = sequence(a map f)
def sequence[A](a: List[Option[A]]): Option[List[A]] = traverse(a)(x ā‡’ x)
EXERCISE 12.14
Hard: Implement map in terms of traverse as a method on Traverse[A]. This establishes that Traverse is an extension
of Functor and that the traverse function is a generalization of map (for this reason we sometimes call these traversable
functors). Note that in implementing map, you can call traverse with your choice of Applicative[G].
Functional Programming in Scala
(by	Paul	Chiusano	and	Runar	Bjarnason)
@pchiusano @runarorama
by	Runar	Bjarnason								@runarorama
Answer to EXERCISE 12.14trait Traverse[F[_]] extends Functor[F] {
def traverse[G[_] : Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] =
sequence(map(fa)(f))
def sequence[G[_] : Applicative, A](fga: F[G[A]]): G[F[A]] =
traverse(fga)(ga => ga)
type Id[A] = A
val idMonad = new Monad[Id] {
def unit[A](a: => A) = a
override def flatMap[A, B](a: A)(f: A => B): B = f(a)
}
def map[A, B](fa: F[A])(f: A => B): F[B] =
traverse[Id, A, B](fa)(f)(idMonad)
}
The simplest possible Applicative
we can use is Id.
We already know this forms a Monad,
so itā€™s also an applicative functor.
We can now implement map by calling
traverse, picking Id as the
Applicative.
Note that we can define traverse in
terms of sequence and map, which
means that a valid Traverse instance
may define sequence and map, or just
traverse.
trait Traverse[F[_]] extends Functor[F] {
def traverse[G[_],A,B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]] =
sequence(map(fa)(f))
def sequence[G[_],A](fga: F[G[A]])(implicit G: Applicative[G]): G[F[A]] =
traverse(fga)(ga => ga)
def map[A,B](fa: F[A])(f: A => B): F[B] = ???
}
trait Traverse[F[_]] {
def traverse[M[_]:Applicative,A,B](fa: F[A])(f: A => M[B]): M[F[B]]
sequence(map(fa)(f))
def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] =
traverse(fma)(ma => ma)
}
trait Traverse[F[_]] extends Functor[F] {
def traverse[M[_]:Applicative,A,B](fa: F[A])(f: A => M[B]): M[F[B]]
sequence(map(fa)(f))
def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] =
traverse(fma)(ma => ma)
def map[A,B](fa: F[A])(f: A => B): F[B] =
traverse[Id, A, B](fa)(f)(idMonad)
}
We had not yet been told that Traverse is a Functor: it either simply defines a traverse function, in
which case it gets free definitions of sequence and map based on traverse, or it defines both a map
function and a sequence function and both are then used to implement traverse. See below for what
was missing from the Traverse trait.
Mind blown: traverse is a generalization of map. Conversely: mapping is a specialization of traversing.
When we traverse using the degenerate Applicative that is the Id Monad, we are just mapping.
Mapping is traversing with the Id Monad as an Applicative.
So thatā€™s why we found it confusing when FPiS first introduced Traverse (below) with a traverse
implementation that referred to an undefined map function.
In the next slide we have a go at using the map function
of listTraverse, optionTraverse and treeTraverse.
@philip_schwarz
trait Functor[F[_]] {
def map[A,B](fa: F[A])(f: A => B): F[B]
}
trait Monad[F[_]] extends Applicative[F] {
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B]
override def map[A,B](m: F[A])(f: A => B): F[B] =
flatMap(m)(a => unit(f(a)))
override def map2[A,B,C](ma:F[A], mb:F[B])(f:(A, B) => C): F[C] =
flatMap(ma)(a => map(mb)(b => f(a, b)))
}
trait Applicative[F[_]] extends Functor[F] {
def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C]
def unit[A](a: => A): F[A]
def apply[A,B](fab: F[A => B])(fa: F[A]): F[B] = map2(fab, fa)(_(_))
def map[A,B](fa: F[A])(f: A => B): F[B] = apply(unit(f))(fa)
}
trait Traverse[F[_]] extends Functor[F] {
def traverse[M[_]:Applicative,A,B](fa:F[A])(f:A=>M[B]):M[F[B]]
def sequence[M[_] : Applicative, A](fma: F[M[A]]): M[F[A]] =
traverse(fma)(ma => ma)
type Id[A] = A
val idMonad = new Monad[Id] {
def unit[A](a: => A) = a
override def flatMap[A, B](a: A)(f: A => B): B = f(a)
}
def map[A, B](fa: F[A])(f: A => B): F[B] =
traverse[Id, A, B](fa)(f)(idMonad)
}
val listTraverse = new Traverse[List] {
override def traverse[M[_], A, B](as: List[A])(f: A => M[B])
(implicit M: Applicative[M]): M[List[B]] =
as.foldRight(M.unit(List[B]()))
((a, fbs) => M.map2(f(a), fbs)(_ :: _))
}
val optionTraverse = new Traverse[Option] {
override def traverse[M[_],A,B](oa: Option[A])(f: A => M[B])
(implicit M: Applicative[M]): M[Option[B]] =
oa match {
case Some(a) => M.map(f(a))(Some(_))
case None => M.unit(None)
}
}
case class Tree[+A](head: A, tail: List[Tree[A]])
val treeTraverse = new Traverse[Tree] {
override def traverse[M[_], A, B](ta: Tree[A])(f: A => M[B])
(implicit M: Applicative[M]): M[Tree[B]] =
M.map2(f(ta.head),
listTraverse.traverse(ta.tail)(a => traverse(a)(f))
)(Tree(_, _))
}
val double: Int => Int = _ * 2
assert(listTraverse.map(List(1,2,3))(double) == List(2,4,6))
assert(optionTraverse.map(Some(2))(double) == Some(4))
val tree = Tree(2,List(Tree(1, Nil), Tree(3, Nil)))
val doubledTree = Tree(4,List(Tree(2, Nil), Tree(6, Nil)))
assert(treeTraverse.map(tree)(double) == doubledTree)
And in the next slide we use another example to look a bit closer
at how mapping is just traversing with the Id Monad Applicative.
implicit val optionApplicative = new Applicative[Option] {
def map2[A, B, C](fa: Option[A], fb: Option[B])(f: (A, B) => C): Option[C] =
(fa, fb) match {
case (Some(a), Some(b)) => Some(f(a,b))
case _ => None
}
def unit[A](a: => A): Option[A] = Some(a)
}
type Id[A] = A
val idMonad = new Monad[Id] {
def unit[A](a: => A) = a
override def flatMap[A, B](a: A)(f: A => B): B = f(a)
}
val parseInt: String => Option[Int] = x => scala.util.Try{ x.toInt }.toOption
assert( listTraverse.traverse(List("1","2","3"))(parseInt)(optionApplicative) == Some(List(1,2,3)))
List("1","2","3") Ć  List(1,2,3) Ć  List(1,2,3)
List("1","2","3") Ć  List(Id(1), Id(2), Id(3)) Ć  Id( List(1,2,3) )
List("1","2","3") Ć  List(idMonad.unit(1),idMonad.unit(2),idMonad.unit(3)) Ć  idMonad.unit( List(1,2,3) )
List[String] Ć  List[Id[Int]] Ć  Id[List[Int]]
List[String] Ć  List[Id[Int]] Ć  Id[List[Int]]
List[String] Ć  List[ Int ] Ć  List[Int]
val toInt: String => Id[Int] = _.toInt
assert( listTraverse.map(List("1","2","3"))(toInt) == List(1,2,3))
assert( listTraverse.traverse(List("1","2","3"))(toInt)(idMonad) == List(1,2,3))
List("1","2","3") Ć  List(Some(1),Some(2),Some(3)) Ć  Some(List(1,2,3) )
List[String] Ć  List[Option[Int]] Ć  Option[List[Int]]
Here we use Id(x) to
represent x lifted into
the Id Monad.
Having compared Traverse.traverse with Foldable.foldMap and seen the
connection between Traverse.traverse and Functor.map, we know go
back to looking at the connection between Traverse and Foldable.
@philip_schwarz
12.7.1 From monoids to applicative functors
Weā€™ve just learned that traverse is more general than map. Next weā€™ll learn that traverse can also express foldMap
and by extension foldLeft and foldRight! Take another look at the signature of traverse:
def traverse[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]]
Suppose that our G were a type constructor ConstInt that takes any type to Int, so that ConstInt[A] throws away its
type argument A and just gives us Int:
type ConstInt[A] = Int
Then in the type signature for traverse, if we instantiate G to be ConstInt, it becomes
def traverse[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]]
def traverse[A,B](fa: F[A])(f: A => Int): Int
Functional Programming in Scala
(by	Paul	Chiusano	and	Runar	Bjarnason)
@pchiusano @runarorama
G[X] ===> ConstInt[X] == Int
trait Foldable[F[_]] {
def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B =
foldMap(as)(f.curried)(endoMonoid[B])(z)
def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B =
foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z)
def foldMap[A, B](as: F[A])(f: A => B)(mb: Monoid[B]): B =
foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b))
def concatenate[A](as: F[A])(m: Monoid[A]): A =
foldLeft(as)(m.zero)(m.op)
}
This looks a lot like foldMap from Foldable. Indeed, if F is something like
List, then what we need to implement this signature is a way of combining the
Int values returned by f for each element of the list, and a ā€œstartingā€ value for
handling the empty list. In other words, we only need a Monoid[Int]. And thatā€™s
easy to come by.
In fact, given a constant functor like we have here, we can turn any Monoid
into an Applicative. (see next slide)
Listing 12.8 Turning a Monoid into an Applicative
type Const[M, B] = M
implicit def monoidApplicative[M](M: Monoid[M]) =
new Applicative[({ type f[x] = Const[M, x] })#f] {
def unit[A](a: => A): M = M.zero
def map2[A,B,C](m1: M, m2: M)(f: (A,B) => C): M = M.op(m1,m2)
}
This means that Traverse can extend Foldable and we can give a default implementation of foldMap in terms of
traverse:
trait Traverse[F[_]] extends Functor[F] with Foldable[F] {
ā€¦
override def foldMap[A,M](as: F[A])(f: A => M)(mb: Monoid[M]): M =
traverse[({type f[x] = Const[M,x]})#f,A,Nothing](as)(f)(monoidApplicative(mb))
}
Note that Traverse now extends both Foldable and Functor ! Importantly, Foldable itself canā€™t extend Functor.
Even though itā€™s possible to write map in terms of a fold for most foldable data structures like List, itā€™s not possible in
general.
Functional Programming in Scala
(by	Paul	Chiusano	and	Runar	Bjarnason)
@pchiusano @runarorama
Earlier I had a Mind Blown moment because traverse is a generalization of map.
Mind Blown again: traverse can also express foldMap.
So although earlier we said that the difference between traverse and foldMap is
that traverse preserves the original structure whereas foldMap discards the
structure, if we pass traverse a monoid applicative then it behaves like foldMap
and discards the structure (replacing it with the operations of a monoid).
The next slide is a final recap of how, by using Id and Const, we
can get Traverse to implement map and foldMap, which means
that Traverse is both a Functor and a Foldable.
@philip_schwarz
def traverse[G[_],A,B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]]
G[X] ===> Id[X] == X G[X] ===> Const[M,	X]		== M
def foldMap[A,M](as: F[A])(f: A => M)(mb: Monoid[M]): M =
traverse[({type f[x] = Const[M,x]})#f,A,Nothing]
(as)(f)(monoidApplicative(mb))
def map[A, B](fa: F[A])(f: A => B): F[B] =
traverse[Id, A, B](fa)(f)(idMonad)
type Const[M,B] = Mtype Id[A] = A
G[F[B]] ==> F[B]G[B] ==> B G[F[B]] ==> MG[B] ==> M
G = Id Monad G = Applicative Monoid
trait Traverse[F[_]] extends Functor[F] with Foldable[F] {
ā€¦
def map[A,B](fa: F[A])(f: A => B): F[B] = traverseā€¦
def foldMap[A,M](as: F[A])(f: A => M)(mb: Monoid[M]): M = traverseā€¦
def traverse[G[_],A,B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]]
ā€¦
}
5. Scalaz Typeclasses
Before we introduce the typeclass hierarchy, we will peek at the four most important methods from a control flow
perspective, the methods we will use the most in typical FP applications:
ā€¦
ā€¦
traverse is useful for rearranging type constructors. If you find yourself with an F[G[_]] but you really need a
G[F[_]] then you need Traverse. For example, say you have a List[Future[Int]] but you need it to be
a Future[List[Int]], just call .traverse(identity), or its simpler sibling .sequence.
ā€¦
5.4 Mappable Things
Weā€™re focusing on things that can be mapped over,
or traversed, in some senseā€¦
ā€¦
Sam	Halliday
@fommil
5.4.3 Traverse
Traverse is what happens when you cross a Functor with a Foldable
trait Traverse[F[_]] extends Functor[F] with Foldable[F] {
def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
def sequence[G[_]: Applicative, A](fga: F[G[A]]): G[F[A]] = ...
def reverse[A](fa: F[A]): F[A] = ...
def zipL[A, B](fa: F[A], fb: F[B]): F[(A, Option[B])] = ...
def zipR[A, B](fa: F[A], fb: F[B]): F[(Option[A], B)] = ...
def indexed[A](fa: F[A]): F[(Int, A)] = ...
def zipWithL[A, B, C](fa: F[A], fb: F[B])(f: (A, Option[B]) => C): F[C] = ...
def zipWithR[A, B, C](fa: F[A], fb: F[B])(f: (Option[A], B) => C): F[C] = ...
def mapAccumL[S, A, B](fa: F[A], z: S)(f: (S, A) => (S, B)): (S, F[B]) = ...
def mapAccumR[S, A, B](fa: F[A], z: S)(f: (S, A) => (S, B)): (S, F[B]) = ...
}
At the beginning of the chapter we showed the importance of traverse and sequence for swapping
around type constructors to fit a requirement (e.g. List[Future[_]] to Future[List[_]]). You will
use these methods more than you could possibly imagine.
Functor Foldable
TraverseSam	Halliday
@fommil
You will use these methods (sequence
and traverse) more than you could
possibly imagine.
Traverse is what happens when you
cross a Functor with a Foldable.
Sam	Halliday
Sam	Halliday
In the next two slides we have a go at using a
Traverse instance (now that Traverse is both a
Functor and a Foldable).
trait Applicative[F[_]] extends Functor[F] {
def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C]
def unit[A](a: => A): F[A]
def map[B](fa: F[A])(f: A => B): F[B] =
map2(fa, unit(()))((a, _) => f(a))
def sequence[A](fas: List[F[A]]): F[List[A]] =
traverse(fas)(fa => fa)
def traverse[A,B](as: List[A])(f: A => F[B]): F[List[B]]
as.foldRight(unit(List[B]()))((a, fbs) => map2(f(a), fbs)(_ :: _))
ā€¦
}
trait Foldable[F[_]] {
import Monoid._
def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B =
foldMap(as)(f.curried)(endoMonoid[B])(z)
def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B =
foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z)
def foldMap[A,B](as:F[A])(f:A=>B)(implicit mb: Monoid[B]):B =
foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b))
def concatenate[A](as: F[A])(implicit m: Monoid[A]): A =
foldLeft(as)(m.zero)(m.op)
}
trait Functor[F[_]] {
def map[A,B](fa: F[A])(f: A => B): F[B]
}
trait Monad[F[_]] extends Applicative[F] {
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B]
override def map[A,B](m: F[A])(f: A => B): F[B] =
flatMap(m)(a => unit(f(a)))
override def map2[A,B,C](ma:F[A], mb:F[B])(f:(A, B) => C): F[C] =
flatMap(ma)(a => map(mb)(b => f(a, b)))
}
trait Traverse[F[_]] extends Functor[F] with Foldable[F] { self =>
def traverse[M[_]:Applicative,A,B](fa:F[A])(f:A=>M[B]):M[F[B]]
def sequence[M[_] : Applicative, A](fma: F[M[A]]): M[F[A]] =
traverse(fma)(ma => ma)
type Id[A] = A
val idMonad = new Monad[Id] {
def unit[A](a: => A) = a
override def flatMap[A, B](a: A)(f: A => B): B = f(a)
}
def map[A, B](fa: F[A])(f: A => B): F[B] =
traverse[Id, A, B](fa)(f)(idMonad)
import Applicative._
override def foldMap[A,B](as: F[A])(f: A => B)
(implicit mb: Monoid[B]): B =
traverse[({type f[x] = Const[B,x]})#f,A,Nothing](
as)(f)(monoidApplicative(mb))
ā€¦
}
type Const[M, B] = M
implicit def monoidApplicative[M](M: Monoid[M]) =
new Applicative[({ type f[x] = Const[M, x] })#f] {
def unit[A](a: => A): M = M.zero
def map2[A,B,C](m1: M, m2: M)(f: (A,B) => C): M = M.op(m1,m2)
}
trait Monoid[A] {
def op(x: A, y: A): A
def zero: A
}
implicit val optionApplicative = new Applicative[Option] {
def map2[A, B, C](fa: Option[A], fb: Option[B])(f: (A, B) => C): Option[C] =
(fa, fb) match {
case (Some(a), Some(b)) => Some(f(a,b))
case _ => None
}
def unit[A](a: => A): Option[A] = Some(a)
}
val parseInt: String => Option[Int] = (s:String) => scala.util.Try(s.toInt).toOption
// Traverse
assert( listTraverse.traverse(List("1","2","3"))(parseInt) == Some(List(1, 2, 3)) )
assert( listTraverse.sequence(List(Option(1),Option(2),Option(3))) == Some(List(1, 2, 3)) )
// Functor
assert( listTraverse.map(List(1,2,3))(_ + 1) == List(2,3,4))
// Foldable
assert( listTraverse.foldMap(List("1","2","3"))(_ toInt) == 6 )
assert( listTraverse.concatenate(List(1,2,3)) == 6 )
assert( listTraverse.foldRight(List(1,2,3))(0)(_ + _) == 6 )
assert( listTraverse.foldLeft(List(1,2,3))(0)(_ + _) == 6 )
val listTraverse = new Traverse[List] {
override def traverse[M[_], A, B](as: List[A])(f: A => M[B])(implicit M: Applicative[M]): M[List[B]] =
as.foldRight(M.unit(List[B]()))((a, fbs) => M.map2(f(a), fbs)(_ :: _))
}
implicit val integerAdditionMonoid = new Monoid[Int] {
def op(x: Int, y: Int): Int = x + y
def zero: Int = 0
}
implicit optionApplicative implicit integerAdditionMonoid
uses	monoidApplicative
uses	IdMonad
Creating a Traverse[List] instance
and exercising its functions, including
its Functor and Foldable functions.
To	be	continued	in	part	IV

More Related Content

What's hot

Abstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsAbstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsPhilip Schwarz
Ā 
Kleisli composition, flatMap, join, map, unit - implementation and interrelation
Kleisli composition, flatMap, join, map, unit - implementation and interrelationKleisli composition, flatMap, join, map, unit - implementation and interrelation
Kleisli composition, flatMap, join, map, unit - implementation and interrelationPhilip Schwarz
Ā 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Philip Schwarz
Ā 
Fp in scala part 1
Fp in scala part 1Fp in scala part 1
Fp in scala part 1Hang Zhao
Ā 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Piotr Paradziński
Ā 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsPhilip Schwarz
Ā 
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
Ā 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adtsHang Zhao
Ā 
Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and ScalaFunctional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and ScalaPhilip Schwarz
Ā 
Scala. Introduction to FP. Monads
Scala. Introduction to FP. MonadsScala. Introduction to FP. Monads
Scala. Introduction to FP. MonadsKirill Kozlov
Ā 
Contravariant functors in scala
Contravariant functors in scalaContravariant functors in scala
Contravariant functors in scalaPiotr Paradziński
Ā 
Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'Philip Schwarz
Ā 
Functions In Scala
Functions In Scala Functions In Scala
Functions In Scala Knoldus Inc.
Ā 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Philip Schwarz
Ā 
Real World Haskell: Lecture 5
Real World Haskell: Lecture 5Real World Haskell: Lecture 5
Real World Haskell: Lecture 5Bryan O'Sullivan
Ā 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersPiotr Paradziński
Ā 
Real World Haskell: Lecture 4
Real World Haskell: Lecture 4Real World Haskell: Lecture 4
Real World Haskell: Lecture 4Bryan O'Sullivan
Ā 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2Hang Zhao
Ā 

What's hot (20)

Abstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsAbstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generators
Ā 
Kleisli composition, flatMap, join, map, unit - implementation and interrelation
Kleisli composition, flatMap, join, map, unit - implementation and interrelationKleisli composition, flatMap, join, map, unit - implementation and interrelation
Kleisli composition, flatMap, join, map, unit - implementation and interrelation
Ā 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Ā 
Fp in scala part 1
Fp in scala part 1Fp in scala part 1
Fp in scala part 1
Ā 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
Ā 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
Ā 
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
Ā 
Monad Fact #4
Monad Fact #4Monad Fact #4
Monad Fact #4
Ā 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adts
Ā 
Monad Fact #2
Monad Fact #2Monad Fact #2
Monad Fact #2
Ā 
Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and ScalaFunctional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Ā 
Scala. Introduction to FP. Monads
Scala. Introduction to FP. MonadsScala. Introduction to FP. Monads
Scala. Introduction to FP. Monads
Ā 
Contravariant functors in scala
Contravariant functors in scalaContravariant functors in scala
Contravariant functors in scala
Ā 
Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'
Ā 
Functions In Scala
Functions In Scala Functions In Scala
Functions In Scala
Ā 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Ā 
Real World Haskell: Lecture 5
Real World Haskell: Lecture 5Real World Haskell: Lecture 5
Real World Haskell: Lecture 5
Ā 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly matters
Ā 
Real World Haskell: Lecture 4
Real World Haskell: Lecture 4Real World Haskell: Lecture 4
Real World Haskell: Lecture 4
Ā 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2
Ā 

Similar to Sequence and Traverse - Part 3

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
Ā 
Oh, All the things you'll traverse
Oh, All the things you'll traverseOh, All the things you'll traverse
Oh, All the things you'll traverseLuka Jacobowitz
Ā 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?Tomasz Wrobel
Ā 
Monads and Monoids by Oleksiy Dyagilev
Monads and Monoids by Oleksiy DyagilevMonads and Monoids by Oleksiy Dyagilev
Monads and Monoids by Oleksiy DyagilevJavaDayUA
Ā 
Algebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsAlgebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsVasil Remeniuk
Ā 
Functional programming with_scala
Functional programming with_scalaFunctional programming with_scala
Functional programming with_scalaRaymond Tay
Ā 
Rewriting Java In Scala
Rewriting Java In ScalaRewriting Java In Scala
Rewriting Java In ScalaSkills Matter
Ā 
Real World Haskell: Lecture 2
Real World Haskell: Lecture 2Real World Haskell: Lecture 2
Real World Haskell: Lecture 2Bryan O'Sullivan
Ā 
Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009David Pollak
Ā 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheetRuslan Shevchenko
Ā 
Introducing scala
Introducing scalaIntroducing scala
Introducing scalaMeetu Maltiar
Ā 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming iiPrashant Kalkar
Ā 
Scala Bootcamp 1
Scala Bootcamp 1Scala Bootcamp 1
Scala Bootcamp 1Knoldus Inc.
Ā 
Practical cats
Practical catsPractical cats
Practical catsRaymond Tay
Ā 
Why Haskell Matters
Why Haskell MattersWhy Haskell Matters
Why Haskell Mattersromanandreg
Ā 
Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patternsleague
Ā 
Morel, a Functional Query Language
Morel, a Functional Query LanguageMorel, a Functional Query Language
Morel, a Functional Query LanguageJulian Hyde
Ā 

Similar to Sequence and Traverse - Part 3 (20)

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
Ā 
Frp2016 3
Frp2016 3Frp2016 3
Frp2016 3
Ā 
Scala for curious
Scala for curiousScala for curious
Scala for curious
Ā 
Oh, All the things you'll traverse
Oh, All the things you'll traverseOh, All the things you'll traverse
Oh, All the things you'll traverse
Ā 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
Ā 
Monads and Monoids by Oleksiy Dyagilev
Monads and Monoids by Oleksiy DyagilevMonads and Monoids by Oleksiy Dyagilev
Monads and Monoids by Oleksiy Dyagilev
Ā 
Algebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsAlgebraic Data Types and Origami Patterns
Algebraic Data Types and Origami Patterns
Ā 
Functional programming with_scala
Functional programming with_scalaFunctional programming with_scala
Functional programming with_scala
Ā 
Rewriting Java In Scala
Rewriting Java In ScalaRewriting Java In Scala
Rewriting Java In Scala
Ā 
Real World Haskell: Lecture 2
Real World Haskell: Lecture 2Real World Haskell: Lecture 2
Real World Haskell: Lecture 2
Ā 
Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009
Ā 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheet
Ā 
Introducing scala
Introducing scalaIntroducing scala
Introducing scala
Ā 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming ii
Ā 
Scala Bootcamp 1
Scala Bootcamp 1Scala Bootcamp 1
Scala Bootcamp 1
Ā 
Practical cats
Practical catsPractical cats
Practical cats
Ā 
Why Haskell Matters
Why Haskell MattersWhy Haskell Matters
Why Haskell Matters
Ā 
Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patterns
Ā 
Morel, a Functional Query Language
Morel, a Functional Query LanguageMorel, a Functional Query Language
Morel, a Functional Query Language
Ā 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
Ā 

More from Philip Schwarz

Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
Ā 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
Ā 
Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesPhilip Schwarz
Ā 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesPhilip Schwarz
Ā 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesPhilip Schwarz
Ā 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three ApproachesPhilip Schwarz
Ā 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsPhilip Schwarz
Ā 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsPhilip Schwarz
Ā 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaPhilip Schwarz
Ā 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaPhilip Schwarz
Ā 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaPhilip Schwarz
Ā 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsPhilip Schwarz
Ā 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Philip Schwarz
Ā 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...Philip Schwarz
Ā 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
Ā 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
Ā 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...Philip Schwarz
Ā 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
Ā 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...Philip Schwarz
Ā 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsPhilip Schwarz
Ā 

More from Philip Schwarz (20)

Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Ā 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
Ā 
Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a series
Ā 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a series
Ā 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a series
Ā 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three Approaches
Ā 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also Programs
Ā 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with Views
Ā 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in Scala
Ā 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in Scala
Ā 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in Scala
Ā 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets Cats
Ā 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Ā 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
Ā 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Ā 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Ā 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
Ā 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Ā 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Ā 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axioms
Ā 

Recently uploaded

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
Ā 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
Ā 
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE9953056974 Low Rate Call Girls In Saket, Delhi NCR
Ā 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
Ā 
Shapes for Sharing between Graph Data SpacesĀ - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data SpacesĀ - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data SpacesĀ - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data SpacesĀ - and Epistemic Querying of RDF-...Steffen Staab
Ā 
CALL ON āž„8923113531 šŸ”Call Girls Kakori Lucknow best sexual service Online ā˜‚ļø
CALL ON āž„8923113531 šŸ”Call Girls Kakori Lucknow best sexual service Online  ā˜‚ļøCALL ON āž„8923113531 šŸ”Call Girls Kakori Lucknow best sexual service Online  ā˜‚ļø
CALL ON āž„8923113531 šŸ”Call Girls Kakori Lucknow best sexual service Online ā˜‚ļøanilsa9823
Ā 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
Ā 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
Ā 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
Ā 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
Ā 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
Ā 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
Ā 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
Ā 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
Ā 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
Ā 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
Ā 
CALL ON āž„8923113531 šŸ”Call Girls Badshah Nagar Lucknow best Female service
CALL ON āž„8923113531 šŸ”Call Girls Badshah Nagar Lucknow best Female serviceCALL ON āž„8923113531 šŸ”Call Girls Badshah Nagar Lucknow best Female service
CALL ON āž„8923113531 šŸ”Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
Ā 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
Ā 
call girls in Vaishali (Ghaziabad) šŸ” >ą¼’8448380779 šŸ” genuine Escort Service šŸ”āœ”ļøāœ”ļø
call girls in Vaishali (Ghaziabad) šŸ” >ą¼’8448380779 šŸ” genuine Escort Service šŸ”āœ”ļøāœ”ļøcall girls in Vaishali (Ghaziabad) šŸ” >ą¼’8448380779 šŸ” genuine Escort Service šŸ”āœ”ļøāœ”ļø
call girls in Vaishali (Ghaziabad) šŸ” >ą¼’8448380779 šŸ” genuine Escort Service šŸ”āœ”ļøāœ”ļøDelhi Call girls
Ā 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
Ā 

Recently uploaded (20)

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
Ā 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Ā 
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
Ā 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
Ā 
Shapes for Sharing between Graph Data SpacesĀ - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data SpacesĀ - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data SpacesĀ - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data SpacesĀ - and Epistemic Querying of RDF-...
Ā 
CALL ON āž„8923113531 šŸ”Call Girls Kakori Lucknow best sexual service Online ā˜‚ļø
CALL ON āž„8923113531 šŸ”Call Girls Kakori Lucknow best sexual service Online  ā˜‚ļøCALL ON āž„8923113531 šŸ”Call Girls Kakori Lucknow best sexual service Online  ā˜‚ļø
CALL ON āž„8923113531 šŸ”Call Girls Kakori Lucknow best sexual service Online ā˜‚ļø
Ā 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Ā 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
Ā 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
Ā 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
Ā 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
Ā 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
Ā 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
Ā 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
Ā 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
Ā 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Ā 
CALL ON āž„8923113531 šŸ”Call Girls Badshah Nagar Lucknow best Female service
CALL ON āž„8923113531 šŸ”Call Girls Badshah Nagar Lucknow best Female serviceCALL ON āž„8923113531 šŸ”Call Girls Badshah Nagar Lucknow best Female service
CALL ON āž„8923113531 šŸ”Call Girls Badshah Nagar Lucknow best Female service
Ā 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
Ā 
call girls in Vaishali (Ghaziabad) šŸ” >ą¼’8448380779 šŸ” genuine Escort Service šŸ”āœ”ļøāœ”ļø
call girls in Vaishali (Ghaziabad) šŸ” >ą¼’8448380779 šŸ” genuine Escort Service šŸ”āœ”ļøāœ”ļøcall girls in Vaishali (Ghaziabad) šŸ” >ą¼’8448380779 šŸ” genuine Escort Service šŸ”āœ”ļøāœ”ļø
call girls in Vaishali (Ghaziabad) šŸ” >ą¼’8448380779 šŸ” genuine Escort Service šŸ”āœ”ļøāœ”ļø
Ā 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
Ā 

Sequence and Traverse - Part 3

  • 2. We now have instances of Traverse for List, Option, Map, and Tree . What does this generalized traverse /sequence mean? Letā€™s just try plugging in some concrete type signatures for calls to sequence. We can speculate about what these functions do, just based on their signatures: ā€¢ List[Option[A]] => Option[List[A]] (a call to Traverse[List].sequence with Option as the Applicative ) returns None if any of the input List is None; otherwise it returns the original List wrapped in Some. ā€¢ Tree[Option[A]] => Option[Tree[A]] (a call to Traverse[Tree].sequence with Option as the Applicative ) returns None if any of the input Tree is None; otherwise it returns the original Tree wrapped in Some. ā€¢ Map[K, Par[A]] => Par[Map[K,A]] (a call to Traverse[Map[K,_]].sequence with Par as the Applicative ) produces a parallel computation that evaluates all values of the map in parallel. Functional Programming in Scala (by Paul Chiusano and Runar Bjarnason) @pchiusano @runarorama trait Traverse[F[_]] { def traverse[M[_]:Applicative,A,B](fa: F[A])(f: A => M[B]): M[F[B]] sequence(map(fa)(f)) def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] = traverse(fma)(ma => ma) }
  • 3. For more details on Monoids, see this and this. For more details on Foldable see slide 26 onwards of this (start from slide 16 for even more of an introduction to folding). In upcoming slides we are going to be referring to the Foldable trait and the Monoid trait. The next four slides are a minimal introduction to Monoids. The subsequent three slides are a minimal introduction to Foldable. https://www.slideshare.net/pjschwarz/monoids-with-examples-using-scalaz-and-cats-part-1 @philip_schwarz https://www.slideshare.net/pjschwarz/monoids-with-examples-using-scalaz-and-cats-part-2 @philip_schwarz
  • 4. What is a monoid? Letā€™s consider the algebra of string concatenation. We can add "foo" + "bar" to get "foobar", and the empty string is an identity element for that operation. That is, if we say (s + "") or ("" + s), the result is always s. scala> val s = "foo" + "bar" s: String = foobar scala> assert( s == s + "" ) scala> assert( s == "" + s ) scala> scala> val (r,s,t) = ("foo","bar","baz") r: String = foo s: String = bar t: String = baz scala> assert( ( ( r + s ) + t ) == ( r + ( s + t ) ) ) scala> assert( ( ( r + s ) + t ) == "foobarbaz" ) scala> Furthermore, if we combine three strings by saying (r + s + t), the operation is associative ā€”it doesnā€™t matter whether we parenthesize it: ((r + s) + t) or (r + (s + t)). The exact same rules govern integer addition. Itā€™s associative, since (x + y) + z is always equal to x + (y + z) scala> val (x,y,z) = (1,2,3) x: Int = 1 y: Int = 2 z: Int = 3 scala> assert( ( ( x + y ) + z ) == ( x + ( y + z ) ) ) scala> assert( ( ( x + y ) + z ) == 6 ) scala> and it has an identity element, 0 , which ā€œdoes nothingā€ when added to another integer scala> val s = 3 s: Int = 3 scala> assert( s == s + 0) scala> assert( s == 0 + s) scala>
  • 5. Ditto for integer multiplication scala> val s = 3 s: Int = 3 scala> assert( s == s * 1) scala> assert( s == 1 * s) scala> scala> val (x,y,z) = (2,3,4) x: Int = 2 y: Int = 3 z: Int = 4 scala> assert(( ( x * y ) * z ) == ( x * ( y * z ) )) scala> assert(( ( x * y ) * z ) == 24) scala> whose identity element is 1 The Boolean operators && and || are likewise associative and they have identity elements true and false, respectively scala> val (p,q,r) = (true,false,true) p: Boolean = true q: Boolean = false r: Boolean = true scala> assert(( ( p || q ) || r ) == ( p || ( q || r ) )) scala> assert(( ( p || q ) || r ) == true ) scala> assert(( ( p && q ) && r ) == ( p && ( q && r ) )) scala> assert(( ( p && q ) && r ) == false ) scala> val s = true s: Boolean = true scala> assert( s == ( s && true ) ) scala> assert( s == ( true && s ) ) scala> assert( s == ( s || false ) ) scala> assert( s == ( false || s ) )
  • 6. These are just a few simple examples, but algebras like this are virtually everywhere. The term for this kind of algebra is monoid. The laws of associativity and identity are collectively called the monoid laws. A monoid consists of the following: ā€¢ Some type A ā€¢ An associative binary operation, op, that takes two values of type A and combines them into one: op(op(x,y), z) == op(x, op(y,z)) for any choice of x: A, y: A, z: A ā€¢ A value, zero: A, that is an identity for that operation: op(x, zero) == x and op(zero, x) == x for any x: A trait Monoid[A] { def op(a1: A, a2: A): A def zero: A } val stringMonoid = new Monoid[String] { def op(a1: String, a2: String) = a1 + a2 val zero = "" } An example instance of this trait is the String monoid: def listMonoid[A] = new Monoid[List[A]] { def op(a1: List[A], a2: List[A]) = a1 ++ a2 val zero = Nil } List concatenation also forms a monoid: Functional Programming in Scala (by Paul Chiusano and Runar Bjarnason) @pchiusano @runarorama We can express this with a Scala trait: List function returning a new list containing the elements from the left hand operand followed by the elements from the right hand operand String concatenation function
  • 7. Monoid instances for integer addition and multiplication as well as the Boolean operators implicit val intAdditionMonoid = new Monoid[Int] { def op(x: Int, y: Int) = x + y val zero = 0 } implicit val intMultiplicationMonoid = new Monoid[Int] { def op(x: Int, y: Int) = x * y val zero = 1 } Just what is a monoid, then? Itā€™s simply a type A and an implementation of Monoid[A] that satisfies the laws. Stated tersely, a monoid is a type together with a binary operation (op) over that type, satisfying associativity and having an identity element (zero). What does this buy us? Just like any abstraction, a monoid is useful to the extent that we can write useful generic code assuming only the capabilities provided by the abstraction. Can we write any interesting programs, knowing nothing about a type other than that it forms a monoid? Absolutely! implicit val booleanOr = new Monoid[Boolean] { def op(x: Boolean, y: Boolean) = x || y val zero = false } implicit val booleanAnd = new Monoid[Boolean] { def op(x: Boolean, y: Boolean) = x && y val zero = true } Functional Programming in Scala (by Paul Chiusano and Runar Bjarnason) @pchiusano @runarorama (by Runar Bjarnason) @runarorama
  • 8. That was the minimal introduction to Monoid. Next, we have three slides with a minimal introduction to Foldable. @philip_schwarz
  • 9. Foldable data structures In chapter 3, we implemented the data structures List and Tree, both of which could be folded. In chapter 5, we wrote Stream, a lazy structure that also can be folded much like a List can, and now weā€™ve just written a fold for IndexedSeq. When weā€™re writing code that needs to process data contained in one of these structures, we often donā€™t care about the shape of the structure (whether itā€™s a tree or a list), or whether itā€™s lazy or not, or provides efficient random access, and so forth. For example, if we have a structure full of integers and want to calculate their sum, we can use foldRight: ints.foldRight(0)(_ + _) Looking at just this code snippet, we shouldnā€™t have to care about the type of ints. It could be a Vector, a Stream, or a List, or anything at all with a foldRight method. We can capture this commonality in a trait: Functional Programming in Scala (by Paul Chiusano and Runar Bjarnason) @pchiusano @runarorama trait Foldable[F[_]] { def foldRight[A,B](as: F[A])(z: B)(f: (A,B) => B): B def foldLeft[A,B](as: F[A])(z: B)(f: (B,A) => B): B def foldMap[A,B](as: F[A])(f: A => B)(mb: Monoid[B]): B def concatenate[A](as: F[A])(m: Monoid[A]): A = foldLeft(as)(m.zero)(m.op) } Here weā€™re abstracting over a type constructor F, much like we did with the Parser type in the previous chapter. We write it as F[_], where the underscore indicates that F is not a type but a type constructor that takes one type argument. Just like functions that take other functions as arguments are called higher-order functions, something like Foldable is a higher- order type constructor or a higher-kinded type .7 7 Just like values and functions have types, types and type constructors have kinds. Scala uses kinds to track how many type arguments a type constructor takes, whether itā€™s co- or contravariant in those arguments, and what the kinds of those arguments are.
  • 10. EXERCISE 10.12 Implement Foldable[List], Foldable[IndexedSeq], and Foldable[Stream]. Remember that foldRight, foldLeft, and foldMap can all be implemented in terms of each other, but that might not be the most efficient implementation. A Companion booklet to FP in Scala FP in Scala trait Foldable[F[_]] { def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B = foldMap(as)(f.curried)(endoMonoid[B])(z) def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B = foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z) def foldMap[A, B](as: F[A])(f: A => B)(mb: Monoid[B]): B = foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b)) def concatenate[A](as: F[A])(m: Monoid[A]): A = foldLeft(as)(m.zero)(m.op) } object ListFoldable extends Foldable[List] { override def foldRight[A, B](as:List[A])(z:B)(f:(A,B)=>B) = as.foldRight(z)(f) override def foldLeft[A, B](as:List[A])(z:B)(f:(B,A)=>B) = as.foldLeft(z)(f) override def foldMap[A, B](as:List[A])(f:A=>B)(mb:Monoid[B]):B = foldLeft(as)(mb.zero)((b, a) => mb.op(b, f(a))) } object IndexedSeqFoldable extends Foldable[IndexedSeq] {ā€¦} object StreamFoldable extends Foldable[Stream] { override def foldRight[A, B](as:Stream[A])(z:B)(f:(A,B)=>B) = as.foldRight(z)(f) override def foldLeft[A, B](as:Stream[A])(z:B)(f:(B,A)=>B) = as.foldLeft(z)(f) } assert( ListFoldable.foldLeft(List(1,2,3))(0)(_+_) == 6) assert( ListFoldable.foldRight(List(1,2,3))(0)(_+_) == 6) assert( ListFoldable.concatenate(List(1,2,3))(intAdditionMonoid) == 6) assert( ListFoldable.foldMap(List("1","2","3"))(_ toInt)(intAdditionMonoid) == 6) assert( StreamFoldable.foldLeft(Stream(1,2,3))(0)(_+_) == 6) assert( StreamFoldable.foldRight(Stream(1,2,3))(0)(_+_) == 6) assert( StreamFoldable.concatenate(Stream(1,2,3))(intAdditionMonoid) == 6) assert( StreamFoldable.foldMap(Stream("1","2","3"))(_ toInt)(intAdditionMonoid) == 6) assert( ListFoldable.foldLeft(List("a","b","c"))("")(_+_) == "abc") assert( ListFoldable.foldRight(List("a","b","c"))("")(_+_) == "abc") assert( ListFoldable.concatenate(List("a","b","c"))(stringMonoid) == "abc") assert( ListFoldable.foldMap(List(1,2,3))(_ toString)(stringMonoid) == "123") assert( StreamFoldable.foldLeft(Stream("a","b","c"))("")(_+_) == "abc") assert( StreamFoldable.foldRight(Stream("a","b","c"))("")(_+_) == "abc") assert( StreamFoldable.concatenate(Stream("a","b","c"))(stringMonoid) == "abc") assert( StreamFoldable.foldMap(Stream(1,2,3))(_ toString)(stringMonoid) == "123") Using the methods of ListFoldable and StreamFoldable to fold Lists/Streams of Ints and Strings. If you are new to monoids, donā€™t worry about the implementation of foldRight and foldLeft except for the fact that it is possible to define them using foldMap.
  • 11. Sam Halliday @fommil Technically, Foldable is for data structures that can be walked to produce a summary value. However, this undersells the fact that it is a one-typeclass army that can provide most of what youā€™d expect to see in a Collections API. You might recognise foldMap by its marketing buzzword name, MapReduce. Given an F[A], a function from A to B, and a way to combine B (provided by the Monoid, along with a zero B), we can produce a summary value of type B. There is no enforced operation order, allowing for parallel computation. foldRight does not require its parameters to have a Monoid, meaning that it needs a starting value z and a way to combine each element of the data structure with the summary value. The order for traversing the elements is from right to left and therefore it cannot be parallelised. foldLeft traverses elements from left to right. foldLeft can be implemented in terms of foldMap, but most instances choose to implement it because it is such a basic operation. Since it is usually implemented with tail recursion, there are no byname parameters. The simplest thing to do with foldMap is to use the identity function, giving fold (the natural sum of the monoidal elements), with left/right variants to allow choosing based on performance criteria: @typeclass trait Foldable[F[_]] { def foldMap[A, B: Monoid](fa: F[A])(f: A => B): B def foldRight[A, B](fa: F[A], z: =>B)(f: (A, =>B) => B): B def foldLeft[A, B](fa: F[A], z: B)(f: (B, A) => B): B = ... def fold[A: Monoid](t: F[A]): A = ... def sumr[A: Monoid](fa: F[A]): A = ... def suml[A: Monoid](fa: F[A]): A = ... ā€¦ In FPiS, fold is called concatenate. Sam Halliday Anything youā€™d expect to find in a collection library is probably on Foldable and if it isnā€™t already, it probably should be.
  • 12. With that refresher on Monoid and Foldable out of the way, letā€™s first compare Traverse.traverse with Foldable.foldMap and then see the connection between Traverse.traverse and Functor.map. @philip_schwarz
  • 13. A traversal is similar to a fold in that both take some data structure and apply a function to the data within in order to produce a result. The difference is that traverse preserves the original structure , whereas foldMap discards the structure and replaces it with the operations of a monoid. Look at the signature Tree[Option[A]] => Option[Tree[A]], for instance. Weā€™re preserving the Tree structure, not merely collapsing the values using some monoid. trait Traverse[F[_]] { def traverse[M[_]:Applicative,A,B](as: F[A])(f: A => M[B]): M[F[B]] def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] = traverse(fma)(ma => ma) } trait Foldable[F[_]] { def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B = foldMap(as)(f.curried)(endoMonoid[B])(z) def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B = foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z) def foldMap[A, B](as: F[A])(f: A => B)(mb: Monoid[B]): B = foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b)) def concatenate[A](as: F[A])(m: Monoid[A]): A = foldLeft(as)(m.zero)(m.op) } traverse(as: Tree[String])(f: String => Option[Int])(implicit G: Applicative[Option]): Option[Tree[Int]] foldMap(as: Tree[String])(f: String => Int) (implicit mb: Monoid[Int]) : Int // foldMap using integer addition monoid // // "2" --> 2 --> 6 // / / // "1" "3" 1 3 // traverse // // "2" --> Some(2) --> Some( 2 ) // / / / // "1" "3" Some(1) Some(3) 1 3 To illustrate this difference between how traverse preserves the structure of a Tree and foldMap collapses the structure using some monoid, we are going to look at an example in which both traverse and foldMap convert the elements of the Tree from String values to Int values, but while traverse produces an Option[Tree[Int]], foldMap produces an Int. FP in Scala See the next slide for the full example. @philip_schwarz
  • 14. case class Tree[+A](head: A, tail: List[Tree[A]]) val tree = Tree("2",List(Tree("1", Nil), Tree("3", Nil))) val toInt: String => Int = _.toInt val folded = 6 assert( treeFoldable.foldMap(tree)(toInt)(intMonoid) == folded ) // treeFoldable.foldMap(tree)(toInt)(intMonoid) // // "2" --> 2 --> 6 // / / // "1" "3" 1 3 // treeTraverse.traverse(tree)(parseInt)(optionApplicative) // // "2" --> Some(2) --> Some( 2 ) // / / / // "1" "3" Some(1) Some(3) 1 3 val listTraverse = new Traverse[List] { override def traverse[M[_],A,B](as:List[A])(f: A=>M[B])(implicit M:Applicative[M]):M[List[B]] = as.foldRight(M.unit(List[B]()))((a, fbs) => M.map2(f(a), fbs)(_ :: _)) } val treeTraverse = new Traverse[Tree] { override def traverse[G[_],A,B](ta:Tree[A])(f: A=>G[B])(implicit G:Applicative[G]):G[Tree[B]] = G.map2(f(ta.head), listTraverse.traverse(ta.tail)(a => traverse(a)(f)))(Tree(_, _)) } implicit val optionApplicative = new Applicative[Option] { def map2[A, B, C](fa: Option[A], fb: Option[B])(f: (A, B) => C): Option[C] = (fa, fb) match { case (Some(a), Some(b)) => Some(f(a,b)) case _ => None } def unit[A](a: => A): Option[A] = Some(a) } val treeFoldable = new Foldable[Tree] { override def foldMap[A,B](as:Tree[A])(f:A=>B)(mb:Monoid[B]):B = as match { case Tree(head,Nil) => f(head) case Tree(head,tree::rest) => mb.op(foldMap(Tree(head,rest))(f)(mb), foldMap(tree)(f)(mb)) } } val parseInt: String => Option[Int] = x => Try{ x.toInt }.toOption val traversed = Some(Tree(2,List(Tree(1,Nil), Tree(3,Nil)))) assert( treeTraverse.traverse(tree)(parseInt)(optionApplicative) == traversed ) ā€Ø // "2" // / // "1" "3" implicit val intMonoid = new Monoid[Int]{ def op(a1: Int, a2: Int): Int = a1 + a2 def zero: Int = 0 } In FPiS the Tree type that treeFoldable operates on is a bit different from the one that treeTraverse operates on. Here I rewrote treeFoldable to operate on the same Tree type as treeTraverse, so that I can show an example of traversing and folding the same tree. Traversing and folding the same tree.
  • 15. We were first introduced to the Traverse trait in Part 2 So at that time I suggested we think of Traverseā€˜s traverse method as not having a body, i.e. being abstract. I reckoned the body was just there to point out that if Traverse did have a map function then it could be used to implement traverse. All the traverse instances we have looked at so far implemented traverse without using a map function. In the next two slides we are finally going to see the connection between Traverse and map. trait Traverse[F[_]] { def traverse[M[_]:Applicative,A,B](fa: F[A])(f: A => M[B]): M[F[B]] sequence(map(fa)(f)) def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] = traverse(fma)(ma => ma) } At that time we found it confusing that Traverseā€˜s traverse function used a map function that was not defined anywhere We did however know, from Part 1, that just like flatMap is map and then flatten, traverse is map and then sequence. def flatMap[A,B](ma: F[A])(f: A ā‡’ F[B]): F[B] = flatten(ma map f) def flatten[A](mma: F[F[A]]): F[A] = flatMap(mma)(x ā‡’ x) def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] = sequence(a map f) def sequence[A](a: List[Option[A]]): Option[List[A]] = traverse(a)(x ā‡’ x)
  • 16. EXERCISE 12.14 Hard: Implement map in terms of traverse as a method on Traverse[A]. This establishes that Traverse is an extension of Functor and that the traverse function is a generalization of map (for this reason we sometimes call these traversable functors). Note that in implementing map, you can call traverse with your choice of Applicative[G]. Functional Programming in Scala (by Paul Chiusano and Runar Bjarnason) @pchiusano @runarorama by Runar Bjarnason @runarorama Answer to EXERCISE 12.14trait Traverse[F[_]] extends Functor[F] { def traverse[G[_] : Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] = sequence(map(fa)(f)) def sequence[G[_] : Applicative, A](fga: F[G[A]]): G[F[A]] = traverse(fga)(ga => ga) type Id[A] = A val idMonad = new Monad[Id] { def unit[A](a: => A) = a override def flatMap[A, B](a: A)(f: A => B): B = f(a) } def map[A, B](fa: F[A])(f: A => B): F[B] = traverse[Id, A, B](fa)(f)(idMonad) } The simplest possible Applicative we can use is Id. We already know this forms a Monad, so itā€™s also an applicative functor. We can now implement map by calling traverse, picking Id as the Applicative. Note that we can define traverse in terms of sequence and map, which means that a valid Traverse instance may define sequence and map, or just traverse. trait Traverse[F[_]] extends Functor[F] { def traverse[G[_],A,B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]] = sequence(map(fa)(f)) def sequence[G[_],A](fga: F[G[A]])(implicit G: Applicative[G]): G[F[A]] = traverse(fga)(ga => ga) def map[A,B](fa: F[A])(f: A => B): F[B] = ??? }
  • 17. trait Traverse[F[_]] { def traverse[M[_]:Applicative,A,B](fa: F[A])(f: A => M[B]): M[F[B]] sequence(map(fa)(f)) def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] = traverse(fma)(ma => ma) } trait Traverse[F[_]] extends Functor[F] { def traverse[M[_]:Applicative,A,B](fa: F[A])(f: A => M[B]): M[F[B]] sequence(map(fa)(f)) def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] = traverse(fma)(ma => ma) def map[A,B](fa: F[A])(f: A => B): F[B] = traverse[Id, A, B](fa)(f)(idMonad) } We had not yet been told that Traverse is a Functor: it either simply defines a traverse function, in which case it gets free definitions of sequence and map based on traverse, or it defines both a map function and a sequence function and both are then used to implement traverse. See below for what was missing from the Traverse trait. Mind blown: traverse is a generalization of map. Conversely: mapping is a specialization of traversing. When we traverse using the degenerate Applicative that is the Id Monad, we are just mapping. Mapping is traversing with the Id Monad as an Applicative. So thatā€™s why we found it confusing when FPiS first introduced Traverse (below) with a traverse implementation that referred to an undefined map function.
  • 18. In the next slide we have a go at using the map function of listTraverse, optionTraverse and treeTraverse. @philip_schwarz
  • 19. trait Functor[F[_]] { def map[A,B](fa: F[A])(f: A => B): F[B] } trait Monad[F[_]] extends Applicative[F] { def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] override def map[A,B](m: F[A])(f: A => B): F[B] = flatMap(m)(a => unit(f(a))) override def map2[A,B,C](ma:F[A], mb:F[B])(f:(A, B) => C): F[C] = flatMap(ma)(a => map(mb)(b => f(a, b))) } trait Applicative[F[_]] extends Functor[F] { def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] def unit[A](a: => A): F[A] def apply[A,B](fab: F[A => B])(fa: F[A]): F[B] = map2(fab, fa)(_(_)) def map[A,B](fa: F[A])(f: A => B): F[B] = apply(unit(f))(fa) } trait Traverse[F[_]] extends Functor[F] { def traverse[M[_]:Applicative,A,B](fa:F[A])(f:A=>M[B]):M[F[B]] def sequence[M[_] : Applicative, A](fma: F[M[A]]): M[F[A]] = traverse(fma)(ma => ma) type Id[A] = A val idMonad = new Monad[Id] { def unit[A](a: => A) = a override def flatMap[A, B](a: A)(f: A => B): B = f(a) } def map[A, B](fa: F[A])(f: A => B): F[B] = traverse[Id, A, B](fa)(f)(idMonad) } val listTraverse = new Traverse[List] { override def traverse[M[_], A, B](as: List[A])(f: A => M[B]) (implicit M: Applicative[M]): M[List[B]] = as.foldRight(M.unit(List[B]())) ((a, fbs) => M.map2(f(a), fbs)(_ :: _)) } val optionTraverse = new Traverse[Option] { override def traverse[M[_],A,B](oa: Option[A])(f: A => M[B]) (implicit M: Applicative[M]): M[Option[B]] = oa match { case Some(a) => M.map(f(a))(Some(_)) case None => M.unit(None) } } case class Tree[+A](head: A, tail: List[Tree[A]]) val treeTraverse = new Traverse[Tree] { override def traverse[M[_], A, B](ta: Tree[A])(f: A => M[B]) (implicit M: Applicative[M]): M[Tree[B]] = M.map2(f(ta.head), listTraverse.traverse(ta.tail)(a => traverse(a)(f)) )(Tree(_, _)) } val double: Int => Int = _ * 2 assert(listTraverse.map(List(1,2,3))(double) == List(2,4,6)) assert(optionTraverse.map(Some(2))(double) == Some(4)) val tree = Tree(2,List(Tree(1, Nil), Tree(3, Nil))) val doubledTree = Tree(4,List(Tree(2, Nil), Tree(6, Nil))) assert(treeTraverse.map(tree)(double) == doubledTree)
  • 20. And in the next slide we use another example to look a bit closer at how mapping is just traversing with the Id Monad Applicative.
  • 21. implicit val optionApplicative = new Applicative[Option] { def map2[A, B, C](fa: Option[A], fb: Option[B])(f: (A, B) => C): Option[C] = (fa, fb) match { case (Some(a), Some(b)) => Some(f(a,b)) case _ => None } def unit[A](a: => A): Option[A] = Some(a) } type Id[A] = A val idMonad = new Monad[Id] { def unit[A](a: => A) = a override def flatMap[A, B](a: A)(f: A => B): B = f(a) } val parseInt: String => Option[Int] = x => scala.util.Try{ x.toInt }.toOption assert( listTraverse.traverse(List("1","2","3"))(parseInt)(optionApplicative) == Some(List(1,2,3))) List("1","2","3") Ć  List(1,2,3) Ć  List(1,2,3) List("1","2","3") Ć  List(Id(1), Id(2), Id(3)) Ć  Id( List(1,2,3) ) List("1","2","3") Ć  List(idMonad.unit(1),idMonad.unit(2),idMonad.unit(3)) Ć  idMonad.unit( List(1,2,3) ) List[String] Ć  List[Id[Int]] Ć  Id[List[Int]] List[String] Ć  List[Id[Int]] Ć  Id[List[Int]] List[String] Ć  List[ Int ] Ć  List[Int] val toInt: String => Id[Int] = _.toInt assert( listTraverse.map(List("1","2","3"))(toInt) == List(1,2,3)) assert( listTraverse.traverse(List("1","2","3"))(toInt)(idMonad) == List(1,2,3)) List("1","2","3") Ć  List(Some(1),Some(2),Some(3)) Ć  Some(List(1,2,3) ) List[String] Ć  List[Option[Int]] Ć  Option[List[Int]] Here we use Id(x) to represent x lifted into the Id Monad.
  • 22. Having compared Traverse.traverse with Foldable.foldMap and seen the connection between Traverse.traverse and Functor.map, we know go back to looking at the connection between Traverse and Foldable. @philip_schwarz
  • 23. 12.7.1 From monoids to applicative functors Weā€™ve just learned that traverse is more general than map. Next weā€™ll learn that traverse can also express foldMap and by extension foldLeft and foldRight! Take another look at the signature of traverse: def traverse[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]] Suppose that our G were a type constructor ConstInt that takes any type to Int, so that ConstInt[A] throws away its type argument A and just gives us Int: type ConstInt[A] = Int Then in the type signature for traverse, if we instantiate G to be ConstInt, it becomes def traverse[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]] def traverse[A,B](fa: F[A])(f: A => Int): Int Functional Programming in Scala (by Paul Chiusano and Runar Bjarnason) @pchiusano @runarorama G[X] ===> ConstInt[X] == Int trait Foldable[F[_]] { def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B = foldMap(as)(f.curried)(endoMonoid[B])(z) def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B = foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z) def foldMap[A, B](as: F[A])(f: A => B)(mb: Monoid[B]): B = foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b)) def concatenate[A](as: F[A])(m: Monoid[A]): A = foldLeft(as)(m.zero)(m.op) } This looks a lot like foldMap from Foldable. Indeed, if F is something like List, then what we need to implement this signature is a way of combining the Int values returned by f for each element of the list, and a ā€œstartingā€ value for handling the empty list. In other words, we only need a Monoid[Int]. And thatā€™s easy to come by. In fact, given a constant functor like we have here, we can turn any Monoid into an Applicative. (see next slide)
  • 24. Listing 12.8 Turning a Monoid into an Applicative type Const[M, B] = M implicit def monoidApplicative[M](M: Monoid[M]) = new Applicative[({ type f[x] = Const[M, x] })#f] { def unit[A](a: => A): M = M.zero def map2[A,B,C](m1: M, m2: M)(f: (A,B) => C): M = M.op(m1,m2) } This means that Traverse can extend Foldable and we can give a default implementation of foldMap in terms of traverse: trait Traverse[F[_]] extends Functor[F] with Foldable[F] { ā€¦ override def foldMap[A,M](as: F[A])(f: A => M)(mb: Monoid[M]): M = traverse[({type f[x] = Const[M,x]})#f,A,Nothing](as)(f)(monoidApplicative(mb)) } Note that Traverse now extends both Foldable and Functor ! Importantly, Foldable itself canā€™t extend Functor. Even though itā€™s possible to write map in terms of a fold for most foldable data structures like List, itā€™s not possible in general. Functional Programming in Scala (by Paul Chiusano and Runar Bjarnason) @pchiusano @runarorama
  • 25. Earlier I had a Mind Blown moment because traverse is a generalization of map. Mind Blown again: traverse can also express foldMap. So although earlier we said that the difference between traverse and foldMap is that traverse preserves the original structure whereas foldMap discards the structure, if we pass traverse a monoid applicative then it behaves like foldMap and discards the structure (replacing it with the operations of a monoid).
  • 26. The next slide is a final recap of how, by using Id and Const, we can get Traverse to implement map and foldMap, which means that Traverse is both a Functor and a Foldable. @philip_schwarz
  • 27. def traverse[G[_],A,B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]] G[X] ===> Id[X] == X G[X] ===> Const[M, X] == M def foldMap[A,M](as: F[A])(f: A => M)(mb: Monoid[M]): M = traverse[({type f[x] = Const[M,x]})#f,A,Nothing] (as)(f)(monoidApplicative(mb)) def map[A, B](fa: F[A])(f: A => B): F[B] = traverse[Id, A, B](fa)(f)(idMonad) type Const[M,B] = Mtype Id[A] = A G[F[B]] ==> F[B]G[B] ==> B G[F[B]] ==> MG[B] ==> M G = Id Monad G = Applicative Monoid trait Traverse[F[_]] extends Functor[F] with Foldable[F] { ā€¦ def map[A,B](fa: F[A])(f: A => B): F[B] = traverseā€¦ def foldMap[A,M](as: F[A])(f: A => M)(mb: Monoid[M]): M = traverseā€¦ def traverse[G[_],A,B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]] ā€¦ }
  • 28. 5. Scalaz Typeclasses Before we introduce the typeclass hierarchy, we will peek at the four most important methods from a control flow perspective, the methods we will use the most in typical FP applications: ā€¦ ā€¦ traverse is useful for rearranging type constructors. If you find yourself with an F[G[_]] but you really need a G[F[_]] then you need Traverse. For example, say you have a List[Future[Int]] but you need it to be a Future[List[Int]], just call .traverse(identity), or its simpler sibling .sequence. ā€¦ 5.4 Mappable Things Weā€™re focusing on things that can be mapped over, or traversed, in some senseā€¦ ā€¦ Sam Halliday @fommil
  • 29. 5.4.3 Traverse Traverse is what happens when you cross a Functor with a Foldable trait Traverse[F[_]] extends Functor[F] with Foldable[F] { def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] def sequence[G[_]: Applicative, A](fga: F[G[A]]): G[F[A]] = ... def reverse[A](fa: F[A]): F[A] = ... def zipL[A, B](fa: F[A], fb: F[B]): F[(A, Option[B])] = ... def zipR[A, B](fa: F[A], fb: F[B]): F[(Option[A], B)] = ... def indexed[A](fa: F[A]): F[(Int, A)] = ... def zipWithL[A, B, C](fa: F[A], fb: F[B])(f: (A, Option[B]) => C): F[C] = ... def zipWithR[A, B, C](fa: F[A], fb: F[B])(f: (Option[A], B) => C): F[C] = ... def mapAccumL[S, A, B](fa: F[A], z: S)(f: (S, A) => (S, B)): (S, F[B]) = ... def mapAccumR[S, A, B](fa: F[A], z: S)(f: (S, A) => (S, B)): (S, F[B]) = ... } At the beginning of the chapter we showed the importance of traverse and sequence for swapping around type constructors to fit a requirement (e.g. List[Future[_]] to Future[List[_]]). You will use these methods more than you could possibly imagine. Functor Foldable TraverseSam Halliday @fommil You will use these methods (sequence and traverse) more than you could possibly imagine. Traverse is what happens when you cross a Functor with a Foldable. Sam Halliday Sam Halliday
  • 30. In the next two slides we have a go at using a Traverse instance (now that Traverse is both a Functor and a Foldable).
  • 31. trait Applicative[F[_]] extends Functor[F] { def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] def unit[A](a: => A): F[A] def map[B](fa: F[A])(f: A => B): F[B] = map2(fa, unit(()))((a, _) => f(a)) def sequence[A](fas: List[F[A]]): F[List[A]] = traverse(fas)(fa => fa) def traverse[A,B](as: List[A])(f: A => F[B]): F[List[B]] as.foldRight(unit(List[B]()))((a, fbs) => map2(f(a), fbs)(_ :: _)) ā€¦ } trait Foldable[F[_]] { import Monoid._ def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B = foldMap(as)(f.curried)(endoMonoid[B])(z) def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B = foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z) def foldMap[A,B](as:F[A])(f:A=>B)(implicit mb: Monoid[B]):B = foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b)) def concatenate[A](as: F[A])(implicit m: Monoid[A]): A = foldLeft(as)(m.zero)(m.op) } trait Functor[F[_]] { def map[A,B](fa: F[A])(f: A => B): F[B] } trait Monad[F[_]] extends Applicative[F] { def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] override def map[A,B](m: F[A])(f: A => B): F[B] = flatMap(m)(a => unit(f(a))) override def map2[A,B,C](ma:F[A], mb:F[B])(f:(A, B) => C): F[C] = flatMap(ma)(a => map(mb)(b => f(a, b))) } trait Traverse[F[_]] extends Functor[F] with Foldable[F] { self => def traverse[M[_]:Applicative,A,B](fa:F[A])(f:A=>M[B]):M[F[B]] def sequence[M[_] : Applicative, A](fma: F[M[A]]): M[F[A]] = traverse(fma)(ma => ma) type Id[A] = A val idMonad = new Monad[Id] { def unit[A](a: => A) = a override def flatMap[A, B](a: A)(f: A => B): B = f(a) } def map[A, B](fa: F[A])(f: A => B): F[B] = traverse[Id, A, B](fa)(f)(idMonad) import Applicative._ override def foldMap[A,B](as: F[A])(f: A => B) (implicit mb: Monoid[B]): B = traverse[({type f[x] = Const[B,x]})#f,A,Nothing]( as)(f)(monoidApplicative(mb)) ā€¦ } type Const[M, B] = M implicit def monoidApplicative[M](M: Monoid[M]) = new Applicative[({ type f[x] = Const[M, x] })#f] { def unit[A](a: => A): M = M.zero def map2[A,B,C](m1: M, m2: M)(f: (A,B) => C): M = M.op(m1,m2) } trait Monoid[A] { def op(x: A, y: A): A def zero: A }
  • 32. implicit val optionApplicative = new Applicative[Option] { def map2[A, B, C](fa: Option[A], fb: Option[B])(f: (A, B) => C): Option[C] = (fa, fb) match { case (Some(a), Some(b)) => Some(f(a,b)) case _ => None } def unit[A](a: => A): Option[A] = Some(a) } val parseInt: String => Option[Int] = (s:String) => scala.util.Try(s.toInt).toOption // Traverse assert( listTraverse.traverse(List("1","2","3"))(parseInt) == Some(List(1, 2, 3)) ) assert( listTraverse.sequence(List(Option(1),Option(2),Option(3))) == Some(List(1, 2, 3)) ) // Functor assert( listTraverse.map(List(1,2,3))(_ + 1) == List(2,3,4)) // Foldable assert( listTraverse.foldMap(List("1","2","3"))(_ toInt) == 6 ) assert( listTraverse.concatenate(List(1,2,3)) == 6 ) assert( listTraverse.foldRight(List(1,2,3))(0)(_ + _) == 6 ) assert( listTraverse.foldLeft(List(1,2,3))(0)(_ + _) == 6 ) val listTraverse = new Traverse[List] { override def traverse[M[_], A, B](as: List[A])(f: A => M[B])(implicit M: Applicative[M]): M[List[B]] = as.foldRight(M.unit(List[B]()))((a, fbs) => M.map2(f(a), fbs)(_ :: _)) } implicit val integerAdditionMonoid = new Monoid[Int] { def op(x: Int, y: Int): Int = x + y def zero: Int = 0 } implicit optionApplicative implicit integerAdditionMonoid uses monoidApplicative uses IdMonad Creating a Traverse[List] instance and exercising its functions, including its Functor and Foldable functions.