Haskell VSCode setup

Haskell VSCode setup

This is a quick guide on how to set up or customise your VSCode text editor for Haskell (e.g. code-highlighting, code-hinting, linter, etc), it does not attempt to explain how to install VSCode. For this reason, you need to have VSCode installed on your machine and at least the Haskell dev stack .

The following instructions are based on VSCode for macOS but should be similar to other operating systems.

Syntax highlighting#

Open the extensions in the sidebar, look for Haskell Syntax Highlighting by Justus Adam and click to install.

It adds syntax highlighting support for Haskell (.hs and .lhs) and support for Cabal files (.cabal) via concoction Also adds automatic indentation after where, do, -> etc. and surrounding brackets ([], {} etc).

To complete, add the Haskell Language Server extension which depends on Haskell Syntax Highlighting.

Open the settings.json by opening the command palette (either with F1 or Ctrl+Shift+P) and clicking on Open Settings (JSON) to configure at your liking (use the Haskell Language Server documentation to help configure to your liking).

Here’s an example of my settings.json, where I define Brittany as my code formatting provider (you’ll find the instructions below to learn how to install Brittany, so skip this step for now).

{
	"haskell.hlint.executablePath": "/Users/username/.local/bin/hlint",
  "haskell.formattingProvider": "brittany",
  "[haskell]": {
		"editor.defaultFormatter": "haskell.haskell",
	  "editor.formatOnSave": true,
  },
}

Code Linting#

Linting is the automated checking of your source code for programmatic and stylistic errors. This is done by using a lint tool (otherwise known as linter). A lint tool is a basic static code analyzer.

Linting is important to reduce errors and improve the overall quality of your code. Using lint tools can help you accelerate development and reduce costs by finding errors earlier.

We’ll add the Hlint extension to VScode (HLint is a tool for suggesting possible improvements to Haskell code. These suggestions include ideas such as using alternative functions, simplifying code and spotting redundancies).

The Hlint extension provides the integration of Hlint to VSCode, it does not work on its own, as such you’ll have to install Hlint in your system. The easiest way to install is by using stack tool (if you have followed the Haskell dev stack guide, you should have it installed):

stack install hlint

If you’d like to execute hlint through the command line and if the stack install haven’t add hlint to your operating system PATH (type hlint --version to see if available), locate the stack install output to identity the location where the binary was installed to:

Copied executables to /Users/Username/.local/bin:

Copy the path and add it to your PATH in your shell profile, here’s an example for my ~/.zshrc (I’m using zsh, you might be using bash where .bashrc would be the equivalent):

export PATH="/Users/username/.local/bin:$PATH"

After you add to the PATH, remember to source the shell profile, otherwise, you need to close and open the terminal window for the binary to be available, here’s an example:

source ~/.zshrc

Once complete, open the VSCode extensions, look for Haskell-linter and install it.

There might be a case where VSCode can not locate the Hlint path, so add the path to the hlint executable to your VScode settings (the three dots, means that other settings might exist, so you add a new field to the existing, I did it this way to keep it succinct)

{
  ...
	"haskell.hlint.executablePath": "Path\To\Executable"
}

If you don’t know the pathname for the hlint executable, you can use the command line which (if you are not on a linux/macOS machine, google search for the equivalent for your operating system)

which hlint

Code formatter#

For code formatting, consistency and enforcement of a style install Brittany

stack install brittany

Notice that we install the binary to our operating system first. We then s et up our Haskell Language server to use it, as instructed in the Code Highlighting step above.

At the time, of writing, Brittany dropped support for GHC 8.x, which made the installation process quite difficult to figure out.

Here’s a failed attempt, which requested a change in the stack.yaml

❯ stack install brittany-0.13.1.2                                                                ─╯

Error: While constructing the build plan, the following exceptions were encountered:

In the dependencies for brittany-0.13.1.2:
    data-tree-print needed, but the stack configuration has no specified version  (latest matching
                    version is 0.1.0.2)
needed since brittany is a build target.

Some different approaches to resolving this:

  * Recommended action: try adding the following to your extra-deps
    in /Users/punkbit/.stack/global-project/stack.yaml:

- data-tree-print-0.1.0.2@sha256:d845e99f322df70e0c06d6743bf80336f5918d5423498528beb0593a2afc1703,1620

Plan construction failed.

The required update in the stack.yaml

# This is the implicit global project's config file, which is only used when
# 'stack' is run outside of a real project.  Settings here do _not_ act as
# defaults for all projects.  To change stack's default settings, edit
# '/Users/punkbit/.stack/config.yaml' instead.
#
# For more information about stack's configuration, see
# http://docs.haskellstack.org/en/stable/yaml_configuration/
#
packages: []
resolver: lts-18.21
extra-deps:
  - data-tree-print-0.1.0.2@sha256:d845e99f322df70e0c06d6743bf80336f5918d5423498528beb0593a2afc1703,1620

Followed by calling the installation command

stack install brittany-0.13.1.2

🤔 If wondering how this was solved, the package version details and related dependencies, on which the decision was based are located in the right sidebar of https://hackage.haskell.org/package/brittany where the version before GHC 8.x is dropped is https://hackage.haskell.org/package/brittany-0.13.1.2

💡 Brittany would be installed seamlessly if installed through Cabal package manager, which takes care of the dependencies. But will build it using your ghcup-installed ghc, not the stack-installed ghc. Cabal should automatically pick an older version after seeing the base constraint.

References

https://svejcar.dev/posts/2020/01/01/my-vscode-setup-for-haskell/

https://dev.to/egregors/vscode-for-haskell-in-2020-5dn8

https://stackoverflow.com/questions/59030132/how-do-i-install-haskell-stack-on-mac

https://stackoverflow.com/questions/30913145/what-is-the-difference-between-cabal-and-stack

https://haskell-language-server.readthedocs.io/en/latest/configuration.html

http://urchin.earth.li/~ian/style/haskell.html

comments powered by Disqus