It was my understanding that backpack could solve this. Unfortunately, from what I know, backpack is not yet widely supported. And I might be wrong about this.
Yeah, backpack could let you depend on an abstract interface which can be instantiated by both x and x2. Then the end-user can choose which concrete implementation to use. But then someone would have to maintain that abstract interface. Backpack is supported by GHC and Cabal, but not really by other tooling (notably Stack, Hackage, and HLS). I think the lack of support never made it convenient enough to gain traction and nobody wants to improve the tooling support because it is not used by anyone.
I think scenarios like the one(s) discussed in this topic make a point that backpack or similar progress is needed.
Wish I had more free time ![]()
Backpack is supported by hackage (eg lsp-types: Haskell library for the Microsoft Language Server Protocol, data types)
Although further UI work has been discussed and is welcome (eg UI for multiple public libraries · Issue #1218 · haskell/hackage-server · GitHub)
I don’t see any backpack in lsp-types, only multiple public sublibraries. It does seem like it has some support for backpack, for example it does list the Key signature for the unpacked-containers package. However, it seems to choke on raaz (perhaps that is also related to the issue you linked?).
Fair points. When you say it chokes on raaz, what do you mean? Do you mean that it does not display the modules it should? (I think it does). Or do you mean that not all the modules have documentation? If the latter, this may be a haddock issue or an issue with how cabal invokes haddock (cf: Backpack and multiple public library interop · Issue #1363 · haskell/haddock)
In either case, I do think more work and patches are welcome. As is however, certainly packages using backpack can be posted to hackage, at least somewhat browsed, and then in turn used by cabal. While ergonomics and UI can be improved, I do not think this is a barrier to adoption.
I don’t think Backpack, by itself, would be a solution for the “basement” problem.
All the libraries that used “basement” would have to remain “indefinite” in the Backpack sense and depend on a signature instead. We would only commit to an implementation in executables (and test suites).
So we’re back to a big coordination problem. And it would be difficult for participants to agree from the beginning because, when starting to depend on a library like “basement”, one doesn’t expect for it to become unmaintained!
I believe Backpack makes more sense when multiple instantiations of some library are planned from the beginning. But in the “basement” case, we need something like a way to “override” packages while the dependencies slowly adapt across the ecosystem.
Perhaps we should normalize everybody specifying interfaces for all their dependencies. Even if you only ever want to use one specific implementation, it is still good for maintainability to specify what specific parts of your dependencies you are using and how that forms a cohesive interface. Making your interfaces explicit is the first step to keeping them small, increasing cohesion and reducing coupling.
The main problem I can think of is the extra maintenance burden of maintaining these interfaces. If HLS had a code action to add things to a backpack signature just like it has one for adding an import or making all imports explicit, then perhaps this would be more feasible.
That would be an interesting experiment. I suspect it could even help with LLM-based coding because, on one hand, a signature is the natural place to document how you intend to use some library and, on the other, it would help the LLM to find relevant context without jumping around too much. I think this (not Haskell related) video is relevant.
One problem with it is that we would lose the information provided by dependency version bounds. But perhaps we can always provide a properly instantiated version of the code in a separate public library.