What’s the difference between an effect and a “coroutine” where calls in the function body to other coroutines are implicitly yielded? Or is that not a real coroutine?
Both effects and coroutines can (and typically do) work implicitly across calls like that. The version with forwarding operators like in this post is something of a Rust-ism, or more generally an async/await-ism, or a stackless coroutine-ism.
The more fundamental difference between effects and coroutines is that a `yield` in a coroutine always goes to the one unique resumer, and carries a single type of value. On the other hand, an expression may have several effects, each of which may be handled in a different place, in the same way that distinct exception types may be caught in different places.
That’s what Kotlin’s `suspend fun` does.