[web-devel] A little trouble upgrading to conduit 0.4.x

Michael Snoyman michael at snoyman.com
Wed Apr 4 17:45:11 CEST 2012

On Apr 4, 2012 6:20 PM, "Bardur Arantsson" <spam at 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 at scientician.net>
>>> Hi all,
>>> I'm upgrading various bits and bobs to conduit 0.4.x, but I've hit a
>>> 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 at 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.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/web-devel/attachments/20120404/fd108f5f/attachment.htm>

More information about the web-devel mailing list