Creating a Haskell development environment with LSP on NixOS

I had a new Haskell project that I wanted to do, so I of course wanted to setup my editor of choice, neovim with LSP for making my programming more productive. I also decided to use Nix to make getting non-Haskell dependencies automatic.

Though the technical merits of Haskell and Nix are well known, combining them to a nice experience involves a lot of moving parts and pouring through scattered documentation and tutorials on the internet, so hopefully this post will help you.

Setting up the editor

I’m going to use coc.nvim (client) and haskell-language-server for this tutorial.

 environment.systemPackages = with pkgs; [
   ghc
   cabal2nix
   cabal-install
   nodejs # For coc-nvim
   haskellPackages.haskell-language-server
   (neovim.override {
     configure = {
       packages.myPlugins = with pkgs.vimPlugins; {
         start = [ coc-nvim ];
         opt = [];
       };
     };
    })
  ];

Here’s what my /etc/nixos/configuration.nix looks like for setting neovim up (the first three packages are going to be used later).

Now, run sudo nixos-rebuild switch to rebuild the system with these packages.
But before we get LSP support with Haskell, we need to configure coc.nvim (gah, non-reproducibility!) by issuing :CocConfig in neovim, and enter the following:
{                               
 "languageserver":{                                             
   "haskell": {
     "command": "haskell-language-server-wrapper",
     "args": ["--lsp"],
     "filetypes": ["haskell", "lhaskell"]
   }
 }
}

When that’s done, we can open up our LSP-enabled neovim with nvim Foo.hs:

Tada!

Very cool! While LSP support is great for just playing around for learning the language, let’s see how we can use it in a “real” project next.

Setting up a project for use with our setup

Now we’re going to create a project that we’ll build with nix.

mkdir testproj && cd testproj.
cabal init && touch LICENSE
cabal2nix . > default.nix
Here we’ve created an empty cabal project and converted it to a nix expression, but to build the package, we need to create another nix expression called release.nix with the following contents:

let
 pkgs = import <nixpkgs> {};
in
 pkgs.haskellPackages.callPackage ./default.nix {}
Now do nix-build release.nix && result/bin/testproj.
At the end you should see the line Hello, Haskell! which tells us our program ran successfully.

Adding a dependency

Few Haskell programs have no other dependencies than Prelude, so let’s add gi-gtk as a dependency to our project:

Regenerate the nix expression: cabal2nix . > default.nix
Now we can start working with gi-gtk by entering nix-shell:
nix-shell --attr env release.nix
Next let’s write a small GTK hello world program (LSP might take a while to start up), and build it as before
(nix-build release.nix && result/bin/testproj)

Here we have a nice GTK window, and what’s best, we didn’t need to bother downloading a million system dependencies on our own like you would have to with just cabal to be able to build gi-gtk.

Now, go make something awesome with Nix and Haskell!

One thought on “Creating a Haskell development environment with LSP on NixOS

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website at WordPress.com
Get started
%d bloggers like this: