> if it's handled by `Choose.toList` and then `Abort.toOptional` in that order you end up with `Optional [a]` whereas if you do in the other order you have `[Optional a]` right?
I mean, not necessarily. Something that handles a `'{Abort} a` doesn't necessarily produce an `Optional a`. It could produce a Boolean, it could produce an Int, whatever. This is really up to the handler. But I still don't see how you produce a "bug" because you can dispatch the requests to abilities in either order. You couldn't, for example, ever produce a (well-typed) situation where a call to abort doesn't abort, or a call to Choose.toList would fail to produce a list. (Perhaps if toList were allowed to also use {Abort} but it is not)
Maybe I'm misunderstanding how abilities work, but I think I can break Exception.bracket with this right?
I think if I pass something that has e.g. `{Abort, Exception, IO}` to `bracket` and then handle Exception before Abort, my Abort handler can break out of `bracket` before the finalizer action can run.
More generally I must always process any ability with a "bracket"-like function last to prevent this from happening right? And if I have multiple abilities that all have "bracket"-like functions they can step on each other's toes?
Even more generally I think any sort of "scoped" function in an ability has this problem.
This theoretically seems scary (imagine you have some big complicated action that does some bracket deep under the covers to e.g. release file handles; if I handle abilities in the wrong order the file handles might not ever be released, even if I have individually reasonable ability-handler pairs that locally don't do anything silly), but I'm not sure practically how often this comes up, and how much "just always handle Exception last" fixes that (i.e. how unlikely it is for any other ability to have a bracket function).
Got it. But you're locked into IO and Exception then and can't use any other abilities right? I guess you could always convert back and forth at the `run` boundary.
Also I would suggest removing Exception.bracket from base then, or at least changing the file handle example for Exception.bracket, since it seems a tad dangerous.
> if it's handled by `Choose.toList` and then `Abort.toOptional` in that order you end up with `Optional [a]` whereas if you do in the other order you have `[Optional a]` right?
I mean, not necessarily. Something that handles a `'{Abort} a` doesn't necessarily produce an `Optional a`. It could produce a Boolean, it could produce an Int, whatever. This is really up to the handler. But I still don't see how you produce a "bug" because you can dispatch the requests to abilities in either order. You couldn't, for example, ever produce a (well-typed) situation where a call to abort doesn't abort, or a call to Choose.toList would fail to produce a list. (Perhaps if toList were allowed to also use {Abort} but it is not)