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

Michael Snoyman michael at snoyman.com
Wed Apr 4 16:22:48 CEST 2012


On Wed, Apr 4, 2012 at 5:17 PM, Bardur Arantsson <spam at 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:
>
>> sourceQuery :: Database -> String -> [SQLData] -> Source IO [SQLData]
>> sourceQuery database sql parameters =
>>   sourceStateIO
>>   (do
>>       stmt <- SQL.prepare database sql
>>       return (Unbound,stmt))
>>   (\(_,stmt) -> SQL.finalize stmt)
>>   (\(state,stmt) -> do
>>       -- Bind parameters if necessary.
>>       when (state == Unbound) $ do
>>         SQL.bind stmt parameters
>>       -- Fetch results.
>>       nextResult <- SQL.step stmt
>>       case nextResult of
>>         Done -> return StateClosed
>>         Row -> liftM (StateOpen (Bound,stmt)) $ SQL.columns stmt)
>
> All the SQL.xyz bits run in the IO monad. This code runs fine in Conduit
> 0.2.x, but on Conduit 0.4.x it fails to compile with the following error:
>
> src/Data/CQRS/EventStore/Backend/Sqlite3Utils.hs:43:3:
>    No instance for
> (resourcet-0.3.2:Control.Monad.Trans.Resource.MonadResource
>                       IO)
>      arising from a use of `sourceStateIO'
>    Possible fix:
>      add an instance declaration for
>      (resourcet-0.3.2:Control.Monad.Trans.Resource.MonadResource IO)
>    In the expression:
>      sourceStateIO
>        [rest elided; just the rest of the definition of sourceQuery]
>    In an equation for `sourceQuery':
>        sourceQuery database sql parameters
>          = sourceStateIO
>                [rest elided; just the rest of the definition of sourceQuery]
>
> I can see that I'm missing an instance, but I can't seem to find a direct
> instance for MonadResource IO, nor can I tell which indirect instance could
> get me there. I there some specific import I need to get the necessary
> instances, or do I need to do something else?
>
> Regards,
>
>
> _______________________________________________
> web-devel mailing list
> web-devel at haskell.org
> http://www.haskell.org/mailman/listinfo/web-devel

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`.

tl;dr: Change your type signature to:

    sourceQuery :: Database -> String -> [SQLData] -> Source
(ResourceT IO) [SQLData]

You'll also need to call liftIO in a few places.

HTH,
Michael



More information about the web-devel mailing list