Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to interoperate with ResourceT #451

Open
newhoggy opened this issue May 28, 2022 · 6 comments
Open

How to interoperate with ResourceT #451

newhoggy opened this issue May 28, 2022 · 6 comments

Comments

@newhoggy
Copy link

newhoggy commented May 28, 2022

Is there a way to call a function in ResourceT IO a from Members '[Embed IO, Resource) r] => Sem r a?

@tek
Copy link
Member

tek commented May 28, 2022

there are a few discussions on here that attempt to do that, for example here: #361 (comment)

@newhoggy
Copy link
Author

I'd like to be able to use libraries like amazonka which expose MonadResource in their API with polysemy.

This means the polysemy based application stack needs to have a MonadResource. None of the discussion I can see covers this case.

I have something that looks like it is working here.

Would there be interest in integrating this into polysemy.

It's unfortunate that the Polysemy.Resource module is already taken by something that seems to me should have been called Polysemy.Bracket. For that resource, even though the new library provides MonadResource based, I have called it new module Polsemy.Managed.

@tek
Copy link
Member

tek commented May 29, 2022

this one talks specifically about amazonka, did you find it? it's a bit old, so unclear whether it's still relevant. your link seems to point to a private repo btw

@newhoggy
Copy link
Author

Oops, it's public now.

@newhoggy
Copy link
Author

newhoggy commented May 29, 2022

The discussion specifically about amazonka also doesn't answer the question I have.

For example this code is noted as having a bug:

runBrokenStore :: FilePath -> IO ByteString
runBrokenStore path =
    bracket
      (IO.openFile path IO.ReadMode)
      (\h -> IO.hClose h >> print "Closed")
      (\h -> print "Using" >> LBS.hGetContents h)

main :: IO ()
main = do
  BS.writeFile filePath "long and uninteresting content goes here"
  print =<< runBrokenStore filePath

Which is true, but IO.openFile is a function that does lazy IO. amazonka as an API also sometimes does lazy IO as well.

I would like to use lazy IO in my polysemy application, so being restricted only to strict values is not an adequate answer.

ResourceT and MonadResource allows us to define the scope within which the lazy IO is valid, but the problem that Alexey experienced was that he was forced to use runResourceT to implement his API functions, which makes the scope too small and closes the handle too early.

With Polsemy.Managed I can do this:

runManaged $ do
   lbs <- getLazyByteString
   consumeLazyByteString lbs

In the above, getLazyByteString and consumeLazyByteString no longer have to be implemented with runResourceT because runManaged takes a monad value that has a MonadResource instance.

@googleson78
Copy link
Member

Tangential, but I have this thing that uses the Acquire facilities in resourcet.

I used it to interop with persistent, until they stopped providing an interface that uses Acquire. This seems to be for good reason(yesodweb/persistent#1199, yesodweb/persistent#1207) so I'm not sure if it should be used even if such an interface is provided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants