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
* TOC
{: toc }
The changes I'm comitting now were actually done this past Friday. It's not a ton of work but it wasn't pulling teeth - it was fun. And I'm excited enough about it that I actually made my girlfriend listen to me read it to her - she was a great sport. The langauge is a bit technical / high level. There's a lot I need to expound on / elaborate in there, and I imagine that some ambiguity in the essay are weak spots I need to explore more.
Yesterday I had a lot of fun comparing and contrasting TodoMVC in Elm and Redux. I printed out the code for both on paper and wrote all over them. I have a lot of questions about the types of things in Redux that I'll have to investigate next.
One idea I had is that to make the comparison more apples-to-apples, I could write TodoMVC in Redux but with the Elm Architecture - this is possible but not the reverse. However, that is a bunch of work considering how slow my Reflex/ghcjs feedback loop is. Another possible task is implementing focus on input elements, localstorage, and url hash get/set in Reflex to make them truly equal - but that's not really the point so it may be more work than it's worth.
I only have two weeks before I have to submit to REBLS. I think I have enough for the paper in progress section, but I want to make it as best I can before that date. However, I also have work for Dark and First Round I should do this week - as well as taking some time off to spend with family that's around this month. It's a lot going on!
### Dark research
I spent 3 hours this morning compiling lists of various interesting progrmming environments. What I'm most excited about is my list of classics that I've never played with:
* Hypercard
* squeak / etoys / morphicjs / pharo / http://gtoolkit.org/
* Labview
* apl
* Self
* Forth
* Prolog
* Sketchpad
* Matlab / simulink
* Yahoo pipes
As well as a few I keep haering about:
* prograph
* paxmsp and pure data vvvv
* JetBrains MPS
* emacs org mode
* TLA+ / Alloy
* Sonic Pi
* R
* https://www.blender.org/
* Godot engine
* Qt
* Chalktalk
* http://mbeddr.com/
* http://openendedgroup.com/field/OverviewBanners2.html
Copy file name to clipboardExpand all lines: drafts/frp.md
+21-18Lines changed: 21 additions & 18 deletions
Original file line number
Diff line number
Diff line change
@@ -9,45 +9,45 @@ title: FRP
9
9
10
10
## 1. Introduction
11
11
12
-
Explicit dependencies clarify which sections of code are independent to our current investigations, keeping the "effort needed to concieve or to understand a program ... not more than proportional to the program length" [Humble Programmer].
12
+
When trying to understand a small piece of a large software project, explicit dependencies clarify which sections of code are independent to our current investigations, keeping the "effort needed to concieve or to understand a program ... not more than proportional to the program length" [Humble Programmer].
13
13
14
-
In pure functional programming, all terms explicitly list what they depend upon - as opposed to imperitive programming where terms can "be dependent on many, many different hidden mutable variables" [Out of the Tarpit].
14
+
Explict data relationships is one of the benefits of functional programming, because all terms explicitly list what they depend upon. This contrasts with imperitive programming, where terms can "be dependent on many, many different hidden mutable variables" [Out of the Tarpit].
15
15
16
-
However, functional programming isn't immune to hidden dependencies:
16
+
However, functional programming can simulate "hidden mutable variables" via an compound state value that it passes around as an extra parameter:
17
17
18
-
> 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).
18
+
> 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).[Out of the Tarpit]
19
19
20
-
The popular Functional Reactive Elm Architecture suffers from this problem. I argue that the way to maintain explicit dependencies in Functional Reactive Programming is through cyclic and higher-order streams, as demonstrated by the Reflex framework.
20
+
While this is considered an anti-pattern in many functional programming settings [TODO source needed], a variation on it has become the dominant architecture in Functional Reactive Programming. Originally concieved for the Elm programming langauge, The Elm Architecture has since inspired ReactJS's Redux, VueJS's Vuex, CycleJS's Onionify, among many other front-end state management libraries. [TODO source needed]
21
21
22
-
2. The Elm Architecture
22
+
This paper contrasts the Elm Architecture with Haskell's Reflex, featuring higher-order streams and cyclic streams, with an eye towards idepedent comprehensibility through explicit data dependencies.
23
23
24
-
Elm is a pure functional language in the spirit of Haskell that compiles to JavaScript. It is an FRP-inspired langauge that only allows first-order and non-cyclic streams.
24
+
## 2. The Elm Architecture
25
25
26
-
The Elm Architecture follows directly from the first-order, non-cyclic restrictions. Because streams cannot contain other streams, nor be cyclical, the only way to construct a user interface, which is inherently cyclical, is to have a single, large, language-supported cycle.
26
+
Elm is a pure functional language in the spirit of Haskell. It compiles to JavaScript. It is an FRP-inspired langauge that only allows first-order and non-cyclic streams for reasons discussed in [TODO disease worse than cure?].
The Elm Architecture follows directly from Elm's first-order, non-cyclic nature: because streams cannot contain other streams, nor be cyclic, the only way to construct user interfaces, which are inherently cyclical, is to have a single, large, language-supported cycle.
29
29
30
-
The Elm Architecture was built originally for use in Elm, but has since inspired ReactJS's Redux, VueJS's Vuex, CycleJS's Onionify, among many other front-end state management libraries.
Let's examine the architecture. The reducer is a function that takes the old state and an event, and returns a newly computed state.
32
+
The core of this architectureis its a compound state value, which along with the reducer, which returns a new state in response to events, "simulate[s] an arbitrarily large set of mutable variables." [Tarpit]
33
33
34
34
```haskell
35
35
reducer::state->event->state
36
36
```
37
37
38
-
Theway the view sends events to the `reducer` differs between the frameworks.As we saw above, CycleJS derives event information *outside* the view, such as `const clicks =DOM.select('#counter-button').events('click')`.ReactandElm generate events from *within* view, such as `<button onClick={this.handleClick()}>` or `button [ onClick Increment ]`, respectively.
38
+
The view is a pure function of state.
39
39
40
-
Additionally, these frameworks sometimes wrap events in semantic labels called "actions"or"messages".For example, above the `onClick` event is labeled as the `Increment` action.This will become clearer in the Elm example below.
40
+
The way the view sends events to the `reducer` differs between frameworks.CycleJS derives event information *outside*the view, such as `const clicks =DOM.select('#counter-button').events('click')`.React/ReduxandElm generate events from *within* view, such as `<button onClick={this.handleClick()}>` or `button [ onClick Increment ]`, respectively.
41
41
42
-
In the ElmArchitecture, we are explicit about the initial value of state, how the state determines the view, and how various events effect the state.This is a huge improvement over the ImperativeButton above.For one, it gives us serializable state, which we can use for hot-swapping and time travel debugging!
42
+
Additionally, these frameworks sometimes wrap events in semantic labels called "actions"or"messages".For example, an `onClick` event can be labeled as the `Increment` action.This will become clearer in the Elm example below.
43
43
44
-
However, let's examine the ElmArchitecturefrom a modular comprehensibility point ofview.
44
+
Just like in imperitive programming, the ElmArchitectureis explict only about the *initial* values ofstates.
45
45
46
46
Any message can modify any state.In the reducer, called `update`in [ElmToDoMVC](https://github.com/evancz/elm-todomvc/blob/master/Todo.elm), the `Add` message triggers an update of three different pieces of state:
This means that you can't modularly gain a complete understanding ofany piece of state.You have to look through *all*the messages for any piece of state, which may be spread across many files.
50
+
This means that you can't modularly gain a complete understanding ofany piece of state.You have to look through *all* messages to see ifand how it affects the state in question.
51
51
52
52
There's also a subtler way this undermines explicit dependencies: each piece of state can be modified in terms of*any other piece of state*.There's no explicit isolation between independent states.
53
53
@@ -57,6 +57,10 @@ Additionally, any view element can emit any message. Again from [Elm ToDoMVC](ht
57
57
58
58
If we’re looking to understand a single piece of state, we’re not much better off than with an entirely imperative framework: we still have to read more-or-less the whole application evenif we wish only to comprehend only a small piece.
59
59
60
+
## 3. Reflex
61
+
62
+
TheReflex library was built for Haskell web development via ghcjs.It features higher-order and cyclic streams.
63
+
60
64
## ToDo
61
65
62
66
*maybereverse the order of the introduction
@@ -65,8 +69,7 @@ If we’re looking to understand a single piece of state, we’re not much bette
65
69
* inversion of control (http://degoes.net/articles/destroy-all-ifs)
66
70
* explicit in the math formula sense
67
71
* the elm architecture section
68
-
* edit this section a lot
69
-
* the elm architecture simulates imperitive, von-neuman, one word at a time architecture in a functional setting
72
+
*maybe simulates von-neuman, one word at a time
70
73
* argue that it's difficult to mechanically convert to explicit form
71
74
* argue the treatment is *not* worse than the disease
72
75
*This design decision was made consciously inElm to decrease coupling. [3]
0 commit comments