The Trouble with FRP and Laziness

The Problem

Imagine you are using foldp [0] in a lazy language, building up computations as events occur. Perhaps the value that you are building up is only examined every couple minutes, but is being updated every couple seconds. Bam! Space Leak!

In a lazy language, all of the intermediate would be built up until you actually examine the value. This can cause huge slow downs for no real reason. It can also happen in less extreme cases than described above. These delays have been demonstrated in Arrowized FRP [1] and should be a problem for any FRP framework embedded in a lazy language.

A History of Pain

As they put it in Plugging a Space Leak with an Arrow [2pdf] (a paper on Arrowized FRP): “Despite the heralded advantages of functional languages, perhaps their biggest drawback is their sometimes poor and often unpredictable consumption of space, especially for non-strict (lazy) languages such as Haskell.” And with FRP, laziness is usually more harmful than helpful.

One way to avoid the issues caused by laziness is to just not use a lazy language, which in the case of Elm, was a good solution for many reasons [4]. For more details on how Elm avoids some of the traditional problems of FRP (needless recomputation and eventually global delays), see my thesis (fast link, reliable link). Other strict formulations of FRP are Real-Time FRP [5] and Event-Driven FRP [6]. Both were co-authored by Hudak and quite influential in Elm’s design.

Elm and Laziness

There are definitely some really great benefits to laziness [7], and there’s definitely a case to be made that the benefits outweigh the costs when dealing with FRP.  But for me, searching for space leaks is not worth it in general (but especially with FRP). The part that troubles me most is that it is not readily apparent at the source level what is going to happen. Sometimes that is okay/convenient, and sometimes that is hours down the drain (as I found out while writing Elm’s type inference algorithm!).

That said, one really important part of Elm is its purity. All externally-observable effects are handled by Elm’s runtime system (i.e. cannot appear in Elm source code), so there is no fundamental reason why laziness cannot be added and turned on at the level of modules.

The OCaml method of laziness [8] is also really easy to add. Not as pretty to write, but no surprises with this method.



Comments are closed.