Stability | experimental |
---|---|
Maintainer | conal@conal.net |
Safe Haskell | None |
FRP.Reactive
Description
A library for programming with functional reactive behaviors.
- type TimeT = Double
- type ITime = ImpBounds TimeT
- data EventG t a
- type Event = EventG ITime
- accumE :: a -> EventG t (a -> a) -> EventG t a
- withTimeE :: Ord t => EventG (ImpBounds t) d -> EventG (ImpBounds t) (d, t)
- withTimeE_ :: Ord t => EventG (ImpBounds t) d -> EventG (ImpBounds t) t
- zipE :: (Ord t, Bounded t) => (c, d) -> (EventG t c, EventG t d) -> EventG t (c, d)
- scanlE :: (Ord t, Bounded t) => (a -> b -> a) -> a -> EventG t b -> EventG t a
- monoidE :: (Ord t, Bounded t, Monoid o) => EventG t o -> EventG t o
- mealy :: (Ord t, Bounded t) => s -> (s -> s) -> EventG t b -> EventG t (b, s)
- mealy_ :: (Ord t, Bounded t) => s -> (s -> s) -> EventG t b -> EventG t s
- countE :: (Ord t, Bounded t, Num n) => EventG t b -> EventG t (b, n)
- countE_ :: (Ord t, Bounded t, Num n) => EventG t b -> EventG t n
- diffE :: (Ord t, Bounded t, AffineSpace a) => EventG t a -> EventG t (Diff a)
- withPrevE :: (Ord t, Bounded t) => EventG t a -> EventG t (a, a)
- withPrevEWith :: (Ord t, Bounded t) => (a -> a -> b) -> EventG t a -> EventG t b
- eitherE :: (Ord t, Bounded t) => EventG t a -> EventG t b -> EventG t (Either a b)
- justE :: (Ord t, Bounded t) => EventG t (Maybe a) -> EventG t a
- filterE :: (Ord t, Bounded t) => (a -> Bool) -> EventG t a -> EventG t a
- listE :: [(TimeT, a)] -> Event a
- atTimes :: [TimeT] -> Event ()
- atTime :: TimeT -> Event ()
- once :: (Ord t, Bounded t) => EventG t a -> EventG t a
- firstRestE :: (Ord t, Bounded t) => EventG t a -> (a, EventG t a)
- firstE :: (Ord t, Bounded t) => EventG t a -> a
- restE :: (Ord t, Bounded t) => EventG t a -> EventG t a
- snapRemainderE :: (Ord t, Bounded t) => EventG t b -> EventG t a -> EventG t (a, EventG t b)
- withRestE :: EventG t a -> EventG t (a, EventG t a)
- untilE :: (Ord t, Bounded t) => EventG t a -> EventG t b -> EventG t a
- splitE :: (Ord t, Bounded t) => EventG t b -> EventG t a -> EventG t (a, EventG t b)
- switchE :: (Ord t, Bounded t) => EventG t (EventG t a) -> EventG t a
- joinMaybes :: MonadPlus m => m (Maybe a) -> m a
- filterMP :: MonadPlus m => (a -> Bool) -> m a -> m a
- data BehaviorG tr tf a
- type Behavior = BehaviorI TimeT
- type Behaviour = Behavior
- time :: Ord t => BehaviorI t t
- stepper :: a -> EventI t a -> BehaviorI t a
- switcher :: (Ord tr, Bounded tr) => BehaviorG tr tf a -> EventG tr (BehaviorG tr tf a) -> BehaviorG tr tf a
- snapshotWith :: Ord t => (a -> b -> c) -> BehaviorI t b -> EventI t a -> EventI t c
- snapshot :: Ord t => BehaviorI t b -> EventI t a -> EventI t (a, b)
- snapshot_ :: Ord t => BehaviorI t b -> EventI t a -> EventI t b
- whenE :: Ord t => BehaviorI t Bool -> EventI t a -> EventI t a
- accumB :: a -> EventI t (a -> a) -> BehaviorI t a
- scanlB :: forall a b tr tf. (Ord tr, Bounded tr) => (b -> BehaviorG tr tf a -> BehaviorG tr tf a) -> BehaviorG tr tf a -> EventG tr b -> BehaviorG tr tf a
- monoidB :: (Ord tr, Bounded tr, Monoid a) => EventG tr (BehaviorG tr tf a) -> BehaviorG tr tf a
- maybeB :: Ord t => EventI t a -> EventI t b -> BehaviorI t (Maybe a)
- flipFlop :: Ord t => EventI t a -> EventI t b -> BehaviorI t Bool
- countB :: (Ord t, Num n) => EventI t a -> BehaviorI t n
- sumB :: (Ord t, AdditiveGroup a) => EventI t a -> BehaviorI t a
- integral :: (VectorSpace v, AffineSpace t, Scalar v ~ Diff t, Ord t) => EventI t a -> BehaviorI t v -> BehaviorI t v
Events
data EventG t a
Events. Semantically: time-ordered list of future values. Instances:
-
Monoid
:mempty
is the event that never occurs, ande
is the event that combines occurrences frommappend
e'e
ande'
. -
Functor
:fmap f e
is the event that occurs whenevere
occurs, and whose occurrence values come from applyingf
to the values frome
. -
Applicative
:pure a
is an event with a single occurrence at time -Infinity.ef <*> ex
is an event whose occurrences are made from the product of the occurrences ofef
andex
. For every occurrencef
at timetf
ofef
and occurrencex
at timetx
ofex
,ef <*> ex
has an occurrencef x
at timetf
. N.B.: I don't expect this instance to be very useful. Ifmax
txef
hasnf
instances andex
hasnx
instances, thenef <*> ex
hasnf*nx
instances. However, there are onlynf+nx
possibilities fortf
, so many of the occurrences are simultaneous. If you think you want to use this instance, consider usingmax
txReactive
instead. -
Monad
:return a
is the same aspure a
(as usual). Ine >>= f
, each occurrence ofe
leads, throughf
, to a new event. Similarly forjoin ee
, which is somehow simpler for me to think about. The occurrences ofe >>= f
(orjoin ee
) correspond to the union of the occurrences (temporal interleaving) 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. An especially useful monad-based function isjoinMaybes
, which filters a Maybe-valued event.
Instances
(Ord t, Bounded t) => Monad (EventG t) | |
Functor (EventG t) | |
(Ord t, Bounded t) => MonadPlus (EventG t) | |
(Ord t, Bounded t) => Applicative (EventG t) | |
Unzip (EventG t) | |
(Ord t, Bounded t) => Monoid_f (EventG t) | |
(Ord t, Bounded t) => Alternative (EventG t) | |
Copointed (EventG t) | |
(Eq t, Bounded t, Show t, Show a) => Show (EventG t a) | |
(Arbitrary t, Ord t, Bounded t, Num t, Arbitrary a) => Arbitrary (EventG t a) | |
(CoArbitrary t, CoArbitrary a) => CoArbitrary (EventG t a) | |
(Ord t, Bounded t) => Monoid (EventG t a) | |
(Ord t, Bounded t, Cozip f) => Zip (:. (EventG t) f) | |
(Ord t, Bounded t) => Monoid_f (:. (EventG t) f) | |
(Bounded t, Eq t, Eq a, EqProp t, EqProp a) => EqProp (EventG t a) | |
(Ord t, Bounded t) => Monoid (:. (EventG t) f a) |
accumE :: a -> EventG t (a -> a) -> EventG t a
Accumulating event, starting from an initial value and a
update-function event. See also accumR
.
withTimeE :: Ord t => EventG (ImpBounds t) d -> EventG (ImpBounds t) (d, t)
Access occurrence times in an event. See withTimeGE
for more
general notions of time.
withTimeE :: Event a -> Event (a, TimeT)
withTimeE_ :: Ord t => EventG (ImpBounds t) d -> EventG (ImpBounds t) t
Access occurrence times in an event. Discard the rest. See also
withTimeE
.
withTimeE_ :: Event a -> Event TimeT
scanlE :: (Ord t, Bounded t) => (a -> b -> a) -> a -> EventG t b -> EventG t a
Like scanl
for events.
mealy :: (Ord t, Bounded t) => s -> (s -> s) -> EventG t b -> EventG t (b, s)
Mealy-style state machine, given initial value and transition
function. Carries along event data. See also mealy_
.
mealy_ :: (Ord t, Bounded t) => s -> (s -> s) -> EventG t b -> EventG t s
Mealy-style state machine, given initial value and transition
function. Forgetful version of mealy
.
countE :: (Ord t, Bounded t, Num n) => EventG t b -> EventG t (b, n)
Count occurrences of an event, remembering the occurrence values.
See also countE_
.
countE_ :: (Ord t, Bounded t, Num n) => EventG t b -> EventG t n
Count occurrences of an event, forgetting the occurrence values. See
also countE
.
diffE :: (Ord t, Bounded t, AffineSpace a) => EventG t a -> EventG t (Diff a)
Difference of successive event occurrences. See withPrevE
for a
trick to supply an initial previous value.
withPrevE :: (Ord t, Bounded t) => EventG t a -> EventG t (a, a)
Pair each event value with the previous one. The second result is
the old one. Nothing will come out for the first occurrence of e
,
but if you have an initial value a
, you can do withPrevE (pure a
.
mappend
e)
withPrevEWith :: (Ord t, Bounded t) => (a -> a -> b) -> EventG t a -> EventG t b
Same as withPrevE
, but allow a function to combine the values.
Provided for convenience.
eitherE :: (Ord t, Bounded t) => EventG t a -> EventG t b -> EventG t (Either a b)
Combine two events into one.
justE :: (Ord t, Bounded t) => EventG t (Maybe a) -> EventG t a
Experimental specialization of joinMaybes
.
filterE :: (Ord t, Bounded t) => (a -> Bool) -> EventG t a -> EventG t a
Experimental specialization of filterMP
.
More esoteric
listE :: [(TimeT, a)] -> Event a
Convert a temporally monotonic list of timed values to an event. See also
the generalization listEG
firstRestE :: (Ord t, Bounded t) => EventG t a -> (a, EventG t a)
firstE :: (Ord t, Bounded t) => EventG t a -> a
Extract the first occurrence value of an event. See also
firstRestE
and restE
.
restE :: (Ord t, Bounded t) => EventG t a -> EventG t a
Extract the remainder an event, after its first occurrence. See also
firstRestE
and firstE
.
snapRemainderE :: (Ord t, Bounded t) => EventG t b -> EventG t a -> EventG t (a, EventG t b)
Tack remainders a second event onto values of a first event. Occurs when the first event occurs.
untilE :: (Ord t, Bounded t) => EventG t a -> EventG t b -> EventG t a
Truncate first event at first occurrence of second event.
splitE :: (Ord t, Bounded t) => EventG t b -> EventG t a -> EventG t (a, EventG t b)
Partition an event into segments.
switchE :: (Ord t, Bounded t) => EventG t (EventG t a) -> EventG t a
Switch from one event to another, as they occur. (Doesn't merge, as
join
does.)
Useful with events.
joinMaybes :: MonadPlus m => m (Maybe a) -> m a
Pass through Just
occurrences.
Behaviors
data BehaviorG tr tf a
Reactive behaviors. They can be understood in terms of a simple
model (denotational semantics) as functions of time, namely at ::
BehaviorG t a -> (t -> a)
.
The semantics of BehaviorG
instances are given by corresponding
instances for the semantic model (functions). See
http://conal.net/blog/posts/simplifying-semantics-with-type-class-morphisms/.
-
Functor
:at (fmap f r) == fmap f (at r)
, i.e.,fmap f r
.at
t == f (rat
t) -
Applicative
:at (pure a) == pure a
, andat (s <*> r) == at s <*> at t
. That is,pure a
, andat
t == a(s <*> r)
.at
t == (sat
t) (rat
t) -
Monad
:at (return a) == return a
, andat (join rr) == join (at . at rr)
. That is,return a
, andat
t == ajoin rr
. As always,at
t == (rrat
t)at
t(r >>= f) == join (fmap f r)
.at (r >>= f) == at r >>= at . f
. -
Monoid
: a typical lifted monoid. Ifo
is a monoid, thenReactive o
is a monoid, withmempty == pure mempty
, andmappend == liftA2 mappend
. That is,mempty
, andat
t == mempty(r
mappend
s)at
t == (rat
t)mappend
(sat
t).
Instances
Enum a => Enum (Behavior a) | |
Eq (Behavior b) | |
Floating b => Floating (Behavior b) | |
Fractional b => Fractional (Behavior b) | |
Integral a => Integral (Behavior a) | |
Num b => Num (Behavior b) | |
Ord b => Ord (Behavior b) | |
(Num a, Ord a) => Real (Behavior a) | |
RealFloat a => RealFloat (Behavior a) | |
RealFrac a => RealFrac (Behavior a) | |
Show (Behavior b) | |
VectorSpace v => VectorSpace (Behavior v) | |
AdditiveGroup v => AdditiveGroup (Behavior v) | |
Functor (BehaviorG tr tf) | |
(Bounded tr, Ord tr) => Applicative (BehaviorG tr tf) | |
(Ord tr, Bounded tr) => Zip (BehaviorG tr tf) | |
Unzip (BehaviorG tr tf) | |
(Monoid tr, Monoid tf, Semigroup tf) => Copointed (BehaviorG tr tf) | |
(Bounded tr, Ord tr, Monoid a) => Monoid (BehaviorG tr tf a) |
type Behavior = BehaviorI TimeT
Time-specialized behaviors. Note: The signatures of all of the behavior functions can be generalized. Is the interface generality worth the complexity?
time :: Ord t => BehaviorI t t
The identity generalized behavior. Has value t
at time t
.
time :: Behavior TimeT
stepper :: a -> EventI t a -> BehaviorI t a
Discretely changing behavior, based on an initial value and a new-value event.
stepper :: a -> Event a -> Behavior a
switcher :: (Ord tr, Bounded tr) => BehaviorG tr tf a -> EventG tr (BehaviorG tr tf a) -> BehaviorG tr tf a
Switch between behaviors.
switcher :: Behavior a -> Event (Behavior a) -> Behavior a
snapshotWith :: Ord t => (a -> b -> c) -> BehaviorI t b -> EventI t a -> EventI t c
Snapshots a behavior whenever an event occurs and combines the values using the combining function passed. Take careful note of the order of arguments and results.
snapshotWith :: (a -> b -> c) -> Behavior b -> Event a -> Event c
snapshot :: Ord t => BehaviorI t b -> EventI t a -> EventI t (a, b)
Snapshot a behavior whenever an event occurs. See also
snapshotWith
. Take careful note of the order of arguments and
results.
snapshot :: Behavior b -> Event a -> Event (a,b)
snapshot_ :: Ord t => BehaviorI t b -> EventI t a -> EventI t b
Like snapshot
but discarding event data (often a
is '()').
snapshot_ :: Behavior b -> Event a -> Event b
whenE :: Ord t => BehaviorI t Bool -> EventI t a -> EventI t a
Filter an event according to whether a reactive boolean is true.
whenE :: Behavior Bool -> Event a -> Event a
accumB :: a -> EventI t (a -> a) -> BehaviorI t a
Behavior from an initial value and an updater event. See also
accumE
.
accumB :: a -> Event (a -> a) -> Behavior a
scanlB :: forall a b tr tf. (Ord tr, Bounded tr) => (b -> BehaviorG tr tf a -> BehaviorG tr tf a) -> BehaviorG tr tf a -> EventG tr b -> BehaviorG tr tf a
Like scanl
for behaviors. See also scanlE
.
scanlB :: forall a. (Behavior a -> Behavior a -> Behavior a) -> Behavior a -> Event (Behavior a) -> Behavior a
flipFlop :: Ord t => EventI t a -> EventI t b -> BehaviorI t Bool
Flip-flopping behavior. Turns true whenever first event occurs and false whenever the second event occurs.
flipFlop :: Event a -> Event b -> Behavior Bool
countB :: (Ord t, Num n) => EventI t a -> BehaviorI t n
Count occurrences of an event. See also countE
.
countB :: Num n => Event a -> Behavior n
sumB :: (Ord t, AdditiveGroup a) => EventI t a -> BehaviorI t a
Like sum
for behaviors.
sumB :: AdditiveGroup a => Event a -> Behavior a
integral :: (VectorSpace v, AffineSpace t, Scalar v ~ Diff t, Ord t) => EventI t a -> BehaviorI t v -> BehaviorI t v
Euler integral.
integral :: (VectorSpace v, Scalar v ~ TimeT) => Event () -> Behavior v -> Behavior v