So, I’ve not done any blogging since the ill-fated Midwinter Polyphasic Sleep Experiment. I have a backlog of articles I want to write, but most of those involve some significant investment of time and effort. So you get this instead…
It’s a fairly complicated application that needs to manage literate Markdown documents describing statistical models, data sets for analysis and a bunch of other stuff. The first thing I looked at was a tool for building statistical models based on dynamical systems represented as systems of ordinary or stochastic differential equations. This tool allows you to give algebraic representations of ODEs or SDEs, which are then rendered as MathML (for prettiness and familiarity), you can do simulations of the systems and visualise the results, you can specify data sets that correspond to observations of system variables, you can set up prior distributions for system parameters, and you can then get some code (in a proprietary Haskell-like language specialised for statistical modelling) that can be used to drive MCMC inference for the parameter values.
All that stuff happens on the client side, except for the listing of the available data sets and the rendering of the model into code. This means that you need client side code for expression parsing, analysis of coupled systems of ODEs and SDEs (to turn them into a canonical form that you can simulate from), numerical integration of ODEs and SDEs, graphing, and a framework to tie it all together. That’s a lot of client side code!
My original inclination was to use Fay, both because it’s fun and because the server side is all Haskell, but I was a little anxious that it might be too much of a moving target. There’s a lot of work being done at the moment to make Fay better and more robust, which is great, but I don’t have the resources to contribute to that as well as trying to write something fairly substantial using Fay, with the expectation that my code will rot quite quickly as Fay development proceeds.
Angular it is then
Directives: you can “extend” the HTML language by defining new attributes, classes or element types. These can have HTML templates associated with them, as well as bits of code that can run at different points during Angular’s “HTML compilation” process. Directives are flexible enough that you can (with a little patience) do more or less anything.
A couple of examples of how these things really help: first, the equation editing input elements are now
<equation> tags, where
equation is an Angular directive that encapsulates a normal input element (active when the element has the focus), error reporting elements and a MathML rendering of the equation content. All of the equation parsing and event handling associated with the interactions between these three elements is encapsulated within the
equation directive. The second example is a
<scrubbable> element directive. This is a new kind of input element that shows a MathML rendered equation for a parameter (e.g. ). Clicking on the element allows the user to edit it, control-clicking resets the original value, and click-dragging continuously (or discretely, if an attribute on the element is set appropriately) varies the value of the parameter. Using data binding, the changing value of the “scrubbed” parameter can be directly communicated to other code: in the dynamical systems simulation page, this is used to trigger re-running of simulations and re-rendering of plots.
Furthermore, the integration with Yesod is really great. Michael Snoyman wrote a little
yesod-angular module as part of his Yesod client-side experimentation, and it turns out to be really rather nice. I’ve hacked my version around quite a bit to help with managing Angular’s dependency injection mechanism, but that’s about all I’ve had to change. Perhaps the nicest feature is the idea of “commands”. Here, in my Yesod handler, in the bit of code that runs in the
Angular monad, I can define commands as, for example
TreeItem is some type with a
ToJSON instance so that it can be converted to JSON for transmission back to the client. On the client side, you can call this command as
All the data marshalling is handled by
FromJSON instances. On the server side, the code is in Yesod’s
Handler monad, so you can do all the kinds of things you might normally do in response to client requests, and everything is nicely encapsulated. It’s a really good system.
Writing a Haskell web app? Dithering about the client side? If you can take the uncertainty of programming against a dynamic and developing interface, go with Fay. A lot of people are investing a lot of time in it, it’s already really good, and it’s going to be great. Can’t stand the uncertainty? Look at
Yesod.Angular. It’s in Michael’s
To get an idea of the issue here, think about the differential equation . If you want to integrate this numerically, you need to break it into the two equations , , where we introduce a new function for the first derivative of . This is the simplest case. You also get cases where you end up with a matrix equation for the first derivatives. And you need to deal with SDEs. It’s not very hard to do on paper, but writing code to do it systematically in all cases is more challenging.↩