I apologize if my response sounded dismissive, I typed it out on my phone in a rush.
> I might write foo with an assumption that errors rollback, and bar with an assumption that errors abort. [...] These things have color we're just choosing to be blind to it!
This is more of a question of API design than something inherit to effect systems. I think it would be a good idea to use separate types for rolled-back errors and aborting errors; in the case where two functions use the same effect with different handlers, you can always mask the effect[0].
I do not think effect systems ignore color, rather, they give the end-user control over how color is manifested. Sometimes it's desirable to be blind to color.
On the other hand, I do agree that effect systems throw away layering information, much in the same way that auto-collapsing a nested Option None to None defeats the whole purpose of Option types.
Effects can be used with traditional monads, and it's possible to reify effects into monad-like objects that can be handled like values. I mean, that's what an effect handler does: it matches on the enum of effects in scope as if they were a value!
[0]: Scroll down to 3.4.7 in https://koka-lang.github.io/koka/doc/book.html#sec-combine
> but I've come to believe they're simply not an improvement over mtl-style constraints with layering expressed when we need it.
Typed tagless form is great, and (on an unrelated note) I love typed tagless final interpreters.
Although I agree that specifying layering relationships is an important component of managing effectful composition, I think the largest issue with mtl-style constraints is that the constraints require higher-kinded types by design. HKTs are really cool, but like a lot of meta-functiinal features can really drag down compilation times.
Effects are nice because they can be implemented as a single pass + cps transform, and existing control flow constructs can be re-written as sugar in terms of effects with no additional overhead (as delimited continuations do not require making a copy of the stack).
But I digress. Monads (and more generally HKTs) give you powerful tools that allow you to prove certain properties about the way effect constraints propogate through a system. I advocate for effects not because they are a replacement for monads, but because they are a nice method for reifying disparate threads of computation in a trivially composable manner.
I also don't think that all layering should be replaced with effects. I think careful layering with the occasional effect when needed is the way to go. Balance and simplicity in all things.