GHC Emacs Development Workflow with haskell-mode

Hey everyone! I am doing some work to bring a new feature to GHC. However, I am finding the workflow of below pretty exhausting:

  1. Edit code in emacs
  2. Build in terminal with hadrian/build -j --flavour=quick --freeze1
  3. Read errors as they come up and edit in emacs appropriately

This is quite slow, as often I just want to check if one individual module typechecks. My usual workflow with other Haskell projects in Emacs is to just use C-c C-l in haskell-mode, which loads that module into GHCi. However, when developing GHCi, this doesnā€™t seem to work. I get the following error in my haskell-process-log:

(ā€œStarting inferior `cabal replā€™ process using cabal ā€¦ā€ ā€œghcā€ nil ā€œcabalā€ ā€œreplā€ ā€œā€“ghc-option=-ferror-spansā€)
ā†’ Prelude.putStrLn ā€œā€
:set -v1
:set +c
ā†’ :set prompt ā€œ\4ā€
ā†’ :set prompt-cont "Ī»| "
ā† Resolving dependenciesā€¦

ā† Error: cabal: Could not resolve dependencies:
[__0] next goal: ghc (user goal)

ā† [__0] rejecting: ghc-9.9 (constraint from non-upgradeable package requires
installed instance)
[__0] rejecting: ghc-9.6.1, ghc-9.4.5, ghc-9.4.4, ghc-9.4.3, ghc-9.4.2,
ghc-9.4.1, ghc-9.2.8, ghc-9.2.7/installed-9.2.7, ghc-9.2.7, ghc-9.2.6,
ghc-9.2.5, ghc-9.2.4, ghc-9.2.3, ghc-9.2.2, ghc-9.2.1, ghc-9.0.2, ghc-8.10.7,

ā† ghc-8.10.2, ghc-8.10.1, ghc-8.8.3, ghc-8.8.1, ghc-8.6.5, ghc-8.6.4, ghc-8.6.1,
ghc-8.4.4, ghc-8.4.3, ghc-8.4.1, ghc-8.2.2, ghc-8.2.1, ghc-9.2.3.20220620
(constraint from user target requires ==9.9)
[__0] fail (backjumping, conflict set: ghc)
After searching the rest of the dependency tree exhaustively, these were the

ā† goals Iā€™ve had most trouble fulfilling: ghc

Event: "exited abnormally with code 1
"

Process reset.

The answer to my problem feels somehow related to this bit of the wiki, but I cannot figure out how to make the connection. This part of the wiki does seem to imply that on the fly typechecking from within Emacs is indeed possible.

Is there something I am missing? Am I meant to somehow point haskell-mode to use the version of GHC built locally? If someone helps me to understand how to get this working, I am happy to update whatever documentation necessary so that it is clearer to others. Or if there is a piece of documentation I am missing, please direct me! Thanks so much :slight_smile:

1 Like

I donā€™t think Iā€™ve heard of anyone using plain haskell-mode in a while. The recommendation these days is to use HLS, which I seem to recall is usable for GHC development (not that Iā€™ve ever needed to try that).

Really? Iā€™ve been using plain haskell-mode for a decade. If it worked for 21yo me completely new to Haskell, it can work for anyone.

But I generally think tooling beyond ghci is more sugar than substance. Mostly for cycle-time-minute-shavers which I think is flawed for reasons I havenā€™t quite verbalized (yet). Productivity theater I guess is the term Iā€™d use.

1 Like

What I do:

  • Open any Haskell file from the GHC repo in Emacs
  • Now Iā€™m in a projectile project and can compile it with F8, so I press it
  • Type the appropriate Hadrian command hadrian/build --freeze1 -j8 (this can be saved in .dir-locals.el)
  • compilation runs in another buffer and if thereā€™s an error, I can jump to next/previous error within Emacs using F7/M-F7.

You can try this with my Emacs config (GitHub - arybczak/emacs-config) to see if it works for you and adapt appropriate bits (youā€™ll at least need projectile). If you clone the repo to otherwise empty .emacs.d, emacs will install all necessary packages automatically and you can try the steps I described above.

Btw, you can use ghc-tags for navigation. Readme has an example config for ghc (though it might be slightly outdated).

2 Likes

This feels a little presumptuous to me. Personally, I like the convenience of HLS ā€” not in a ā€˜cycle-time-minute-shavingā€™ way, just that itā€™s easy to setup and use, works pretty well and gives me some useful tools (sadly less now since Wingman became unmaintained).

It should be possible to tweak your configuration to get ghci information on the file

Indeed, as said in the linked wiki bit, itā€™s possible to load ghc in ghci, with the hadrian/ghci script. But that script uses ghci directly rather than cabal repl, which is what your editor seems to be trying to do. See hadrian/ghci-cabal (which is invoked by hadrian/ghci and generated by ./configure), as it might hint to a way to do it (likely it involves modifying the tool youā€™re using to use a different invocation)

As others pointed out, HLS works in the ghc code base (thereā€™s a hie.yaml file which configures HLS to work in that context), so you might also change to use HLS or try to look at the scripts.

I personally donā€™t use emacs so Iā€™m sorry if I canā€™t be of more help (but do ping me if you have any more questions).

2 Likes