marc walter

Debugging in Elm

2021-02-12

Programming in Elm is pretty awesome, but sometimes you still have to do some debugging.
Like most languages, the language tooling can help you.

Debug.log

Elm has the Debug.log function that allows you to print any Elm data structure to the browser console. This works well for small structures, but it only prints it as one line and that is hard to read if it contains more data.
Fortunately, the Elm community member kraklin has created an Elm debug helper browser extension for that, so your code printed with Debug.log will become an expandable tree and might look like this:

Example output

Image source: Nicer Debug.log console output by @kraklin

Even if you can't or don't want to install it as an extension, you can still use it directly as an npm package or by adding a minimal snippet to your HTML in any browser.

<script src="https://unpkg.com/elm-debug-transformer@latest/dist/elm-console-debug.js"></script>
<script>ElmConsoleDebug.register()</script>

Time-Traveling Debugger (in elm/browser)

debugger button Debugging in Elm is quite nice with the time-traveling debugger.

You don't need to install a browser extension like the react developer tools or something like that, you just need to compile the code with the debug flag, e.g. elm make --debug src/Main.elm.

Then you will see the debugger in the bottom right corner of your page, can see the internal state and all the commands that were executed, and can go forward and backward in time to reproduce for instance a bug.

You can for instance watch this youtube video when this feature was introduced in 2016 and also read the announcement post "The perfect bug report".

Using the debugger with many subscriptions

I understand that the time traveling debugger might seem to not be very usable when you have many subscriptions (e.g. 60fps for an animation or game), but when paired with one of these approaches, I think one can still use the debugger to find bugs or trace the behavior.

  1. Manually open the debugger and use the slider to go back in time - subscriptions and other messages are paused until manually pressing play.
  2. Add a button to stop subscriptions (many games will anyway need a “pause” button)
  3. Add a port to stop subscriptions, so you can use app.ports.pause.send(true); in the browser console and then pass false to enable it again.
  4. Change the update function to disable the subscriptions if an unexpected state has happened (I like this one best during development)

This is a small example that shows the options (and the simple output of the elm debug helper).

In case the iframe does not load, either open it in another page, or download the example, or check it out on https://ellie-app.com/fVVrMgYnwTGa1.

Alternative time-traveling debuggers

By jinjor (Yosuke Torii)

See released Elm 0.19 package savvard/elm-time-travel.

This is a replacement for the elm/browser package for rendering to the DOM.
It features also filtering of specific command types, which is also useful when many commands are generated (e.g. in a game).

By opvasger (Asger Nielsen)

See this discourse post. Which links following into the (archived) github repo, you will find e.g. this meta-issue for a ton of great information that I have on my reading list for a long time…


Note: I wanted to persist some information from a post on discourse about debugging in Elm