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
Copy file name to clipboardExpand all lines: drafts/dctp.md
+97-40Lines changed: 97 additions & 40 deletions
Original file line number
Diff line number
Diff line change
@@ -31,17 +31,44 @@ Then someone (I forget who - if this is you, THANK YOU!!!) suggested I listen to
31
31
32
32
Now I am cursed to be one of those condescending assholes, a Conal zombie, doomed to roam the land, pleading other to "go back and read Conal", while knowing full well how hard it will be for them to see the light. This essay is how I hope to give you my disease.
33
33
34
-
## The Curse of Coining a Programming Paradigm
34
+
## DCTP & Denotational
35
+
36
+
### The Curse of Coining a Programming Paradigm
35
37
36
38
When a programming language designer defines a word in their language, that's the end of the story. But when a programming language designer coins a phrase in English, that's only the beginning of their ordeal. Alan Kay coined the phrase "object-oriented programming" (OOP) in the 70s, but OOP took on a life of its own, [which has caused much confusion and heartache to its creator](http://wiki.c2.com/?AlanKaysDefinitionOfObjectOriented).
37
39
38
40
Functional reactive programming (FRP) has [a similarly confused and contested etymology](https://medium.com/@andrestaltz/why-i-cannot-say-frp-but-i-just-did-d5ffaa23973b). In the 90s, Conal Elliott pioneered a new software paradigm for programming interactive animations and dubbed it "Functional Reactive Programming" (FRP). Like Kay, Elliott then watched others use his term to describe things totally opposed to his original vision. Conal eventually conceded defeat. Like OOP, FRP now is a bastardized term that refers to work *inspired* by the "original FRP." Conal has retreated to coining a new, less-sexy (maybe on purpose?) phrase to describe his original vision: Denotative Continuous Time Programming (DCTP). From here on out I will use DCTP to refer to "original FRP."
39
41
42
+
### Denotational Programming
43
+
44
+
Aren't spreadsheets wonderful? A key to their success is that there is no control flow, no sequencing of instructions. Only data flow.
45
+
46
+
In [What's Functional Programming All About?](http://www.lihaoyi.com/post/WhatsFunctionalProgrammingAllAbout.html), Li Hayoi explains: "The core of Functional Programming is thinking about data-flow rather than control-flow." He demostrates this beautifully by converting a stateful imperitive tiramisu recipe to a dataflow diagram:
In [The Next 700 Programming Languages](https://www.cs.cmu.edu/~crary/819-f09/Landin66.pdf), Peter Landin calls such languages "denotative":
53
+
54
+
> (a) each expression has a nesting subexpression structure, (b) each subexpression
55
+
denotes something (usually a number, truth value ornumerical function), (c) the thing an expression denotes, i.e., its "value", depends only on the values of its subexpressions, not on other properties of them.
56
+
57
+
In other words "denotative" languages contain no statements, but only nested mathmatical expressions, where each expression *denotes* (can be model by) some mathmatical object.
58
+
59
+
Denotational programming has a number of benefits:
60
+
61
+
1.**Equational reasoning**. In denotational programming, the equal sign (=) means what it does in a mathematics textbook: we can replace instances of the left with the expression to the right or vice-a-versa.
62
+
2.**Definitional reasoning**. We can *fully* understand an expression by its subexpressions, and their subexpressions, recursively. There are no spooky action-at-a-distance side-effects that can manipulate things from afar. In this way, we don't have to read the entire codebase to understand all the places our state could be manipulated.
63
+
3.**Modularity & Composibility**. TODO
64
+
65
+
I will follow Landin and [Elliott](http://conal.net/blog/posts/is-haskell-a-purely-functional-language) in using the phrase "denotational" instead of "functional", and "imperitive" to describe its opposite.
66
+
40
67
## Continuity
41
68
42
69
The [inspiration for DCTP came in the form of a question from John Reynolds](http://conal.net/blog/posts/early-inspirations-and-new-directions-in-functional-reactive-programming). It roughly amounted to:
43
70
44
-
> What would programming look like if time were continuous?
71
+
> What would it be like to program in continuous time?
45
72
46
73
This is a wonderful question, but it's hard to answer it directly, partly because time is hard to visualize. Let's come at this via a slightly different question and then circle back to time:
47
74
@@ -61,7 +88,7 @@ SVGs retain all the relevant info until the very last moment when the computer f
61
88
62
89
#### What is a graphic?
63
90
64
-
Let's get a bit more mathematical[[1](#1)] with our definitions. A graphic is something that relates x- and y- coordinates to colors. You give it an x-y pair; it gives you a color.
91
+
Let's get a bit more mathematical (or denotational)[1](#1) with our definitions. A graphic is something that relates x- and y- coordinates to colors. You give it an x-y pair; it gives you a color.
65
92
66
93
Here's the difference between bitmaps and SVGs: what kind of numbers make up the x-y pairs?
67
94
@@ -114,7 +141,7 @@ In most programming, time is discrete. The ticks of time can be counted one-by-o
114
141
115
142
Now let's return to the original question that inspired FRP:
116
143
117
-
> What would programming look like if time were continuous?
144
+
> What would it be like to program in continuous time?
118
145
119
146
#### What is an animation?
120
147
@@ -190,7 +217,7 @@ const example6 = layer([
190
217
191
218
## Interactivity
192
219
193
-
The above animations are neat, but they are static in the sense that movies are static: no interactivity. We want to be able to press, click, type, and play with our screens. Let's go deeper into the DCTP rabbithole.
220
+
The above animations are neat, but there's no interactivity. We want to be able to press, click, type, and play with our screens. Let's go deeper into the DCTP rabbithole.
194
221
195
222
### Behaviors and Events
196
223
@@ -209,7 +236,7 @@ Behaviors are continuous functions of time:
What if we want the button to count inside itself?
230
277
278
+
<button onclick="this.innerText -= -1">0</button>
279
+
280
+
```javascript
281
+
constcounter=loop(
282
+
// create a cycle with `loop`
283
+
// the `clicks` Behavior (defined in the function below) is passed in
284
+
({ clicks }) =>function*() {
285
+
286
+
// use the `clicks` Behavior BEFORE IT's DEFINED
287
+
const { click:clickEvent } =yieldbutton(clicks);
288
+
289
+
// define `clicks_`
290
+
constclicks_=yieldliftNow(sample(scan((n, m) => m +1, 0, clickEvent)));
291
+
292
+
// set `clicks` to `clicks_` to tie the recursive knot
293
+
return { clicks: clicks_ };
294
+
}
295
+
);
296
+
```
297
+
[](https://codesandbox.io/s/xorqy1q73q)
298
+
299
+
[TODO drawn flows?]
300
+
231
301
### Higher-order Flows
232
302
233
-
What if we want a variable number of counters? [maybe simpler]
303
+
TODO
234
304
235
305
### Higher-order & Cyclical Flows
236
306
237
-
What if we want counters that make counters that make counters...? [maybe simplier]
238
-
307
+
What if we want a button that makes buttons that make buttons... but only the odd buttons can make buttons? This example may seem contrived, but it's a good minimal example to test the expressivity of a UI paradigm.
239
308
240
-
This example may seem contrived, but it's a good minimal example to test the expressivity of a UI paradigm.
@@ -249,26 +318,9 @@ I have a hunch: visualize the flows.
249
318
250
319
There's been some interesting work done here [TODO linkify], and I'm hoping to further it by building similar visualization tools for Hareactive and Turbine.
251
320
252
-
## "Why program with continuous time?"
253
-
254
-
[TODO this section needs cleaning]
255
-
256
-
Of course, for the computer to render the above graphics on the screen, it must at some point convert the continuous time and space to discretized pixels and ticks of time. So what's the point of programming in continuous time if it will eventually be discretized?
257
-
258
-
There are a [lot](https://github.com/conal/talk-2014-bayhac-denotational-design#why-continuous-time-matters) of [reasons](http://conal.net/blog/posts/why-program-with-continuous-time). The most compelling argument for me is for the same reason we use SVGs: resolution independence. We want to be able to transform our programs "in time and space with ease and without propagating and amplifying sampling artifacts." We want to discretize at the last possible moment, and stay as abstract as possible for as long as possible.
259
-
260
-
Aren't spreadsheets wonderful? A key to their success is that there is no control flow, no sequencing of instructions. Only data flow.
261
-
262
-
In [The Next 700 Programming Languages](https://www.cs.cmu.edu/~crary/819-f09/Landin66.pdf), Peter Landin calls such languages "denotative" when they contain only nested mathmatical expressions, and each expression *denotes* (can be model by) some mathmatical object. And, "The antithesis of denotative is 'imperative.'"
263
-
264
-
As Conal says:
265
-
266
-
> There is a lot of confusion about the meaning of “functional” and “declarative” as descriptions of programming languages and paradigms.... I’ve started using the more specific term “denotational programming” in my blog subtitle and elsewhere, as an alternative to what I used to call “functional programming”. While there are other notions of “functional”, applicable even to monadic IO, I think “denotational” captures the fundamental and far-reaching benefits that we called “good for reasoning about” and “powerfully compositional”. - [Is Haskell a purely functional language?](http://conal.net/blog/posts/is-haskell-a-purely-functional-language)
267
-
268
-
Haskell is such a denotative lanugage... That is, except for monads.
269
-
270
-
[TODO Explain why continuous time (and laziness) are key for compositionality and modularity, maybe citing my FRP paper]
321
+
## Denotational Programming Beyond User Interfaces
271
322
323
+
TODO
272
324
273
325
### Monads are Imperitive
274
326
@@ -308,13 +360,23 @@ One day in the shower, I was wondering how to incorporate HTTP requests into the
308
360
309
361
The same is true of all imperative APIs, including databases, files, sockets, etc. It's not that we have to abandon these technologies entirely. But only as the _implementation_ of a denotative programming system. The computer's job should making HTTP requets, reading and writing to files and databases, on your behalf, just like React mutates the DOM on your behalf.
310
362
311
-
## Common Gotchas
363
+
## FAQ and Common Gotchas
364
+
365
+
### Why program with continuous time?
366
+
367
+
Of course, for the computer to render animations on the screen, it must at some point convert the continuous time and space to discretized pixels and ticks of time. So what's the point of programming in continuous time if it will eventually be discretized?
368
+
369
+
There are a [lot](https://github.com/conal/talk-2014-bayhac-denotational-design#why-continuous-time-matters) of [reasons](http://conal.net/blog/posts/why-program-with-continuous-time). The most compelling argument for me is for the same reason we use SVGs: resolution independence. We want to be able to transform our programs "in time and space with ease and without propagating and amplifying sampling artifacts." We want to discretize at the last possible moment, and stay as abstract as possible for as long as possible.
370
+
371
+
### Thinking about DAGs or propagation
312
372
313
-
DCTP is notoriously difficult to understand. Even if you get most of it, you are likely not yet entirely rid of imperitive thinking habits.
373
+
A very common misconception with DCTP is confusing it with its implementation details. If you catch yourself thinking of DCTP as a DAG (directed acyclic graph), you still haven't quite gotten it.
314
374
315
-
### Thinking about DAGs
375
+
> Every time you hear somebody talk about FRP in terms of graphs or propagation or something like that, they are missing the point entirely. Because they are taking about some sort of operational, mechanistic model, not about what it means.
376
+
>
377
+
> - Conal Elliott on the Haskellcast Podcast
316
378
317
-
A very common misconception with DCTP is confusing it with its implementation details. If you catch yourself thinking of DCTP as a DAG (directed acyclic graph), you still haven't quite gotten it. The builder of a DCTP framework or library _may_ decided to choose a DAG as an internal data structure, but they may choose an entirely different underlying evaluation strategy. In fact, a DAG is likely the wrong structure for DCTP because DAGs are (definitionally) acyclic, but DCTP often requires cycles (recursively defined Behaviors and Events) to represent the full range of user interfaces.
379
+
The builder of a DCTP framework or library _may_ decided to choose a DAG as an internal data structure, but they may choose an entirely different underlying evaluation strategy. In fact, a DAG is likely the wrong structure for DCTP because DAGs are (definitionally) acyclic, but DCTP often requires cycles (recursively defined Behaviors and Events) to represent the full range of user interfaces.
318
380
319
381
### Doing vs Being
320
382
@@ -324,12 +386,6 @@ If you find describing your code in terms of _steps_, you've probably slipped ba
324
386
325
387
I find it helpful to ask myself: What _is_ it? [TODO]
326
388
327
-
In [What's Functional Programming All About?](http://www.lihaoyi.com/post/WhatsFunctionalProgrammingAllAbout.html), Li Hayoi explains: "The core of Functional Programming [or denotative programming] is thinking about data-flow rather than control-flow." He demostrates this beautifully by converting an imperitive tiramisu recipe to a dataflow diagram:
It's well known that FRP has suffered space and time leaks. People often complain about the performance of denotational langauges like Haskell.
@@ -346,6 +402,7 @@ When your code is abstract and free of imperitive, technological, operational co
346
402
* [Let's reinvent FRP](http://vindum.io/blog/lets-reinvent-frp/) by Simon Friis Vindum
347
403
* [The Essense and Origins of FRP](https://github.com/conal/talk-2015-essence-and-origins-of-frp)
348
404
* [Functional Reactive Animation](http://conal.net/papers/icfp97/) - the original FRP paper by Conal Elliott and Paul Hudak
405
+
* [The introduction to Reactive Programming you've been missing](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754) by Andre Staltz
<a name="1" href="#1">[1]</a> - The "D" in DCTP stands for "denotational semantics." The original name for denotational semantics was "mathematical semantics". It was pioneered by Chris Strachey and Dana Scott in the early 1970s. It is an approach to model a programming language with mathematical objects. For example, in this essay we model static graphics as a functions from `x` and `y` to `Color` and moving animations from `x`, `y`, and `t` to `Color`. You can learn more about denotational design and semantics from Conal's [video](https://www.youtube.com/watch?v=bmKYiUOEo2A) and [paper](http://conal.net/papers/type-class-morphisms/).
417
+
<a name="1" href="#1">[1]</a> - The "D" in DCTP stands for "denotational semantics." The original name for denotational semantics was "mathematical semantics". It was pioneered by Chris Strachey and Dana Scott in the early 1970s. It is an approach to model a programming language with mathematical objects. For example, in this essay we model static graphics as a functions from `x` and `y` to `Color` and moving animations from `x`, `y`, and `t` to `Color`. You can learn more about denotational design and semantics from Conal's [video](https://www.youtube.com/watch?v=bmKYiUOEo2A) and [paper](http://conal.net/papers/type-class-morphisms/).
0 commit comments