Closed isovector closed 5 years ago
@ocharles I don't understand. Mind fleshing out that idea a little further?
Sorry, I serves me right for leaving comments late at night!
Let's say I have some kind of app where I already have some MyApp
monad. This carries with it a Redis connection, and a PostgreSQL connection. I want to lay on polysemy
for some stuff, in particular the KV store using Redis, but also my own custom SQL
effect. Currently, this PR gives me:
runKVStoreInRedis :: Member (Lift R.Redis) r => Sem (KVStore k v ': r) a -> Sem r a
But I may also have written my own
runSQL :: Member (Lift MyApp) r => Sem (SQL ': r) a -> Sem r a
Then I can't compose these together, because the only thing I can do with Lift
is runM
which needs exactly one Lift
.
My suggestion is a more general Embed
effect instead of lift, that when ran would let you apply a natural transformation back into Lift
. So in this can I could run the R.Redis
embedding with R.Redis ~> MyApp
natural transformatino.
Or am I missing something?
Then I can't compose these together, because the only thing I can do with Lift is runM which needs exactly one Lift.
This is not true, you can interpret
Lift
s just like any other effect. This is probably worth exposing in the form runLift :: Member (Lift m2) r => (forall x. m1 x -> m2 x) -> Sem (Lift m1 ': r) a -> Sem r a
, which seems like the gist of what you're suggesting?
Yea exactly. Right now Lift is in an Internal module suggesting it shouldn't be touched
I wonder if we should have some kind of
Embed
type, likeLift
, but with some kind ofrun
function that lets you run to anyMonadIO
and automatically lift that back intoSem
:I say that because this PR requires me to run to the
Redis
monad, but what if I have a different base?