Difference between revisions of "Old-reactive"

From HaskellWiki
Jump to navigation Jump to search
(Preparing for 0.0 release)
Line 6: Line 6:
 
== 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 a data-driven implementation. The main difference between Reactive and DataDriven are
+
'''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 builds on STM-based IVars, 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 algebra 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.
 
* 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 [[DataDriven#GC_favors_demand-driven_computation|GC favors demand-driven computation]].)
 
* 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 [[DataDriven#GC_favors_demand-driven_computation|GC favors demand-driven computation]].)
  +
* Reactive elegantly and efficiently ''caches'' values.
  +
* Reactive uses the term "rneactive values" (<hask>Reactive</hask>), where DataDriven uses "sources" (<hask>Source</hask>).
   
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. 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 last argument to which to apply a new function.)
+
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 Monoid, Functor, Applicative, and Monad.
+
As with [[DataDriven]], Reactive provides instances for <hask>Monoid</hask>, <hask>Functor</hask>, <hask>Applicative</hask>, and <hask>Monad</hask>.
   
 
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/reactive the Haddock docs].
 
* Read [http://darcs.haskell.org/packages/reactive/doc/html/reactive 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/reactive</tt>'''.
* Install from Hackage (''coming'').
+
* Install from [http://hackage.haskell.org Hackage].
 
* See the [[Reactive/Versions| version history]].
 
* See the [[Reactive/Versions| version history]].
   
 
Please leave comments at the [[Talk:Reactive|Talk page]].
 
Please leave comments at the [[Talk:Reactive|Talk page]].
   
== IVars ==
+
== Modules ==
   
  +
=== Data.Future ===
== Events and reactive values ==
 
   
  +
A "[http://en.wikipedia.org/wiki/Futures_and_promises 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".
== Constant-optimized functions ==
 
  +
  +
Composition is via standard type classes: <hask>Functor</hask>, <hask>Applicative</hask>, <hask>Monad</hask>, and <hask>Monoid</hask>.
  +
* <hask>Monoid</hask>: <hask>mempty</hask> is a future that never becomes knowable. <hask>a `mappend` b</hask> is whichever of <hask>a</hask> and <hask>b</hask> is knowable first.
  +
* <hask>Functor</hask>: apply a function to a future. The result is knowable when the given future is knowable.
  +
* <hask>Applicative</hask>: <hask>pure</hask> gives value knowable since the beginning of time. <hask>(<*>)</hask> applies 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: <hask>return</hask> is the same as <hask>pure</hask> (as always). <hask>(>>=)</hask> cascades futures. <hask>join</hask> resolves a future future value into a future value.
  +
  +
The current implementation is nondeterministic in <hask>mappend</hask> for futures that become knowable at the same time or nearly the same time. I want to make a deterministic implementation.
  +
  +
=== Data.SFuture ===
  +
  +
A denotational semantics for Data.Future -- simple, precise, and deterministic, in terms of time/value pairs.
  +
  +
=== 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 a current value and an event (the future values), while an event is simply a future reactive value.
  +
<haskell>
  +
newtype Event a = Event (Future (Reactive a))
  +
data Reactive a = Reactive a (Event a)
  +
</haskell>
  +
  +
This <hask>Reactive</hask> representation can be thought of a "reactive weak head normal form", to which arbitrary reactive expressions may be rewritten. The rewrite rules and their justification in terms of simple denotational semantics will be described in an upcoming paper.
  +
  +
Although the basic <hask>Reactive</hask> type describes ''discretely''-changing values, ''continuously''-changing are defined simply by composing <hask>Reactive</hask> and a simple type functions of time (see below).
  +
<haskell>
  +
type Time = Double
  +
type ReactiveB = Reactive :. Fun Time
  +
</haskell>
  +
Because the combination of <hask>Reactive</hask> and <hask>Fun Time</hask> is wrapped in a [[TypeCompose|type composition]], we get <hask>Functor</hask> and <hask>Applicative</hask> instances for free.
  +
  +
The exact packaging of discrete vs continuous will probably change with more experience. Perhaps I'll fold <hask>Fun Time a</hask> into the <hask>Reactive</hask> type, making a dynamic rather than static distinction.
  +
  +
=== Data.Fun ===
  +
  +
This module defines a type of functions optimized for the constant case, together with instances of <hask>Functor</hask>, <hask>Applicative</hask>, <hask>Monad</hask>, and <hask>Arrow</hask>.

Revision as of 00:23, 19 December 2007


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

  • 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 "rneactive values" (Reactive), where DataDriven uses "sources" (Source).

The inspiration for Reactive was Mike Sperber's [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 f <*> a 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 Monoid, Functor, Applicative, and Monad.

Besides this wiki page, here are more ways to find out about Reactive:

Please leave comments at the Talk page.

Modules

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".

Composition is via standard type classes: Functor, Applicative, Monad, and Monoid.

  • Monoid: mempty is a future that never becomes knowable. a `mappend` b is whichever of a and b is knowable first.
  • Functor: apply a function to a future. The result is knowable when the given future is knowable.
  • Applicative: pure gives value knowable since the beginning of time. (<*>) applies 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: return is the same as pure (as always). (>>=) cascades futures. join resolves a future future value into a future value.

The current implementation is nondeterministic in mappend for futures that become knowable at the same time or nearly the same time. I want to make a deterministic implementation.

Data.SFuture

A denotational semantics for Data.Future -- simple, precise, and deterministic, in terms of time/value pairs.

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 a current value and an event (the future values), while an event is simply a future reactive value.

newtype Event a = Event (Future (Reactive a))
data Reactive a = Reactive a (Event a)

This Reactive representation can be thought of a "reactive weak head normal form", to which arbitrary reactive expressions may be rewritten. The rewrite rules and their justification in terms of simple denotational semantics will be described in an upcoming paper.

Although the basic Reactive type describes discretely-changing values, continuously-changing are defined simply by composing Reactive and a simple type functions of time (see below).

type Time = Double
type ReactiveB = Reactive :. Fun Time

Because the combination of Reactive and Fun Time is wrapped in a type composition, we get Functor and Applicative instances for free.

The exact packaging of discrete vs continuous will probably change with more experience. Perhaps I'll fold Fun Time a into the Reactive type, making a dynamic rather than static distinction.

Data.Fun

This module defines a type of functions optimized for the constant case, together with instances of Functor, Applicative, Monad, and Arrow.