Old-reactive
From HaskellWiki
m (→Data.Reactive) |
(Category:Reactivity removed (overlap with FRP), Category:Event removed (it is for meetings)) |
||
(8 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | |||
− | |||
[[Category:FRP]] | [[Category:FRP]] | ||
[[Category:Packages]] | [[Category:Packages]] | ||
Line 6: | Line 4: | ||
== Abstract == | == Abstract == | ||
− | '''Reactive''' is a simple foundation for programming reactive systems functionally. Like Fran/FRP, it has a notions of (reactive) behaviors and events. Like [[DataDriven]], Reactive has an efficient, data-driven implementation. The main difference between Reactive and DataDriven are | + | '''Note:''' I have retired the old version of Reactive on darcs.haskell.org. |
+ | Please use the new [[Reactive]]. | ||
+ | |||
+ | ---- | ||
+ | |||
+ | '''Reactive''' is a simple foundation for [[Functional Reactive Programming|programming reactive systems functionally]]. Like Fran/FRP, it has a notions of (reactive) behaviors and events. Like [[DataDriven]], Reactive has an efficient, data-driven implementation. The main difference between Reactive and DataDriven are | ||
* Reactive provides and builds on "functional futures", which in turn build on [[GHC/Concurrency|Concurrent Haskell]] threads, while DataDriven builds on continuation-based computations; and | * Reactive provides and builds on "functional futures", which in turn build on [[GHC/Concurrency|Concurrent Haskell]] threads, while DataDriven builds on continuation-based computations; and | ||
* The algebras of events and reactive values (called events and sources in DataDriven) are ''purely'' functional. I couldn't figure out how to accomplish that in DataDriven. | * The algebras of events and reactive values (called events and sources in DataDriven) are ''purely'' functional. I couldn't figure out how to accomplish that in DataDriven. | ||
Line 13: | Line 16: | ||
* Reactive uses the term "reactive values" (<hask>Reactive</hask>), where DataDriven uses "sources" (<hask>Source</hask>). | * Reactive uses the term "reactive values" (<hask>Reactive</hask>), where DataDriven uses "sources" (<hask>Source</hask>). | ||
− | The inspiration for Reactive was Mike Sperber's | + | The inspiration for Reactive was Mike Sperber's [http://www-pu.informatik.uni-tuebingen.de/lula/deutsch/publications.html Lula] implementation of FRP. Mike used blocking threads, which I had never considered for FRP before a conversation with him at ICFP 2007. While playing with the idea, I realized that I could give a very elegant and efficient solution to caching, which DataDriven doesn't do. (For an application <hask>f <*> a</hask> of a varying function to a varying argument, caching remembers the latest function to apply to a new argument and the latest argument to which to apply a new function.) |
As with [[DataDriven]], Reactive provides instances for <hask>Monoid</hask>, <hask>Functor</hask>, <hask>Applicative</hask>, and <hask>Monad</hask>. | As with [[DataDriven]], Reactive provides instances for <hask>Monoid</hask>, <hask>Functor</hask>, <hask>Applicative</hask>, and <hask>Monad</hask>. | ||
Line 19: | Line 22: | ||
Besides this wiki page, here are more ways to find out about Reactive: | Besides this wiki page, here are more ways to find out about Reactive: | ||
* Read [http://darcs.haskell.org/packages/reactive/doc/html the Haddock docs]. | * Read [http://darcs.haskell.org/packages/reactive/doc/html the Haddock docs]. | ||
− | * Get the code repository: '''<tt>darcs get http://darcs.haskell.org/packages/reactive</tt>'''. | + | * Get the code repository: '''<tt>darcs get http://darcs.haskell.org/packages/old-reactive/</tt>'''. (Old version, to be replaced in September 08.) |
* Install from [http://hackage.haskell.org Hackage]. | * Install from [http://hackage.haskell.org Hackage]. | ||
* See the [[Reactive/Versions| version history]]. | * See the [[Reactive/Versions| version history]]. | ||
− | + | Also, the paper ''[http://conal.net/papers/simply-reactive/ Simply Efficient Functional Reactivity]'', and its [http://conal.net/blog/posts/simply-efficient-functional-reactivity/ blog post with discussion], describe a (not-yet-released) successor to Reactive that solves the determinacy problem mentioned below. | |
== Modules == | == Modules == |
Latest revision as of 10:40, 17 July 2011
Contents |
[edit] 1 Abstract
Note: I have retired the old version of Reactive on darcs.haskell.org. Please use the new Reactive.
Reactive is a simple foundation for programming reactive systems functionally. Like Fran/FRP, it has a notions of (reactive) behaviors and events. Like DataDriven, Reactive has an efficient, data-driven implementation. The main difference between Reactive and DataDriven are
- Reactive provides and builds on "functional futures", which in turn build on Concurrent Haskell threads, while DataDriven builds on continuation-based computations; and
- The algebras of events and reactive values (called events and sources in DataDriven) are purely functional. I couldn't figure out how to accomplish that in DataDriven.
- Reactive manages (I hope) to get the efficiency of data-driven computation with a (sort-of) demand-driven architecture. For that reason, Reactive is garbage-collector-friendly, while DataDriven depends on weak references (because GC favors demand-driven computation.)
- Reactive elegantly and efficiently caches values.
- Reactive uses the term "reactive values" (), where DataDriven uses "sources" (Reactive).Source
Besides this wiki page, here are more ways to find out about Reactive:
- Read the Haddock docs.
- Get the code repository: darcs get http://darcs.haskell.org/packages/old-reactive/. (Old version, to be replaced in September 08.)
- Install from Hackage.
- See the version history.
Also, the paper Simply Efficient Functional Reactivity, and its blog post with discussion, describe a (not-yet-released) successor to Reactive that solves the determinacy problem mentioned below.
[edit] 2 Modules
[edit] 2.1 Data.Future
A future is a value that will become knowable only later. Primitive futures can be things like "the value of the next key you press", or "the value of LambdaPix stock at noon next Monday". The term "promise" might be more fitting.
Composition is via standard type classes:- :Monoidis a future that never becomes knowable.memptyis whichever ofa `mappend` bandais knowable first.b
- : apply a function to a future. The result is knowable when the given future is knowable.Functor
- :Applicativegives value knowable since the beginning of time.pureapplies a future function to a future argument. Result available when both are available, i.e., it becomes knowable when the later of the two futures becomes knowable.(<*>)
- Monad: is the same asreturn(as always).purecascades futures.(>>=)resolves a future future value into a future value.join
[edit] 2.1.1 Garbage collection of futures
Baker & Hewitt's 1977 paper The Incremental Garbage Collection of Processes discusses using garbage collection to prevent the useless threads from consuming resources. In particular, consider[edit] 2.1.2 Concurrent Haskell vs STM
Futures are implemented using Concurrent Haskell's[edit] 2.2 Data.SFuture
A target denotational semantics for Data.Future -- simple, precise, and deterministic, in terms of time/value pairs.
[edit] 2.3 Data.Reactive
This module defines events and reactive values. An event is stream of future values in order of availability. A reactive value is a discretly time-varying value. These two types are closely linked: a reactive value is defined by an initial value and an event that yields future values; while an event is simply a future reactive value.
data Reactive a = a `Stepper` Event a newtype Event a = Event (Future (Reactive a))
Many of the operations on events and reactive values are packaged as instances of standard classes, as described below. See the module documentation for the other operations.
[edit] 2.3.1 Instances for Event
- :Monoidis the event that never occurs, andmemptyis the event that combines occurrences frome `mappend` e'ande. (Fran'se'andneverE.)(.|.)
- :Functoris the event that occurs wheneverfmap f eoccurs, and whose occurrence values come from applyingeto the values fromf. (Fran'se.)(==>)
- :Applicativeis an event with a single occurrence, available from the beginning of time.pure ais an event whose occurrences are made from the product of the occurrences ofef <*> exandef. For every occurrenceexat timefoftfand occurrenceefat timexoftx,exhas an occurrenceef <*> exat timef x.max tf tx
- :Monadis the same asreturn a(as always). Inpure a, each occurrence ofe >>= fleads, throughe, to a new event. Similarly forf, which is somehow simpler for me to think about. The occurrences ofjoin ee(ore >>= f) correspond to the union of the occurrences of all such events. For example, suppose we're playing Asteroids and tracking collisions. Each collision can break an asteroid into more of them, each of which has to be tracked for more collisions. Another example: A chat room has an "enter" event, whose occurrences contain new events like "speak".join ee
[edit] 2.3.2 Instances for Reactive
The instances for- : a typical lifted monoid. IfMonoidis a monoid, thenois a monoid, withReactive o, andmempty = pure mempty. In other words,mappend = liftA2 mappend, andmempty `at` t == mempty(r `mappend` s) `at` t == (r `at` t) `mappend` (s `at` t).
- :Functor.fmap f r `at` t == f (r `at` t)
- :Applicative, andpure a `at` t == a.(s <*> r) `at` t == (s `at` t) (r `at` t)
- :Monad, andreturn a `at` t == a. As always,join rr `at` t == (rr `at` t) `at` t.(r >>= f) == join (fmap f r)
[edit] 2.3.3 Continuous reactive behaviors
Although the basictype Time = Double type ReactiveB = Reactive :. Fun Time