A Vim + Haskell Workflow

This post is out of date and has been updated for modern workflow.This page is left for posterity.


Hoogle is a Haskell type search engine which can be used online or installed locally.

$ cabal install hoogle

Hoogle can be used from the command line as well from GHCi by adding the following lines to your .ghc/ghci.conf

:def hoogle \s -> return $ ":! hoogle --count=15 \"" ++ s ++ "\""

For instance if we forgot the name of the function associated with (a -> m b) -> [a] -> m b) we could ask hoogle for functions matching. Indeed we see that mapM_ is in the list.


Syntastic is a syntax checking plugin for a variety of languages, including Haskell. It integrates with a either ghcmod or hdevtools to provide type errors inline.

To toggle between active or passive type checking we can enable the following key bindings:

map <silent> <Leader>e :Errors<CR>
map <Leader>s :SyntasticToggleMode<CR>

To always show the errors list when editing we can set the following flag:

let g:syntastic_auto_loc_list=1


ghcmod is a command line tool to analyze Haskell source. It integrates with syntastic to provide integration with GHCi.

$ cabal install ghc-mod

Pressing ( tu ) can then be used to update the background GHC process with the file (from disk). This updates the tagbar and allows you to fill in any missing types by highlighting the toplevel function definition and pressing ( tw ) to infer the corresponding type signature of the highlighted toplevel function and add it to the line above. As usual the signature is the inferred by GHC is guaranteed to be the most general type, not necessarily the most usefull one.

" Reload
map <silent> tu :call GHC_BrowseAll()<CR>
" Type Lookup
map <silent> tw :call GHC_ShowType(1)<CR>


$ cabal install hdevtools

To enable, first install syntastic and then add the following to your .vimrc.

au FileType haskell nnoremap <buffer> <F1> :HdevtoolsType<CR>
au FileType haskell nnoremap <buffer> <silent> <F2> :HdevtoolsClear<CR>
au FileType haskell nnoremap <buffer> <silent> <F3> :HdevtoolsInfo<CR>

Pressing ( F1 ) in Normal mode shows the type under the cursor. Pressing it repeatedly expands the selection to the parent expression up to the toplevel function definition.

Pressing ( F3 ) in Normal mode will show further information about type classes, data constructors or functions, including the source location of definition.


Hlint is a source linter for Haskell which can provide a selection of hints for helping improve your code stylistic and functionally. For instance if you happen to implement one of many Prelude functions it can suggest that you use the builtin instead.

$ cabal install hlint


Tagbar is a plugin for browsing the toplevel definitions in a file. It integrates with ghcmod to generate the tags from

The tags are updated upon write, to open the tagbar bind :TagbarToggle to your key of choice;

nmap <leader>= :TagbarToggle<CR>
let g:tagbar_autofocus = 1


vim-slime is a plugin to allow one-way communication between vim and a tmux shell, allowing you to interactively send code to ghci. To integrate with tmux add the following to your .vimrc, then start a separate terminal process running tmux and ghci.

let g:slime_target = "tmux"
let g:slime_paste_file = tempname()

In visual mode you now press ( Ctrl-C Ctrl-C ) to send the current block to the tmux session. Upon initial load it will prompt you for the tmux session name and vim panel.


Pointfree is a syntax rewriter to eliminate unneccesary free variables from an expression.

$ cabal install pointfree

Then add the following to your .vimrc.

autocmd BufEnter *.hs set formatprg=pointfree

In visual mode you can now press gq to convert a expression to it’s pointfree form. Though quite often the resulting form is more obfuscated than the original.