HaskellWiki

Haskell | Wiki community | Recent changes
Random page | Special pages

 

Not logged in
Log in | Help

Reactive

Categories: Events | Reactivity | FRP | Packages


Contents

1 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

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:

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.

Please leave comments at the Talk page.

2 Modules

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: Functor, Applicative, Monad, and Monoid.

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.

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 Future's mappend (sometimes called "parallel or"). Once one thread completes, the other threads are then useless, and some might consume resources forever. My current implementation kill the losing threads. Baker & Hewitt suggest instead using garbage collection. I'm stumped about how to GC non-winning threads in a race between futures ("parallel or"). The winner-kills-loser approach seems to work fine, though is potentially dangerous w.r.t locked resources. Still, the elegance of a GC-based solution appeals to me.

2.1.2 Concurrent Haskell vs STM

Futures are implemented using Concurrent Haskell's MVars. I first tried using STM and TVars, simply using orElse to implement mappend for futures. However, I didn't see how to avoid nesting atomically, which yielded a run-time error.

2.2 Data.SFuture

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

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))

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.

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.

2.3.1 Instances for Event

2.3.2 Instances for Reactive

The instances for Reactive can be understood in terms of (a) a simple semantics of reactive values as functions of time, and (b) the corresponding instances for functions. The semantics is given by the function at :: Reactive a -> (Time -> a).

2.3.3 Continuous reactive behaviors

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.

2.4 Data.Fun

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

Retrieved from "http://haskell.org/haskellwiki/Reactive"

This page has been accessed 4,678 times. This page was last modified 08:49, 1 August 2008. Recent content is available under a simple permissive license.