├── paul-hudak.jpg ├── .gitignore ├── Makefile ├── mine.fmt ├── README.md ├── macros.tex ├── notes.md └── essence-and-origins-of-frp.lhs /paul-hudak.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conal/talk-2015-essence-and-origins-of-frp/HEAD/paul-hudak.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | Junk* 3 | Old* 4 | Stuff 5 | Unused/ 6 | 7 | *.aux 8 | *.log 9 | *.nav 10 | *.out 11 | *.pdf 12 | *.ptb 13 | *.snm 14 | *.toc 15 | 16 | essence-and-origins-of-frp.tex 17 | foo.html 18 | web-token 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARG = essence-and-origins-of-frp 2 | 3 | .PRECIOUS: %.tex %.pdf %.web 4 | 5 | all: $(TARG).pdf 6 | 7 | see: $(TARG).see 8 | 9 | %.pdf: %.tex Makefile 10 | pdflatex $*.tex 11 | 12 | # --poly is default for lhs2TeX 13 | 14 | %.tex: %.lhs macros.tex mine.fmt Makefile 15 | lhs2TeX -o $*.tex $*.lhs 16 | 17 | showpdf = open -a Skim.app 18 | 19 | %.see: %.pdf 20 | ${showpdf} $*.pdf 21 | 22 | clean: 23 | rm $(TARG).{tex,pdf,aux,nav,snm,ptb} 24 | 25 | web: web-token 26 | 27 | STASH=conal@conal.net:/home/conal/web/talks 28 | web: web-token 29 | 30 | web-token: $(TARG).pdf 31 | scp $? $(STASH)/$(TARG)-lambdajam-2015.pdf 32 | touch $@ 33 | -------------------------------------------------------------------------------- /mine.fmt: -------------------------------------------------------------------------------- 1 | %% Misc lhs2TeX directives 2 | 3 | %format Unit = " \mathbf{1} " 4 | %% %format Unit = " \mathbbm{1} " 5 | %format :* = " \times " 6 | %format :+ = " + " 7 | 8 | %% %format <> = " \mathbin{\oplus} " 9 | %% %format `mappend` = " \mathbin{\oplus} " 10 | %format <> = " \diamond " 11 | %format `mappend` = " \diamond " 12 | %format mempty = epsilon 13 | 14 | %% %format <> = " \mathbin{<>} " 15 | 16 | %format <$> = "\mathbin{<\!\!\!\$\!\!\!>}" 17 | 18 | % Got from Andres L: 19 | \newcommand{\calculationcomments}{% 20 | \let\onelinecomment=\onelinecommentchars 21 | \def\commentbegin{\quad\{ }% 22 | \def\commentend{\}}% 23 | } 24 | \calculationcomments 25 | 26 | %format NOTHING = "{}" 27 | 28 | %% hack: add missing space, e.g., before "{" in data type decl 29 | %format SPACE = "\ {}" 30 | 31 | %format PAUSE = "\pause " 32 | 33 | %format BACK = "{\Back}" 34 | %format BACKQ a = "{\Back}" 35 | %format PBACK = "\pause\Back" 36 | 37 | % \renewcommand{\onelinecomment}{\it} 38 | 39 | %% %format (meaning (a)) = "\db{" a "}" 40 | %% %format meaning' (a) x = "\db{" a "}" x 41 | 42 | %format meaning = mu 43 | %format meaning' = mu 44 | %format meaningInv = mu "^{-1}" 45 | 46 | %% %format Meaning = "\Mu" 47 | %% %format meaning = "\mu" 48 | 49 | %% %format Lin1 = Lin "_1" 50 | 51 | %% %format idL = "\Varid{id_L}" 52 | %format idL = "\widehat{" id "}" 53 | 54 | %format @. = "\mathbin{\hat{\circ}}" 55 | %format @* = "\mathbin{\times}" 56 | 57 | %format NO = "{}" 58 | 59 | %format -* = "\multimap" 60 | 61 | %format :-* = "\mathbin{:"-*"}" 62 | 63 | %% %format :-* = "\mathbin{\mathtt{:\!\!-\!*}}" 64 | 65 | 66 | %format Lin = "(":-*")" 67 | 68 | %format :&& = "\mathbin{:\!"&&&"}" 69 | %format :|| = "\mathbin{:\!"|||"}" 70 | 71 | %format *** = "\mathbin{\times}" 72 | %format &&& = "\mathbin{\smalltriangleup}" 73 | %format ||| = "\mathbin{\smalltriangledown}" 74 | 75 | %% %format *** = "\symThree{*}" 76 | %% %format &&& = "\symThree{\&}" 77 | %% %format ||| = "\symThree{|}" 78 | 79 | %format Prod k a b = a "\times_{" k "}" b 80 | %format Coprod k a b = a "+_{" k "}" b 81 | 82 | %% %format T = "{\cal T}" 83 | %% %format T = "{\cal R}" 84 | 85 | %% %format T = "\mathbb{T}" 86 | %format R = "\mathbb{R}" 87 | 88 | %format R2 = "\mathbb{R}^2" 89 | 90 | %format <$> = "\mathbin{<\!\!\!\$\!\!\!>}" 91 | %format <*> = "\mathbin{<\!\!\!*\!\!\!>}" 92 | 93 | %format :->: = "\twoheadrightarrow" 94 | %format <== = "\Leftarrow" 95 | 96 | %format liftA2 = "\Varid{liftA\!_2}" 97 | %format liftA3 = "\Varid{liftA\!_3}" 98 | %format liftA4 = "\Varid{liftA\!_4}" 99 | 100 | %format lift0 = "\Varid{lift_0}" 101 | %format lift1 = "\Varid{lift_1}" 102 | %format lift2 = "\Varid{lift_2}" 103 | %format lift3 = "\Varid{lift_3}" 104 | %format lift4 = "\Varid{lift_4}" 105 | 106 | %format ==> = "\Longrightarrow" 107 | 108 | %format :. = "\circ" 109 | %% %format lub = "\sqcup" 110 | 111 | %format ta = "t_a" 112 | %format b0 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## The essence and origins of FRP 2 | 3 | Versions: 4 | 5 | * [LambdaJam](lambdajam.com) 2015 (July 15--16) keynote: 6 | * [slides](http://conal.net/talks/essence-and-origins-of-frp-lambdajam-2015.pdf) 7 | * [Video](https://www.youtube.com/watch?v=rfmkzp76M4M) 8 | * Related talks, also from Lambda Jam 2015: 9 | * [Denotational Design: from meanings to programs](https://github.com/conal/talk-2014-lambdajam-denotational-design) 10 | * [A more elegant specification for FRP](https://github.com/conal/talk-2015-more-elegant-frp), previously part of the essence-and-origins talk 11 | * Preview version from [BayHac](http://bayhac.org/) 2015 (June 12--14): 12 | * [slides](http://conal.net/talks/essence-and-origins-of-frp-bayhac-2015.pdf) 13 | * [video](http://begriffs.com/posts/2015-07-22-essence-of-frp.html) 14 | 15 | ### Abstract 16 | 17 | Functional Reactive Programming (FRP) is now 20 years old. 18 | Although originally motivated by interactive 3D computer graphics, FRP is a general paradigm for describing dynamic (time-varying) information. 19 | Such information had traditionally been described in software only indirectly, as successive side effects of sequential execution. 20 | In contrast, FRP expressions describe entire evolutions of values over time, representing these evolutions directly as first-class values. 21 | From the start, FRP has been based on two simple and fundamental principles, namely (a) having a precise and simple denotation and (b) continuous time. 22 | The first property, which Peter Landin called "denotative" (and "genuinely functional"), applies across problem domains and ensures a precise, implementation-independent specification, insulated from operational details as found in efficient implementations. 23 | As such, denotative systems can be reasoned about practically and rigorously. 24 | The second property (temporal continuity) is domain-specific and is crucial for simple composability, natural specification of behavior via integration and differentiation, and adaptively efficient implementations. 25 | 26 | Over the last few years, something about FRP has generated a lot of interest among programmers, inspiring several so-called "FRP" systems implemented in various programming languages. 27 | Most of these systems, however, lack both of FRP's fundamental properties. 28 | Missing a denotation, they're defined only in vague and/or operational terms (e.g. "graphs" and "update propagation"). 29 | Missing continuous time, they fail to provide temporal modularity (sampling-independence and natural temporal transformability), committing prematurely to sampling rates that may turn out to be too low for accuracy or too high for efficiency. 30 | For the same reason, these systems cannot express behaviors as integrals or derivatives and must instead express explicit approximations, leading to cluttered code with poor quality and/or performance. 31 | (Discrete notions of imagery have these same drawbacks, remedied by vector graphics and other continuous models.) 32 | 33 | In this talk, I'll share with you the essence of the original (denotative and continuous) FRP. 34 | You'll see the thought processes that led to its design, including the care I took to keep the specification both precise and simple, and hopefully, you'll get a sense of why you might care. 35 | As a more in-depth follow-up, the "Denotational Design" workshop explores how to use denotations to design libraries in general. 36 | 37 | ### Also related 38 | 39 | * My FRP summaries on StackOverflow: 40 | * [What is (functional) reactive programming?](http://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming/1030631#1030631) 41 | * [Specification for a Functional Reactive Programming language](http://stackoverflow.com/questions/5875929/specification-for-a-functional-reactive-programming-language#5878525) 42 | * [The difference between Reactive and Functional-Reactive programming](http://stackoverflow.com/questions/5385377/the-difference-between-reactive-and-functional-reactive-programming/5386908#5386908) 43 | * [The Haskell Cast Episode 9 - Conal Elliott on FRP and Denotational Design](https://www.haskellcast.com/episode/009-conal-elliott-on-frp-and-denotational-design). 44 | -------------------------------------------------------------------------------- /macros.tex: -------------------------------------------------------------------------------- 1 | %% To do: trim these definitions 2 | 3 | \newcommand\nc\newcommand 4 | \nc\rnc\renewcommand 5 | 6 | \usepackage{epsfig} 7 | \usepackage{latexsym} 8 | %% \usepackage{bbold} %% for $\mathbbm{1}$ 9 | 10 | %% %% Look for the \smalltriangleup definition. I expected it in amssymb 11 | %% \nc\smalltriangleup{\scriptscriptstyle \triangle} 12 | %% \nc\smalltriangledown{\scriptscriptstyle \triangledown} 13 | 14 | \nc\out[1]{} 15 | 16 | \nc\mynoteOut[2]{\mynote{#1}\out{#2}} 17 | 18 | % While working, use these defs 19 | %% \nc\mynote[1]{{\em [#1]}} 20 | %% \nc\mynotefoot[1]{\footnote{\mynote{#1}}} 21 | % But for the submission, use these 22 | \nc\mynote\out 23 | \nc\mynotefoot\out 24 | 25 | \nc\todo{\mynote{To do.}} 26 | 27 | \nc\figlabel[1]{\label{fig:#1}} 28 | \nc\figref[1]{Figure~\ref{fig:#1}} 29 | 30 | \nc\seclabel[1]{\label{sec:#1}} 31 | \nc\secref[1]{Section~\ref{sec:#1}} 32 | \nc\secreftwo[2]{Sections~\ref{sec:#1} and~\ref{sec:#2}} 33 | 34 | \nc\appref[1]{Appendix~\ref{sec:#1}} 35 | 36 | %% The name \secdef is already taken 37 | \nc\sectiondef[1]{\section{#1}\seclabel{#1}} 38 | \nc\subsectiondef[1]{\subsection{#1}\seclabel{#1}} 39 | \nc\subsubsectiondef[1]{\subsubsection{#1}\seclabel{#1}} 40 | 41 | \nc\needcite{\mynote{ref}} 42 | 43 | % \nc\myurl\texttt 44 | 45 | % http://cs.wlu.edu/~necaise/refs/latex2e/env-floats.3.html#lnfigure 46 | 47 | % Arguments: env, label, caption, body 48 | \nc\figdefG[4]{\begin{#1}[tbp] 49 | #4 50 | \caption{#3} 51 | \figlabel{#2} 52 | \end{#1}} 53 | 54 | % Arguments: label, caption, body 55 | \nc\figdef{\figdefG{figure}} 56 | \nc\figdefwide{\figdefG{figure*}} 57 | 58 | % Arguments: label, caption, body 59 | \nc\figrefdef[3]{\figref{#1}\figdef{#1}{#2}{#3}} 60 | 61 | \nc\figrefdefwide[3]{\figref{#1}\figdefwide{#1}{#2}{#3}} 62 | 63 | 64 | % Image format: PNG or JPEG? JPEG lets us shrink the files, at some cost 65 | % in fidelity. Png is much slower to process even when the files are 66 | % smaller. I guess there's some conversion process going on. 67 | % JPEG compressed at 35x, the figures are smaller and faster to 68 | % process than png. The eps files are huge (about 80x). 69 | % Since PNG is lossless, keep the master figures in that format and convert. 70 | 71 | 72 | \nc\picext{png} 73 | %\nc\picext{jpg} 74 | %\nc\picext{eps} 75 | %\nc\picext{tif} 76 | 77 | \nc\picfile[1]{pictures/\picext/#1.\picext} 78 | 79 | \nc\pict[1]{\includegraphics[width=3.2in]{\picfile{#1}}} 80 | 81 | \nc\picframe[1]{\frame{\pict{#1}}} 82 | \nc\picframewide[1]{\frame{\includegraphics[width=6in]{\picfile{#1}}}} 83 | 84 | \nc\picdef[2]{\figdef{#1}{#2}{\centering \picframe{#1}}} 85 | \nc\picdefwide[2]{\figdefwide{#1}{#2}{\picframewide{#1}}} 86 | 87 | \nc\picrefdef[2]{\picdef{#1}{#2}\figref{#1}} 88 | \nc\picrefdefwide[2]{\figref{#1}\picdefwide{#1}{#2}} 89 | 90 | \nc\figneeded[1]{\figdef{needed}{#1}} 91 | 92 | \nc\symTwo[1]{\mathbin{#1\!\!\!#1}} 93 | \nc\symThree[1]{\mathbin{#1\!\!\!#1\!\!\!#1}} 94 | 95 | \nc{\lb}{[\![} 96 | \nc{\rb}{]\!]} 97 | \nc{\db}[1]{\lb#1\rb} 98 | 99 | \usepackage{tikz} 100 | %%%< 101 | %% \usepackage[active,tightpage]{preview} 102 | %% \PreviewEnvironment{tikzpicture} 103 | %%%> 104 | \usepackage{amsmath} 105 | 106 | %% \usepackage{tikz-cd} 107 | 108 | %% % I used tikz-cd version 0.3c, of December 30, 2012. 109 | %% % July 2012 version lacks a feature I use (shift left). 110 | 111 | %% \usetikzlibrary{matrix, calc, arrows} 112 | %% \tikzset{ ampersand replacement=\& } 113 | 114 | \nc\wpicture[2]{\includegraphics[width=#1]{#2}} 115 | 116 | \nc\wfig[2]{ 117 | \begin{center} 118 | \wpicture{#1}{#2} 119 | \end{center} 120 | } 121 | \nc\fig[1]{\wfig{4in}{#1}} 122 | 123 | \nc\usebg[1]{\usebackgroundtemplate{\wpicture{1.2\textwidth}{#1}}} 124 | 125 | \nc\framet[2]{\frame{\frametitle{#1}#2}} 126 | 127 | \nc\hidden[1]{} 128 | 129 | \nc\Back{\!\!\!\!\!\!} 130 | 131 | 132 | \nc\pitem{\pause \item} 133 | 134 | \nc\partframe[1]{\framet{}{\begin{center} \vspace{6ex} {\Huge \textcolor{partColor}{#1}} \end{center}}} 135 | %\nc\partframe[1]{\framet{}{\begin{center} \huge \emph{\textcolor{blue}{#1}} \end{center}}} 136 | 137 | \rnc\quote[2]{ 138 | \begin{center}\begin{minipage}[t]{0.7\textwidth}\begin{center} 139 | \emph{#1} 140 | \end{center} 141 | \begin{flushright} 142 | \vspace{-1.2ex} 143 | - #2\hspace{2ex}~ 144 | \end{flushright} 145 | \end{minipage}\end{center} 146 | } 147 | \nc\pquote{\pause\quote} 148 | -------------------------------------------------------------------------------- /notes.md: -------------------------------------------------------------------------------- 1 | # How you could have invented functional reactive programming 2 | 3 | [*A Brief Introduction to ActiveVRML*]: http://conal.net/papers/ActiveVRML/ "Tech report (1996)" 4 | 5 | [*Functional Reactive Animation*]: http://conal.net/papers/icfp97/ "paper" 6 | 7 | [*Push-pull functional reactive programming*]: http://conal.net/papers/push-pull-frp/ "Paper" 8 | 9 | [*From Functional Animation to Sprite-Based Display*]: http://conal.net/papers/padl99/ "paper by Conal Elliott (1999)" 10 | 11 | [*Why Functional Programming Matters*]: http://www.cse.chalmers.se/~rjmh/Papers/whyfp.html "Paper by John Hughes (1984)" 12 | 13 | These notes are for a talk at BayHac 2015 (June 12--14) and keynote at LambdaJam 2015 (July 15--16). 14 | 15 | ## Outline 16 | 17 | ### History 18 | 19 | * 1983-1989 at CMU: 20 | * Went for graphics. 21 | * Did FP, program transformation, type theory, HOU. 22 | * 1989 at CMU: 23 | * Kavi Arya's "functional animation" and John Reynolds insight. 24 | * Finished my dissertation anyway. 25 | * 1990-93 at Sun: TBAG 26 | * 3D geometry etc as first-class immutable values. 27 | * In Common Lisp, C++, Scheme. 28 | * Optimizing compiler to rendering code via partial evaluation & fusion. 29 | * For animation & interaction, immutable functions of time to geometry etc. 30 | * Multi-way constraints, with time-functions for variables. 31 | Off-the-shelf constraint solvers (DeltaBlue & SkyBlue from UW). 32 | * Differentiation, integration and ODEs specified via `deriv`. 33 | Adaptive fifth-order Runge-Kutta ODE solver for speed & accuracy. 34 | * Efficient multi-user distributed execution for free. 35 | * Reactivity via constraint `assert`/`retract` (high-level but imperative). 36 | * C++ version: simpler (no compilation). 37 | * 1994-1999 at Microsoft Research: RBML/ActiveVRML, RBMH/Fran 38 | * Design programming model and fast implementation for new 3D architecture (Talisman). 39 | * Research goal: TBAG + denotative/functional reactivity. 40 | * Drop constraints "at first". 41 | * Add event algebra to behavior algebra. 42 | * Reactivity via behavior-valued events. 43 | * Started in ML as "RBML". 44 | * Rebranded to "[ActiveVRML][*A Brief Introduction to ActiveVRML*]", then "[DirectAnimation](http://www.sworks.com/keng/da.html)". 45 | * Found Haskell: reborn as RBMH (research vehicle). 46 | * Paul Hudak (RIP) suggested names "Fran" and then "FRP". 47 | * Very fast implementation via sprite engine. ([paper][*From Functional Animation to Sprite-Based Display*]) 48 | * 2000 at MSR: attempted first push-based implementation 49 | * Garbage collection problems. 50 | * Determinacy of timing & simultaneity. 51 | * Algebra of event listeners. 52 | * I don't think *anyone* has gotten correct. 53 | * 2009: [Push-pull FRP][*Push-pull functional reactive programming*] 54 | * Modernized API: 55 | * Standard abstractions. 56 | * Semantics as homomorphisms. 57 | * Laws for free. 58 | * Another attempt at push for reactivity and pull for continuous phases. 59 | * Reactive normal form, via equational properties (denotation!). 60 | * "Push" is really blocked pull. 61 | * Uses LUB (basis of PL semantics). 62 | * Implementation subtleties & GHC RTS bugs. 63 | Didn't quite work. 64 | 65 | ## What is FRP? 66 | 67 | Two essential properties: 68 | 69 | * *Continuous* time! (Natural & composable.) 70 | * Denotational design. (Elegant & rigorous.) 71 | 72 | Deterministic, continuous "concurrency". 73 | 74 | More aptly, *"Denotative continuous-time programming"* (DCTP). 75 | 76 | Warning: many modern "FRP" systems have neither property. 77 | 78 | ## Why continuous & infinite (vs discrete/finite) time? 79 | 80 | *From LambdaJam 2014 talk.* 81 | 82 | ## Semantics 83 | 84 | Central abstract type: `Behavior a`. 85 | A "flow" of values. 86 | 87 | Precise & simple semantics: 88 | 89 | > meaning :: Behavior a -> (R -> a) 90 | 91 | API and its specification follows mostly from this one choice. 92 | 93 | ## API 94 | 95 | Note *semantic* instances: 96 | 97 | > instance Functor ((->) t) where ... 98 | > instance Applicative ((->) t) where ... 99 | > instance Monad ((->) t) where ... 100 | > 101 | > instance Monoid ((->) t) where ... 102 | > instance Num ((->) t) where ... 103 | > ... 104 | 105 | API follows in "precise analogy" from semantics. 106 | 107 | ## Homomorphisms 108 | 109 | A "homomorphism" $h$ is a function that preserves an algebraic structure. 110 | For instance, for `Monoid`: 111 | 112 | > h mempty == mempty 113 | > h (as <> bs) == h as <> h bs 114 | 115 | For instance, 116 | 117 | > lenS :: [a] -> Sum Int 118 | > lenS = Sum . length 119 | 120 | > log' :: Product R -> Sum R 121 | > log' = Sum . log . getProduct 122 | 123 | Homomorphism proofs: 124 | 125 | > lenS mempty 126 | > == Sum (length mempty) 127 | > == Sum (length []) 128 | > == Sum 0 129 | > == mempty 130 | 131 | > lenS (as <> bs) 132 | > == Sum (length (as <> bs)) 133 | > == Sum (length (as ++ bs)) 134 | > == Sum (length as + length bs) 135 | > == Sum (length as) <> Sum (length bs) 136 | 137 | ## Specification by semantic homomorphism 138 | 139 | Functor homomorphism (naturality): 140 | 141 | > h (f <$> as) == f <$> h as 142 | 143 | i.e., 144 | 145 | > h . fmap f == fmap f . h 146 | 147 | ## Events 148 | 149 | > meaning :: Event a -> [(R,a)] 150 | 151 | Stylistic tweak for homomorphisms: 152 | 153 | > meaning :: Event a -> ([] :. (,) R) 154 | 155 | or 156 | 157 | > type Event = Behavior :. [] -- discretely non-empty 158 | 159 | ## Reactivity 160 | 161 | Events generate new behavior phases: 162 | 163 | > switcher :: Behavior a -> Event (Behavior a) -> Behavior a 164 | 165 | ---- 166 | 167 | ## Misc 168 | 169 | * There are two essential ideas---one domain-independent, and one domain-specific: 170 | * Build on a precise and simple *denotation*: 171 | * Well-specified, independent of an implementation. 172 | * Enables practical, dependable reasoning. 173 | * Continuous time (resolution-independence): 174 | * Naturalness 175 | * Transformation flexibility with simple & precise semantics 176 | * Modularity/composability, as with pure, non-strict functional programming. 177 | See [*Why Functional Programming Matters*]. 178 | * Efficiency (adapative) 179 | * Quality/accuracy 180 | * Integration and differentiation: natural, accurate, efficient. 181 | * Reconcile differing input sampling rates. 182 | 183 | Warning: most modern "FRP" systems have neither property. 184 | * Origins of functional reactive programming: 185 | * While a grad student at Carnegie Mellon, I had a class in *denotational semantics*, as developed by Chris Strachey and Dana Scott in the late 1960s. 186 | * The idea of denotational semantics is to define a mathematical type ("domain") of meanings (denotations) of utterances in a language, and then define the language's meaning as a mapping from the (abstract) syntax to semantics/meanings. 187 | * The mapping must be *compositional*, i.e., the meaning of an expression depends only on the meaning of its sub-expressions ("structural induction"). 188 | * In 1988 or 1989, when nearing completion at CMU, Kavi Arya gave a talk on "functional animation", as streams of pictures. 189 | Fairly elegant for some operations. 190 | At the end of Kavi's talk, [John Reynolds](http://www.cs.cmu.edu/~jcr/) offered a remark, roughly as follows: 191 | 192 | > 193 | You can think of sequences as functions from the natural numbers. 194 | Have you thought about functions from the reals instead? 195 | Doing so might help with the awkwardness of interpolation. 196 | 197 | I knew at once I'd heard a wonderful idea, so I went back to my office, wrote it down, and promised myself that I wouldn't think about Kavi's work and John's insight until my dissertation was done. 198 | Otherwise, I might never have finished. 199 | See [*Early inspirations and new directions in functional reactive programming*](http://conal.net/blog/posts/early-inspirations-and-new-directions-in-functional-reactive-programming/). 200 | * About two years later, at Sun Microsystems, I started working on functional animation in the [TBAG](http://conal.net/tbag/) system (first in Lisp), modeling animation as functions of *continuous time*, as John Reynolds had suggested. 201 | * In 1994, I moved to Microsoft Research and extended the TBAG ideas to include functional reactivity, forming what came to be called "functional reactive programming" (FRP), first as ActiveVRML and then Fran. 202 | * Instead of a *language*, I applied DS to an API. 203 | * Much more useful, since we define many more APIs than languages. 204 | * Assign a semantic domain to every type. 205 | * Define the meaning of each primitive as a function of the meanings of its arguments. 206 | * Complements the host language's semantics. 207 | * I had designed the "reactive behavior modeling" library to use with ML, but in 1995, I found Haskell and realized that it was a better fit. 208 | * In 1995 or 1996, I was working with an implementation in Haskell, when Paul Hudak (RIP) visited. 209 | I showed him my implementation, about which he was quite enthusiastic. 210 | He suggested that we write a paper together, and that we rename the system "Fran" for "functional reactive animation". 211 | Later, he suggested "functional reactive programming", since "animation" could easily be understood as about visual animation only. 212 | 213 | ---- 214 | 215 | * In the dozens of variations on FRP I've played with over the last 20 years, John's refinement of Kavi's idea has always been the heart of the matter for me. 216 | 217 | ---- 218 | 219 | -------------------------------------------------------------------------------- /essence-and-origins-of-frp.lhs: -------------------------------------------------------------------------------- 1 | %% -*- latex -*- 2 | 3 | %% %let atwork = True 4 | 5 | % Presentation 6 | \documentclass{beamer} 7 | %\documentclass[handout]{beamer} 8 | 9 | %% % Printed, 2-up 10 | %% \documentclass[serif,handout]{beamer} 11 | %% \usepackage{pgfpages} 12 | %% \pgfpagesuselayout{2 on 1}[border shrink=1mm] 13 | 14 | %% % Printed, 4-up 15 | %% \documentclass[serif,handout,landscape]{beamer} 16 | %% \usepackage{pgfpages} 17 | %% \pgfpagesuselayout{4 on 1}[border shrink=1mm] 18 | 19 | \usefonttheme{serif} 20 | 21 | \usepackage{hyperref} 22 | \usepackage{color} 23 | 24 | % \definecolor{linkColor}{rgb}{0.62,0,0} 25 | \definecolor{linkColor}{rgb}{0,0.42,0.3} 26 | \definecolor{partColor}{rgb}{0,0,0.8} 27 | 28 | \hypersetup{colorlinks=true,urlcolor=linkColor} 29 | 30 | %% \usepackage{beamerthemesplit} 31 | 32 | %% % http://www.latex-community.org/forum/viewtopic.php?f=44&t=16603 33 | %% \makeatletter 34 | %% \def\verbatim{\small\@verbatim \frenchspacing\@vobeyspaces \@xverbatim} 35 | %% \makeatother 36 | 37 | \usepackage{graphicx} 38 | \usepackage{color} 39 | \DeclareGraphicsExtensions{.pdf,.png,.jpg} 40 | 41 | %% \usepackage{wasysym} 42 | \usepackage{mathabx} 43 | \usepackage{setspace} 44 | \usepackage{enumerate} 45 | \usepackage{tikzsymbols} 46 | 47 | \useinnertheme[shadow]{rounded} 48 | % \useoutertheme{default} 49 | \useoutertheme{shadow} 50 | \useoutertheme{infolines} 51 | % Suppress navigation arrows 52 | \setbeamertemplate{navigation symbols}{} 53 | 54 | \input{macros} 55 | 56 | %include polycode.fmt 57 | %include forall.fmt 58 | %include greek.fmt 59 | %include mine.fmt 60 | 61 | \title{The essence and origins of FRP} 62 | \subtitle{\emph{or}\\[1.5ex] How you could have invented \\ Functional Reactive Programming} 63 | \author{\href{http://conal.net}{Conal Elliott}} 64 | % \institute{\href{http://tabula.com/}{Tabula}} 65 | % Abbreviate date/venue to fit in infolines space 66 | % \date{June 2015 / BayHac} 67 | \date{LambdaJam 2015} 68 | % \date{\emph{Draft of \today}} 69 | 70 | \setlength{\itemsep}{2ex} 71 | \setlength{\parskip}{1ex} 72 | 73 | % \setlength{\blanklineskip}{1.5ex} 74 | 75 | 76 | %%%% 77 | 78 | % \setbeameroption{show notes} % un-comment to see the notes 79 | 80 | \setstretch{1.2} 81 | 82 | \begin{document} 83 | 84 | \frame{\titlepage} 85 | \partframe{What is FRP?} 86 | 87 | \framet{FRP's two fundamental properties}{ 88 | \begin{itemize}\itemsep3ex 89 | \item Precise, simple denotation. 90 | (Elegant \& rigorous.) 91 | \item \emph{Continuous} time. 92 | (Natural \& composable.) 93 | \end{itemize} 94 | \pause 95 | { 96 | \parskip 3ex 97 | \vspace{4ex} 98 | 99 | Deterministic, continuous ``concurrency''. 100 | 101 | \pause\vspace{4ex} 102 | 103 | Warning: most modern ``FRP'' systems have neither property. {\Large \dSadey} 104 | 105 | % More aptly, \emph{``Denotative continuous-time programming''} (DCTP). 106 | % \vspace{4.3ex} 107 | \ 108 | } 109 | } 110 | 111 | \framet{FRP's two fundamental properties}{ 112 | \begin{itemize}\itemsep3ex 113 | \item Precise, simple denotation. 114 | (Elegant \& rigorous.) 115 | \item \emph{Continuous} time. 116 | (Natural \& composable.) 117 | \end{itemize} 118 | %\pause 119 | 120 | \vspace{2.5ex} 121 | 122 | FRP \emph{is not} about: 123 | \pause 124 | \begin{itemize}\itemsep1.2ex 125 | \item graphs, 126 | \item updates and propagation, 127 | \item streams, 128 | \item doing % (operational) 129 | \end{itemize} 130 | 131 | } 132 | 133 | \framet{Why (precise \& simple) denotation?}{ 134 | \pause 135 | \begin{itemize}\itemsep2ex 136 | \item 137 | Separates specification from implementation. 138 | % Defines intent, independent of implementation and without handwaving. 139 | \item \emph{Simple} so that we \emph{can} reach conclusions. 140 | \item \emph{Precise} so that our conclusions will be \emph{true}. 141 | \item Denotations have elegant, functional-friendly style. 142 | \end{itemize} 143 | 144 | \pause\hspace{2ex} 145 | 146 | An API is a language for communicating about a domain. 147 | 148 | It helps to (really) understand what we're talking about. 149 | 150 | %% \quote{The single biggest problem with communication is the illusion that it has occurred.}{George Bernard Shaw} 151 | 152 | } 153 | 154 | \framet{Why continuous \& infinite (vs discrete/finite) time?}{ 155 | \pause 156 | Same benefits as for space (vector graphics): 157 | %\\ \hspace{6ex} \ldots and for pure, non-strict functional programming. 158 | \pause 159 | \begin{itemize}\itemsep0.3ex 160 | \item Transformation flexibility with simple \& precise semantics. 161 | \item Modularity/reusability/composability: 162 | \begin{itemize} 163 | \item Fewer assumptions, more uses (resolution-independence). 164 | \item More info available for extraction. 165 | \end{itemize} 166 | \item Integration and differentiation: natural, accurate, efficient. 167 | % \item Simplicity: eliminate non-essential details. 168 | \pause 169 | \item Quality/accuracy. 170 | \item Efficiency (adapative). 171 | \item Reconcile differing input sampling rates. 172 | \end{itemize} 173 | \pause 174 | % \fbox{\emph{Principle:} Approximations/prunings compose badly, so postpone.} 175 | \vspace{1ex} 176 | {\color{blue} 177 | \fbox{\normalcolor\emph{Principle:} Approximations/prunings compose badly, so postpone.} 178 | } 179 | 180 | See \href{http://www.cse.chalmers.se/~rjmh/Papers/whyfp.html}{\emph{Why~Functional~Programming~Matters}}. 181 | } 182 | 183 | \framet{Semantics}{ 184 | 185 | Central abstract type: |Behavior a| --- a ``flow'' of values. 186 | \pause\\[5ex] 187 | 188 | Precise \& simple semantics: 189 | 190 | > meaning :: Behavior a -> (T -> a) 191 | 192 | where |T = R| (reals). 193 | \pause\\[4ex] 194 | 195 | Much of API and its specification can follow from this one choice. 196 | %% \\Described in the \emph{Denotational Design} teaser. 197 | } 198 | 199 | \partframe{Original formulation} 200 | 201 | \framet{API}{ 202 | 203 | { \small 204 | 205 | > time :: Behavior T 206 | > lift0 :: a -> Behavior a 207 | > lift1 :: (a -> b) -> Behavior a -> Behavior b 208 | > lift2 :: (a -> b -> c) -> Behavior a -> Behavior b -> Behavior c 209 | > timeTrans :: Behavior a -> Behavior T -> Behavior a 210 | > integral :: VS a => Behavior a -> T -> Behavior a 211 | > NOTHING ... 212 | 213 | > instance Num a => Num (Behavior a) where ... 214 | > ... 215 | 216 | } 217 | Reactivity later. 218 | 219 | } 220 | 221 | \framet{Semantics}{ 222 | 223 | > meaning time = \ t -> t 224 | > meaning (lift0 a) = \ t -> a 225 | > meaning (lift1 f xs) = \ t -> f (meaning xs t) 226 | > meaning (lift2 f xs ys) = \ t -> f (meaning xs t) (meaning ys t) 227 | > meaning (timeTrans xs tt) = \ t -> meaning xs (meaning tt t) 228 | 229 | > instance Num a => Num (Behavior a) where 230 | > fromInteger = lift0 . fromInteger 231 | > (+) = lift2 (+) 232 | > ... 233 | 234 | } 235 | 236 | \framet{Semantics}{ 237 | 238 | > meaning time = id 239 | > meaning (lift0 a) = const a 240 | > meaning (lift1 f xs) = f . meaning xs 241 | > meaning (lift2 f xs ys) = liftA2 f (meaning xs) (meaning ys) 242 | > meaning (timeTrans xs tt) = meaning xs . meaning tt 243 | 244 | > instance Num a => Num (Behavior a) where 245 | > fromInteger = lift0 . fromInteger 246 | > (+) = lift2 (+) 247 | > ... 248 | 249 | } 250 | 251 | \framet{Events}{ 252 | 253 | \emph{Secondary} type: 254 | 255 | > meaning :: Event a -> [(T,a)] -- non-decreasing times 256 | 257 | > never :: Event a 258 | > once :: T -> a -> Event a 259 | > (.|.) :: Event a -> Event a -> Event a 260 | > (==>) :: Event a -> (a -> b) -> Event b 261 | > predicate :: Behavior Bool -> Event () 262 | > snapshot :: Event a -> Behavior b -> Event (a,b) 263 | 264 | \\[2ex] 265 | \emph{Exercise:} define semantics of these operations. 266 | } 267 | 268 | \framet{Reactivity}{ 269 | 270 | \emph{Reactive} behaviors are defined piecewise, via events.\hspace{-3pt}\pause: 271 | 272 | % \vspace{2ex} 273 | 274 | > switcher :: Behavior a -> Event (Behavior a) -> Behavior a 275 | 276 | \pause 277 | Semantics: 278 | 279 | > meaning (b0 `switcher` e) t = meaning (last (b0 : before t (meaning e))) t 280 | > SPACE 281 | > before :: T -> [(T,a)] -> [a] 282 | > before t os = [a | (ta,a) <- os, ta < t] 283 | 284 | Important: |ta < t|, rather than |ta <= t|. 285 | 286 | \out{ 287 | \pause \\ 288 | Event occurrences \emph{cannot} be extracted. 289 | (No |changes|/|updates|.) 290 | } 291 | % \pause \\ Question: Can occurrences be extracted (``|changes|'')? 292 | } 293 | 294 | \partframe{A more elegant specification \\[1.5ex] for FRP (teaser)} 295 | 296 | \framet{API}{ 297 | 298 | Replace operations with standard abstractions where possible: 299 | 300 | > instance Functor Behavior where ... 301 | > instance Applicative Behavior where ... 302 | > instance Monoid a => Monoid (Behavior a) where ... 303 | > SPACE 304 | > instance Functor Event where ... 305 | > instance Monoid (Event a) where ... 306 | 307 | Why?\pause 308 | \begin{itemize}\itemsep1.5ex 309 | \item Less learning, more leverage. 310 | \item Specifications and laws for free. 311 | \end{itemize} 312 | 313 | } 314 | 315 | \setlength{\fboxsep}{-1.7ex} 316 | 317 | \framet{Specifications for free}{ 318 | 319 | The \emph{instance's meaning} follows the \emph{meaning's instance}: 320 | \begin{center} 321 | \fbox{\begin{minipage}[c]{0.55\textwidth} 322 | 323 | > meaning (fmap f as) == fmap f (meaning as) 324 | > SPACE 325 | > meaning (pure a) == pure a 326 | > meaning (fs <*> xs) == meaning fs <*> meaning xs 327 | > SPACE 328 | > mu mempty == mempty 329 | > mu (top <> bot) == mu top <> mu bot 330 | 331 | \end{minipage}} 332 | \end{center} 333 | % So |meaning| is a homomorphism (distributes over class operations). 334 | \pause 335 | %Notes: 336 | \begin{itemize} 337 | \item Corresponds exactly to the original FRP denotation. 338 | \item Follows inevitably from a domain-independent principle. 339 | \item Laws hold for free\out{ (already paid for)}. 340 | %\item Details tomorrow. 341 | \end{itemize} 342 | } 343 | 344 | \partframe{History} 345 | 346 | \framet{1983--1989 at CMU}{ 347 | 348 | \begin{itemize}\itemsep2ex 349 | \item 350 | I went for graphics. 351 | \item 352 | Did program transformation, FP, type theory. 353 | \item 354 | Class in denotational semantics. 355 | \end{itemize} 356 | 357 | } 358 | 359 | \framet{1989 at CMU}{ 360 | 361 | \begin{itemize}\itemsep2ex 362 | \item 363 | {\parskip1ex 364 | Kavi Arya's visit: 365 | \begin{itemize}\parskip1ex 366 | \item \emph{Functional animation} 367 | \item Streams of pictures 368 | \item Elegant, mostly\pause 369 | \end{itemize} 370 | } 371 | \item John Reynolds's insightful remark:\\[1.5ex] 372 | { 373 | \parindent2ex 374 | \small 375 | ``You can think of streams as functions from the natural numbers.\\ 376 | \pause Have you thought about functions from the \emph{reals} instead?\\ 377 | Doing so might help with the awkwardness of interpolation.'' 378 | } 379 | \\[1.5ex] \emph{Continuous time!} 380 | \pitem 381 | I finished my dissertation anyway. 382 | \end{itemize} 383 | 384 | } 385 | 386 | \framet{1990--93 at Sun: \href{http://conal.net/tbag/}{TBAG}}{ 387 | 388 | \begin{itemize}\itemsep1.2ex 389 | \item 3D geometry etc as first-class immutable values. 390 | \item Animation as immutable functions of continuous time. 391 | \pause 392 | \item Multi-way constraints on time-functions. 393 | \\Off-the-shelf constraint solvers (DeltaBlue \& SkyBlue from UW). 394 | \item Differentiation, integration and ODEs specified via |derivative|. 395 | \\Adaptive Runge-Kutta-5 solver (fast \& accurate). 396 | \item Reactivity via \texttt{assert}/\texttt{retract} (high-level but imperative). 397 | \pause 398 | \item Optimizing compiler via partial evaluation. 399 | \item In Common Lisp, C++, Scheme. 400 | \item Efficient multi-user distributed execution for free. 401 | \end{itemize} 402 | 403 | } 404 | 405 | \framet{1994--1996 at Microsoft Research: RBML/ActiveVRML}{ 406 | 407 | \begin{itemize}\itemsep2ex 408 | \item Programming model \& fast implementation for new 3D hardware. 409 | \item TBAG + denotative/functional reactivity. 410 | \pause 411 | \item Add event algebra to behavior algebra. 412 | \item Reactivity via behavior-valued events. 413 | \item Drop multi-way constraints ``at first''. 414 | \pause 415 | \item Started in ML as ``RBML''. 416 | \item Rebranded to 417 | ``\href{http://conal.net/papers/ActiveVRML/}{ActiveVRML}'', then 418 | ``\href{http://www.sworks.com/keng/da.html}{DirectAnimation}''. 419 | \end{itemize} 420 | } 421 | 422 | \framet{1995--1999 at MSR: RBMH/Fran}{ 423 | 424 | \begin{itemize}\itemsep2ex 425 | \item 426 | Found Haskell: reborn as ``RBMH'' (research vehicle). 427 | \item 428 | Very fast implementation \href{http://conal.net/papers/padl99/}{via sprite engine}. 429 | \item 430 | John Hughes suggested using |Arrow|. 431 | \end{itemize} 432 | 433 | } 434 | 435 | \framet{1999 at MSR: \href{http://conal.net/papers/new-fran-draft.pdf}{first try} at push-based implementation}{ 436 | 437 | \begin{itemize}\parskip2ex 438 | \item Algebra of imperative event listeners. 439 | \item Challenges: 440 | \begin{itemize}\itemsep2ex 441 | \item 442 | Garbage collection \& dependency reversal. 443 | \item 444 | Determinacy of timing \& simultaneity. 445 | \item 446 | I doubt anyone has gotten correct. 447 | \end{itemize} 448 | \end{itemize} 449 | 450 | } 451 | 452 | \framet{2009: \href{http://conal.net/papers/push-pull-frp/}{Push-pull FRP}}{ 453 | 454 | \begin{itemize}\itemsep1.5ex 455 | \item Minimal computation, low latency, \emph{provably correct}. 456 | \item Push for reactivity and pull for continuous phases. 457 | \item ``Push'' is really blocked pull. 458 | \item 459 | More elegant API: 460 | \begin{itemize} 461 | \item Standard abstractions. 462 | \item Semantics as homomorphisms. 463 | \item Laws for free. 464 | \end{itemize} 465 | \item 466 | Reactive normal form, via equational properties (denotation!). 467 | \item 468 | Uses |lub| (basis of PL semantics). 469 | \item 470 | Implementation subtleties \& GHC RTS bugs. Didn't quite work. 471 | \end{itemize} 472 | 473 | } 474 | 475 | \framet{1996--2014: Paul Hudak / Yale}{ 476 | 477 | \begin{minipage}[c]{0.6\textwidth} 478 | \begin{itemize}\itemsep2ex 479 | \item Paul Hudak visited MSR in 1996 or so and saw RBMH. 480 | \item Encouraged publishing, and suggested collaboration. 481 | \item Proposed names ``Fran'' \& ``FRP''. 482 | \item \emph{Many} FRP-based papers and theses. 483 | \end{itemize} 484 | \end{minipage} 485 | \begin{minipage}[c]{1.8in} 486 | \begin{center} 487 | \wpicture{1.7in}{paul-hudak}\\ 488 | {\small July 15, 1952 -- April 29, 2015} 489 | \end{center} 490 | \end{minipage} 491 | } 492 | 493 | \out{ 494 | 495 | \framet{2012--now: ``FRP'' diffusion}{ 496 | 497 | \begin{itemize} 498 | \item ``FRP'' systems appear that lack both fundamental properties: 499 | \begin{itemize} 500 | \item Elm 501 | \item Bacon 502 | \end{itemize} 503 | \end{itemize} 504 | 505 | } 506 | } 507 | 508 | \partframe{Questions} 509 | 510 | \framet{}{ 511 | \begin{center} 512 | \Large 513 | ``But computers are discrete, ...'' 514 | \end{center} 515 | } 516 | 517 | \end{document} 518 | --------------------------------------------------------------------------------