Skip to content

Multi-node / Cloud FRP #85

Open
Open

Description

@stevekrouse

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:

Activity

  1. stevekrouse commented on Oct 26, 2018

    @stevekrouse
    CollaboratorAuthor

    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 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...

  2. stevekrouse commented on Oct 26, 2018

    @stevekrouse
    CollaboratorAuthor

    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:

    1. Come up with abstract "uses" you want the library to be able to accomplish
    2. Come up with a sketch of an API
    3. Write down the relevant types
    4. Write down the μ (mu, meaning) of those types as mathematical objects (likely, functions)
    5. Write down the μ of each API function
    6. 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!

    img_20181023_185153

    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.
  3. stevekrouse commented on Oct 26, 2018

    @stevekrouse
    CollaboratorAuthor

    Denotation of users (shower 8/25/18)

    • creating a user is a very imperative notion.
    • 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.

    img_20181025_184131

  4. stevekrouse commented on Nov 14, 2018

    @stevekrouse
    CollaboratorAuthor
    • 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
  5. added a commit that references this issue on Nov 14, 2018
  6. tswast commented on Jan 28, 2019

    @tswast

    Apache Beam shares some ideas with FRP, mainly that you build a graph based on data dependencies (denotational-style).

  7. stevekrouse commented on Feb 12, 2019

    @stevekrouse
    CollaboratorAuthor

    Thanks @tswast!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions