Skip to content

Commit

Permalink
## It's been too long!
Browse files Browse the repository at this point in the history
* TOC
{: toc }

I've been busy with my part-time jobs! I spent the first two days this week working for Dark, and the rest of the week working for my new gig at First Round Capital. I found two other gigs (another one at Dark and one at the Jain Family Institute), but pushed off their start dates for a month to give me some time to get this FRP essay done. However, I do expect to be splitting my time 50/50 for $ and research going forward, and if-anything leaning more heavily on the $-side of things because I want to make sure things are moving forward there. It's exciting to not have to worry about money as much! I wonder if I'll get sick of this context-switching at some point like Paul Chiusano did and want to go full time on the research.

### FRP Draft Feedback

After completing the first draft last week, I sent it over to Jonathan Edwards for feedback. It was truly excellent feedback. I kept reading it over and over again. He was able to highlight the parts of my essay that I was most concerned about, and give very on-point suggestions. Here is his feedback and my thoughts underneath each point:

> “modular comprehensibility” is a heavyweight phrase, and modularity has many meanings. Maybe “locally comprehensible” is lighter and more precise?

Agreed. "module" is a loaded word in tech already. Another phrase could be "piecemeal comprehensible". Or how about "self-contained comprehensibility"?

A metaphor I find helpful is the difference between a novel where anything can happen to anything at any time, and you have to read it sequentially and completely, vs an encyclopedia, which is referential in that you can just look up what you care about (and the entries it specifically references) and be done. So another possible phrase is "referential" or "definitional" comprehensibility.
 
> “implicit dependencies and side effects decrease modular comprehensibility” Is the problem being implicit or non-local? Would non-local explicit dependencies be OK?

Really great question. I totally agree that I don't make this point well, because I'm partially confused by it myself.

For one, it's important to not only list what the dependencies are, but specifically how the dependency affects it's dependent. It's not "this term depends on x", but "this term is precisely 2x + 17".

At the end of the day, I want "data = ...", which is an explicit definition. If the definition of "..." lives in a different file, I don't care because we can build an automated tool to bring them together for visualization purposes. Explicit-ness is the key, and side effects lead to implicit-ness.

In the essay I complain about "action at a distance", but I think you are correct in pointing out that that doesn't really matter. It's more the implicit-ness that's the problem.

> The graphs are larger than needed to make your point. It took me a minute to figure out what you were doing with the edge adjacencies. Probably should explain in figure captions. It might be clearer to make this point with different syntaxes for representing the graph.

Ok, good to know.

> “count is constant in the sense…” is asking for an argument. Is a lazy stream really a constant? You don’t need to pick this fight.

Ok, good to know! (Didn't realize it was a fight.) 

> The reflex example needs more detailed explanation. What does foldDyn do and what is its type? Show how the stream is higher order. Also note the dependence on lazy evaluation (which is also the reason for space leakiness)

Agreed, will do.

> You need to show todomvc in reflex to compare with the Elm example and show how locality is improved. This is the crux of your argument, and you stopped before you got there!

Ah, ok, will do! I think this will help me articulate some of the questions in your comments.

> Don’t credit Glen with inventing live programming. Best citations are Steve Tanimoto and Chris Hancock.

Ok good point, will look them up. 

> You should address the counterargument that your cure is worse than the disease :). Isn’t the bottom line really the cognitive effort to understand the code? Evan says the Elm architecture is no longer FRP and is easier to understand http://elm-lang.org/blog/farewell-to-frp. FRP can get hairy - do you end up just trading non-local dependencies for convoluted semantics?

Totally, totally agreed. I used to have a section in this essay that referred to Elm's Farewell to FRP, but removed it. I'll bring it back!
 
> Some might argue that the data flows are just as complex topologically, you’ve just encoded them in a very terse and abstract way. You propose building code viz tools to help. But perhaps we could also add assistance for understanding the non-local dependencies in Elm also.

Really on-point question. I think about this myself too. One way to phrase this question is: can we build an automated tool to parse an Elm project into a Reflex project? 

I fear that the Elm Architecture is functional in the same way that passing around global state as an explicit argument is functional as they articulate in Out of the Tarpit:

>  There is in principle nothing to stop functional programs from passing a single extra parameter into and out of every single function in the entire system. If this extra parameter were a collection (compound value) of some kind then it could be used to simulate an arbitrarily large set of mutable variables. In effect this approach recreates a single pool of global variables — hence, even though referential transparency is maintained, ease of reasoning is lost (we still know that each function is dependent only upon its arguments, but one of them has become so large and contains irrelevant values that the benefit of this knowledge as an aid to understanding is almost nothing).

### Future of Programming Meetup

We had a fun meetup on Monday of this week. It was great. There were 8 of us at the Work-Bench offices, which was a great location. The way we ran this meeting was that different people showed what they were working on and got some feedback. Nick from Windmill showed a terminal app that runs compile processes in a more visual way. Sam and Rodrigo from Hopscotch showed interface ideas for linking between projects. Steve and Joe from Universe showed a new on-boarding flow that teaches the interface, which reminded me of [this article that I needed some help from Twitter to find](https://twitter.com/stevekrouse/status/1022101883769561089). 

### Interesting links

#### [Functional Programs That Explain Their Work](https://www.youtube.com/watch?v=pqtqaL_ojpk)

I found this link on [lamdu.org](http://lamdu.org). So great! The motivations are very similar to my own FRP essay but they take a very different approach. Their goal is:

> allow the user to selectively focus on parts of the execution to help their understanding

Which sounds a lot like my goal to make reading proportional to comprehension.

#### [Story Generator Redesign](http://glench.com/StoryGeneratorRedesign/)

Glen sent me this link after an email exchange we had. It's a very thought provoking short demo essay thing. It provides evidence for the "we need lots of little visual domain-specific environments" argument.

#### [Seymour: Live Programming for the Classroom](https://harc.github.io/seymour-live2017/)

Crazy I haven't read this yet. Really wonderfully written. Of course I am a bit tired of trying to visualize imperative programs, but this is an interesting take on it. This is a bit more advanced than PythonTutor, which they reference in the essay.

#### [Academic Pensieve](http://drorbn.net/AcademicPensieve/About.html)

Found this article via a Michael Nielsen essay. Turns out my experiment in publishing all my work in progress isn't so new. This guy has been doing it since 2008, and says that it's called [Open-notebook science](https://en.wikipedia.org/wiki/Open-notebook_science).

### My growing Anti-IO-Monad Obsession

My new motto (from I don't know where):

<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Imperative Programming is doing<br>Functional Programming is being</p>&mdash; Steven Krouse (@stevekrouse) <a href="https://twitter.com/stevekrouse/status/1022842371896213504?ref_src=twsrc%5Etfw">July 27, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

My favorite picture (from [What's Functional Programming All About?](http://www.lihaoyi.com/post/WhatsFunctionalProgrammingAllAbout.html)):

![image](https://user-images.githubusercontent.com/2288939/43324921-49e5fa40-9183-11e8-873d-59639e25382a.png)

And my new obsession (from [Can functional programming be liberated from the von Neumann paradigm?](http://conal.net/blog/posts/can-functional-programming-be-liberated-from-the-von-neumann-paradigm)):

> move I/O entirely out of our programming model into the _implementation_ of a denotationally simple model for whole systems

#### HTTP = JQuery

Here's an example of moving I/O out of the programming model. You have a beautiful FRP app. No IO required to render your app. That's what libraries like React are for. They are like JQuery as a service. You tell it what things should look like it and it does the imperative I/O (virtual-dom diffing and patching) below your level of abstraction.

But what about some arbitrary HTTP requests that your app needs to make to some backend service? How do we get this IO out of our code?

My first thought was that we should use a stream of some sort to abstract over the request. But that feels a whole lot like what we already have with JavaScript Promises, and is still very imperative.

Then it hit me (in the shower, as it always does). HTTP requests are like the JQuery DOM queries and mutations. We have to disallow arbitrary HTTP requests in favor of a more holistic abstraction (that will do HTTP under the hood). 

I'm not firm on the specifics yet... but the idea is that you would declaratively say which data are needed on the frontend, and others should be persisted on the backend. Potentially, the way to do this right is to blur the front-end and back-end to a single codebase that speaks in a higher-level abstraction, which is then broken up when the app is compiled -- maybe like Meteor. This could help solve many of the issues with trying to the front and back ends.

##### Another HTTP example

Let's take another HTTP example. Let's say you have two services that you want to keep in sync with a third server. Each one sends you webhooks when their data updates. Then you go to the other and update the data there. 

Let's say service A notifies you of a change via a webhook. You go notify service B with a POST.

All is good until service B hits you with a webhook (because you just changed it's data with a POST and it's letting you know that it's data was changed). You could go update A with the changes, but that's a bit crazy because A already has the changes - it was the one who first propagated the changes.

In order to prevent this craziness, you'd need some way at your server to remember what each service knows so you don't send them redundant updates. However, that feels kinda dirty. Shouldn't your service be stateless...?

Here's my take on the no-IO solution to this problem:

```haskell
--------------------------------
-- Functions we need to define
--------------------------------
stateView :: State{serviceA} -> State{serviceB} -> State{internal}
serviceAView :: State{internal} -> State{serviceA}
serviceBView :: State{internal} -> State{serviceB}

------------------------------------------
-- Virtual States for diff and patching
------------------------------------------
initialState :: Service S => State{S}

stateReducer :: Service S => webhook{S} -> state{S} -> state{S}

diffState :: Service S => state{S} -> state{S} -> diff{S}

patch :: Service S => diff{S} -> [HTTP{S}]
```

Our job is to explain how our internal model of the states join together, and then explain how that model should be persisted in each of the views.

Under the hood, our library will pull the initial states from both services (hopefully not the entire states but just the relevant parts), and maintain it's internal model of each service's data (the virtual-state), and when there's a diff in what *is* and what *should be* as specified in our model, it'll do the diff and patch with the appropriate HTTP requests.

One thing to note here is that in the virtual state diffing and patching, I'm using the "Elm Architecture" of a reducer thing, which I normally don't like. In an ideal world, it wouldn't be a global reducer like that but more like how I argue in my FRP draft. However, it hurts my brain to think about how to do it that way... Anyways, it's an implementation detail so it doesn't matter too much either way.

### Now until 8/17/18

I am angling to submit my FRP draft essay to REBLS on 8/17/18, so I'll be mostly working on that, along with my Dark and First Round work, over the next three weeks.

As far as the essay goes, I have plenty of work to do as specified in Jonathan Edward's comments above. In particular I need to get clearer on what's problem (implicit dependencies or non-local dependencies) and also make the case that the solution isn't worse than the disease.
  • Loading branch information
Steve Krouse committed Jul 27, 2018
1 parent c73a703 commit d129e73
Showing 0 changed files with 0 additions and 0 deletions.

0 comments on commit d129e73

Please sign in to comment.