softshipper
softshipper

Reputation: 34071

Functor for sequence computation

I am reading scala cats book from underscore.io. It says following about Monad and Functor:

While monads and functors are the most widely used sequencing data types..

I can see that Monad is using for sequencing data but Functor not at all. Could someone please show about sequencing computation on functors?

Upvotes: 0

Views: 153

Answers (2)

Andrey Tyukin
Andrey Tyukin

Reputation: 44918

Taken out of context, this statement is less clear than it could be.

A fuller version of the quote is:

While monads and functors are the most widely used sequencing data types [...], semigroupals and applicatives are the most general.

The goal of this statement is not to erase the difference between functorial and monadic notions of "sequencing", but rather to contrast them with obviously non-sequential operations provided by Semigroupal.

Both Functor and Monad do support (different) kinds of "sequencing".

Given a value x of type F[X] for some functor F and some type X, we can "sequence" pure functions

f: X => Y
g:      Y => Z

like this:

x map f map g

You can call this "sequencing", at least "elementwise". The point is that g has to wait until f produces at least a single y of type Y in order to do anything useful. However, this does not mean that all invocations of f must be finished before g is invoked for the first time, e.g. if x is a long list, one could process each element in parallel - that's why I called it "elementwise".

With monads that represent monadic effects, the notion of "sequencing" is usually taken a bit more seriously. For example, if you are working with a value x of type M[X] = Writer[Vector[String], X], and you have two functions with the "writing"-effect

f: X => M[Y]
g:        Y => M[Z]

and then you sequence them like this:

x flatMap f flatMap g

you really want f to finish completely, until g begins to write anything into the Vector[String]-typed log. So here, this is literally just "sequencing", without any fine-print.

Now, contrast this with Semigroupal.

Suppose that F is semigroupal, that is, we can always form a F[(A,B)] from F[A] and F[B]. Given two functions

f: X => F[A]
g: X => F[B]

we can build a function

(x: X) => product(f(x), g(x))

that returns results of type F[(A, B)]. Note that now f and g can process x completely independently: whatever it is, it is definitely not sequencing.

Similarly, for an Applicative F and functions

f: A => X
g: B => Y
c:      (X, Y) => Z

and two independent values a: F[A], b: F[B], you can process a and b completely independently with f and g, and then combine the results in the end with c into a single F[Z]:

map2(a, b){ (a, b) => c(f(a), g(b)) }

Again: f and g don't know anything about each other's inputs and outputs, they work completely independently until the very last step c, so this is again not "sequencing".

I hope it clarifies the distinction somewhat.

Upvotes: 2

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27535

Seq(1, 2, 3).map(_ * 2).map(_.toString).foreach(println)

Here: you have a sequence of operations on a sequence of data.

Every monad is actually a functor, because you could implement map with flatMap and unit/pure/whatever your implementation calls it. So if you agree that monads are "sequencing data types", then you should agree on functors being them too.

Upvotes: 3

Related Questions