Making GHC upgrades easy | The Haskell Programming Language's blog
Making GHC upgrades easy
Simon Peyton Jones June 12, 2026 [GHC] #hackage #cabal
What this post is about
When a shiny new version of GHC comes out, it should be easy to upgrade. After all, the new compiler should be more capable than the previous version!
But in practice that isn't even nearly true. The upgrade path is so hard that many companies are using versions of GHC from many years back; it's just too much work for them to upgrade. This is bad in many ways:
It denies those users access to both bug-fixes and cutting-edge work that are embodied in newer GHCs
It strongly inhibits those users from spending resources contributing to GHC, because their work would land in an old version and would not propagate to the HEAD.
It places a maintenance burden on GHC's implementers to support more old versions.
The GHC team has been working hard on this issue, and has made lots of progress. This post summarises what we have done, what remains to be done, and invites your help.
1. Goals
We have two big goals. The most important is this one::
(STABILITY goal) The Big Stability Goal.
Suppose a package P compiles successfully with GHC 10.0. When GHC 10.2 is released, it should be possible to use GHC 10.2 to compile package P, and all its dependencies, without modification.
It is impossible to provide a 100.0% promise of (STABILITY goal): see Section 4.1 below. But we can get very close.
There is a complementary goal, which relates to the base package. The base package provides core functionality to every Haskell program, including all the modules specified in the Haskell Report, especially the Prelude module. Almost every Haskell package in existence depends, directly or indirectly, on base. (Hence its name.)
(BASE goal) The Base Package Goal.
The base package should be a package like any other:
In its own repository
With its own maintainers
With its own changelog, independent of GHC's changelog.
Released on a schedule independent of GHC
Can be refactored without reference to GHC
The version of base that you use must obviously be compilable with the version of GHC that you are using; but you can use any version of base that has that property.
We are now getting very close to achieving these goals. This post explains why it is harder than it looks, what we have done recently, and what we mean by "very close".
The two goals look independent, but in fact overcoming one set of obstacles will unlock both goals, which is why I am treating them together here. Section 2 describes the problem.
2. Background: the problem
In the past, each version of GHC came with a new version of the base package. For example:
GHC 9.8 came with base-4.19.0
GHC 9.10 came with base-4.20.2
GHC 9.12 came with base-4.21.1
GHC 9.14 came with base-4.22.0
Moreover, each version of GHC was indissolubly tied to one, and only one, version of base. For example, every program compiled with (say) GHC 9.10, say, must be compiled against base-4.20.2. No other version of base will do.
2.1 Why tight coupling is a problem
This tight coupling was convenient for the implementers of early versions of GHC, well before we were thinking about stability, even before Cabal and Hackage even existed. But with the benefit of hindsight, the tight coupling is highly undesirable:
Suppose package P, is compiled with GHC 9.10, against base-4.20.2.
To compile P with GHC 9.12, I must use base-4.21.1, because GHC 9.12 insists on that.
So at the very least, I must update P's upper bound on base.
The reason that the base version number changed was because of changes approved by the Core Libraries Committee, perhaps adding new functions, or removing some. These changes may force changes in P beyond just the dependency-bound change.
Even if P is fine with the new base, perhaps P depends on Q; so P cannot be compiled until Q is adapted to the new base. But the maintainer of Q might be otherwise engaged so it may take a while to adapt.
In practice P may depend, directly or indirectly, on dozens of packages, all of which must be adapted (perhaps only by bumping a version bound, but perhaps more) to the new base.
This is very, very bad. It may take months for a wave of version bumps and to sweep through Hackage. It directly contradicts (STABILITY goal).
2.2 The problem of known entities
But why does GHC 9.10, say, insist on base-4.20.2 and nothing else?
The main reason is that GHC needs to "know about" hundreds of functions, types, and classes defined in base. Example: when generating the code for deriving(Show) for a new data type, the generated code needs to refer to auxiliary functions defined in base. By "know about" I mean that GHC needs to know the precise module in which the Show class (and many other auxiliary functions) is defined.
There are many, many other examples: desugaring list comprehensions, or arrow notation, or record accesses. Collectively these functions,...