Closed ProofOfKeags closed 5 years ago
You might like to see how extensible-effects did it: https://github.com/suhailshergill/extensible-effects/pull/83
I'd suggest not going through the effort. You generally need MonadBaseControl
in order to use bracket
and to spin up new threads---both can be accomplished with less weight.
If you want bracket
, just put ResourceT IO
at the bottom of your stack:
bracket
:: Member (ResourceT IO) r
=> IO a
-> (a -> IO ())
-> (a -> Eff r b)
-> Eff r b
bracket alloc dealloc m = do
(key, a) <- send $ allocate alloc dealloc
result <- m a
send $ release key
pure result
If you want to be able to do async, a rough POC looks like this---start a worker thread, and use an effect to pass messages to it:
data AsyncEff capabilities a where
AsyncEff
:: Members capabilities r
=> Eff r a
-> AsyncEff capabilities ()
startAsyncTaskSlave
:: Members capabilities r
=> (forall x. Eff r x -> IO x)
-> IO (InChan (AsyncEff capabilities))
startThreadPool runEff = do
(in, out) <- newChan 10
void . async . forever $ do
m <- readChan out
async $ runEff m
pure in
asyncEff
:: Member IO r
=> InChan (AsyncEff capabilities)
-> Eff (AsyncEff capabilities ': r) a
-> Eff r a
asyncEff chan = handleRelay pure bind
where
bind eff k = send (writeChan chan eff) >>= k
IIUC bracket and withResource accomplish the same thing yeah?
Yup. withResource
can't be used here because "Cont
isn't an algebraic effect", but the explicit acquire and release semantics of ResourceT
do allow for this.
Am I to understand that you only need one ResourceT layer to handle an arbitrary number of resource pools?
Yeah -- you can reimplement withResource
like this:
withResource
:: Member (ResourceT IO) r
=> Pool a
-> (a -> Eff r b)
-> Eff r b
withResource pool f =
bracket (takeResource pool) (uncurry (flip putResource)) (f . fst)
@lexi-lambda would you accept a PR that provides a blessed bracket effect (and the resulting dependency on resourcet
)? This was a stumbling block for me and my company a few years back, and I imagine it's a pretty widespread problem.
I was looking at trying to use resource-pool in an Eff stack and ran into an issue where I could not get a MonadBaseControl instance for an eff stack. This makes sense to me as there are none defined. Is it possible to define them, and if so would this library be interested in accepting a PR that adds it?