Skip to content

Instantly share code, notes, and snippets.

@langston-barrett
Last active July 5, 2022 23:34
Show Gist options
  • Save langston-barrett/52dccab58e91f03a2bebcc994f9a8bb2 to your computer and use it in GitHub Desktop.
Save langston-barrett/52dccab58e91f03a2bebcc994f9a8bb2 to your computer and use it in GitHub Desktop.
Cabal+Nix+Spacemacs+Dante

There's a lot of conflicting information online about using Haskell, Nix, Stack, Cabal, and Spacemacs together. Here's what has worked and not worked for me.

default.nix:

{ pkgs ? import <nixpkgs> {} }:
pkgs.haskellPackages.callCabal2nix "name" ./. { }

shell.nix:

with import <nixpkgs> { };

let name = import ./default.nix { };
in stdenv.mkDerivation {
  name = "name-dev";
  version = "0.1";
  src = lib.sourceFilesBySuffices ./. [ ".cabal" ".hs" ];
  buildInputs =  [
    # You can specify a GHC version like so:
    # haskell.packages.ghc843.ghcWithPackages
    (haskellPackages.ghcWithPackages (hpkgs: with hpkgs; [
      cabal-install
      hoogle
      hlint
      hindent
      ghcid
      packunused
      # ghc-mod  # Broken on GHC 843
      # hasktags # Broken on GHC 843
    ] ++ name.buildInputs ++ name.propagatedBuildInputs))

    # General development
    emacs
    git
    sourceHighlight # Use with ghcid
    haskellPackages.unused # https://unused.codes/
    zsh
  ];
}

If you get an error like this (especially after modifying your nix or cabal files), it's time to re-run cabal configure:

<command line>: cannot satisfy -package-id brick-0.38-9Yht4H8pMMu8WmuSHutUhb
(use -v for more information)

Spacemacs

Unfortunately, it is a known bug that Spacemacs destroys your PATH from nix-shell. This means that all of this is basically unusable, except through an ansi-term in which you also execute nix-shell --pure.

However, using emacs-direnv will fix the PATH if the following is put in .envrc:

use_nix shell.nix

Dante

For some reason, I had to configure dante to use nix-shell --pure in my dotspacemacs/user-config:

(setq dante-repl-command-line '("nix-shell" "--pure" "--run" "cabal repl --builddir=dist/dante"))

Sometimes, Dante will have trouble because cabal repl "doesn't support multiple targets", in which case this works in .dir-locals.el:

((haskell-mode
. ((dante-repl-command-line . ("nix-shell" "--pure" "--run" "cabal repl lib:saw-script --builddir=dist/dante")))))

Fake Agda mode

This is a small guide to a two-monitor workflow for writing Haskell that is akin to agda-mode.

  1. Run SPC SPC flycheck-list-errors
  2. Close the pop-up window without closing the buffer: SPC w d
  3. Open a new frame with SPC F n
  4. Put your new frame on your second monitor, and open the Flycheck buffer
  5. Leave holes _ in your expressions

Now when you leave a hole, Flycheck will get it's type from GHC automatically and show it to you in your second window!

Popular guides

@andregrigon
Copy link

Thank you so much!

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