You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is where I'm going to collect work and thoughts on the work for multi-node or cloud FRP. Below are a few "journal entries" that helped inform this work:
While my intention was to continue my research in the direction of prototype 4, I have been tantilized by the problem of how to extend the FRP abstraction to "the backend". In other words, apps with data stored somewhere "in the cloud".
To extend the simple counter application, simply make it a multi-computer counter, that aggregates all the counts to a button across all computers. As is often the case, once put in those words, the problem doesn't seem so hard. One approach is to have a "lift" operator that would allow us to transform a button's Event () into a MultiWindow [Event ()], upon which we could do various operations, such as merging all the event streams and counting the occurrences.
Or consider the much more complicated problem of a realtime multiplayer game like agar.io or slither.io. As I've learned the hard way, you cannot simply send the x- and y- positions of each player to each other player and update position accordingly. You must instead anticipate where each player is going to be based on their current position and velocity and project them there until you receive the next word on their position and velocity and then you can subtly nudge that player to where they actually are, and are headed.
How could I model such an arrangement without mentioning low level details such as sockets? I think the concept of perspective is relevant here. From a single player's perspective the x- and y- position, and velocity are all FRP Behaviors, defined at all points in time because their computation happens to quickly. However, those values for other players must be modeled as FRP Events, because we only get glimpses of them at discrete points in time. However we must on the screen display other player's positions as continuous behaviors so we must use the complicated logic to predict and update our perception of the other players to construct a Behavior for them out of our Event of them.
My thinking above is lead by my intuition of FRP, types, and what the abstractions allow. However I feel a desperate need to have a proper medium to help shape my thoughts to only go in proper ways. Potentially Haskell or PureScript could be such a medium. I am considering watching/reading Conal's advice on denotative design again. Maybe I need to come up with mathematical objects to model what I mean by a "multi-widow" or "multi-user" application or event stream. These are the question on my mind when I pick up this stream of thoughts...
Conal Elliot is the man. My god, I'm so excited to be able to grok a part of what he has to say! Yesterday I re-watched Denotational Design: from meanings to programs and was re-blown away. It's funny: whenever I recommend Conal to friends I have to caveat it with, "I need to watch his stuff multiple times before I get it." This was true of this talk as well.
So here's the denotational methodology as far as I can tell:
Come up with abstract "uses" you want the library to be able to accomplish
Come up with a sketch of an API
Write down the relevant types
Write down the μ (mu, meaning) of those types as mathematical objects (likely, functions)
Write down the μ of each API function
See if any of your types fit existing type classes (monoid, functor, applicative, monad, comonad, etc)
So I tried to follow it in the shower yesterday and I think it went pretty well!
I had a few key insights:
There should be a way to turn Events a on one computer to something like Event (Event User a), where the outer event represents this computer's perception of the event happening and the inner event represents when the event actually happened.
Another key insight: the default behavior of FRP applications should be to persist data for forever unless programmed otherwise. The resetting of app's data on page reload is a wacky accident!
I was having trouble coming up with the semantics for a User... We want a way to authenticate someone and then we need a unique key to identify them. In terms of access for reading and writing, I imagine that logic should live (like everything else) with the relevant pieces of state.
much better if we say that a user merely is a pair of keys: user :: (public key, private key)
when we want to construct an stream that's tied with a user, we must merely sign :: User -> Stream a -> UserStream a the stream.
setting any user details (name, email address, photo) are merely signing data that claims those things for yourself
Reading seems less natural, but the idea is that when we want data from another computer, we need to lift a Stream to a Stream (Stream) of some sort (to account for when we get the stream as well as when it happens), and in this lifting we can optionally supply a User parameter. Pieces of state themselves will decide if and how they will allow themselves to be lifted, and to which users.
At SPLASH, I was really excited to find ScalaLoci which was about placement types of reactive programming in Scala. Very related to this work. I need to peruse their Related Work section for more details.
I found a way to make sense of reading (which I was having trouble with above). All data is "public" but by default anything you do is encrypted so only you can read it. You can also encrypt it with others' private keys if you want them to have access. We'd probably want to make who can have access be a Behavior so that we can change this if we want to revoke access.
Eventually, the next step here will be implementing this, probably in Haskell
Activity
stevekrouse commentedon Oct 26, 2018
Cloud (or multi-node) FRP (originally here)
While my intention was to continue my research in the direction of prototype 4, I have been tantilized by the problem of how to extend the FRP abstraction to "the backend". In other words, apps with data stored somewhere "in the cloud".
To extend the simple counter application, simply make it a multi-computer counter, that aggregates all the counts to a button across all computers. As is often the case, once put in those words, the problem doesn't seem so hard. One approach is to have a "lift" operator that would allow us to transform a button's
Event ()into aMultiWindow [Event ()], upon which we could do various operations, such as merging all the event streams and counting the occurrences.Or consider the much more complicated problem of a realtime multiplayer game like agar.io or slither.io. As I've learned the hard way, you cannot simply send the x- and y- positions of each player to each other player and update position accordingly. You must instead anticipate where each player is going to be based on their current position and velocity and project them there until you receive the next word on their position and velocity and then you can subtly nudge that player to where they actually are, and are headed.
How could I model such an arrangement without mentioning low level details such as sockets? I think the concept of perspective is relevant here. From a single player's perspective the x- and y- position, and velocity are all FRP Behaviors, defined at all points in time because their computation happens to quickly. However, those values for other players must be modeled as FRP Events, because we only get glimpses of them at discrete points in time. However we must on the screen display other player's positions as continuous behaviors so we must use the complicated logic to predict and update our perception of the other players to construct a Behavior for them out of our Event of them.
My thinking above is lead by my intuition of FRP, types, and what the abstractions allow. However I feel a desperate need to have a proper medium to help shape my thoughts to only go in proper ways. Potentially Haskell or PureScript could be such a medium. I am considering watching/reading Conal's advice on denotative design again. Maybe I need to come up with mathematical objects to model what I mean by a "multi-widow" or "multi-user" application or event stream. These are the question on my mind when I pick up this stream of thoughts...
stevekrouse commentedon Oct 26, 2018
Shower denotational design (originally here)
Conal Elliot is the man. My god, I'm so excited to be able to grok a part of what he has to say! Yesterday I re-watched Denotational Design: from meanings to programs and was re-blown away. It's funny: whenever I recommend Conal to friends I have to caveat it with, "I need to watch his stuff multiple times before I get it." This was true of this talk as well.
So here's the denotational methodology as far as I can tell:
So I tried to follow it in the shower yesterday and I think it went pretty well!
I had a few key insights:
Events aon one computer to something likeEvent (Event User a), where the outer event represents this computer's perception of the event happening and the inner event represents when the event actually happened.stevekrouse commentedon Oct 26, 2018
Denotation of users (shower 8/25/18)
user :: (public key, private key)sign :: User -> Stream a -> UserStream athe stream.liftaStreamto aStream (Stream)of some sort (to account for when we get the stream as well as when it happens), and in this lifting we can optionally supply aUserparameter. Pieces of state themselves will decide if and how they will allow themselves to be lifted, and to which users.## Notes 10/25-26/18
## Notes 10/31/18-11/1/18
stevekrouse commentedon Nov 14, 2018
Behaviorso that we can change this if we want to revoke access.## Mid Nov 2018 Many Thoughts
tswast commentedon Jan 28, 2019
Apache Beam shares some ideas with FRP, mainly that you build a graph based on data dependencies (denotational-style).
stevekrouse commentedon Feb 12, 2019
Thanks @tswast!