From a political perspective, yes for sure. From a technical perspective, less so. The Cats ecosystem and ZIO are meaningfully different with their designs that the two evolving separately isn't so bad in my opinion.
The Scalaz/Cats schism was worse in the sense that they were largely the same (at least at the time) which led to a lot of duplicated effort.
Typelevel and ZIO take completely different approach to certain things. Even if everyone would be holding hands and singing, they would still argue in discussions on GH.
Typelevel and Cats wants everything to be a pluggable library. Everything should be configurable, hardcoding things is avoided. You are in charge of every single effect.
ZIO is basically a type-safe, compile-time, IO-monad-based framework, managing error handling, side effects and dependency injection. It is opinionated, and libraries integrating with it share its opinions. Some people consider this a FP, type safe Spring Framework.
Both can be integrated if you know what you're doing. Both have plenty of people to push things forward. At this point history between JDG and TL is irrelevant to the community. People involved in past dramas still don't like each others but they don't interact with each other during development, so just don't use Twitter and you won't even notice.
I'm holding out hope that ZIO can be the spring for scala. An opinionated framework is sorely needed for a language like Scala which has so many competing styles and libraries that don't naturally work together.
Nowadays many libraries in and around the Typelevel ecosystem work well together.
There seems to be a real demand for the Zio ecosystem and I wish it all the success it deserves, but its opinionated approach doesn't necessarily solve a problem that people have.
Great. No sure how standardizing on Cats Effect is different than standardizing on ZIO. That's basically my point. ZIO provides a bunch of libraries that work well together.
I think there's room for both things, and we don't really have to (passive-agressively) squabble about which is better.
cats-effect is a meta-abstraction _and_ a concrete implementation of that abstraction. All of its functionality is abstract over the effect type, which for a lot of library use cases is good! (for example, this enables using ZIO with c-e ecosystem libraries; if c-e took the same tactic as ZIO then this wouldn't be possible)
When you get down to the application level, though – essentially the effect type is going to be fixed. I doesn't _have_ to be, but it takes superhuman levels of discipline not to make it that way. And ZIO is built for that – if the effect type is fixed to ZIO, it grants a lot of ergonomic benefits. So, ZIO ecosystem components are built with that in mind, and give a lot of ergonomics and higher-level semantics that aren't possible with c-e (or abstract effect types).
If cats-effect split the meta-abstraction and the implementation into two libraries, I think this debate would be moot. But, having the implementation together with the meta-abstraction makes cats-effect more likely to leak the latter into the former (I think it's gotten a lot better about this lately, though).
Anyway, just saying – both libraries are great, and they're different, and nobody should be made to feel bad about using either one of them.
The core difference is that Cats Effect is a fairly extensible effect type, with a full type class hierarchy. It's easy for compatible libraries to use and provide only what they need.
JDG argues against the "tagless final" pattern and brings some valid points, but in practice they aren't a problem if you don't overdo it. So in my case, I don't see the appeal in switching to a less mature ecosystem, at least based on this premise alone.
Before using Cats Effect/http4s/fs2/... I worked a few years using the Akka ecosystem (Play and then Akka http, streams, clustering, event-sourcing, ...) and while the underlying technology is solid, I was not a big fan of the experience overall. To me, the Typelevel ecosystem has mostly figured out what Scala should look like today.
If people find an answer in Zio, that's great, it doesn't have to be zero-sum.
ZIO (the core library) is not really a framework. It's still a library for an IO monad – it's just a pretty different IO monad, in that it absorbs environment (e.g. `ReaderT`) and error (e.g. from `MonadError`) into one data type, and the cases where you don't care about one of those are just type aliases. And it makes use of variance to give (usually) really ergonomic operations on these things. Disclaimer: I use it, and I'm a fan – I'll leave it up to the docs to really sell it; just wanted to take issue with the "framework" notion.
That being said, the sum of the ZIO _ecosystem_ is absolutely a framework, for better or worse.
The readme as well as the homepage mention "100x the performance of Scala's Future"
What makes scala's Future perform poorly, and how does zio avoid that? I feel like they tried really hard to present the project in terms of what it can do for you, and I get that. But if there's some real conceptual insight underlying that 100x improvement, where could I read about that?
> zio has excellent performance, featuring a hand-optimized, low-level interpreter that achieves zero allocations for right-associated binds, and minimal allocations for left-associated binds.
> The benchmarks [1] project may be used to compare IO with other effect monads, including Future (which is not an effect monad but is included for reference), Monix Task, and Cats IO.
> As of the time of this writing, IO is significantly faster than or at least comparable to all other purely functional solutions.
Scala's Futures constantly dip back into their ExecutionContext even when unnecessary; basically every single method on a Future causes it to go back to the ExecutionContext. This means they can incur bookkeeping or at worst thread switching overhead for no good reason.
For example, `map`ping over a completed Future has absolutely no need to go back to the ExecutionContext. Even `flatMap`ping multiple Futures together doesn't necessarily need an ExecutionContext if you offer a separate API to allow `Future`s to switch between threads (this also means that Futures must be delayed and can't run immediately).
These are the big things that make things like ZIO and cats-effect IO faster (there are then other smaller things that differentiate those two from each other).
As it already has been mentioned - Future's poor performance is mostly due redundant context switches on pretty much any operation. If you do `future.map((i: Int) => i + 1)` it can be executed on a different thread, which doesn't make much sense. It was the case in 2.11 stdlib and they're doing lots of improvements in this area, but Future still lags behind all widely-used "IO monads".
But put aside performance, any day of the week I'd choose ZIO (or Cats Effect IO or Monix Task) over Future even if ZIO was 10x slower. Amount of safety and composability "IO monads" give is outstanding.
There is/was a kernel module from Cern named the same I believe. As well as a Zephyr (RTOS) module named the same that I had worked on. It's a fun name, I always thought of it as zero-copy IO (DMA!)
20 comments
[ 3.9 ms ] story [ 46.0 ms ] threadThe Scalaz/Cats schism was worse in the sense that they were largely the same (at least at the time) which led to a lot of duplicated effort.
Typelevel and Cats wants everything to be a pluggable library. Everything should be configurable, hardcoding things is avoided. You are in charge of every single effect.
ZIO is basically a type-safe, compile-time, IO-monad-based framework, managing error handling, side effects and dependency injection. It is opinionated, and libraries integrating with it share its opinions. Some people consider this a FP, type safe Spring Framework.
Both can be integrated if you know what you're doing. Both have plenty of people to push things forward. At this point history between JDG and TL is irrelevant to the community. People involved in past dramas still don't like each others but they don't interact with each other during development, so just don't use Twitter and you won't even notice.
There seems to be a real demand for the Zio ecosystem and I wish it all the success it deserves, but its opinionated approach doesn't necessarily solve a problem that people have.
cats-effect is a meta-abstraction _and_ a concrete implementation of that abstraction. All of its functionality is abstract over the effect type, which for a lot of library use cases is good! (for example, this enables using ZIO with c-e ecosystem libraries; if c-e took the same tactic as ZIO then this wouldn't be possible)
When you get down to the application level, though – essentially the effect type is going to be fixed. I doesn't _have_ to be, but it takes superhuman levels of discipline not to make it that way. And ZIO is built for that – if the effect type is fixed to ZIO, it grants a lot of ergonomic benefits. So, ZIO ecosystem components are built with that in mind, and give a lot of ergonomics and higher-level semantics that aren't possible with c-e (or abstract effect types).
If cats-effect split the meta-abstraction and the implementation into two libraries, I think this debate would be moot. But, having the implementation together with the meta-abstraction makes cats-effect more likely to leak the latter into the former (I think it's gotten a lot better about this lately, though).
Anyway, just saying – both libraries are great, and they're different, and nobody should be made to feel bad about using either one of them.
JDG argues against the "tagless final" pattern and brings some valid points, but in practice they aren't a problem if you don't overdo it. So in my case, I don't see the appeal in switching to a less mature ecosystem, at least based on this premise alone.
Before using Cats Effect/http4s/fs2/... I worked a few years using the Akka ecosystem (Play and then Akka http, streams, clustering, event-sourcing, ...) and while the underlying technology is solid, I was not a big fan of the experience overall. To me, the Typelevel ecosystem has mostly figured out what Scala should look like today.
If people find an answer in Zio, that's great, it doesn't have to be zero-sum.
That being said, the sum of the ZIO _ecosystem_ is absolutely a framework, for better or worse.
What makes scala's Future perform poorly, and how does zio avoid that? I feel like they tried really hard to present the project in terms of what it can do for you, and I get that. But if there's some real conceptual insight underlying that 100x improvement, where could I read about that?
> The benchmarks [1] project may be used to compare IO with other effect monads, including Future (which is not an effect monad but is included for reference), Monix Task, and Cats IO.
> As of the time of this writing, IO is significantly faster than or at least comparable to all other purely functional solutions.
https://zio.dev/docs/overview/overview_performance
[1] https://github.com/zio/zio/tree/master/benchmarks
For example, `map`ping over a completed Future has absolutely no need to go back to the ExecutionContext. Even `flatMap`ping multiple Futures together doesn't necessarily need an ExecutionContext if you offer a separate API to allow `Future`s to switch between threads (this also means that Futures must be delayed and can't run immediately).
These are the big things that make things like ZIO and cats-effect IO faster (there are then other smaller things that differentiate those two from each other).
But put aside performance, any day of the week I'd choose ZIO (or Cats Effect IO or Monix Task) over Future even if ZIO was 10x slower. Amount of safety and composability "IO monads" give is outstanding.