Saturday, March 21, 2020

Haskell IDE 2020

Haskell tooling has improved, but getting an IDE-like setup is still tricky. It took me some trial and error finding a good Haskell environment. I tried 5 modern libraries implementing IDE functionality for Haskell:

  • Intero
  • haskell-ide-engine (HIE )
  • haskell-language-server
  • Spacemacs Haskell Layer
  • SpaceVim Haskell Layer


Intero


I had good experience combining Intero and Haskero VS Code plugin. It is not great but I got it to work with syntax highlighting, code completion and goto definitions.



Intero is based on a fork of the GHC compiler and a downside is that Intero is no longer maintained, but it works up till GHC 8.6 the second last version of the GHC compiler.

Intero Installation


  • Install Stack
  • Install Intero using Stack
  • Install the Haskero VS Code plugin
  • Create a project that is using GHC 8.6
  • Open VS Code in the project


Creating New Project


stack install intero
export PATH=$PATH:~/.local/bin/
stack new myproject --resolver lts-14.27
cd myproject
code .


haskell-ide-engine (HIE)


haskell-ide-engine is currently the most advanced IDE project for Haskell. It is using the LSP, the language server protocol that was started on VS Code. HIE should work with editors supporting LSP.


HIE with VS Code


Here is a post about getting HIE working with VS Code on the Mac. It kept crashing on me but recently it has been more stable. Adding a hie.yaml file sometimes helps.




HIE with Neovim


HIE works with Neovim without too much work. Here is what I did:



Install HIE


git clone https://github.com/haskell/haskell-ide-engine --recursive
cd haskell-ide-engine
stack ./install.hs hie-8.6.5


Install Neovim with LSP Support


I used Neovim 0.5 beta with builtin LSP, language server protocol.

You can also do:
brew install neovim

and install vim-lsp coc.


Configure Neovim to Work with HIE


Add the following to your config file:
~/.config/nvim/init.vim

call plug#begin('~/.vim/plugged')
Plug 'scrooloose/nerdtree'{ 'on':  'NERDTreeToggle' }
Plug 'autozimu/LanguageClient-neovim'{
      \ 'branch''next',
      \ 'do''./install.sh'
      \ }
call plug#end()
let g:LanguageClient_serverCommands = { 'haskell': ['hie-wrapper''--lsp'}
nnoremap :call LanguageClient_contextMenu()
" Or map each action separately                  
nnoremap K :call LanguageClient#textDocument_hover()
nnoremap gd :call LanguageClient#textDocument_definition()
nnoremap :call LanguageClient#textDocument_rename()


Retro with Neovim


Neovim is more complicated than I like an editor to be. However with LSP integration Vim and Neovim are providing power that justifies a small learning curve.

Programming Haskell in Neovim brings me back to computing in the 1980s, before we had GUI there were still very powerful development environments running in very little memory.


haskell-language-server


The long awaited haskell-language-server is starting to work. I got it to work for a simple GCH 8.6 and GHC 8,8 project. It looks good and is full featured when it works.



Install haskell-language-server


export PATH=$PATH:~/.local/bin
git clone https://github.com/haskell/haskell-language-server --recurse-submodules
cd haskell-language-server
stack ./install.hs help
stack ./install.hs hls
stack ./install.hs data
stack ./install.hs hls-8.6.5


VS Code setting


Integration with VS Code still seems immature.

Problems with Stack and manually edited cabal file

I am using Stack as my build tool, but I also had a manually edited cabal file. When I deleted my cabal file and generated it from package.yaml it worked better.


Spacemacs Haskell Layer


It had a good experience using the Spacemacs Haskell layer.





Install a newer Emacs and install Spacemacs. Press the following four keys to get to the config file:
"space" f e d

You should add haskell to the list of layers. Here is my layers list:

   dotspacemacs-configuration-layers
   '(
     html
     yaml     

     helm
     auto-completion

     emacs-lisp
     git
     haskell
     markdown
     org
     python
     spell-checking

     )

There are a few Haskell packages that need to be installed. You can try this:

export PATH=$PATH:~/.local/bin/
stack new myproject --resolver lts-14.27
cd myproject
stack install apply-refact hlint hasktags hoogle

git clone git@github.com:jaspervdj/stylish-haskell.git
cd stylish-haskell
stack install

Doing the install under a project will make it reuse the resolver for that project.

When I did my install, stylish-haskell had an version conflict problem, so I had to do a git clone of stylish-haskell and installed from there instead.


SpaceVim Haskell Layer


It took a little work to get SpaceVim installed on Windows. First I installed Neovim with Scoop:

scoop install neovim

SpaceVim is a configuration for Vim and Neovim. The main idea in SpaceVim is that you hit the space bar and it will show you what options you have.

The Haskell Layer worked quite well and looked good. I used the new Windows Terminal with split screen and a stack build loop in the other pane.


Configure Neovim / SpaceVim


Installing Spacevim Haskell Layer was very easy. Just add these 2 lines to ~/.SpaceVim/init.toml:

[[layers]]
  name = "lang#haskell"



OS for testing


Libraries should generally be cross platform. This is what I tested on.

OS X and Windows 10

Intero and SpaceVim Haskell layer.

OS X

haskell-ide-engine and Spacemacs Haskell layer.

But they should probably also work on Linux, WSL etc.


Conclusion


Haskell already has an intimidating learning curve. With immature tooling Haskell is a language for language researchers and diehard hackers.

Haskell tooling has gotten much better, but I am spoiled and I prefer to work in an IDE-like environment.

Haskell does not have a first class IDE like IntelliJ for Java, but all libraries provide a pleasant development environment. They are not super stable, and I find myself going back and forth between them depending on the project.

Haskell is now ready for casual users to explore a pure functional language and see if they find mathematical enlightenment.

6 comments:

Unknown said...

I'm one of those "spoiled" developers used to work with an IDE.

My favourite setup for Haskell development is Intellij plus intellij-Haskell plugin (https://plugins.jetbrains.com/plugin/8258-intellij-haskell).

It offers everything that you would expect from a modern IDE:
- syntax highlighting
- code completion
- code navigation (also into library code.
All external libraries can be directly explored from the IDE)
- Linting
- code formatting
- support for automated refactorings
- running unit tests

Sami Badawi said...

Thanks. Good to know about IntelliJ.

Andy said...

I guess `haskell-language-server` will be the future :)

Sami Badawi said...

I have gone to the haskell-language-server GitHub page so many time thinking it will accelerate a release. Not sure if it is working

Nicola Bonelli said...

What's your problem with HIE and vscode? I'm currently using the HIE version 1.2 and it works nicely with both ghc 8.6.x and ghc 8.8.x with Haskell Language Server plugin of vscode.

Sami Badawi said...

I kept getting this error message:
"Haskell HIE server crashed 5 times in the last 3 minutes."

I ran HIE manually and fixed the errors that HIE reported. Still the crash persisted so I tried HIE with Neovim instead.

I also wanted to check how easy it is to setup a Haskell IDE for a casual user.