FRP Rant

FRP is eating my life away!

Here’s the thing. I love FRP. I love the concept, so much so that I am having a very hard time writing anything without it. I want to make games, servers, UI libraries, with it. I want to make things! But I am stuck in research mode, where I am still looking for an FRP library in which to make these things.

Why am I stuck searching? Because I don’t like Reactive. It’s just difficult to use, and difficult to make easy to use. The semantics are unclean (not all of them, just some essential pieces like Event, integral, and stepper), it’s abstracted so high that it takes me forever just to figure out that it doesn’t quite make sense in this little corner, and it’s all coupled together so I can’t figure out how to fix it without rewriting the whole damn thing. And, according to Conal, it still has the dreaded spacetime leak (which can fortunately but rather annoyingly be circumvented as I described almost a year ago).

What am I searching for? Well, whatever ends up being beautiful and easy to use. I’ve got a bunch of leads varying in ease of use and possibility of implementation. The ones which are obviously implementable are basically Reactive. However, my dream would be a pull-implementation of Fregl (the source code now lives here), because Fregl was great! I actually made stuff with it! In particular, everything to do with Events just rolled off my fingertips. The waiter semantics and the monad instance were the power tools analogous to the axiom of choice, where previously careful, meticulous reasoning becomes tactless and obvious under the great sledgehammer. I want a sledgehammer; that’s why I program in a Turing-complete language rather than a total one.

Fregl is no beauty on the inside, however, and this impaired the efficiency of the programs implemented in it. The GHC optimizer is dumbstruck trying to optimize any code written using the library; because of the nature of the GHC garbage collector and weak references, far more work ended up being done than necessary. Basically it was a completely push implementation, and everything in Haskell is optimized for pull implementations, so performance was terrible.

What I want most for christmas is a Haskellian Fregl implementation.


6 thoughts on “FRP Rant

  1. Funny that you’d feel that way, because the semantics of Event are one of the things I like quite a bit about Conal’s Reactive library. What feels unclean about it to you?

    I’m also taking a bit of a look at your Fregl library. I’ve got a backlog of small games that I’d like to port over to an frp system at some point, whether that be Fregl or a new release of Reactive.

  2. The semantics of Event certainly seem nice at first glance. But once I got down and dirty with them a number of warts popped up:

    (1) Event as a “list of monotone futures” assumes that time begins at some point, rather than extending to negative infinity as we’d like it to. This is also my problem with stepper and integral. And they can not be trivially extended to account for this, it requires a fair amount of machinery.

    (2) Try to describe “joinE” in two or fewer sentences in terms of its semantics.

    (3) It seems to be devoid of any nice algebraic properties between its operations other than the ones enforced by its type classes. Irritatingly, it looks like a monad but fails associativity.

    So, although its domain looks simple, it is algebraically quite involved. Nowadays I’m a proponent of replacing Event with:

    Waiter a = Time -> Future a

    (intuitively, “delays for an interval before yielding a value”) which looks like it could be a more complex domain, but is algebraically very well-behaved and easy to reason about.

    But we FRP folks have nary such luxury to choose this, as it is still a challenge to get something efficient and expressive as it is.

  3. Now it’s quite possible that I’m just being dense, but I still have some questions and comments:
    (1) What’s the use case for needing your events to extend back infinitely? It seems fairly natural to me to assume that the world is “created” at time zero.
    (2) What do you mean by a description of the semantics? Doesn’t joinE just merge together event streams that are created over time, only considering events that take place after the new event stream was created.
    (3) Wait, are you saying that joinE and return for Event don’t actually follow the monad laws?

  4. (1) No use case. Conal is a big fan of semantic purity, and he taught me to be too. “Time” in FRP is actual time: not local time, not time in its own special universe, but actual time. And reactive currently breaks that. But there are probably reasonable use cases, involving a switcher far down in a program where you don’t want to have to chomp through all the earlier states. But that’s just a hunch.

    (2) Well, basically what you described. Unfortunately your intuition about joinE is incorrect; if there are occurrences of an “inner” event before the corresponding “outer” event, it doesn’t discard them, but rather smashes them all up, pretending that they actually occurred at the occurrence of the outer one. I’m not sure why this is; perhaps it is to satisfy the right unit law: e >>= return = e, so the events at negative infinity are moved up to their corresponding occurrences in e. But it is for naught, because:

    (3) Yes, Event is not a monad, despite the instance declaration currently in the library (that is a bug): joinE . joinE /= joinE . fmap joinE (I wish I could come up with a snappy counterexample, but… as we are seeing, joinE is pretty complicated—but quickcheck finds one :-). Using do notation on it is a sin.

  5. I don’t see why Event is not a monad. In my own implementation of Reactive (quickly becoming something else entirely, though), I have no such problem with either QuickCheck or SmallCheck (running up to around 5 million tests with SmallCheck so far!), and my Event does have the semantics described in Conal’s paper. Perhaps it is simply a bug in Conal’s implementation.

  6. according to Conal, it still has the dreaded spacetime leak

    I’m not sure what you’re referring to. Do you remember more specifically what you heard me say?

    And yeah, to me too, Event doesn’t have as simple & inevitable a feel as the other Reactive types. And monadic associativity trips over the simultaneity/reordering issue.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s