I covered the requirements of the smart date picker in my last post, which ended with a data flow diagram. Today I aim to translate that conceptual view to primitives within Sodium, a functional reactive programming (FRP) library supported on multiple languages. The only types in Sodium are Cells and Streams. I will attempt to provide a brief explanation.
In essence, a Cell is a value that changes over time. Specifically, it is a generic type Cell
The reason Sodium calls it a Cell is because it is conceptually similar to a cell in a spreadsheet. Individual cells in a spreadsheet contain a value but they are not constant. They can change over time, especially in response to changes in other parts of the workbook. Let me illustrate that with Excel’s personal budget template:
This is a simple template where you can put in your income, expenses, and savings. It then shows you a summary for the month with a chart and totals. Let’s trace the precedents and dependents of the Total Monthly Income cell:
It is straightforward. Total Monthly Income is a function that sums up all income sources, and its result is in turn used by the Cash Balance cell to determine how much extra you have left in your bank account. It is also used by the chart data to construct a delicious pie chart. See what happend when I add a new line of income:
When I do that, the Total Monthly Income, Cash Balance, and pie chart are all updated simultaneously. There is no need to manually recalculate because Excel knows the dependency between the cells and so knows the correct order to update them.
This brings us to the concept of Streams.
I find it easiest to think of a Stream as an event handler/listener. I’m sure there are differences between them but I view it as a functional event handler that plugs in to the rest of the Sodium framework. Realistically, one would provide a function that executes when the specified stream fires. This is no different from writing an event handler method but with the added ability to work with Cells and other Sodium primitive operations.
I believe it is called a Stream like the body of water that continuously meanders across the earth. Similarly, a Stream
Smart Date Picker
So what are the Cells and Streams of the smart date picker I am trying to implement? I would look at the data flow diagram I created last week and ponder upon what values are being held and what sources of events are present.
At a theoretical level, I think they would be:
- Data Availability Dates
- Period Type (whether it is Weeks, Months, or Quarters)
- Date Range (the selected start and end date for the report)
- Select Weeks
- Select Months
- Select Quarters
- Select Start Date
- Select End Date
You might have noticed a few omissions in my cells and streams. I did not put Start Date and End Date as a Cell because ultimately the date pickers are only sources of events. Whatever the user picks are merely a suggestion. The date bumping logic still needs to decide if it is valid, which then updates the date picker and the Date Range cell with the final outcome.
Changes in Data Availability Dates might resemble a Stream, but I did not model it as one because the changes are initiated from outside the application, i.e. database updates. There is a strict requirement of referential transparency in Sodium, which means:
- you must not perform any I/O;
- you must not throw any exceptions unless they are caught and handled within the function;
- you must not read the value of any external variable if its value can change, but constants are allowed and encouraged;
- you must not modify any externally visible state;
- you must not keep any state between invocations of the function;
(The above list is excerpted from the book Functional Reactive Programming)
Because checking the Data Availability Dates would require I/O (query the DB), it needs to be done outside of FRP. I know you’re asking: How would one integrate FRP into an application that needs to do I/O and throw exceptions? That is a question I have often asked myself as I read the book but the authors insist on keeping those details under wraps until halfway through the book in Chapter 8. This is done under the guise of keeping the reader’s mind ‘pure’ in FRP-Land before the messy reality of integration hits. I have not formed an opinion regarding this approach yet as I’m still reading the book, but will return to this later.
My list of cells and streams for the smart date picker might change as I start implementing it and discover better ways of looking at the problem. Next week: I will write about some of the operational primitives I may need in Sodium to transform cells and streams from one form to another.
This is part of an ongoing series where I review the book Functional Reactive Programming by Stephen Blackheath and Anthony Jones. Kindly note that anything I write here may be incorrect and not indicative of the author’s intent. After all, making mistakes is the mother of learning and this book review is meant to be a truthful reflection of my own experiences grasping a new concept. The review copy I received was version 11 in their Manning’s Early Access Program, so the book’s contents may differ at the time of publication.