[Haskell-cafe] Re-exports of resourcet in conduit

Michael Snoyman michael at snoyman.com
Sun Jun 3 11:00:50 CEST 2012

The easiest thing to do is just build your code with cabal, which will
ensure you're using consistent versions. (Similar questions came up
twice recently on Stack Overflow[1][2].) Wiping our your ~/.ghc and
installing from scratch should work also, but it's like using a
tactical nuke instead of a scalpel.

As for checking versions of dependencies, try `ghc-pkg describe conduit`.


[1] http://stackoverflow.com/questions/10729291/lifting-trouble-with-resourcet/10730909#10730909
[2] http://stackoverflow.com/questions/10843547/snap-monad-liftio-and-ghc-7-4-1/10847401#10847401

On Sun, Jun 3, 2012 at 3:01 AM, Myles C. Maxfield
<myles.maxfield at gmail.com> wrote:
> It could be. Do you know how I can check which versions of packages other
> packages have built against with Cabal? Will it help if I remove all the
> relevant packages and then re-install only a single version?
> Thanks,
> Myles
> On Saturday, June 2, 2012, Antoine Latter wrote:
>> Is it possible that you are puuling in two different versions of the
>> package that defines the MonadThrow class?
>> That is, package a was built against version 1, but package b was built
>> against version 2? This would make GHC think the type-class were
>> incompatable.
>> This is just a guess - I have not tried what you are trying.
>> On Jun 2, 2012 6:35 PM, "Myles C. Maxfield" <myles.maxfield at gmail.com>
>> wrote:
>>> To: Michael Snoyman
>>> CC: haskell-cafe
>>> Hello,
>>> I'm having a problem working with the conduit library, and was hoping
>>> you could help me out.
>>> Data.Conduit re-exports ResourceT, MonadResource, and MonadThrow (but
>>> not ExceptionT) from Control.Monad.Trans.Resource. I have a conduit
>>> which operates on a monad in the MonadThrow class. I am trying to
>>> figure out which MonadThrow class this should be (the
>>> Data.Conduit.MonadThrow class, or the
>>> Montrol.Monad.Trans.Resource.MonadThrow class, since apparently GHC
>>> doesn't recognize them as the same, even though one is just a
>>> re-export of the other).
>>> If a user of this conduit wants to chain this conduit up with
>>> something like sourceFile, the underlying monad has to be a member of
>>> Data.Conduit.MonadResource and whatever MonadThrow class I chose to
>>> use. I would like to be able to use an existing instance to lift the
>>> class of the inner monad to the class of the entire monad stack (so I
>>> don't have to tell the user of my conduit that they have to define
>>> their own instances), and the only rule that I can find that does that
>>> is the following from Data.Conduit:
>>> Data.Conduit.MonadThrow m => Data.Conduit.MonadThrow
>>> (Data.Conduit.ResourceT m)
>>> However, GHC doesn't seem to think that
>>> Control.Monad.Trans.Resource.ExceptionT is an instance of
>>> Data.Conduit.MonadThrow:
>>>    No instance for (Data.Conduit.MonadThrow (ExceptionT IO))
>>>      arising from a use of `.....'
>>> Control.Monad.Trans.Resource has a similar instance:
>>> Control.Monad.Trans.Resource.MonadThrow m =>
>>> Control.Monad.Trans.Resource.MonadThrow
>>> (Control.Monad.Trans.Resource.ResourceT m)
>>> but because sourceFile operates in the Data.Conduit.MonadResource
>>> class, and Control.Monad.Trans.Resource.ResourceT isn't a member of
>>> that class (it's only a member of
>>> Control.Monad.Trans.Resource.MonadResource), that doesn't help:
>>>    No instance for (Data.Conduit.MonadResource
>>>                       (Control.Monad.Trans.Resource.ResourceT (ExceptionT
>>> IO)))
>>>      arising from a use of `.....'
>>> It should be noted that neither module defines anything like the
>>> following:
>>> MonadResource m => MonadResource (ExceptionT m)
>>> It seems like the underlying problem here is that:
>>> 1) I am required to use the Control.Monad.Trans.Resource.ExceptionT
>>> class, because Data.Conduit doesn't re-export it
>>> 2) I am required to use the Data.Conduit.MonadResource class, because
>>> sourceFile and others require it
>>> 3) There doesn't seem to be an existing instance that bridges between the
>>> two.
>>> This seems like a fundamental flaw with re-exporting; it can only work
>>> if you re-export every single last thing from the original module.
>>> This doesn't seem tenable because the orignal module might not be
>>> under your control, so its author can add new symbols whenever he/she
>>> wants to.
>>> I see two solutions to this problem:
>>> 1) Re-export Control.Monad.Trans.Resource.ExceptionT in Data.Conduit.
>>> This will work until someone adds something to the resourcet package
>>> and someone wants to use the new addition and Data.Conduit.ResourceT
>>> in the same stack
>>> 2) Don't re-export anything in Data.Conduit; make sourceFile and
>>> others explicitly depend on types in another module, but this might
>>> break compatibility with existing programs if they use fully-qualified
>>> symbol names.
>>> 3) Make anyone who wants to use a monad stack in MonadThrow and
>>> MonadResource define their own instances. This is probably no good
>>> because it means that many different modules will implement the same
>>> instance in potentially many different ways.
>>> I feel like option 2) is probably the best solution here. I'm
>>> perfectly happy to issue a pull request for whichever option you think
>>> is best, but I don't know which solution you think is best for your
>>> project. What do you think?
>>> --Myles
>>> _______________________________________________
>>> Haskell-Cafe mailing list
>>> Haskell-Cafe at haskell.org
>>> http://www.haskell.org/mailman/listinfo/haskell-cafe

More information about the Haskell-Cafe mailing list