# PVP Compliance of .Internal modules

**URL:** <https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784>\
**Category:** Uncategorized\
**Created:** [July 1, 2023, 8:23am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784 "2023-07-01T08:23:46Z")\
**Posts on this page:** 20\
**Page:** 1

<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:** [July 1, 2023, 8:23am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/1 "2023-07-01T08:23:46Z")

</div>

> [@New Hackage Server Features](http://discourse.haskell.org/t/new-hackage-server-features/2621/55):
>
> I’m considering using public sublibraries for publishing `.Internal` modules.

That sounds like you’re not going to be PVP compliant. Unless you bump major version when your internals change.

So this is generally the wrong approach. Please don’t do it.

You can read on it here: [Internal convention is a mistake – Functional programming debugs you](https://nikita-volkov.github.io/internal-convention-is-a-mistake/)

---

<div class="post-metadata">

**Author:** ![danidiaz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/danidiaz/32/92_2.png) [@danidiaz](https://discourse.haskell.org/u/danidiaz)\
**Post date:** [July 1, 2023, 8:34am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/2 "2023-07-01T08:34:54Z")

</div>

The solution spoused in that post is correct and principled, and it also causes too much friction because managing one extra package is a hassle.

Meanwhile, the public sublibrary would improve the situation with a fraction of the effort. And it could serve as a stepping-stone towards extracting the internals to its own package with its own independent versionin, if really needed.

---

<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:** [July 1, 2023, 8:35am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/3 "2023-07-01T08:35:39Z")

</div>

Isn’t the point of using a public sublibrary for this exactly to become PVP compliant? As I understand it the non-internal sublibrary can depend on a range of versions of the internal sublibrary. Or did I get that wrong?

---

<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:** [July 1, 2023, 8:39am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/4 "2023-07-01T08:39:41Z")

</div>

> [@New Hackage Server Features](http://discourse.haskell.org/t/new-hackage-server-features/2621/58):
>
> Isn’t the point of using a public sublibrary for this exactly to become PVP compliant?

Can you set different versions for the sublibraries? If not, then I don’t see how you can achieve strict PVP compliance.

> [@danidiaz](#):
>
> The solution spoused in that post is correct and principled, and it also causes too much friction because managing one extra package is a hassle.

Well, I’m getting even less excited about public sublibraries now if people use them to violate PVP even more easily.

That’s going to be a net negative result for the ecosystem.

I wish we had a way to block such packages from being uploaded to hackage, but we don’t.

---

<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:** [July 1, 2023, 8:45am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/5 "2023-07-01T08:45:36Z")

</div>

> [@hasufell](#):
>
> Can you set different versions for the sublibraries?

I don’t think so.

> If not, then I don’t see how you can achieve strict PVP compliance.

Why not?

Consider this procedure: Any time you break the internal subpackage API without breaking the non-internal API you bump the package’s major version from `X` to `X+1`. That forces the non-internal subpackage to bump from `X` to `X + 1` too, which is redundant, but non-internal `X` can use internal `X+1` (which perhaps requires a Hackage revision) and everything’s perfectly PVP compliant as far as I can see.

---

<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:** [July 1, 2023, 8:48am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/6 "2023-07-01T08:48:33Z")

</div>

> [@tomjaguarpaw](#):
>
> Consider this procedure: Any time you break the internal subpackage API without breaking the non-internal API you bump the package’s major version from `X` to `X+1`. That forces the non-internal subpackage to bump from `X` to `X + 1` too, which is redundant, but non-internal `X` can use internal `X+1` (which perhaps requires a Hackage revision) and everything’s perfectly PVP compliant as far as I can see.

That effectively means you’re creating lots of new major version bumps, although the non-internal API didn’t change.

This means a lot of work for downstream maintainers. They don’t know which release is a proper release and have to bump bounds all the time.

---

<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:** [July 1, 2023, 8:58am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/7 "2023-07-01T08:58:23Z")

</div>

Yes, true. Then I still don’t know a good way to share test code between multiple libraries ☹

---

<div class="post-metadata">

**Author:** ![danidiaz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/danidiaz/32/92_2.png) [@danidiaz](https://discourse.haskell.org/u/danidiaz)\
**Post date:** [July 1, 2023, 10:27am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/8 "2023-07-01T10:27:27Z")

</div>

Continuing with the idea of using public sublibraries for exposing internal modules, I wonder if it would be worth it if Cabal allowed us to tag a public sublibrary as “fragile”, meaning that it doesn’t really respect the PVP, and even minor bumps can break things. (It wouldn’t make sense for the main library to be “fragile”.)

I’m not sure how this information could be used by tooling however. Maybe Hackage could use it to automate the insertion of "The Package Versioning Policy **does not apply**" warnings in the haddocks.

---

<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:** [July 1, 2023, 10:53am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/9 "2023-07-01T10:53:24Z")

</div>

> [@danidiaz](#):
>
> I wonder if it would be worth it if Cabal allowed us to tag a public sublibrary as “fragile”, meaning that it doesn’t really respect the PVP, and even minor bumps can break things.

This is sounding more and more like public sublibraries have ergonomics benefits for maintainers but fail to hit other desirable goals and we should look for ways of improving the ergonomics of other methods that _do_ hit the other desirable goals.

---

<div class="post-metadata">

**Author:** ![danidiaz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/danidiaz/32/92_2.png) [@danidiaz](https://discourse.haskell.org/u/danidiaz)\
**Post date:** [July 1, 2023, 11:09am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/10 "2023-07-01T11:09:51Z")

</div>

This is a bit like the [vaping](https://en.wikipedia.org/wiki/Electronic_cigarette) debate but for package management. On one hand, automated tooling and documentation for some less-than-ideal practice could improve the current situation, but critics fear it would disentivize quitting “cold turkey” the less-than-ideal practice.

---

<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:** [July 1, 2023, 11:21am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/11 "2023-07-01T11:21:40Z")

</div>

It shares some similarities, but we have far more options available to us than public health regulators, and a much smaller group of stakeholders, so our job ought to be a lot easier.

---

<div class="post-metadata">

**Author:** ![FPtje](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/fptje/32/5773_2.png) [@FPtje](https://discourse.haskell.org/u/FPtje)\
**Post date:** [July 1, 2023, 1:02pm UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/12 "2023-07-01T13:02:37Z")

</div>

I think there’s another important reason why people don’t necessarily respect pvp: it’s hard, a lot of effort, and even with the best effort it’s VERY easy to make mistakes.

I wonder how hard it would be to automate versioning, like how Elm does it. If you can somehow diff the exposed data types, classes and function signatures, you can write a function that decides what the next version should be. This function could follow PVP, semver or whatever else.

I think there’s a lot that can be investigated and/or done in this direction. It’s a lot of effort, though.

---

<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:** [July 1, 2023, 1:27pm UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/13 "2023-07-01T13:27:27Z")

</div>

If you can determine the API that a library provides, the API that the consumer requires, and check whether the former is a superset of the latter than you don’t even need version numbers at all (and without having thought very hard about it I suspect that’s ultimately the direction we should be aiming to go).

---

<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:** [July 1, 2023, 1:57pm UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/14 "2023-07-01T13:57:46Z")

</div>

> [@tomjaguarpaw](#):
>
> determine the API that a library provides, the API that the consumer requires, and check whether the former is a superset of the latter

That sounds like what Backpack does.

---

<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:** [July 1, 2023, 5:41pm UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/15 "2023-07-01T17:41:47Z")

</div>

> [@danidiaz](#):
>
> I wonder if it would be worth it if Cabal allowed us to tag a public sublibrary as “fragile”

What for? What’s the reason to not follow PVP? Because you don’t care?

Well, that’s your choice, but we shouldn’t support bad choices with tooling.

---

<div class="post-metadata">

**Author:** ![chreekat](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/chreekat/32/2669_2.png) [@chreekat](https://discourse.haskell.org/u/chreekat)\
**Post date:** [July 2, 2023, 6:53am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/16 "2023-07-02T06:53:34Z")

</div>

I think this thread is a very good argument for enabling separate versioning of sublibs. It won’t always be useful, but in some cases it will make it a lot easier to follow PVP.

---

<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:** [July 2, 2023, 6:58am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/17 "2023-07-02T06:58:50Z")

</div>

How is that going to work? A package tarball has one distinct version… on hackage, in the cabal store and in the index (afaik), in stacks pantry etc… Sounds like a very large breaking change.

---

<div class="post-metadata">

**Author:** ![chreekat](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/chreekat/32/2669_2.png) [@chreekat](https://discourse.haskell.org/u/chreekat)\
**Post date:** [July 2, 2023, 7:05am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/18 "2023-07-02T07:05:59Z")

</div>

In that case, I share your concern over how this will affect PVP compliance. I don’t feel too strongly about it though.

---

<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:** [July 2, 2023, 8:36am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/19 "2023-07-02T08:36:00Z")

</div>

FWIW, I don’t think multiple public libraries really help with the internal module problem much, except in the way originally mentioned by @danidiaz : moving them from the _main_ library to a separately named sub library can act as a _signal_ to users.

In particular, since they share a version, a PVP compatible package with multiple public libraries should bump the major version if _any_ of the libraries needs a major version bump. We might need to update the PVP page to discuss this!

> Well, I’m getting even less excited about public sublibraries now if people use them to violate PVP even more easily.

It’s not… easier? It’s exactly the same. Moving the code from the main library to a sub-library doesn’t change anything about the versioning going on, AFAICT. I think this whole discussion is just not really the point of public sublibs.

---

<div class="post-metadata">

**Author:** ![taylorfausak](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/taylorfausak/32/54_2.png) [@taylorfausak](https://discourse.haskell.org/u/taylorfausak)\
**Post date:** [July 2, 2023, 11:37am UTC](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784/20 "2023-07-02T11:37:34Z")

</div>

I feel like I’m missing something basic here. Isn’t the whole point of `Internal` modules that they _aren’t_ compliant with the PVP? I thought they were supposed to signal that they may contain useful things, but they are not part of the stable API and therefore could change at any time.

Also I wanted to mention [hackage-diff](https://hackage.haskell.org/package/hackage-diff-0.1.0.1) and [cabal-diff](https://github.com/phadej/cabal-extras/tree/e22c5845bafb600d9eed8bce6e3d6d0ca982872b/cabal-diff), which are relevant to this discussion.

[Next page](https://discourse.haskell.org/t/pvp-compliance-of-internal-modules/6784.md?page=2)
