Comments (14)
Let's including the emails discussion. My first response:
Hmm... not only does it not exist, but I don't see an immediately obvious way of implementing it even with access to the internals, given the current implementation. You can use transResourceT
to change the inner monad, however.
In order to achieve this behavior, I think we'd need to add the following method to the MonadResource typeclass:
liftResourceT :: ResourceT IO a -> m a
For the ResourceT
instance, we'd have:
liftResourceT = transResourceT liftIO
and for everything else:
liftResourceT = lift . liftResourceT
In fact, with that approach, we could probably take the other three methods out of the typeclass. This would technically be a breaking change, so we'd need to bump to 0.4.
If we're thinking about this, here's another change I was thinking of: making MonadBaseControl IO m a superclass of MonadResource. It would prevent some transformers (particularly ContT) from being instances of MonadResource, but would simplify some type signatures (e.g., the http function in http-conduit). I'm leaning more heavily away from this change as I think about it more, but I thought I'd mention it.
from conduit.
And the relevant part of my response to your first response:
Sounds good. Perhaps there is a way to have the liftResourceT not have to change the below-ResourceT monad, so the ResourceT the instance could be liftResourceT = id, and add another function that takes care of the transResourceT, just to split up responsibilities and perhaps be a bit more flexible.
Not sure if that's worth the added complexity.
from conduit.
I think we'd have to play around with the types quite a bit to make that change (what would the signature of such a decomposed function look like?). Did you have an idea on what that would look like?
from conduit.
Again, not sure if it's worth the added complexity, but one way might be roughly like this (pseudo-Haskell):
class MonadResource ... r where
type BelowResourceT r :: * -> *
liftResourceT :: ResourceT (BelowResourceT r) a -> r a
instance MonadResource (ResourceT m) where
type BelowResourceT (ResourceT m) = m
liftResourceT = id
instance MonadResource m => MonadResource (FooT m a) where
type BelowResourceT (FooT m) = BelowResourceT m
liftResourceT = lift
Basically a lift that stops at ResourceT.
from conduit.
Got it, that makes sense. I don't think the extra complexity is warranted, however. I've made a new branch for the modified version, check out the attached commit.
from conduit.
I like it.
One thing popped in my mind: Would it be possible to make MonadResource compatible with ST or ExceptionT ST? I guess ST itself has no exceptions, but with ExceptionT you get them and then you probably might want resource management too. Not that I need it myself, ResourceT IO makes me happy, but I guess as a Haskeller one just sometimes feels this urge for generality. :)
from conduit.
The original implementation of resourcet that went into conduit 0.0 allowed for such generality... and it was a mess. More to the point: the only monad in which you should be allowed to allocate resources is IO
(and transformers built on it). So there shouldn't be any use case which would require resourcet.
from conduit.
Fair enough. Is there any reason for ResourceT to be a transformer, then? Because you might as well just use ResourceT IO all the time and build your transformer stacks on top of that. The new MonadResource class already strongly encourages that, I think. :)
from conduit.
There are many cases where you need a separate inner monad. Imagine the following contrived example:
import Control.Monad.Writer
import Data.Conduit
import qualified Data.Conduit.List as CL
import Data.Conduit.Binary (sourceFile)
foo fp = runWriterT $ runResourceT $ sourceFile fp $$ CL.mapM_ tell
More realistic use cases come into play fast when dealing with libraries that define their own monad stacks, and you want to be able to run some conduit code that interacts with them.
from conduit.
Those are not instances of MonadResource then though?
Am 14.08.2012 16:08 schrieb "Michael Snoyman" [email protected]:
There are many cases where you need a separate inner monad. Imagine the
following contrived example:import Control.Monad.Writer
import Data.Conduit
import qualified Data.Conduit.List as CL
import Data.Conduit.Binary (sourceFile)foo fp = runWriterT $ runResourceT $ sourceFile fp $$ CL.mapM_ tell
More realistic use cases come into play fast when dealing with libraries
that define their own monad stacks, and you want to be able to run some
conduit code that interacts with them.—
Reply to this email directly or view it on GitHubhttps://github.com//issues/61#issuecomment-7726840.
from conduit.
Nevermind, I misunderstood it for a bit. OK, I think the implementation in that branch is good.
from conduit.
@snoyberg +1 for your last argument, it can cause bad headaches when transformers want to sit in a certain place. I recently had that problem with Haskeline, and it made it impossible to implement a simple use case (you couldn't use local
to change environments any more).
from conduit.
@nh2 I just misunderstood the way MonadResource works, I don't actually disagree anymore. The implementation in 6953fc2 looks good to me.
from conduit.
The new version is up on Hackage now (was released a while ago actually).
from conduit.
Related Issues (20)
- `ResourceT` is subject to the `forever` space leak
- slidingWindowC makes consuming tail elements inconvenient HOT 3
- Quadratic performance on left-associated binds HOT 6
- resourcet needs unliftio-core >=0.1.1.0 lower bound
- "stdout" test stalls temporarily sometimes HOT 3
- Implementing delay operator HOT 3
- Clarification regarding `sinkFile` and `sinkFileBS` HOT 1
- Compatibility with mtl-2.3 HOT 5
- Lots of inline-rule-shadowing warnings
- Accumulate ByteStrings into single result HOT 3
- bracketP with custom monad stack HOT 1
- Flaky test suite failure with GHC 9.4.2 / text-2.0.1 HOT 6
- *> leaks space where >> doesn't - so should the *> implementation be optimized? HOT 1
- Confusion with `sourceProcessWithStreams` and `takeExactly` HOT 1
- `sourceProcessWithStreams` without hijacking `stderr`? HOT 2
- Support incrementally feeding into Conduits HOT 1
- Better performance with a left associative `.|`? HOT 2
- Functor instance causes memory leak when used with Shake
- Running a conduit in a function with an unrelated parameter twice leaks memory
- network-conduit-tls-1.4.0 test suite build failure with crypton-connection-0.4 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from conduit.