In my view the only true benefit to effect systems is that it’s the only sane way of getting dynamic dispatch in Haskell, so for anything production-grade you *could* have a mirror test system that behaves exactly the same, but calls test versions of all real-world things it links to. It’s still a remarkably hard thing to achieve however: you have to know how to structure your code and you have to avoid any type shenanigans because recursive type families are exponentially slow.
I sympathize with the idea that it would be nice to keep track of which effects are used in any given function, it’s a strongly typed language after all, but having to choose one of five effect libraries and then getting “rewarded” with both a bulkier codebase and performance overheads squarely puts this in the “only use at work on the high level” territory. If GHC had seamless native support for this and some way to precompile functions that only use one implementation at runtime, it would be a no-brainer.
I don’t see a natural benefit of using Reader
s over plain argument passing. Passing arguments indeed looks bulkier at the first glance, but it allows me to divide the context to the smallest necessary bits at every point. Reader
on the other hand necessitates using lens (or more recently field selectors), blurs the line between which arguments are actually needed in a given function, and does not look any prettier.
I don’t see a need in checked exceptions, I lean on the side of “if I expect something to fail without terminating the process, then it’s not an exception”. It’s a natural extension of trying to decouple everything pure from effects, as I can simply use datatypes to convey that an undesired (but not critical) condition has occurred instead of breaking the control flow. It’s also faster.
Regarding lack of modularity in effects libraries, that’s pretty much how all of Haskell’s ecosystem works: instead of providing the minimal tools and letting users stitch things together, it’s instead expected that you use one of fifteen convenient runner functions and for anything beyond that you have to dive into non-PVP-compliant internals. This won’t change unless the community agrees it’s undesirable, good luck with that.