PVP Compliance of .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


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.


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?

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

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.

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.

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.

1 Like

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

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.

1 Like

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.

This is a bit like the vaping 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.

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.

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.


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).

That sounds like what Backpack does.

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.

1 Like

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.

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.


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

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.


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 and cabal-diff, which are relevant to this discussion.