When developing software the length of your feedback cycle can significantly impact development processes and productivity. Developers have seen how things like incremental compilation in IDEs can essentially eliminate the need to fix syntax errors with an iterative code -> compile workflow. The overall lesson here is that improvements to a process can yield exponential increases in productivity because they can enable exploratory patterns of work that couldn’t even be conceived of before.

Haskell with laziness, purity, and sophisticated static type systems generally doesn’t fare as well in this department. The feedback loop between Haskell code and your end application will necessarily be slowed down because we’ve made a deliberate choice to do a lot in the compilation phase. But for web applications this doesn’t have to apply to everything. Specifically, with Heist, HTML markup doesn’t need to go through the Haskell compilation phase, so we can speed up the feedback loop of writing HTML, deploying it in your running app, and seeing the output.

For quite some time, Snap has had two mechanisms for doing reloading: dynamic code recompiling, and on-the-fly application reloading. Dynamic code recompilation lets you make code changes and test them quickly, but once your application gets beyond a certain size it becomes unusable. On-the-fly reloading (via the /admin/reload URL) lets you quickly test changes to markup and filesystem resources, but it too becomes unusable if your application has a complicated and time consuming initialization.

Snap 0.12 addressed these shortcomings with the ability to reload individual snaplets. The release also included the addition of a reloader for the Heist snaplet.

We’ve created a screencast that shows how we use this functionality to solve our reload slowness. We then combine that with other tools to shorten the feedback loop even more.

For reference, here is the fswatch command we use when running on MacOS:

fswatch snaplets/heist "curl http://localhost:8000/heist/heistReload"

If you’re running Linux, you need to use inotifywait. Its interface is a little different, which makes it more complicated to use. Here’s the script that I ended up with.

#!/bin/sh

while true; do
  find snaplets -print0 | xargs -0 \
    inotifywait -e create -e modify -e delete
  rc=$?
  if [[ $rc == 130 ]] ; then
    exit 0
  fi
  curl http://localhost:8000/heist/heistReload
  echo
  echo Restarting inotifywait
done