"for" syntax for parallel computations (afor / applicative for comprehension))

But this is terrible–you what if you want f(a1, b1), f(a1, b2), ..., f(a1, bN), f(a2, b1) ...? The for comprehension to produce that looks exactly the same as what you’re proposing!

If you want the zipped versions, you should add map and flatMap and I guess filterWith as extension methods onto tuples, which implement these using zipWith on their contents. Then you can for ((x, y) <- (a, b)) yield f(x,y).


I am not sure I follow, there is nothing about tuples with zipWith. I thought it was a more idiomatic way of composing parallel computations in Scala than the splat operator (Apply.ap in cats) because functions are not curried by default.

It opens up the possibility for data types to limit themselves at having an implementation of zipWith and not one for flatMap, while still having the nice syntactic sugar of for-comprehensions. An example would be cats.data.Validated.

Suppose you have a type that has flatMap, map, and zipWith. Then you do this:

  x <- xs
  y <- ys
  yield f(x, y)

Does this produce xs.flatMap(x => ys.map(y => f(x,y)) or xs.zipWith(ys)(f)? What do you do if you want the other one?

The latter, but it makes no difference, as the latter reduces to the former, i.e. if a type has flatMap then its implementation of zipWith has to be equivalent as what you wrote.

You said that xs.zipWith(ys)(_ -> _) is equivalent to xs zip ys ("zipWith subsumes zip").

You also said that xs.flatMap(x => ys.map(y => f(x, y)) is equivalent to xs.zipWith(ys)(f).

But for collections, xs zip ys is not the same as xs.flatMap(x => ys.map(y => x -> y)). So I don’t know what you mean.

Also, flatMap+map should not really be the same as zipWith. By normal naming conventions, zipWith would be a zip, not an outer product. Zips preserve length; flatMap+map multiplies lengths.

1 Like

ha, you are right Sir. I suppose I should have used the same naming convention as cats’s, i.e. product and productWith instead of zip and zipWith, that would have been less confusing.

I’m taking a stab at this in macro form: https://twitter.com/kitlangton/status/1489783479403491328
I’ll have a repo up tomorrow in case anyone wants to help out (or heckle) :stuck_out_tongue_winking_eye:

It’ll probably rely on a custom zippable type class so it can be used with any fathomably zippable entity. Imagining particular integrations for the relevant zio-prelude/cats type classes as well.

Thanks for all the great examples @regiskuckaertz :heart:


WIP repo is here: https://github.com/kitlangton/parallel-for


Corne de bouc! It is Christmas AGAIN :heart_eyes: Chapeau bas, Monsieur :tophat:

1 Like