Skip to content

Instantly share code, notes, and snippets.

@lsmor
Last active February 21, 2024 10:28
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save lsmor/bb632565cd96be9da589b6e91f80f9ba to your computer and use it in GitHub Desktop.
Save lsmor/bb632565cd96be9da589b6e91f80f9ba to your computer and use it in GitHub Desktop.

Set Up a Haskell Development Environment in Three Steps

a Haskell Development Environment consist in a compiler (ghc), a language server (hls), a building tool (cabal or stack), and an editor compatible with the language server protocol.

The best way to have a coherent installation of these components is with the ghcup tool.

  • Step 1: Install GHCup. You'll be prompted to install some tools. Say yes to hls. Do not install stack yet (see below).
  • Step 2: Install vscode
  • Step 3: Open vscode and install the haskell extension either using the extension panel or pressing CTRL+P and ext install haskell.haskell.

Integration with other editors

If you want an editor different from vscode, check the documentation here

Integration with stack.

to integrate stack with haskell-language-server, you should configure it properly.

The key point is to prevent stack to install ghc on its own. Follow these steps:

  • First, You still need to follow the three steps at the top of this guide. You can't get a proper working environment solely with stack.

  • Skip this point if you installed stack independently from ghcup. In a terminal run ghcup install stack

  • Configure stack to use system's ghc. Configuration can be either global (recomended) or local

    • Global (recomended)
      # Run on a terminal if you want to set a global configuration
      stack config set install-ghc --global false
      stack config set system-ghc --global true 
    • Local:
      # On stack.yaml add this line if you want to set a local configuration
      system-ghc: true 
  • You must use a stack snapshot compatible with the ghc version installed by ghcup. Visit stackage to get the ghc version on each sanpshot. For example lts-18.28 uses ghc-8.10.7. You can check version compatibility with:

    # This prints the ghc's version installed by ghcup
    > ghcup list -c installed -t ghc
    ✔✔ ghc  8.10.7  recommended,base-4.14.3.0 hls-powered
    
    # Your resolver should point to 18.28      ---------------------------------------------------
    > cat stack.yaml    #                                                                    vvvvv    
    resolver:
      url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/28.yaml
    

What if I need to use a different snapshot?

In case you need to use a different snapshot you have to install it's ghc version with ghcup. For the sake of example, let say you are using lts-16.31, which uses ghc-8.8.4. Then you need to run ghcup install ghc 8.8.4 on a terminal. Also, depending on which snapshot you are using, you might loose integration with hls. Check hls documentation for more info.

@lsmor
Copy link
Author

lsmor commented Jul 22, 2022

@AlekseyChusov Sorry, I don't understand what you mean

@googleson78
Copy link

to integrate stack with haskell-language-server, you should configure it properly.

But hls by default tries to do this automagically, via haskell-language-server-wrapper and the fact that it can detect stack-based projects. At least I personally haven't had to ever use a system ghc in order to have hls working, and this is intended, afaik. Did you encounter some issues with this setup? It might be worth opening a bug report/issue over at the hls repo.

@lsmor
Copy link
Author

lsmor commented Oct 11, 2022

It might be worth opening a bug report/issue over at the hls repo.

This isn't a bug. It is the expected behaviour, but poorly documented in my opinion.

up to the hls release page

If you get your GHC binaries from a source other than https://downloads.haskell.org/ (or GHCup), then you will need to build HLS from source yourself.

Meaning that if you use stack to install ghc then hls won't be able to work (and if it does, It is just luck). Moreover, I've being able to reproduce this and get a very strange error. Also, notice that this is fixed in the most recent release of stack but I haven't updated the guide

Also this same configuration is refered in the stack guide:
https://docs.haskellstack.org/en/stable/Stack_and_VS_Code/#workaround-1

@googleson78
Copy link

googleson78 commented Oct 11, 2022

I see! I've never encountered that before by using the ghcup-installed hls + stack-downloaded ghc workflow before. I guess it's still not impossible though. I'm interested in what your error is - do you want to share it, if you still have it on hand?

I would still not call it working "luck" though - from the same document you linked:

For the most part, the versions of HLS provided by GHCup are built with the same versions of GHC that Stack downloads from its default setup-info dictionary (see YAML configuration: setup-info). Stack's default is to mirror the 'official' binary distributions published by GHC. However, in some cases, it is possible that a GHCup-supplied and GHCup-selected HLS has been built with a different binary distribution of GHC than the one which Stack has installed.

So it sounds to me like the expected case is that it would work, and it not working is a case of misfortune (unless it happens that this is not the reality more often than not, in which case the stack docs should be updated.).

Another point that reinforces this hypothesis is the fact that the default ghc mirrors stack uses (as far as I can tell) are the same ones as the ones hosted on https://downloads.haskell.org, which means that for

If you get your GHC binaries from a source other than downloads.haskell.org (or GHCup), then you will need to build HLS from source yourself.

stack should be falling under the first clause, and should not require a HLS built from source.

@lsmor
Copy link
Author

lsmor commented Oct 21, 2022

I'm interested in what your error is - do you want to share it, if you still have it on hand?

I don't remember well but something like "hls has failed three times in the last five minutes. not restarting".

Here you have a SO addressing this issue.

https://stackoverflow.com/questions/73155847/using-vscode-with-haskell-ghcup-and-stack-hls-crashes-with-newer-versions-of

Actually, if you look at SO's tag haskell-language-server you can find many people having issues with stack/hls

https://stackoverflow.com/questions/tagged/haskell-language-server

@asarkar
Copy link

asarkar commented Dec 28, 2023

Saying no to GHCup HLS (yes to everything else), and then letting the Haskell extension install HLS seems to work fine. Either GHCup or the extension, I don't know which one, creates a stack hook to prevent it from installing its own GHC. There's no further need to mess with stack anyway.
https://www.haskell.org/ghcup/guide/#strategy-1-stack-hooks-new-recommended

Debugging and testing (HSpec) still don't work from VSCode though. The debug adapter extension is $shit.

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