Integration point for ghcide and haskell-ide-engine. One IDE to rule them all. Read the project's background.
- Haskell Language Server (HLS)
-
Code evaluation codelens (inspired by Dante). You can evaluate code by writing it in a comment of the form -- >>>
-
Type information and documentation on hover. Note that currently, in order for docs to be displayed for dependencies, they must have been built with GHC's
-haddockflag:-
For cabal:
- Add to your global config file (e.g.
~/.cabal/config):program-default-options ghc-options: -haddock - Or, for a single project, run
cabal configure --ghc-options=-haddock
- Add to your global config file (e.g.
-
For stack, add to global
$STACK_ROOT\config.yaml, or project'sstack.yaml:ghc-options: "$everything": -haddock
This will cause compilation errors if a dependency contains invalid Haddock markup, though from GHC version 9.0, these will be demoted to warnings.
-
-
Integration with retrie
-
Code lenses for explicit import lists
-
Many more (TBD)
- For standalone
.hs/.lhsfiles, ghc must be installed and on the PATH. The easiest way to install it is with ghcup or Chocolatey on Windows. - For Cabal based projects, both ghc and cabal-install must be installed and on the PATH. It can also be installed with ghcup or Chocolatey on Windows.
- For Stack based projects, stack must be installed and on the PATH.
If you are using ghcup to manage your installations, you can install the latest version of haskell-language-server with
ghcup install hls
If you are using Visual Studio Code, the Haskell extension will automatically download and install haskell-language-server for you.
There are pre-built binaries available from the releases page for Linux, Windows and macOS.
To install, download the haskell-language-server-wrapper executable for your platform as well as any haskell-language-server executables for the GHC versions you plan on working with, and either put them on your PATH or point your client to them.
stackorcabalmust be in your PATH- You need stack version >= 2.1.1 or cabal >= 2.4.0.0
gitmust be in your PATH- The directory where
stackorcabalput the binaries must be in you PATH:- For stack you can get it with
stack path --local-bin - For cabal it is by default
$HOME/.cabal/binin linux and%APPDATA%\cabal\binin windows.
- For stack you can get it with
Tip: you can quickly check if some command is in your path by running the command. If you receive some meaningful output instead of "command not found"-like message then it means you have the command in PATH.
On Linux you will need install a couple of extra libraries:
Debian 9/Ubuntu 18.04 or earlier:
sudo apt install libicu-dev libtinfo-dev libgmp-dev zlib1g-devDebian 10/Ubuntu 18.10 or later:
sudo apt install libicu-dev libncurses-dev libgmp-dev zlib1g-devFedora:
sudo dnf install libicu-devel ncurses-devel zlib-develIn order to avoid problems with long paths on Windows you can do either one of the following:
-
Clone the
haskell-language-serverto a short path, for example the root of your logical drive (e.g. toC:\hls). Even if you chooseC:\haskell-language-serveryou could hit the problem. If this doesn't work or you want to use a longer path, try the second option. -
If the
Local Group Policy Editoris available on your system, go to:Local Computer Policy -> Computer Configuration -> Administrative Templates -> System -> FilesystemsetEnable Win32 long pathstoEnabled. If you don't have the policy editor you can use regedit by using the following instructions here. You also need to configure git to allow longer paths by using unicode paths. To set this for all your git repositories usegit config --system core.longpaths true(you probably need an administrative shell for this) or for just this one repository usegit config core.longpaths true.
In addition make sure haskell-language-server.exe is not running by closing your editor, otherwise in case of an upgrade the executable can not be installed.
git clone https://github.com/haskell/haskell-language-server --recurse-submodules
cd haskell-language-serverNote, on first invocation of the build script with stack, a GHC is being installed for execution.
The GHC used for the install.hs can be adjusted in ./install/stack.yaml by using a different resolver.
Available commands can be seen with:
stack ./install.hs helpRemember, this will take time to download a Stackage-LTS and an appropriate GHC for build haskell-language-server the first time.
The install-script can be invoked via cabal instead of stack with the command
cabal v2-run ./install.hs --project-file install/shake.project <target>or using the existing alias script
./cabal-hls-install <target>Running the script with cabal on windows requires a cabal version greater or equal to 3.0.0.0.
For brevity, only the stack-based commands are presented in the following sections.
The script will install the executables haskell-language-server-wrapper and haskell-language-server.
It will copy the latter appending the used ghc version, needed by the wrapper to choose the suitable version for the project at hand.
So installing the executables directly with stack install or cabal v2-install may not be enough
for it to work properly.
Install haskell-language-server for the latest available and supported GHC version (and hoogle docs):
stack ./install.hs hlsInstall haskell-language-server for a specific GHC version (and hoogle docs):
stack ./install.hs hls-8.8.3
stack ./install.hs datahls-8.8.3 target will build the project and install haskell-language-server-wrapper,
haskell-language-server, haskell-language-server-8.8.3 and haskell-language-server-8.8
executables.
The Haskell Language Server can also be built with cabal v2-build instead of stack build.
This has the advantage that you can decide how the GHC versions have been installed.
To see what GHC versions are available, the command cabal-hls-install ghcs can be used.
It will list all supported GHC versions that are on the path for build with their respective installation directory.
If you think, this list is incomplete, you can try to modify the PATH variable, such that the executables can be found.
Note, that the targets hls and data depend on the found GHC versions.
An example output is:
> ./cabal-hls-install ghcs
******************************************************************
Found the following GHC paths:
ghc-8.6.5: /opt/bin/ghc-8.6.5
ghc-8.8.3: /opt/bin/ghc-8.8.3
******************************************************************If your desired ghc has been found, you use it to install haskell-language-server.
./cabal-hls-install hls-8.6.5
./cabal-hls-install datahaskell-language-server supports some forms of configuration.
This configuration is done via the LSP settings you provide with your editor and/or LSP client. Some examples include:
- in VSCode/VSCodium this is done via the
Settingstab - with
LanguageClient-neovimyou can point theg:LanguageClient_settingsPathvariable to the file in which you want to keep your LSP settings
By default, haskell-language-server is compiled with support for several different formatters.
These include
floskellfourmoluormolustylish-haskellbrittany(if compiled with AGPL)
For a full explanation of possible configurations, refer to hie-bios/README.
haskell-language-server has some limited support via hie-bios to detect automatically your project configuration and set up the environment for GHC. The plan is to improve it to handle most use cases.
However, for now, the more reliable way is using a hie.yaml file in the root
of the workspace to explicitly describe how to setup the environment.
For that you need to know what components have your project and the path
associated with each one. So you will need some knowledge about
stack or cabal components.
You also can use this utility to generate automatically hie.yaml files for
the most common stack and cabal configurations
For example, to state that you want to use stack then the configuration file
would look like:
cradle:
stack:
component: "haskell-language-server:lib"If you use cabal then you probably need to specify which component you want
to use.
cradle:
cabal:
component: "lib:haskell-language-server"If you have a project with multiple components, you can use a cabal-multi cradle:
cradle:
cabal:
- path: "./test/functional/"
component: "haskell-language-server:func-test"
- path: "./test/utils/"
component: "haskell-language-server:hls-test-utils"
- path: "./exe/Main.hs"
component: "haskell-language-server:exe:haskell-language-server"
- path: "./exe/Wrapper.hs"
component: "haskell-language-server:exe:haskell-language-server-wrapper"
- path: "./src"
component: "lib:haskell-language-server"
- path: "./ghcide/src"
component: "ghcide:lib:ghcide"
- path: "./ghcide/exe"
component: "ghcide:exe:ghcide"Equivalently, you can use stack:
cradle:
stack:
- path: "./test/functional/"
component: "haskell-language-server:func-test"
- path: "./exe/Main.hs"
component: "haskell-language-server:exe:haskell-language-server"
- path: "./exe/Wrapper.hs"
component: "haskell-language-server:exe:haskell-language-server-wrapper"
- path: "./src"
component: "haskell-language-server:lib"
- path: "./ghcide/src"
component: "ghcide:lib:ghcide"
- path: "./ghcide/exe"
component: "ghcide:exe:ghcide"Or you can explicitly state the program which should be used to collect the options by supplying the path to the program. It is interpreted relative to the current working directory if it is not an absolute path.
cradle:
bios:
program: ".hie-bios"The complete configuration is a subset of
cradle:
cabal:
component: "optional component name"
stack:
component: "optional component name"
bios:
program: "program to run"
dependency-program: "optional program to run"
direct:
arguments: ["list","of","ghc","arguments"]
default:
none:
dependencies:
- someDepNote to editor integrators: there is a haskell-language-server-wrapper executable, which is installed alongside the haskell-language-server executable. When this is invoked in the project root directory, it attempts to work out the GHC version used in the project, and then launch the matching haskell-language-server executable.
All of the editor integrations assume that you have already installed haskell-language-server (see above) and that the installation script put the haskell-language-server and haskell-language-server-wrapper binaries in your PATH (usually ~/.local/bin or ~/.cabal/bin on Linux and macOS, %APPDATA%\local\bin or %APPDATA%\cabal\bin on Windows).
Install from
the VSCode marketplace, or manually from the repository vscode-haskell.
The haskell-language-server and haskell-language-server-wrapper binaries will be automatically downloaded on an ad-hoc basis, but if you have them already installed on your PATH then it will just use them instead.
- Install LSP using Package Control
- From Sublime Text, go to Preferences and search for LSP Settings
- Paste in these settings. Make sure to change the command path to your
haskell-language-server-wrapper
{
"clients": {
"haskell-language-server": {
"command": ["haskell-language-server-wrapper", "--lsp"],
"scopes": ["source.haskell"],
"syntaxes": ["Packages/Haskell/Haskell.sublime-syntax"],
"languageId": "haskell"
}
}
}Now open a Haskell project with Sublime Text and enable Language Server in the project. You should have these features available:
- Errors are underlined in red
- LSP: Show Diagnostics will show a list of hints and errors
- LSP: Format Document will prettify the file
You can use Coc, LanguageClient-neovim or any other Vim Language server protocol client. Coc is recommend since it is the only complete LSP implementation for Vim and Neovim and offers snippets and floating documentation out of the box.
Follow Coc's installation instructions.
Then issue :CocConfig and add the following to your Coc config file.
{
"languageserver": {
"haskell": {
"command": "haskell-language-server-wrapper",
"args": ["--lsp"],
"rootPatterns": ["*.cabal", "stack.yaml", "cabal.project", "package.yaml", "hie.yaml"],
"filetypes": ["haskell", "lhaskell"]
}
}
}If you use vim-plug, then you can do this by e.g.,
including the following line in the Plug section of your init.vim or ~/.vimrc:
Plug 'autozimu/LanguageClient-neovim', {
\ 'branch': 'next',
\ 'do': 'bash install.sh'
\ }
and issuing a :PlugInstall command within Neovim or Vim.
As an alternative to using vim-plug shown above, clone LanguageClient-neovim
into ~/.vim/pack/XXX/start/, where XXX is just a name for your "plugin suite".
set rtp+=~/.vim/pack/XXX/start/LanguageClient-neovim
let g:LanguageClient_serverCommands = { 'haskell': ['haskell-language-server-wrapper', '--lsp'] }You'll probably want to add some mappings for common commands:
nnoremap <F5> :call LanguageClient_contextMenu()<CR>
map <Leader>lk :call LanguageClient#textDocument_hover()<CR>
map <Leader>lg :call LanguageClient#textDocument_definition()<CR>
map <Leader>lr :call LanguageClient#textDocument_rename()<CR>
map <Leader>lf :call LanguageClient#textDocument_formatting()<CR>
map <Leader>lb :call LanguageClient#textDocument_references()<CR>
map <Leader>la :call LanguageClient#textDocument_codeAction()<CR>
map <Leader>ls :call LanguageClient#textDocument_documentSymbol()<CR>Use Ctrl+xCtrl+o (<C-x><C-o>) to open up the auto-complete menu,
or for asynchronous auto-completion, follow the setup instructions on
LanguageClient.
If you'd like diagnostics to be highlighted, add a highlight group for ALEError/ALEWarning/ALEInfo,
or customize g:LanguageClient_diagnosticsDisplay:
hi link ALEError Error
hi Warning term=underline cterm=underline ctermfg=Yellow gui=undercurl guisp=Gold
hi link ALEWarning Warning
hi link ALEInfo SpellCapIf you're finding that the server isn't starting at the correct project root, it may also be helpful to also specify root markers:
let g:LanguageClient_rootMarkers = ['*.cabal', 'stack.yaml']Install the two Atom packages atom-ide-ui and haskell,
$ apm install language-haskell atom-ide-ui haskellInstall HLS along with the following emacs packages:
Make sure to follow the instructions in the README of each of these packages.
The default lsp-haskell-server-path is set to haskell-language-server-wrapper. In
case you would like your editor to use a specific version of the hls server, then this
variable can be updated. Information on other configurations can be found at
lsp-haskell
Using haskell-language-server with doom-emacs
Install haskell-language-server, and then enable the lsp module and the haskell lang module with lsp flag in .doom.d/init.el:
:tools
lsp
;;...
:lang
(haskell +lsp)then do $HOME/.emacs.d/bin/doom sync
Using haskell-language-server with Kakoune
- Grab a copy of kak-lsp, and follow the setup instructions.
- Point your
kak-lsp.tomltohaskell-language-server-wrapper.
[language.haskell]
filetypes = ["haskell"]
roots = ["Setup.hs", "stack.yaml", "*.cabal"]
command = "haskell-language-server-wrapper"
args = ["--lsp"]HLS is not yet able to find project preprocessors, which may result in could not execute: <preprocessor> errors. This problem is
tracked in haskell#176 and originally comes from haskell/hie-bios#125
As a workaround, you need to ensure the preprocessor is available in the path (install globally with Stack or Cabal, provide in shell.nix, etc.).
Example with tasty-discover:
{-# OPTIONS_GHC -F -pgmF tasty-discover #-}This returns an error in HLS if 'tasty-discover' is not in the path: could not execute: tasty-discover.
❤️ The Haskell tooling dream is near, we need your help! ❤️
- Join our IRC channel at
#haskell-ide-engineonfreenode. - Fork this repo and ghcide and hack as much as you can.
The project includes a .editorconfig file with the editor basic settings used by the project.
However, most editors will need some action to honour those settings automatically.
For example vscode needs to have installed a specific extension.
Please, try to follow those basic settings to keep the codebase as uniform as possible.
The project can be built with both cabal build and stack build.
haskell-language-server can also be used with itself. We provide preset samples of hie.yaml for Cabal and Stack.
Note: the ./install/ folder is not directly tied to the project so it has dedicated ./install/hie.yaml.[cbl|stack]
templates.
$ cp hie.yaml.cbl hie.yaml
$ cp install/hie.yaml.cbl install/hie.yamlNote: Stack project must also be built once until this issue is fixed.
$ cp hie.yaml.stack hie.yaml
$ cp install/hie.yaml.stack install/hie.yaml
$ stack build --test --no-run-tests
$ cd install
$ stack buildPepeiborra wrote an tutorial on writing a plugin in HLS.
If you want to test HLS while hacking on it, follow the steps below.
To do once:
- Open some codebase on which you want to test your hacked HLS in your favorite editor
- Configure this editor to use your custom HLS executable
- With Cabal:
- On Unix systems:
cabal exec which haskell-language-server - On Windows:
cabal exec where haskell-language-server
- On Unix systems:
- With Stack:
$(stack path --dist-dir)/build/haskell-language-server/haskell-language-server
- With Cabal:
To do every time you changed code and want to test it:
- Build HLS
- With Cabal:
cabal build exe:haskell-language-server - With Stack:
stack build haskell-language-server:exe:haskell-language-server
- With Cabal:
- Restart HLS
- With VS Code:
Haskell: Restart Haskell LSP Server
- With VS Code:


