MTL interop
Opened this issue · 8 comments
Looks like you can't do seamless (i.e. without newtypes) MTL style effects interop, as already evidenced by how Eff can't have a MonadIO instance?
That's right, you can't give Bluefin's Eff
a MonadWhatever
instance, because the effect is at the value level rather than the constraint level.
This approach of passing in multiple effects seems not entirely terrible:
bluefin/bluefin-internal/src/Bluefin/Internal.hs
Lines 252 to 268 in c7b2b1f
Looks like you can't do seamless (i.e. without newtypes) MTL style effects interop
So, for a better answer to your question, you can do MTL style effects interop without (defining your own) newtypes. Whether that's "seamless" or not is up for debate.
Considering that in the "real world" code you will have interleaving of MTL style functions and "native" effects, looks like it's going to be a pain with this approach 🤔
in the "real world" code you will have interleaving of MTL style functions and "native" effects
By '"native" Effects' do you mean Eff
? If so, that's fine too (see liftEffStack
):
bluefin/bluefin-internal/src/Bluefin/Internal.hs
Lines 260 to 272 in b9c1354
I'm not going to say this is the most ergonomic thing I've ever seen, but considering it was the first thing I thought of and I worked on it for about an hour, I think it's promising.
You could also apply the conversion to individual actions to get the back into Eff
immediately. I don't know what's going to work out the most ergonomically in practice. In this example everything is done in Eff
so the yield
doesn't need to be lifted in any way.
bluefin/bluefin-internal/src/Bluefin/Internal.hs
Lines 279 to 294 in eeb06e3
What if you want to call a function f :: (MonadA m, MonadB m) => m ()
etc. for more classes?
That one needs the following form (because mtl
is just runMTLStyle
fused with handleMTLWith
):
runMTLStyle $ handleMTLWith aHandle $ handleMTLWith bHandle $ f
Maybe this form, or some infix operator, would be more ergonomic? It remains to be seen.
runMTLStyle (f `handleMTLWith` aHandle `handleMTLWith` bHandle)