At dinner last night we touched on UI libraries based on Functional Reactive Programming (FRP).
As an aside: for the longest time it used to annoy me that FRP seemed to have a fuzzy definition and meant different things to different people.
I'd been exposed to "classic FRP" as espoused by Paul Hudak & Conal Elliot (see eg "Haskell School of Expression" , FRAN, or
http://conal.net/blog/posts/why-classic-frp-does-not-fit-interactive-behavior), which emphasized "Behaviors" as functions from time to values.
But that Behavior stuff was an apparent evolutionary dead end. Another community took the term FRP to mean "Signal-oriented programming", a looser and more feasible idea, and I think this branch has won.
So I now use FRP as a term describing Signal-oriented programming, a stream-like series of values that vary over time, typically originating at a mutable cell.
The main distinction of Signals vs Streams is that the consumer or handler of a Signal doesn't control when the next value is pushed out. Whereas, with Streams, the consumer can pull the next value at their leisure; a good fit for reading bytes from a file, but less good for mouse clicks.
In this FRP UIs, we model the data that powers the UI as a Signal; a Signal[List[Customer]] for example in Scala syntax. We then transform these data signals into Signal[UIComponent] and the framework provides an efficient way of updating the screen/DOM/canvas etc from such signals.
However, there's a classic problem with this approach, which I mentioned last night, but thought I should clarify..
Imagine we have a screen showing a table of 100 customers as rows. One single customer changes their boolean subscription status. Since the List[Customer] data has changed, that signal pushes out a new update. If we handle this naively, we will re-render the entire table despite the change being far more localised to a single checkbox.
Laminar, a leading Scala FRP UI framework, has a good explanation of the problem and a good solution (probably evolved from earlier frameworks; Laminar is just where I joined the story):
https://laminar.dev/documentation#performant-children-rendering--splitConceptually, a signal over a collection is split into many signals over the parts, and only those parts that have actually changed generate updated events.
I expect something like this is essential for any FRP UI framework that succeeds industrially at scale.
@Peter: you mentioned "Sodium" [
https://github.com/SodiumFRP/sodium]. I had a look at the Manning book and couldn't locate a specific analog to Laminar's split. And Sodium's website is down atm :(
-Ben