See a typo? Have a suggestion? Edit this page on Github
My
previous blog post
discussed a possible upcoming breaking change to the conduit library:
dropping finalizers. This is one of a number of other breaking changes
I have planned. Another one is switching over from MonadBaseControl
to MonadUnliftIO
, for reasons I've
discussed
at
length
before and
spoken
about too.
Beyond this change, I have a number of others planned out as well, some more solidly than others. I've started a document describing some of these, and I wanted to bring up one point in this design space for some user feedback: conduit dependency trees.
Today
The situation today is that we have a dependency graph that looks something like the following:
resourcet
is at the base of the hierarchy, and defines some non-conduit-specific types and functions used throughout the conduit ecosystem. It currently depends on a number of packages, likemonad-control
, but that number will naturally drop as we move over toMonadUnliftIO
exclusively.conduit
is designed to provide basic conduit functionality with fewer dependencies. It does depend onresourcet
, and packages likemonad-control
. But it does not depend onbytestring
,text
, orvector
, even though these are almost always wanted with conduit. It provides theData.Conduit.List
set of combinators, which are not the best ones out there.conduit-extra
adds lots of dependencies, including things likeattoparsec
, and provides a nicer set of helpers aroundbytestring
andtext
.- And finally, at the top of the tree (or our tree for today), we've
got
conduit-combinators
, which provides the combinators I actually recommend people use in theData.Conduit.Combinator
module. This has lots of dependencies, since it inherits fromconduit-extra
and also adds in some extra things likemwc-random
.
Benefits:
- You can use
resourcet
without touching the conduit ecosystem at all - You can use
conduit
without pulling in lots of resources Data.Conduit.Combinators
is fully loaded
Downsides:
- The current dependency footprint even at the base is higher than I'd like, though that's getting fixed soon regardless.
- The
conduit
package is not super useful on its own due to lack ofbytestring
,text
, andvector
support. - To get the functionality you want in either
conduit-extra
orconduit-combinators
, you end up with a much larger dependency footprint.
Plans for the next version
I have a number of different ideas in mind. I'll start off with the most conservative plan, and mention some variants below.
- As already mentioned,
resourcet
drops a bunch of dependencies. Nothing too interesting there. conduit
adds a dependency onbytestring
,text
, andvector
as basic libraries everyone should be using anyway. We move overData.Conduit.Combinators
and provide most of its functionality inconduit
itself, and start recommending againstData.Conduit.List
,Data.Conduit.Binary
, andData.Conduit.Text
.conduit-extra
basically remains as-isconduit-combinators
retains the extra functionality not present in the newconduit
Benefits:
- The
conduit
package now provides most of the functionality you'll want on a day-to-day basis - The dependency footprint for the
Data.Conduit.Combinators
module is much reduced - We can finally get away from the not-well-named functions in
Data.Conduit.List
There aren't necessarily downsides to this approach, as I think it's simply better than what we have today already. But I want to list out the alternatives, which will make clear some things that could be possibly better still.
- What do we do with the
mono-traversable
package? It's currently a dependency ofconduit-combinators
, and the simplest path forward for the above is to makeconduit
depend onmono-traversable
. However, this is a slightly heavier dependency footprint, requiring adding inunordered-containers
andvector-algorithms
. Alternatives:- Strip down
mono-traversable
to have less deps - Redefine parts of
mono-traversable
needed forconduit
inconduit
itself - Going crazy: really move
mono-traversable
intoconduit
and swap the dependency tree around - My inclination: minimize
mono-traversable
's dependencies a bit more (like dropping thesplit
package, and maybevector-algorithms
) and make it a dependency ofconduit
.
- Strip down
- Do we really need
conduit-combinators
as well asconduit-extra
? It's just adding a few extra pieces of functionality overconduit-extra
, and perhaps those should be folded intoconduit-extra
itself. - Some people may not like the heavier dep footprint of
conduit
now. Should we split off aconduit-core
package providing the core data types, functions, and operators, and haveconduit
depend on that? - It feels almost silly to have the
ResourceT
data type live in a separate package.- If we have
conduit-core
, that could be a logical place to put it, since it won't have any extra dependencies versus theresourcet
package itself, and then we can turnresourcet
into a backwards compatibility layer. - Or it may be logical to place
ResourceT
in theunliftio-core
package, since both concepts help with resource cleanup in monad transformers. The former is necessary for continuation-based monads, while the latter (MonadUnliftIO
) works for simpler monads.
- If we have
If people have feedback, I'm happy to hear about it. I've spent an unfortunate amount of time bouncing around between these different options, so hopefully writing it all down and hearing some outside opinions can help move this forward.