Journal entry for


It’s been a long while since I wrote here! I attended the GHC Contributors Workshop and ZuriHac in the meanwhile and I’ve been working on implementing a Reflex-style FRP from scratch.

The GHC Contributors Workshop was a great event and made me feel more comfortable to dive into the GHC code. ZuriHac as always was lovely and chilled out, and even had a Conal talk to keep the denotative programming spirits up <3.

I met Ken Micklas during ZuriHac who, as it turned out, had been doing the same thing and was able to give me useful tips. He had some interesting ideas about how to improve the FRP interface, for example by avoiding

merge :: Event a -> Event b -> Event (These a b)

You no longer have to wait to know wether an event occurs simultaneously with another, and you can start working with events which have hidden multiple simultaneous occurrences. Only when folding over them would you have to decide what to do with these. He wrote about this idea and others in his “A trilemma in functional reactive programming models” post.

My WIP FRP library status

I now understand in general terms how to implement the graph traversal algorithm for events with a priority queue, and hold to create behaviors. My current implementation isn’t entirely correct though I believe, even though I’ve copied Reflex’ test suite and that passes. So, there is still some work to do.

As a next step I should probably implement a GUI to-do list app to make sure I have enough primitives to make that work and to check if my implementation is correct. It’s looking like Monomer has one as an example so maybe I’ll go with that library.

A simple and concise implementation

I started out with a simple interface to implement many functions with fewer primitives based on occurs and nowToEvent functions:

occurs :: Event a -> Now (Maybe a)
nowToEvent :: Now (Maybe a) -> Event a

For example:

never = nowToEvent (pure Nothing)
coincidence = nowToEvent . runMaybeT . (MaybeT . occurs <=< MaybeT . occurs)

This is easy to implement if you use a pull-based system (polling the list of all events to make sure behaviors are updated), but it will be interesting to see if I can make a similar interface which does the push-based graph traversal optimizations.

I wrote down the implementation of some primitives using occurs and hope to reverse engineer an implementation for them from the efficient one I’m writing.