Breaking the Space-Time Barrier with Haskell: Time-Traveling and Debugging in CodeWorld (A Google Summer of Code Odyssey)
How does one explore the unknown using a dream, ingenuity and human will to conquer the impossible? The following is a journey involving Time Travel, Maths, Space, and of course, Haskell.
This summer, as part of Google Summer of Code, I created debugging tools to be used by students programming in the CodeWorld environment. As a current learner of Haskell and of CodeWorld, I believe tools that help users reason about logic are very useful. I wanted to help users identify breaks in logic, and reason about mathematics and code. The tools I built can decompose a larger, more ambiguous problem (“Help! My programme doesn’t work!”) into a smaller, more precise one (“The starting coordinate for our spacecraft’s trajectory is not correct”).
When a student builds an drawing, animation or game in CodeWorld, my new debugging tools help them deconstruct what the programme does in
- time: by enabling slow-motion, fast-forward and scrolling through the history of the programme.
- position : by enabling the user to zoom in and out and move around to get a different perspective.
- organization: by giving the user a deeper understanding of the properties of parts of their pictures.
This video gives a cursory view of these tools.
Features I created:
I built four different features for debugging. They are useful explicitly and in conjunction with each other.
1. Viewable Properties in Inspect Mode
Last summer, Eric Roberts created the Inspect Button for debugging for CodeWorld. I expanded on this tool by showing the viewable properties and their evaluated arguments.
Eric created an Inspect button that shows the highlighted code to the left and the display of each component (that is tied to the source code) on the coordinate plane. However, the source code does not currently show what the expression evaluated to unless we use the new viewable properties functionality within the Inspect button. This new feature allows a user to see the evaluated expressions for attributes of the picture, which is very helpful in debugging pictures with multiple functions and arguments that work together.
In the above example, we can see that the actual thick polyline expressions are composed of points and thicknesses, and the precise values that give the results shown. We can create a pipeline of expected values vs actual values with this method of debugging.
2. Zooming and Panning
I created buttons that can zoom in, zoom out and reset to the default view this summer. I also created a slider that can zoom in and out, and panning functionality for the drawing canvas. In this example (below), details of a fractal composition are viewable because of these new tools.
In the video, we can see more detail by using the zoom-in and zoom-out buttons, and by panning. This allows us to see smaller patterns within a larger pattern.
3. Time Travel Debugger (History Slider)
Have you ever played a game and not liked the result? Let’s fix that! I’m curious to see what it would like if I won. I want to go back in time to “debug” what would have happened if I had not lost.
Cheating…it’s a feature, not a bug.
The way this works is by having two lists: one that represents the list of past states and one that represents future states. We can then pop off the most recent value from either the stack of past states or future states to travel back or forward in time.
This uses the zipper data structure where the state is a pair of lists (,).
4. Speed Slider
The new speed slider allows you to speed up an animation. Playing through an animation at different speeds allows a user to identify patterns in an animation, as well as inconsistencies in those patterns. These inconsistencies can be broken down as either intentional and useful, or as breaks in logic or bugs.
“Why moments” in Programming (bugs)
In the example below, we have a bouncing ball that has a defined boundary in the code.
import CodeWorldmain = debugSimulationOf initial step pictureinitial = (0, 20)step dt state = bounce (inertia dt state)inertia dt (x, vx) = (x + vx * dt, vx)bounce (x, vx)
| x < -9 = (x, -vx)
| x > 9 = (x, -vx)
| otherwise = (x, vx)picture(x, vx) = translated x 0 (solidCircle 1) & rectangle 20 20
It seems to work just fine initially, but when I speed it up by using speedSlider, we see moments when the ball is stuck. This is a bug.
To find out how and why this happens, I paused CodeWorld when the bug occurred, and then stepped backwards and panned to see where this occurs and why. By panning, I am not limited to the viewing boundary of the ball as dictated by the viewing pane, so I get a different perspective. Here, we see that the ball bounces, but is stuck and bounces again, but that wedges the ball in further. We can even rewind to the point at which the ball was bouncing as expected.
Revealing Illusion in an Animation
This animation shows the journey of a hot-air balloon into Space, whereby the traveler becomes a NASA astronaut. When the window is constrained, it is not apparent how the animation is made. It appears as delightful magic.
By using the new debugging, this magic is deconstructed, like a Noh Theatre act that is unmasked.
Challenges Along the Way
One of the other issues we discovered was that the CodeWorld install script did not work correctly on 32 bit machines. My first pull request made a change to fix this issue. It wasn’t long before I also realized that smaller screens (such as that of my $20 refurbished computer, which runs 32-bit Ubuntu 16.04) didn’t have room for the debug controls I was trying to add. So I had to make another side-trip to add resizing of the programme before I could get started on debugging. This involved CSS and HTML.
In retrospect, these were good ways to get my feet wet with the project.
Next, there were a series of hardware issues I encountered. In all, I wiped two operating systems and installed Ubuntu 18.04 three times in three months on two machines.
In July, I received a Helium Grant. I used the funding to finally get reliable hardware. This was pivotal in completing the project, as I was able to screen-share and pair-programme with my mentors with video conferencing. Without the support of Nadia Eghbal and the great sponsors at heliumgrant.org, my experience would have been a lot more painful.
We have liftoff!
These new tools make debugging a more pleasant experience for the user. They help users to reason better about code and break larger problems into smaller ones. More importantly, they give the user more control, so that their intentions are interpreted more precisely, giving a better feedback loop between the user and the programme.
“Imagination will often carry us to worlds that never were. But without it we go nowhere.” - Carl Sagan
Far away from Earth, the astronaut looked back. Earth was just a pale, blue dot in a sea of stars. I hope you enjoyed this journey through Time and Space with me, and that it has brought you as much joy as writing Haskell has for me this summer.
Last but not least
- If you’d like to learn more about the nuts and bolts, feel free to look at the Pull requests here.
- Thank you also to the previous work by Eric Roberts in Summer of Haskell, and to the organizers of BayHac (an event at which I was able to meet my mentors in person). Thank you for Haskell.org, my host organization, for giving me the opportunity to promote and use Haskell this summer.
- Finally, thank you to my two mentors, Chris Smith and Gabriel Gonzalez, for your guidance and patience, and for a great Summer.