On Apr 4, 2012 6:20 PM, "Bardur Arantsson" <spam@scientician.net> wrote:
>
> On 04/04/2012 04:22 PM, Michael Snoyman wrote:
>>
>> On Wed, Apr 4, 2012 at 5:17 PM, Bardur Arantsson<spam@scientician.net>  wrote:
>>>
>>> Hi all,
>>>
>>> I'm upgrading various bits and bobs to conduit 0.4.x, but I've hit a little
>>> snag with "sourceStateIO". The following function fails to compile:
>>>
>> In conduit 0.2, a Source always implicitly wrapped up the inner monad
>> in a ResourceT transformer. This caused complications, so now you need
>> to explicitly add a ResourceT wrapper when it's needed.
>> `sourceStateIO` is an example of such a function that requires the
>> functionality of a `ResourceT`. Instead of making a requirements in
>> the type that the inner monad be `ResourceT m`, there's a class
>> constraint that the inner monad be an instance of `MonadResource`.
>
>
> I'm wondering if I can just have a simple
>
>    transPipe runResourceT $ sourceQuery ...
>
> wrapper so that old callers can remain unmodified. This would give the old callers the (Source IO [SQLData]) that they expect. As far as I can tell, the open/close behavior would not be modified by transPipe.
>
> Is there any reason that this wouldn't work?
>
>
> Regards,
>
>
> _______________________________________________
> web-devel mailing list
> web-devel@haskell.org
> http://www.haskell.org/mailman/listinfo/web-devel

Unfortunately that won't work, and would be very dangerous. In fact, I should update the docs to explain what transPipe does, and the limited cases in which it can work correctly.

transPipe will call runResourceT on each individual monadic action performed by the Pipe in question. In this case, the result would be that runResourceT right after the first chunk of data is returned, which is certainly *not* what you want.

The fact is that in version 0.2 of conduit, *every* Source, Sink, and Conduit lived in ResourceT. So if you want to keep things working the same way as before, just explicitly add the ResourceT wrappers. Your code already has a call to runResourceT somewhere to unwrap those.

Possibly a better approach would be to use type variables for the monads in your type signature and start off with a `Monad m` context. Then GHC will tell you when you need to use liftIO (because m isn't IO) and when you need to change the context to MonadResource.

I'll try to put together a larger example of this stuff in the next few days, but the combination of the upcoming Yesod release a Passover next week (and the requisite crunch at work) leaves me with less time than usual.

Michael