IDEs and Linters

As of March 2020, School of Haskell has been switched to read-only mode.

Incomplete. Need to add:

  • Emacs: haskell-mode + hlint stylish-haskell Additional: multi-tags search * projectile for projects
  • Vim: pretty much everything
  • fpcomplete IDE
  • other IDEs not listed here

Emacs

Emacs is one of most popular Haskell editors out there. If you are able to use it, you can get a very nice development environment.

Prerequisites

Cask (or use-package)

It's assumed in this tutorial you have modern package manager Cask installed. You can install it by following the cask user guide. For older Emacs versions (< 24), please figure out other method of package-installation.

Make sure a Cask file in your .emacs.d directory has marmelade repo, ensure it looks something like this:

(source gnu)
(source melpa)
(source marmalade)

And check that your ~/.emacs file has:

(require 'cask "~/.cask/cask.el")
(cask-initialize)

After adding dependencies to your Cask file, run cask install in that directory.

If instead of Cask you are using use-package to manage your packages, then make sure that you have this in your init.el file:

(setq package-archives
      '(("gnu"         . "http://elpa.gnu.org/packages/")
        ("marmalade"   . "http://marmalade-repo.org/packages/")
        ("melpa" . "http://melpa.milkbox.net/packages/")))
(package-initialize)
(require 'use-package)

Make sure that you install use-package from the package manager. Following tutorial should be straightforward.

exec-path-from-shell

On MacOS X you will also need exec-path-from-shell in order to get your environment variables from your shell (bash or zsh) into your emacs, so that it inherits your $PATH and sees proper ~/.cabal/bin/cabal, for example. To install, add following to your Cask file:

(depends-on "exec-path-from-shell")

and run cask install from Cask-file directory. Add following to your ~/.emacs:

(when (memq window-system '(mac ns))
  (exec-path-from-shell-initialize))

haskell-mode

First of all, you should use haskell-mode for editing .hs and .cabal files. Add this line to your Cask:

(depends-on "haskell-mode")

and run cask install in that file's directory. This should install a fresh haskell-mode for you. Restart your emacs and you should be ready to open any .cabal or .hs file for editing. You will see syntax highlighted, you'll be able to run commands like M-x haskell-process-load-file.

However, you can't yet use haskell-mode in full because you haven't configured indentation mode and interaction. Go read haskell-mode tutorial on setting the indentation-mode you like and Haskell Interactive Mode Setup pages, or just put something like this to your .emacs (if you already have custom-set-variables in your .emacs -- extend it):

(defun turn-on-subword-mode ()
  (interactive)
  (subword-mode 1))
(defun my-haskell-mode-hook ()
  (define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-or-reload)
  (define-key haskell-mode-map (kbd "C-`") 'haskell-interactive-bring)
  (define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type)
  (define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info)
  (define-key haskell-mode-map (kbd "C-c C-c") 'haskell-process-cabal-build)
  (define-key haskell-mode-map (kbd "C-c C-k") 'haskell-interactive-mode-clear)
  (define-key haskell-mode-map (kbd "C-c c") 'haskell-process-cabal)
  (define-key haskell-mode-map (kbd "SPC") 'haskell-mode-contextual-space))
(custom-set-variables
 '(haskell-mode-hook
   (quote
    (interactive-haskell-mode 
     turn-on-haskell-indent 
     turn-on-subword-mode
     turn-on-haskell-decl-scan 
     my-haskell-mode-hook)))
 '(haskell-process-type 'cabal-repl))

Now you're more or less ready, but this is just a beginning. Go ahead, open some .hs file and press C-h ? b. You will see list of bindings available. Search for haskell- to see all haskell-related bindings. Also, run M-x haskell- and press TAB for list of available commands starting with haskell-. There's plenty of them!

Press C-c C-l to open a cabal repl shell with current module loaded. You can easily play with your code like this. Also, pressing C-c C-i will inspect symbol under cursor and show you some info. Neat!

ghc-mod

Ghc-mod is a tool that helps your editor become more close to an IDE. It lets you do things like blazingly-fast error-reporting upon save, autocompletion and more.

First, install ghc-mod itself:

cabal install ghc-mod

Then, add this to your Cask file:

(depends-on "ghc")

And this to your ~/.emacs:

(autoload 'ghc-init "ghc" nil t)
(autoload 'ghc-debug "ghc" nil t)

and extend your my-haskell-mode-hook with call to (ghc-init) like this:

(defun my-haskell-mode-hook ()
  (ghc-init)
  ; ... all previous contents
  )

After this is done, relaunch your Emacs (or re-eval config) and open some .hs-file. Make a mistake and save the file, mistake should now become underlined with red, and pressing M-S-? while keeping curstor on top of it will show the error, and M-n M-p should navigate between next/prev errors.

Check out ghc-mod homepage and other resources to know more.

TAGS

In order to get a "goto by name" functionality you can use standard Emacs TAGS support. Haskell has a special program, called hasktags:

cabal install hasktags

In order to generate tags, you can use haskell-mode's M-x haskell-process-generate-tags, or you can manually run hasktags -e. in your project's root.

haskell-mode replaces standard M-. tag-search with it's own, trying to search via ghci first, and only then via standard TAGS mechanism.

Auto-completion via company-ghc

Auto-completion via company-ghc is pretty simple. Put this to your Cask:

(depends-on "company")
(depends-on "company-ghc")

Then put this to your .emacs:

(require 'company)
(add-hook 'after-init-hook 'global-company-mode)
(add-to-list 'company-backends 'company-ghc)

Voila! Beautiful auto-complete from ghc-mod works like a charm.