tweag / haskell-stack-nix-example

Examples of valid and invalid Stack + Nix integration
MIT License
20 stars 5 forks source link

How would you add a Haskell language server? #4

Closed malteneuss closed 1 year ago

malteneuss commented 2 years ago

Hi Tweag members. I'm really thankful for your guide on Stack in Nix and all your other high-quality blog posts. To me this is the first really understandable tutorial on how Stack's Nix integration works (the official Stack docs are way too convoluted). For an even better developer setup, maybe you can extend it to integrate other tools like HLS.

Is your feature request related to a problem? Please describe. The developer tools would be part of shell.nix but you would need to select a HLS version from haskell.packages which matches the selected GHC version, which is only available in /nix/stack-nix-integration.nix. Do you have to select a HLS version manually and keep in sync in Stack and Nix manually?

Describe the solution you'd like An adaptation of the example that also automatically selects the right Haskell Language Server version for the Stackage LTS GHC version.

what-the-functor commented 1 year ago

@malteneuss, see this example. Stack will use GHC, and HLS provided by Nix. The '--no-nix' flag keeps stack completely Nix agnostic, since Stack will use the GHC on the path (the '--system-ghc' flag), and the tools are provided by Nix. The '--no-install-ghc' flag will cause Stack to error out if no GHC is found, rather than to try to install GHC. This is what we want, because GHC should be provided by Nix.

See this section in the Stack docs.

{ pkgs ? import <nixpkgs> { } }:

with pkgs;

let
  hsPkgs = pkgs.haskell.packages."ghc902"; #Align with LTS from stack.yaml

  # Provide Nix integration for Stack as a wrapper,
  # so that Stack configuration is Nix agnostic.
  # GHC, Haskell tools, and non-Haskell dependencies are provided by Nix
  # https://www.tweag.io/blog/2022-06-02-haskell-stack-nix-shell/
  stack-wrapped = symlinkJoin {
    name = "stack";
    paths = [ pkgs.stack ];
    buildInputs = [ pkgs.makeWrapper ];
    postBuild = ''
      wrapProgram $out/bin/stack \
        --add-flags "\
          --no-nix \
          --system-ghc \
          --no-install-ghc \
        "
      '';
  };

in
mkShell {
  buildInputs = [
    hsPkgs.ghc
    hsPkgs.haskell-language-server
    hsPkgs.ormolu
    stack-wrapped
  ];
}
malteneuss commented 1 year ago

@what-the-functor Thanks for that hint. A funny coincidence is that i actually wrote that Stack section^^