I don’t think the fact that it’s a syntactic transformation is necessarily the problem here, it’s that the syntactic constructs and underlying operations that those constructs are translated to in the current for
comprehension aren’t sufficient to avoid those warts.
I don’t think it’s as hopeless as this
Look again at the F# computation expressions. The way that it works is substantially similar to the way the for
translation works in Scala. However there are more operations supported by the translation than those supported by Scala’s for
comprehension, perhaps enough to support libraries similar to Cats Effect.
See for example the translation of while
expressions:
{ while expr do cexpr } builder.While(fun () -> expr, builder.Delay({ cexpr }))
The requirements to use the while
construct in a computation expression are that the underlying builder object implements the Delay: (unit -> M<'T>) -> M<'T>
and While (unit -> bool) * M<'T> -> M<'T>
methods. I think that it would be really interesting to see how far we could get by supporting a richer vocabulary of operations using a syntactic transformation like @sideeffffect suggets.
It’s not so hard to imagine translating while(cond) { a <- expr }
to something implemented using whileM
. Also, the fact that it’s a syntactic transformation enables all of the implicit constraints required by libraries like Cats Effect to be used.
@yangbo already has a relevant proposal here.
Another approach that seems interesting is prototyping a replacement for the for
translation using the new metaprogramming system in Scala 3 as this would enable the translation to make more use of type information.