Scala provides a concise syntax for working with Monads(map & flatMap):
the for comprehension.
Following is a proposal for a concise syntax for working with Comonads(map, extract & coflatMap):
the cofor comprehension.
The proposal has an existing implementation in PR 5725
Consider the following class:
StreamZipper[A] represents a non-empty Stream of As with a cursor (focus).
The map method invokes f on every element and produces a StreamZipper of
The extract method returns the value at the cursor
The coflatMap method invokes f on every cursor (all possible zippers) providing a contextual global operation.
The result is a StreamZipper[B] of the results with a cursor pointing at the same location as this.
The above implementation for coflatMap was left out for brevity. See 3.
Now, consider the following methods:
And, let’s say we have a StreamZipper[Person]:
We would like to get the following:
It seems we can re-use the isInTheMiddle and numberOfTrues methods.
However, without the proposed cofor syntax we’ll probably end with:
From the code above, you can see that it is quite cumbersome to handle the passing of
the context between the invocations of coflatMap.
The proposed syntax allows for the following usage:
The proposed syntax is based on the paper by Dominic Orchard and Alan Mycroft 1.
The syntax for cofor is defined as:
The result type of a cofor expression is a function from the comonad type to
a result (T[A] => B).
This means that the return type must be available at call-site!
Note that unlike for, guards and assignments are not supported.
A cofor desugaring is much more complex than the respective for.
The above cofor expression will be desugared into the following function:
Adding a new keyword to the language makes it more complex
Understanding the desugaring and concept behind cofor is not
trivial and it's much more complex than for (which many developers still
don't feel at ease with).