Skip to content

Update to cabal (3.0) and ghc (9.10) compilation target#100

Open
harryprayiv wants to merge 8 commits intomarcosh:mainfrom
harryprayiv:update
Open

Update to cabal (3.0) and ghc (9.10) compilation target#100
harryprayiv wants to merge 8 commits intomarcosh:mainfrom
harryprayiv:update

Conversation

@harryprayiv
Copy link

I finally got DocTests to compile after many changes. TIL, the doctest-parallel module has changed DRASTICALLY!
My goal was to get it working with updated cabal (3.0) and ghc (9.10). Mission accomplished on my machine (where I tend to provision everything with nix).

Please don't hesitate to be brutally honest if I made any unwelcome changes.

Thanks for building this amazingly futuristic module!

@harryprayiv
Copy link
Author

Granular details:

1. Role annotations throughout the library

GHC 9.10 infers more conservative roles for type constructors in the presence of type families and GADTs, and with -Weverything this surfaces as hard errors rather than just warnings. The fix is to declare the roles explicitly, which also serves as useful documentation of the intended variance.

The affected types are:

  • BaseMachineT, InitialState, ActionResult in Crem.BaseMachine
  • Decider, EvolutionResult in Crem.Decider
  • Graph in Crem.Graph
  • TreeMetadata in Crem.Render.RenderFlow
  • AllVertices in Crem.Render.RenderableVertices
  • StateMachineT in Crem.StateMachine
  • AllowTransition in Crem.Topology
  • TriangularState in Crem.Example.TriangularMachine

Each annotation was chosen to match the actual usage: representational where coercion is safe, nominal where the type is used as a kind index or appears under a type family, and phantom where the parameter does not appear at the value level at all (as in the output parameter of EvolutionResult).

The TypeAbstractions extension is enabled in Crem.Topology and several example modules; this is required for the singletons-generated code to typecheck under 9.10.

The map variable name in Crem.Topology was renamed to tmap in the AllowAddingVertex case and its associated instance, since GHC 9.10 warns about shadowing the Prelude.map function at the type level.


2. Suppression of new warnings introduced in GHC 9.10

The library uses -Weverything, which means any new warning category introduced by a GHC release immediately becomes a build failure. GHC 9.10 introduced -Wmissing-role-annotations and -Wmissing-poly-kind-signatures. Where the annotations are not yet provided (primarily in the example modules and in Crem.Decider where singletons TH splices generate types we do not control), the warnings are suppressed with OPTIONS_GHC pragmas. In the core library modules the annotations are provided directly rather than suppressed.


3. Upper bound relaxations in the cabal file

The existing bounds on base, machines, nothunks, profunctors, and singletons-base all excluded the versions shipping with GHC 9.10. The bounds have been relaxed to open-ended lower bounds (or, in the case of text, extended to < 2.2). The cabal-version is bumped to 3.0, and the subcomponent dependency syntax crem:crem-examples is used where appropriate, which requires cabal 3.0.

The directory and filepath packages are added as explicit dependencies of the crem-doctests test suite, since they are used directly in the rewritten Main.hs (see below) and relying on them being transitively available is fragile.


4. Adaptation of the doctest runner to the current doctest-parallel API

The mainFromLibrary entry point used in doctest/Main.hs is no longer present in the version of doctest-parallel that builds against GHC 9.10. The runner has been rewritten to call runModules directly, constructing the GHCi argument lists via libraryToGhciArgs and passing them in separately for the parse and eval phases.

The one subtlety is that doctest-parallel needs the package-id of the crem-examples sublibrary when evaluating expressions, but this identifier is not easily derivable without running the build. The workaround is to locate the .ghc.environment.* file that cabal writes into the working directory and parse the relevant package-id line from it. This is admittedly a hack, but it reflects the reality of how doctest-parallel currently expects to be driven, and it is no worse than what other packages in the ecosystem do.


Testing

The full test suite (crem-spec, crem-doctests) passes under GHC 9.10.3 with the Nix configuration included in the patch. The existing GHC 9.2 and 9.4 configurations are unaffected; I have not removed any compatibility there.

@marcosh
Copy link
Owner

marcosh commented Mar 20, 2026

Thanks a lot for this!

I'm slowly looking at everything and actually trying to redo it myself to see which options come more naturally.

One thing I'd surely like to solve differently is the doctests in the literate Haskell file. I guess I found the issue (see martijnbastiaan/doctest-parallel#101) so it's probably just a matter of time that that gest solved without touching anything in crem

@harryprayiv
Copy link
Author

Thanks a lot for this!

No problem at all. Thank YOU. It was an honor to help in whatever way I could.

I'm slowly looking at everything and actually trying to redo it myself to see which options come more naturally.

This is a very wise and respectable course of action as I am by no means an expert in Role annotations or any of the advanced singleton magic you're doing here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants