# How to give libraries optional dependencies?

**URL:** <https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752>\
**Category:** Learn\
**Created:** [June 17, 2024, 5:03pm UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752 "2024-06-17T17:03:31Z")\
**Posts on this page:** 16\
**Page:** 2

<div class="post-metadata">

**Author:** ![BurningWitness](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/burningwitness/32/3665_2.png) [@BurningWitness](https://discourse.haskell.org/u/BurningWitness)\
**Post date:** [June 28, 2024, 12:44pm UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/21 "2024-06-28T12:44:22Z")

</div>

> [@blamario](#):
>
> Are you saying the serialization typeclasses are useless for writing good programs?

No, I’m saying:

- An instance that does what is already possible except worse is most probably only useful for collecting dust and confusing newcomers (documentation conciseness is a concern too).

- For serialization in either direction unambiguous conversions are quite rare.

Violating either of these points doesn’t make the instance outright useless, it just makes it bad.

> [@blamario](#):
>
> It’s far better to acknowledge that the problems exist

Perhaps, but out of all the problems the language has this is a relatively minor one and solving it nicely is in no way obvious, as I assume any proper solution would require changes to both GHC (with syntax additions), Hackage and Cabal.

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [June 29, 2024, 7:43am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/22 "2024-06-29T07:43:54Z")

</div>

> [@qqwy](#):
>
> Is there a way to do this?

No.

It is very bad to make cabal flags that control exposed API, because a library `foo` depending on `length` cannot specify that it requires flags of length. So you end up with compile errors depending on the flags that are set.

**Public sublibraries are irrelevant to this topic** , so I’m not sure why people are bringing them up.

> [@waivio](#):
>
> That sounds like Gentoo Linux’s feature of Use Flags

Yes, and I urge everyone to take a moment and consider the amount of packager coordination and end user config fiddling this concept causes. It is nothing but bad UX. And hackage isn’t a managed repo like the portage tree. We’d be steering into a disaster.

* * *

For the specific issue, I suggest to embrace orphan instances.

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [June 29, 2024, 8:53am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/23 "2024-06-29T08:53:19Z")

</div>

> [@hasufell](#):
>
> For the specific issue, I suggest to embrace orphan instances.

I, too, suspect this is the approach that will lead to, by far, the least pain in practice.

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [June 29, 2024, 9:40am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/24 "2024-06-29T09:40:38Z")

</div>

> [@hasufell](#):
>
> **Public sublibraries are irrelevant to this topic**

If public sublibraries are irrelevant to this topic, then I feel like they’re irrelevant to any topic. Indeed, you can always just replace them by multiple proper packages. However, this seems like a prime example of where public sublibraries could facilitate maintenance and discoverability.

There is an argument to be made that public sublibraries introduce more complexity in the tooling than they are worth, but it is not very productive to make that argument in passing when a potential use case for public sublibraries comes up.

Or have I misunderstood what you’re saying?

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [June 29, 2024, 9:59am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/25 "2024-06-29T09:59:05Z")

</div>

> [@jaror](#):
>
> If public sublibraries are irrelevant to this topic, then I feel like they’re irrelevant to any topic

The only use case for them is:

- you have a huge number of packages
- all these packages should share the same PVP version

This is a bit awkward to achieve with multiple packages. And yet, the only use case I’ve seen so far is HLS and its plugins, **but** I’m not convinced that the current versioning that is used (plugins share the same version as HLS core itself) is proper.

It is a theoretical use case and I’ve never seen it in the wild. We’re solving a problem that is not really a problem.

> [@jaror](#):
>
> However, this seems like a prime example of where public sublibraries could facilitate maintenance and discoverability.

It’s more likely that this approach will lead to bad PVP versioning, because maintainers just don’t care that their sublibraries didn’t change API, but now since they’re sublibraries and not proper packages, they will follow all the major version bumps.

This can lead to a degradation of quality of hackage.

> [@jaror](#):
>
> There is an argument to be made that public sublibraries introduce more complexity in the tooling than they are worth, but it is not very productive to make that argument in passing when a potential use case for public sublibraries comes up.

It’s questionable whether they’re appropriate here. Only if package `length` just consists of the class definition **and nothing else** , then it would be sound. Otherwise you’re coupling major versions bumps of the instance sub-libraries to any API change in `length`, which is nonsensical.

I’m pretty sure most users of sub-libraries will not consider this.

---

<div class="post-metadata">

**Author:** ![BurningWitness](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/burningwitness/32/3665_2.png) [@BurningWitness](https://discourse.haskell.org/u/BurningWitness)\
**Post date:** [June 29, 2024, 10:12am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/26 "2024-06-29T10:12:56Z")

</div>

> [@hasufell](#):
>
> all these packages should share the same PVP version

That’s merely Cabal file format convention, it doesn’t have to be this way.

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [June 29, 2024, 10:13am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/27 "2024-06-29T10:13:38Z")

</div>

Are you proposing that one cabal file can describe multiple versions? That sounds horrible and will break even more tooling.

---

<div class="post-metadata">

**Author:** ![Kleidukos](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/kleidukos/32/1213_2.png) [@Kleidukos](https://discourse.haskell.org/u/Kleidukos)\
**Post date:** [June 29, 2024, 10:16am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/28 "2024-06-29T10:16:42Z")

</div>

Your suggestion is unclear, what are you trying to say?

---

<div class="post-metadata">

**Author:** ![BurningWitness](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/burningwitness/32/3665_2.png) [@BurningWitness](https://discourse.haskell.org/u/BurningWitness)\
**Post date:** [June 29, 2024, 11:12am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/29 "2024-06-29T11:12:04Z")

</div>

That at the end of the day each public library has its own version and so the Cabal file could allow each library entry to specify it explicltly instead of inheriting from the “file version”. Sharing versions with the common stanzas makes total sense in my mind.

I have an idea for a setup I’ve expressed in a [different topic](http://discourse.haskell.org/t/monorepo-cabal-internal-libraries-vs-multi-package-cabal/7424/16) that would benefit from this.

---

<div class="post-metadata">

**Author:** ![michaelpj](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/michaelpj/32/417_2.png) [@michaelpj](https://discourse.haskell.org/u/michaelpj)\
**Post date:** [June 29, 2024, 11:14am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/30 "2024-06-29T11:14:30Z")

</div>

Having multiple libraries share the same version is no different from having multiple modules share the same version, it just allows you to split those modules up in a convenient way.

Fine-grained versioning can be nice but can also be a lot of work for marginal gain. That’s why we don’t have exclusively one-module packages. There’s nothing wrong with sometimes having coarser-grained versioning.

So I don’t see how this would lead to a degradation of hackage.

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [June 29, 2024, 11:49am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/31 "2024-06-29T11:49:39Z")

</div>

> [@michaelpj](#):
>
> So I don’t see how this would lead to a degradation of hackage.

It gives you one more way to get PVP wrong in the name of convenience.

The way it’s aggressively advertised all over discourse without any mention that you should **still think about whether it actually makes sense to have lock-step versioning** doesn’t make the status quo better.

People already fail to follow PVP wrt internals. Explaining that you can use a separate package to have better PVP is already an uphill battle. Public sublibraries are going to make it worse, because of said convenience.

---

<div class="post-metadata">

**Author:** ![Kleidukos](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/kleidukos/32/1213_2.png) [@Kleidukos](https://discourse.haskell.org/u/Kleidukos)\
**Post date:** [June 29, 2024, 6:29pm UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/32 "2024-06-29T18:29:50Z")

</div>

Well, you’re free to have your own `cabal` binary that reads and interprets those cabal files, but I heavily doubt we in the cabal team will implement such a thing. And I don’t think any reasonable package repository out there will do the same.

---

<div class="post-metadata">

**Author:** ![BurningWitness](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/burningwitness/32/3665_2.png) [@BurningWitness](https://discourse.haskell.org/u/BurningWitness)\
**Post date:** [June 29, 2024, 7:09pm UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/33 "2024-06-29T19:09:06Z")

</div>

Well, if they [the Cabal team] solve the related issues in any other way or determine that the current approach is the lesser of all evils, they’re free to communicate that to the broader public. In the absence of such a statement I consider the status quo lackluster (I don’t like importing `.Internal` modules).

---

<div class="post-metadata">

**Author:** ![jackdk](https://avatars.discourse-cdn.com/v4/letter/j/9f8e36/32.png) [@jackdk](https://discourse.haskell.org/u/jackdk)\
**Post date:** [June 30, 2024, 1:04am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/34 "2024-06-30T01:04:11Z")

</div>

I hope one day to provide Amazonka as a single package with public sublibraries, instead of 300+ (and rising) standalone libraries.

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [June 30, 2024, 9:49am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/35 "2024-06-30T09:49:29Z")

</div>

I sympathize, since I can imagine the amount of work this must require.

But, conceptually, if one data type in the core changes, do _all_ 300 packages need a major version bump? 🙂

---

<div class="post-metadata">

**Author:** ![jackdk](https://avatars.discourse-cdn.com/v4/letter/j/9f8e36/32.png) [@jackdk](https://discourse.haskell.org/u/jackdk)\
**Post date:** [June 30, 2024, 11:39am UTC](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752/36 "2024-06-30T11:39:34Z")

</div>

Technically no, but realistically yes: if we’re sending something to Hackage, in an ideal world we’d always regenerate the service against the most recent AWS-provided definitions just before shipping. (We can’t do that right now because of [reasons](https://github.com/brendanhay/amazonka/issues/888).)

[Previous page](https://discourse.haskell.org/t/how-to-give-libraries-optional-dependencies/9752.md?page=1)
