I have an object
object Producer {
def apply() :IO[Foo] = ???
}
It is in code I do not control. I am composing (flat mapping) several functions returning IO. One of them hides a Ref, and exposes update method compatible with it:
object State {
def update(update: Bar => Bar) :IO[Bar] = ???
}
This one I do control, although introducing significant changes would cause a large refactor.
Problem:
for {
bar <- State.update { arg => ??? }
} yield ()
In some cases, but not all, I need a Foo to produce a new Bar inside the lambda passed to State.update.
Can it be done without always evaluating foo <- Producer as the first step?
One way of thinking of
IO[A]is that it is() => A(or() => Future[A]).So
() => IO[T]andIO[() => T]are kinda the same idea, just with a different ergonomics (and different ways of evaluating what's inside). So you should be able to go from one into another and back e.g. with:However, the devil is in the details:
runUnsafeSyncwill not propagate cancellation from the outer IO to the inner IOIOLocalso making a bullet-proof conversion this way would be... rather difficult.
And hardly ever it would be useful as with ergonomics there comes a convention:
IO[A]suggest a side-effect (or at least a possibility of it)X => non-IOsuggest pure computation - takeX, then return sth without mutation nor talking to external world() =>provides no new information, so such pure function would have to be constant (it might be a lazy value basically)so if we followed the convention, we could convert
fa: () => IO[A]intoIO[() => A]by doingIt should make the conversion trivial, but it would also mean that all these
() =>in the context ofIO[A]are kinda pointless. Unless you need to do them to adapt your code to some external interface which expects() => F[A]orF[() => A], it's just noise.