2019-04-07
One of the downsides of developing web applications in Haskell is the long recompilation cycle. While working on code, it is convenient to have an editor open in one window and a browser open in another. When making changes to your Haskell code, it is nice to be able to immediately flip to your browser and interact with the updated web application.
However, long compile times for Haskell prevent this from working smoothly. Running stack build && stack exec mywebapp
every time you make a change to your Haskell code is annoying. It takes time for stack build
to finish. It also doesn't happen automatically on file change.
ghcid
can be used to make this process much quicker and smoother.
ghcid
ghcid
is used to quickly reload your Haskell code every time it changes. It loads your Haskell project in a GHCi session and uses the GHC API to recompile your source code on every file change.
Normally, ghcid
is used like the following (for a stack
project):
This runs stack ghci
to load your code in GHCi. Then, on each file change, ghcid
automatically runs the GHCi command :reload
to recompile and reload all your Haskell modules. If there is a compilation error, it is reported by ghcid
.
Running :reload
within GHCi is very fast, so using ghcid
for development is quite an improvement over manually re-running stack build
.
However, the above command doesn't automatically run your web application if compilation succeeds.
--test
Flag
Despite its name, the --test
flag can be used for running your web application whenever compilation succeeds.
The --test
flag takes any valid GHCi expression as an argument. There are two common expressions that are used.
Any valid Haskell expression. A function with the type
IO ()
that runs your web application is usually used. For instance, if you have a functiondefaultMain :: IO ()
in your codebase, you can run that function whenever your haskell code compiles correctly with the following command:Any valid GHCi command. For instance, the GHCi command
:main
runs themain :: IO ()
function defined in your Haskell project. You can use the following command to do this:
ghcid
will run the expression you have passed to --test
if compilation succeeds. When ghcid
detects a change in one of your Haskell files, it will kill the expression passed to --test
, recompile the code, then re-run the expression.
This is perfect for use with web applications. As long as your code compiles correctly, your web application will always be running. Recompilation is very quick, so you should almost always be able to access it from the browser.
Running Despite GHC Warnings
By default, GHCi doesn't re-run the expression passed to --test
if there are GHC compilation warnings. This is sometimes inconvenient. In order to get around this, you can use the --warnings
flag. This forces ghcid
to run the expression even if there are still GHC warnings.
Here is an example of using the --warnings
flag:
Running Tests
Normally, the --test
flag is used to actually run tests as long as compilation has succeeded.
Here's an example of how you can do this with stack
:
The stack ghci --test --main-is mypackage:mypackage-test
command runs GHCi using stack
in the Haskell package called mypackage
. This assumes you have a test suite defined in your .cabal
file called mypackage-test
.
The full ghcid
command will re-run the main :: IO ()
function defined in the mypackage-test
test suite whenever there is a change in any of your Haskell files.
Related Work
There are a couple other often-used methods for re-building and running a web application on file change.
If you're using stack
, the easiest method is probably as follows:
This assumes you have an executable defined in your .cabal
called backend
.
This is easy, but stack build --fast
is normally slower than reloading in GHCi.
Conclusion
ghcid
is a nice command for a fast feedback loop when doing Haskell development. It allows for (mostly) stress-free development of web applications in Haskell.
tags: haskell