Concurrent, a few things can happen:
Async, without using real concurrency (you write a scheduler for concurrent actions that does the interleaving). This is nice but not the main point
Concurrentto also be
Asyncto use the real implementation. But then if every
Async, why not
Concurrent <: Async(which is the current situation)? Well, because we'd like to take an
F[_]: Concurrentconstraint and know that we can have concurrent control flow, without also having the ability to do every possible effect ever (which
Async <: Syncimplies)
Blockersay that it shouldn't be passed implicitly (https://github.com/typelevel/cats-effect/blob/master/core/shared/src/main/scala/cats/effect/Blocker.scala#L31). What is the reason behind this recommendation? I used to pass it implicitly and haven't seen any obvious drawbacks so far.
implicitvalues should never hold state. The implications of this are pretty profound and far-reaching, and a lot of it comes from experience in violating this rule (and paying the price later). An analogous "best practice" is that you should never do something like
implicit def strToInt(s: String): Int = .... You certainly can do this, and it'll work sometimes, but you would reject any PR that introduced something like that, wouldn't you? Same thing with
Blockerwill bite you. I guess the best thing to look at is the frustrations that people often have around
ExecutionContexts in the
FlatMap+ the run loop essentially a trampoline?
implicitvalues should never hold state."