Difference between revisions of "Functional Reactive Programming"

From HaskellWiki
Jump to: navigation, search
(Libraries: Added a link to the Sodium package)
m
 
(32 intermediate revisions by 13 users not shown)
Line 1: Line 1:
 
Functional Reactive Programming (FRP) integrates time flow and compositional events into functional programming.  This provides an elegant way to express computation in domains such as interactive animations, robotics, computer vision, user interfaces, and simulation.
 
Functional Reactive Programming (FRP) integrates time flow and compositional events into functional programming.  This provides an elegant way to express computation in domains such as interactive animations, robotics, computer vision, user interfaces, and simulation.
 +
 +
 +
== Introduction ==
 +
 +
The original formulation of Functional Reactive Programming can be found in the ICFP 97 paper [http://conal.net/papers/icfp97/ Functional Reactive Animation] by Conal Elliott and Paul Hudak. It introduces the following ''semantic functions'':
 +
 +
* <b>at</b> : <i>Behavior<sub>α</sub> → Time → α</i>
 +
 +
* <b>occ</b> : <i>Event<sub>α</sub> → Time × α</i>
 +
 +
to provide a formal description of operations on values now commonly known as ''behaviors'' and ''events''. But what are they?
 +
 +
=== Behaviors ===
 +
 +
Traditionally a widget-based user interface is created by a series of imperative actions.  First an action is invoked to create an edit widget, then additional actions can be invoked to read its current content, set it to a specific value or to assign an event callback for when the content changes.  This is tedious and error-prone.
 +
 +
A better way to represent an edit widget's content is a time-varying value, called a ''behavior''.  The basic idea is that a time-varying value can be represented as a function of time:
 +
 +
<haskell>
 +
newtype Behavior a =
 +
    Behavior {
 +
      at :: Time -> a
 +
    }
 +
 +
myTodoList                :: Behavior Text
 +
yesterday                :: Time
 +
myTodoList `at` yesterday :: Text
 +
</haskell>
 +
 +
This is only a theoretical model, because a time-varying value can represent something impure like the content of an edit widget, the current value of a database entry as well as the system clock's current time.  Using this model the current content of an edit widget would be a regular first class value:
 +
 +
<haskell>
 +
myEditWidget :: Behavior Text
 +
</haskell>
 +
 +
In most frameworks there is an applicative interface for behaviors, such that you can combine them easily:
 +
 +
<haskell>
 +
liftA2 (<>) myEdit1 myEdit2
 +
</haskell>
 +
 +
The result is a time-varying value that represents the concatenation of <hask>myEdit1</hask> and <hask>myEdit2</hask>.  This could be the value of a third widget, a label, to display the concatenation.  The following is a hypothetical example:
 +
 +
<haskell>
 +
do edit1 <- editWidget
 +
  edit2 <- editWidget
 +
  label <- label (liftA2 (<>) edit1 edit2)
 +
  {- ... -}
 +
</haskell>
 +
 +
Without behaviors you would have to write event callback ''actions'' for the edit widgets to ''update'' the label's content.  With behaviors you can express this relationship declaratively.
 +
 +
=== Events ===
 +
 +
While behaviours work well for describing properties which are continuous (e.g. the motion of an animated object), other properties are more ''discrete'' (e.g. what button on the mouse was clicked or the screen position where it happened). Events more easily accommodate information like this, by associating the data value of interest with a particular time:
 +
 +
<haskell>
 +
newtype Event a =
 +
    Event {
 +
      occ :: (Time, a)
 +
    }
 +
 +
mouseInWindowNow    :: Event Bool
 +
occ mouseInWindowNow :: (Time, Bool)
 +
</haskell>
 +
 +
A series of events is most easily represented as a list of <code>Event</code>-values, commonly referred to as an ''event stream'' (or simply a ''stream'').
  
 
== Libraries ==
 
== Libraries ==
* [http://hackage.haskell.org/package/sodium Sodium]
+
* [[DataDriven]]
 +
* [http://hackage.haskell.org/package/elerea Elerea]
 +
* [http://conal.net/fran/ Fran] (discontinued)
 
* [[Grapefruit]]
 
* [[Grapefruit]]
 +
* [[Netwire]]
 
* [[Reactive]]
 
* [[Reactive]]
* [[DataDriven]]
+
* [[Reactive-banana|reactive-banana]]
 +
* [https://reflex-frp.org/ Reflex]
 +
* [http://hackage.haskell.org/package/sodium Sodium]
 +
* [[WxFruit|wxFruit]]
 
* [[Yampa]]
 
* [[Yampa]]
* [[WxFruit|wxFruit]]
+
*[[https://github.com/ivanperez-keera/dunai Dunai]]
* [http://hackage.haskell.org/package/elerea Elerea]
+
* [[Rhine]]
* [[Reactive-banana|reactive-banana]]
+
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:FRP Hackage packages in the category FRP]
* [[Netwire]]
+
A simple, practical comparison between FRP libraries is done by [https://github.com/gelisam/frp-zoo frp-zoo]
* [http://conal.net/fran/ Fran] (discontinued)
+
 
 +
== Publications and talks ==
 +
 
 +
* [https://www.youtube.com/watch?v=zgNRM8tZguY ICFP 2014: Settable and Non-Interfering Signal Functions for FRP - Daniel Winograd-Cort] (video)
 +
* [https://web.archive.org/web/20150217184805/https://www.cs.rit.edu/~eca7215/frp-independent-study/Survey.pdf A Survey of Functional Reactive Programming]
 +
* [http://conal.net/papers/frp.html Conal Elliott’s FRP-related publications]
 +
* [https://wolfgang.jeltsch.info/publications-and-talks Grapefruit-related publications and talks]
 +
* [https://web.archive.org/web/20171012164802/http://haskell.cs.yale.edu/publications/#FunctionalReactiveProgramming The Yale Haskell Group’s FRP-related publications] (archived)
 +
* [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.11.6997&rep=rep1&type=pdf FROB: A Transformational Approach to the Design of Robot Software - Gregory D. Hager and John Peterson]
 +
* [https://begriffs.com/posts/2015-07-22-essence-of-frp.html The Essence of FRP (Conal Elliott -- July 22, 2015 -- video)]
 +
* [https://begriffs.com/posts/2016-07-27-tikhon-on-frp.html A Sensible Intro to FRP (Tikhon Jelvis -- July 27, 2016 -- video)]
 +
 
 +
== Books ==
 +
* Blackheath, Stephen; Jones, Antony. [http://www.manning.com/blackheath Functional Reactive Programming]. Manning Publications (2015). p.245. ISBN 978-1-6334-3010-5
  
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:frp Hackage packages in the category FRP]
+
== Blog posts ==
  
== Material ==
+
* [https://github.com/gelisam/frp-zoo frp-zoo]; comparing many FRP implementations by reimplementing the same toy app in each.
* [http://www.cs.rit.edu/~eca7215/frp-independent-study/Survey.pdf A Survey of Functional Reactive Programming] (PDF)
+
* [http://blog.reactiveprogramming.org/ Functional Reactive Programming, a better way to build interactive applications] (about the Sodium FRP Library currently for C#, C++, Haskell and Java and more to come)
* Conal Elliott’s FRP-related [http://conal.net/papers/frp.html papers] and [http://conal.net/blog/tag/functional-reactive-programming/ blog posts]
+
* [http://apfelmus.nfshost.com/blog.html#functional-reactive-programming-frp FRP-related posts on Heinrich Apfelmus’ blog]
* [[Grapefruit#Publications and talks|Grapefruit-related publications and talks]]
+
* [http://conal.net/blog/tag/frp FRP-related posts on Conal Elliott’s blog]
* [http://haskell.cs.yale.edu/?page_id=65#FunctionalReactiveProgramming The Yale Haskell group’s latest publications] on functional reactive programming
+
* [http://jeltsch.wordpress.com/tag/frp/ FRP-related posts on Wolfgang Jeltsch’s blog]
* [http://apfelmus.nfshost.com/blog.html#functional-reactive-programming-frp FRP section] of Heinrich Apfelmus' blog
+
* [http://lukepalmer.wordpress.com/2008/11/28/relative-time-frp/ Relative time FRP] by Luke Palmer
 +
* [http://blog.edwardamsden.com/2011/03/demonstrating-time-leak-in-arrowized.html Demonstrating a Time Leak in Arrowized FRP] by Edward Amsden
 +
* [https://www.reddit.com/r/haskell/comments/3fr5ij/frp_systems_discussion/ FRP Systems discussion] on reddit
 +
* [https://t0yv0.blogspot.com/2014/07/the-fatal-attraction-of-frp.html The fatal attraction of FRP] by  Anton Tayanovskyy (about the WebSharper UI.Next framework for single-page JavaScript applications)
  
 
== People ==
 
== People ==
 
* [http://apfelmus.nfshost.com/ Heinrich Apfelmus]
 
* [http://apfelmus.nfshost.com/ Heinrich Apfelmus]
* [http://www.apocalypse.org/pub/u/antony/work/index.html Antony Courtney]
+
* [http://www.facebook.com/antony.courtney Antony Courtney]
 
* [http://conal.net/ Conal Elliott]
 
* [http://conal.net/ Conal Elliott]
 
* [http://sgate.emt.bme.hu/patai/ Patai Gergely]
 
* [http://sgate.emt.bme.hu/patai/ Patai Gergely]
* [http://www.ittc.ku.edu/~andygill Andy Gill]
+
* [http://www.ittc.ku.edu/csdl/fpg/Users/AndyGill Andy Gill]
 
* Liwen Huang
 
* Liwen Huang
 
* Paul Hudak
 
* Paul Hudak
* [http://www.tu-cottbus.de/fakultaet1/de/programmiersprachen-compilerbau/lehrstuhl/mitarbeiter/wolfgang-jeltsch.html Wolfgang Jeltsch]
+
* [https://wolfgang.jeltsch.info/ Wolfgang Jeltsch]
 
* [http://www.cs.nott.ac.uk/~nhn/ Henrik Nilsson]
 
* [http://www.cs.nott.ac.uk/~nhn/ Henrik Nilsson]
 +
* [http://github.com/ivanperez-keera Ivan Perez]
 
* [http://mcis.western.edu/~jpeterson/ John Peterson]
 
* [http://mcis.western.edu/~jpeterson/ John Peterson]
 +
* Ertugrul Söylemez
 +
 +
== History ==
 +
 +
=== A possible predecessor? ===
 +
 +
In his thesis [https://core.ac.uk/download/9835633.pdf Functional Real-Time Programming: The Language Ruth And Its Semantics], some parts of the semantics Dave Harrison gives for ''Ruth'' bears a curious resemblance to those for FRP:
 +
 +
* from page 48:
 +
:{|
 +
|<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 +
A channel is an infinite stream of timestamped data values, or messages, each message denoting an event in the system.
 +
</div>
 +
<sup> </sup>
 +
<haskell>
 +
type Channel a = [Event a]
 +
</haskell>
 +
|}
 +
 +
* from page 50:
 +
:{|
 +
|<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 +
A unique clock is automatically supplied to each Ruth process at run-time, to provide real-time information, [...]
 +
</div>
 +
<sup> </sup>
 +
<haskell>
 +
type Process a = Clock -> a
 +
</haskell>
 +
 +
where a <code>Clock</code> value is a tree of time-values, in contrast to the direct use of time-values in FRP:
 +
<haskell>
 +
-- from page 61
 +
type Clock = Tree Time
 +
type Time  = Integer -- must be zero or larger
 +
 +
data Tree a = Node { contents :: a,
 +
                    left    :: Tree a,
 +
                    right    :: Tree a }
 +
</haskell>
 +
|}
  
== Blog articles ==
+
As a ''Ruth'' process runs, the nodes of the clock are used incrementally:
* [http://lukepalmer.wordpress.com/2008/11/28/relative-time-frp/ Relative time FRP]
+
* to ascertain the current time (<code>contents</code>), and
* Several on [http://conal.net/blog Conal's blog]
+
* to provide other clocks for use elsewhere  (<code>left</code> and <code>right</code>).
* [http://blog.edwardamsden.com/2011/03/demonstrating-time-leak-in-arrowized.html Demonstrating a Time Leak in Arrowized FRP]
 
  
 
[[Category:FRP|*]]
 
[[Category:FRP|*]]

Latest revision as of 12:52, 14 December 2021

Functional Reactive Programming (FRP) integrates time flow and compositional events into functional programming. This provides an elegant way to express computation in domains such as interactive animations, robotics, computer vision, user interfaces, and simulation.


Introduction

The original formulation of Functional Reactive Programming can be found in the ICFP 97 paper Functional Reactive Animation by Conal Elliott and Paul Hudak. It introduces the following semantic functions:

  • at : Behaviorα → Time → α
  • occ : Eventα → Time × α

to provide a formal description of operations on values now commonly known as behaviors and events. But what are they?

Behaviors

Traditionally a widget-based user interface is created by a series of imperative actions. First an action is invoked to create an edit widget, then additional actions can be invoked to read its current content, set it to a specific value or to assign an event callback for when the content changes. This is tedious and error-prone.

A better way to represent an edit widget's content is a time-varying value, called a behavior. The basic idea is that a time-varying value can be represented as a function of time:

newtype Behavior a =
    Behavior {
      at :: Time -> a
    }

myTodoList                :: Behavior Text
yesterday                 :: Time
myTodoList `at` yesterday :: Text

This is only a theoretical model, because a time-varying value can represent something impure like the content of an edit widget, the current value of a database entry as well as the system clock's current time. Using this model the current content of an edit widget would be a regular first class value:

myEditWidget :: Behavior Text

In most frameworks there is an applicative interface for behaviors, such that you can combine them easily:

liftA2 (<>) myEdit1 myEdit2

The result is a time-varying value that represents the concatenation of myEdit1 and myEdit2. This could be the value of a third widget, a label, to display the concatenation. The following is a hypothetical example:

do edit1 <- editWidget
   edit2 <- editWidget
   label <- label (liftA2 (<>) edit1 edit2)
   {- ... -}

Without behaviors you would have to write event callback actions for the edit widgets to update the label's content. With behaviors you can express this relationship declaratively.

Events

While behaviours work well for describing properties which are continuous (e.g. the motion of an animated object), other properties are more discrete (e.g. what button on the mouse was clicked or the screen position where it happened). Events more easily accommodate information like this, by associating the data value of interest with a particular time:

newtype Event a =
    Event {
      occ :: (Time, a)
    }

mouseInWindowNow     :: Event Bool
occ mouseInWindowNow :: (Time, Bool)

A series of events is most easily represented as a list of Event-values, commonly referred to as an event stream (or simply a stream).

Libraries

A simple, practical comparison between FRP libraries is done by frp-zoo

Publications and talks

Books

Blog posts

People

History

A possible predecessor?

In his thesis Functional Real-Time Programming: The Language Ruth And Its Semantics, some parts of the semantics Dave Harrison gives for Ruth bears a curious resemblance to those for FRP:

  • from page 48:

A channel is an infinite stream of timestamped data values, or messages, each message denoting an event in the system.

type Channel a = [Event a]
  • from page 50:

A unique clock is automatically supplied to each Ruth process at run-time, to provide real-time information, [...]

type Process a = Clock -> a

where a Clock value is a tree of time-values, in contrast to the direct use of time-values in FRP:

 -- from page 61
type Clock = Tree Time
type Time  = Integer -- must be zero or larger

data Tree a = Node { contents :: a,
                     left     :: Tree a,
                     right    :: Tree a }

As a Ruth process runs, the nodes of the clock are used incrementally:

  • to ascertain the current time (contents), and
  • to provide other clocks for use elsewhere (left and right).