ghcid: must-have tool for Haskell developer
Usually when programming in Haskell, I rely a lot on compiler. It catches
many errors that are caused by inattention, which occur especially often
when refactoring large portions of code. In some sense famous "it compiles,
therefore it works" mantra is true (assuming that you don't have logical
errors). The problem with this approach for me for a long time was that
I ran compiler manually and then read its output. The output was usually
quite long, and I had to read it and start fixing errors from the top, otherwise
I might end up fixing wrong error. It was a tedious routine, even with a help of
bash scripts and file watchers, but thanks to ghcid
1, I am free from it now.
ghcid
can be interpreted as "GHCi-daemon" or "GHC-with-a-bit-of-IDE". It is a
rather small program which starts GHCi, imports your modules there, executes
some Haskell expression in it, watches your source code and fires :reload
and
reevaluates expression once something is changed. It also captures warnings and
errors produced by compiler, and presents them in a way where you can see the
topmost ones right away, without scrolling the whole output to the top. Last but
not least is that it plays really well with stack
, which is de-facto
a standard tool for building and testing Haskell projects nowadays.
How to use it
First, install it:
$ stack install ghcid
Now you can run it with stack exec
. At this point I usually make a bash script
and tune ghcid
the way I need it for my application.
First of all we need to setup is the expression which will be evaluated in GHCi
session. You can do it with -T
flag. If you want to run something different
than GHCi, you can pass the command to -c
flag. By default ghcid
detects
whether you're using stack
or just plain cabal
and runs either stack repl
or cabal repl
respectively.
Another thing I usually turn on for my projects are -Wall -Werror
compiler
flags. It catches such errors as redundant imports, orphan instances, unused
variables and helps you keep the codebase clean. However, when working in a REPL
mode, you'd usually concentrate on the big picture and leave those warnings to
be fixed later, e.g. before committing code. When -W
option is passed ghcid
doesn't take those errors into account and evaluate given expression anyway.
By default ghcid
watches only for those source files that were loaded by GHCi.
Sometimes it might not be enough. For example, now I'm working on application
which has Hamlet templates in templates
directory and I'd like to reload the
app each time some of templates is changed. Luckily it's easy to make ghcid
do
so with --restart=<PATH>
or --reload=<PATH>
options. The first one will
rebuild the project and restart the whole GHCi process while the second one will
just fire :reload
command to existing GHCi process whenever any of the files
and directories in <PATH>
is changed.
Issues and ways to improve
One thing that would be nice to have is errors highlighting. Sure they are
printed in bold font now, but having line numbers and error messages in
different colors would help even more. Right now it is possible to achieve by
using ghcid
inside terminal emulator in Neovim or Emacs.
Currently highlighting is the only thing that comes to my mind. Overall ghcid
is a great development tool, and even minor bugs (usually caused by GHCi) can't
really outweigh its advantages. Definitely must-have.