Upgrading the CircuitHub codebase to GHC-9.10
Posted on by Teo Camarasu
We have recently upgraded the CircuitHub codebase from GHC-9.8 to GHC-9.10. Overall it has been a pleasant upgrade experience. This is thanks to the effort that the entire ecosystem has been putting into stability lately, including but not limited to: the Haskell Foundation Stability working group, the GHC steering committee, GHC developers, the core libraries committee, and of course all the individual maintainers. This blog post will list some of the changes we had to make and is inspired by Tom Ellis’s experience report about upgrading from GHC-8.10 to GHC-9.6.
Updating upper-bounds🔗
The vast majority of the required changes consisted of updating upper bounds on our dependencies.
Many packages needed to update their bounds on boot libraries like base
or template-haskell
.
Often no actual changes were required to the library itself.
New exports from Prelude
🔗
base-4.20
now exports foldl'
from Prelude
. This is a welcome change.
It has been a footgun that other folds are exported from Prelude
, but the one you want most of the time wasn’t.
This change led to many redundant import warnings in our project.
Like many production codebases, we disallow warnings, so we had to amend many of our modules’ imports to no longer import foldl'
from Data.Foldable
or Data.List
.
Changes like this make me wish for the ability to apply HLS code actions to an entire codebase. This would have been resolved by applying the “Remove redundant imports” action followed by a reformat.
Data.List.NonEmpty.unzip
warning🔗
In base-4.20
, Data.List.NonEmpty.unzip
gained a new warning about future monomorphisation (See: CLC#86).
We ended up disabling this warning globally by adding -Wno-x-data-list-nonempty-unzip
to the ghc-options
in all of our cabal files.
We use a cabal-fmt
common fragment, so this wasn’t much work for us.
DataKind
warnings🔗
GHC-9.10 added some warnings to do with missing DataKind
pragmas.
Rather than resolving these individually, we ended up just enabling the DataKind
extension globally in our all modules.
This was made quite easy again by our use of a cabal-fmt
common fragment.
Addition of Data.Text.show
🔗
text-2.1.2
exported a new Data.Text.show
identifier.
Packages that didn’t import Data.Text
qualified had to be updated to avoid errors from using show
.
ghc-source-gen
breakage🔗
The ghc-source-gen
lets you generate Haskell code by using GHC’s own ASTs.
By depending on GHC’s AST, you are always guaranteed to be producing valid syntax. On the other hand, depending on GHC internals means that it breaks almost every release and requires significant amounts of CPP.
The package was fixed by Ian-Woo Kim in this PR.
Given that this package is likely to break in the future, the best approach might be to not depend on it if possible.
For instance the popular proto-lens
library makes use of this, and if the maintainers are willing then it would be great if we could rewrite its Haskell generation to not use ghc-source-gen
. See proto-lens#512
.
It has also been identified in the Facundo Domínguez’s GHC API stability work, and that might lead to some improvements.
HIE bug🔗
When upgrading weeder
to use the new compiler, we discovered a bug in its parsing of HIE files.
Zubin Duggal investigated and it turned out to be a bug in weeder
’s usage of the HIE API rather than a bug in GHC.
Conclusion🔗
This was a relatively easy GHC upgrade. Most of the changes were minor and just had to do with imports.
Before trying to upgrade to GHC-9.12, I will try to see if we can remove ghc-source-gen
from our dependency closure. Any package like this which is tightly coupled to the GHC API is likely to need updating after every release. Reducing one’s dependency footprint and removing fragile package is often a good way to make future upgrades easier.
From some cursory attempts to get GHC-9.12 working, it sounds like that upgrade will be even easier.