My note on scalaz.Task approaches. This is mainly for old code!!!!
I have found wrong usages of scalaz.Task in old programs.
Why this is important?
When you bring in FP ornaments into your code, it comes with certain cost. The first and formost is additional learning curve for new developers to come in and understand the concepts of total, side effect free, lazy descriptions of computations. This has its advantage of being able to ship robust code with equational reasoning. But what if the usage of FP constructs itself is wrong?
Most of the old scala-FP code has the usages of scalaz.Task which is one of the most popular FP datastructure then.
It's good to use it even today although there are typelevel libraries and ZIO providing better choices - cats.IO, ZIO, Monix.Task
Just not to get things hairy, its good to make things work with Task.delay which is basically () => Try, and not Task.apply which push the computations to async boundaries.
Task.now disallows all that we could do with Task as it is strict evaluation and executes only once ! Probably that's not what we want either.
Task.delay will keep things simple by making computations within current thread. If we think we really need to push comp to async, wrap it in Task.fork, and if not it will wait for forked comp to join by default.
Can I just ditch this old FP code ?
Yes:
If you find an entire set of compositions done using Task.now.
If there isn't even one property based test / laws hanging around
If there isn't an attempt made anywhere in the whole program ( Either, MonadError, try/catch etc etc)