7 ms·
Yes, but transformers have a few drawbacks: the order of stacking alters behaviour, and you need to write n^2 instances for n transformers. Compare ExceptT e (
by codebje 2y ago
Yes, but transformers have a few drawbacks: the order of stacking alters behaviour, and you need to write n^2 instances for n transformers.
Compare ExceptT e (StateT m a) and StateT (ExceptT e m a): if you just want your computation to have state and exceptions the difference shouldn’t matter.
- throw156754228 2y agoAlso their other well known problem: you lose the program state if an exception is thrown in the monad above.
- tome 2y agoYeah, that's basically the same problem as `StateT s (ExceptT e m)` but for `StateT s m` where `m` throws exceptions.
- dllthomas 2y ago> if you just want your computation to have state and exceptions the difference shouldn’t matter But... you don't just want that. You almost certainly care whether state changes are discarded when an exception is thrown. I don't claim that the types there are the most obvious or natural way to specify that, but there is a meaningful difference that shouldn't be handwaved away.
- codebje 2y agoThe fact that with transformer stacks you can wind up with state changes being discarded on exception if you get the stack arranged in a particular order isn't what I'd call a _feature_ of transformer stacks :-) If effect A is invoked before effect B, effect A should happen and stay that way: if I update state before an exception is thrown, the update should persist. If I send a network message before an exception is thrown, the network message is still sent. If I launch the nukes before an exception is thrown, the missiles are still flying. If I want to batch up state updates to only happen together as a unit, I'll use a transaction effect.
- dullcrisp 2y agoI might have this wrong but I think if you want state and exceptions you probably want StateT (ExceptT e m a). The alternative would be to have state or exceptions, i.e. when you have an exception you no longer have state (which might be a legitimate type in some cases).
- gloria_mundi 2y agoRemember that transformers are "inside-out", i.e. `StateT (ExceptT e m) a` is isomorphic to `m (Except e (State a))`. If we want to keep state if an exception occurs, you need a `m (State (Except e a))` which is `ExceptT e (StateT m) a`.