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

Myles C. Maxfield myles.maxfield at gmail.com
Sun Jun 3 20:33:58 CEST 2012

Yep, that was my problem. Thanks so much!

GHC is smart enough to realize that Data.Conduit.ResourceT is the same
as Control.Monad.Trans.Resource.ResourceT. Yay!


On Sun, Jun 3, 2012 at 2:00 AM, Michael Snoyman <michael at snoyman.com> wrote:
> 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`.
> Michael
> [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