-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Sodium Reactive Programming (FRP) System
--
-- A general purpose Reactive Programming (FRP) system. This is part of a
-- project to implement reactive libraries with similar interfaces across
-- a range of programming languages at
-- http://reactiveprogramming.org/
--
--
-- - Goals include simplicity and completeness.
-- - Applicative style: Event implements Functor and Behaviour
-- implements Applicative.
-- - Instead of the common approach where inputs are fed into the front
-- of a monolithic 'reactimate', Sodium allows you to push inputs in from
-- scattered places in IO.
-- - Integration with IO: Extensible to provide lots of scope for
-- lifting IO into FRP logic.
-- - Push-based imperative implementation.
--
--
-- See the examples directory for test cases and examples.
--
-- Changes: 0.2.0.0 fix some value recursion deadlocks and improve docs;
-- 0.3.0.0 add mergeWith, make cross asynchronous; 0.4.0.0 API revamp to
-- remove an excess type variable. Parallelism stuff to be rethought;
-- 0.5.0.0 Improved tests cases + add Freecell example, API tweaks;
-- 0.5.0.1 Internal improvements; 0.5.0.2 Fix multiple memory leaks; 0.6
-- Minor API changes, particular with accum.
@package sodium
@version 0.6
-- | Generalization of the Sodium API to allow for parallel processing.
module FRP.Sodium.Context
class (Applicative (Reactive r), Monad (Reactive r), MonadFix (Reactive r), Functor (Event r), Applicative (Behavior r)) => Context r where data family Reactive r :: * -> * data family Event r :: * -> * data family Behavior r :: * -> *
sync :: Context r => Reactive r a -> IO a
ioReactive :: Context r => IO a -> Reactive r a
newEvent :: Context r => Reactive r (Event r a, a -> Reactive r ())
listen :: Context r => Event r a -> (a -> IO ()) -> Reactive r (IO ())
never :: Context r => Event r a
merge :: Context r => Event r a -> Event r a -> Event r a
filterJust :: Context r => Event r (Maybe a) -> Event r a
hold :: Context r => a -> Event r a -> Reactive r (Behavior r a)
changes :: Context r => Behavior r a -> Event r a
values :: Context r => Behavior r a -> Event r a
snapshotWith :: Context r => (a -> b -> c) -> Event r a -> Behavior r b -> Event r c
switchE :: Context r => Behavior r (Event r a) -> Event r a
switch :: Context r => Behavior r (Behavior r a) -> Reactive r (Behavior r a)
execute :: Context r => Event r (Reactive r a) -> Event r a
sample :: Context r => Behavior r a -> Reactive r a
coalesce :: Context r => (a -> a -> a) -> Event r a -> Event r a
once :: (Context r, Context r) => Event r a -> Event r a
-- | A time-varying value, British spelling.
type Behaviour r a = Behavior r a
-- | Create a new Behavior along with an action to push changes into
-- it. American spelling.
newBehavior :: Context r => a -> Reactive r (Behavior r a, a -> Reactive r ())
-- | Create a new Behavior along with an action to push changes into
-- it. British spelling.
newBehaviour :: Context r => a -> Reactive r (Behavior r a, a -> Reactive r ())
-- | Merge two streams of events of the same type, combining simultaneous
-- event occurrences.
--
-- In the case where multiple event occurrences are simultaneous (i.e.
-- all within the same transaction), they are combined using the same
-- logic as coalesce.
mergeWith :: Context r => (a -> a -> a) -> Event r a -> Event r a -> Event r a
-- | Only keep event occurrences for which the predicate returns true.
filterE :: Context r => (a -> Bool) -> Event r a -> Event r a
-- | Variant of snapshotWith that throws away the event's value and
-- captures the behavior's.
snapshot :: Context r => Event r a -> Behavior r b -> Event r b
-- | Let event occurrences through only when the behavior's value is True.
-- Note that the behavior's value is as it was at the start of the
-- transaction, that is, no state changes from the current transaction
-- are taken into account.
gate :: Context r => Event r a -> Behavior r Bool -> Event r a
-- | Transform an event with a generalized state loop (a mealy machine).
-- The function is passed the input and the old state and returns the new
-- state and output value.
collectE :: Context r => (a -> s -> (b, s)) -> s -> Event r a -> Reactive r (Event r b)
-- | Transform a behavior with a generalized state loop (a mealy machine).
-- The function is passed the input and the old state and returns the new
-- state and output value.
collect :: Context r => (a -> s -> (b, s)) -> s -> Behavior r a -> Reactive r (Behavior r b)
-- | Accumulate state changes given in the input event.
accum :: Context r => a -> Event r (a -> a) -> Reactive r (Behavior r a)
-- | Count event occurrences, giving a behavior that starts with 0 before
-- the first occurrence.
count :: Context r => Event r a -> Reactive r (Behavior r Int)
module FRP.Sodium.Internal
-- | Variant of listen that allows you to initiate more activity in
-- the current transaction. Useful for implementing new primitives.
listenTrans :: Event a -> (a -> Reactive ()) -> Reactive (IO ())
-- | Variant of listenValue that allows you to initiate more
-- activity in the current transaction. Useful for implementing new
-- primitives.
listenValueTrans :: Behavior a -> (a -> Reactive ()) -> Reactive (IO ())
-- | Queue the specified atomic to run at the end of the priority 2 queue
schedulePrioritized :: Maybe (MVar Node) -> Reactive () -> Reactive ()
scheduleLast :: Reactive () -> Reactive ()
data Listen a
Listen :: (Maybe (MVar Node) -> Bool -> (a -> Reactive ()) -> Reactive (IO ())) -> Listen a
runListen_ :: Listen a -> Maybe (MVar Node) -> Bool -> (a -> Reactive ()) -> Reactive (IO ())
-- | Unwrap an event's listener machinery.
getListen :: Event a -> Reactive (Listen a)
runListen :: Listen a -> Maybe (MVar Node) -> Bool -> (a -> Reactive ()) -> Reactive (IO ())
-- | Listen for firings of this event. The returned IO () is an IO
-- action that unregisters the listener. This is the observer pattern.
linkedListen :: Event a -> Maybe (MVar Node) -> Bool -> (a -> Reactive ()) -> Reactive (IO ())
data Node
-- | Returns an event, and a push action for pushing a value into the
-- event.
newEventLinked :: IO (Event a, a -> Reactive (), MVar Node)
-- | Returns an event, and a push action for pushing a value into the
-- event.
newEvent :: Reactive (Event a, a -> Reactive ())
-- | Returns a Listen for registering listeners, and a push action
-- for pushing a value into the event.
newEventImpl :: IO (Listen a, a -> Reactive (), MVar Node)
-- | Add a finalizer to an event.
finalizeEvent :: Event a -> IO () -> Event a
-- | Add a finalizer to a listener.
finalizeListen :: Listen a -> IO () -> IO (Listen a)
ioReactive :: IO a -> Reactive a
data Unlistener
-- | Cause the things listened to with unlistenize to be unlistened when
-- the specified listener is not referenced any more.
addCleanup_Listen :: Unlistener -> Listen a -> Reactive (Listen a)
data Sample a
Sample :: IO (IO a) -> Sample a
unSample_ :: Sample a -> IO (IO a)
unSample :: Sample a -> IO a
addCleanup_Sample :: Unlistener -> Sample a -> IO (Sample a)
-- | Listen to an input event/behavior and return an Unlistener that
-- can be attached to an output event using addCleanup_Listen.
unlistenize :: Reactive (IO ()) -> Reactive Unlistener
-- | Sodium Reactive Programming (FRP) system.
--
-- See the examples directory for test cases and examples.
--
-- Some functions are pure, and others need to run under the
-- Reactive monad via sync. An Event
-- (Reactive a) can be flattened to an Event
-- a using the execute primitive.
--
-- In addition to the explicit functions in the language, note that you
-- can use
--
--
-- - Functor on Event and Behavior
-- - Applicative on behaviour, e.g. let bsum = (+)
-- <$> ba <*> bb
-- - Applicative pure is used to give a constant
-- Behavior.
-- - Recursive do (using the DoRec language extension) to make state
-- loops with the rec keyword.
--
--
-- Here's an example of recursive do to write state-keeping loops. Note
-- that all holds are delayed, so attachWith will capture
-- the old value of the state s.
--
--
-- {-# LANGUAGE DoRec #-}
-- -- | Accumulate state changes given in the input event.
-- accum :: Context r => a -> Event r (a -> a) -> Reactive r (Behavior r a)
-- accum z efa = do
-- rec
-- s <- hold z $ snapshotWith ($) efa s
-- return s
--
module FRP.Sodium
-- | Phantom type for use with Context type class.
data Plain
-- | A monad for transactional reactive operations. Execute it from
-- IO using sync.
type Reactive a = Reactive Plain a
-- | Execute the specified Reactive within a new transaction,
-- blocking the caller until all resulting processing is complete and all
-- callbacks have been called. This operation is thread-safe, so it may
-- be called from any thread.
--
-- State changes to hold values occur after processing of the
-- transaction is complete.
sync :: Reactive a -> IO a
-- | Returns an event, and a push action for pushing a value into the
-- event.
newEvent :: Reactive (Event a, a -> Reactive ())
-- | Create a new Behavior along with an action to push changes into
-- it. American spelling.
newBehavior :: a -> Reactive (Behavior a, a -> Reactive ())
-- | Create a new Behavior along with an action to push changes into
-- it. British spelling.
newBehaviour :: a -> Reactive (Behavior a, a -> Reactive ())
-- | Listen for firings of this event. The returned IO () is an IO
-- action that unregisters the listener. This is the observer pattern.
--
-- To listen to a Behavior use listen (values b) handler
listen :: Event a -> (a -> IO ()) -> Reactive (IO ())
-- | A stream of events. The individual firings of events are called 'event
-- occurrences'.
type Event a = Event Plain a
-- | A time-varying value, American spelling.
type Behavior a = Behavior Plain a
-- | A time-varying value, British spelling.
type Behaviour a = Behavior Plain a
-- | An event that never fires.
never :: Event a
-- | Merge two streams of events of the same type.
--
-- In the case where two event occurrences are simultaneous (i.e. both
-- within the same transaction), both will be delivered in the same
-- transaction. If the event firings are ordered for some reason, then
-- their ordering is retained. In many common cases the ordering will be
-- undefined.
merge :: Event a -> Event a -> Event a
-- | Unwrap Just values, and discard event occurrences with Nothing values.
filterJust :: Event (Maybe a) -> Event a
-- | Create a behavior with the specified initial value, that gets updated
-- by the values coming through the event. The 'current value' of the
-- behavior is notionally the value as it was 'at the start of the
-- transaction'. That is, state updates caused by event firings get
-- processed at the end of the transaction.
hold :: a -> Event a -> Reactive (Behavior a)
-- | An event that gives the updates for the behavior. It doesn't do any
-- equality comparison as the name might imply.
changes :: Behavior a -> Event a
-- | An event that is guaranteed to fire once when you listen to it, giving
-- the current value of the behavior, and thereafter behaves like
-- changes, firing for each update to the behavior's value.
values :: Behavior a -> Event a
-- | Sample the behavior at the time of the event firing. Note that the
-- 'current value' of the behavior that's sampled is the value as at the
-- start of the transaction before any state changes of the current
-- transaction are applied through holds.
snapshotWith :: (a -> b -> c) -> Event a -> Behavior b -> Event c
-- | Unwrap an event inside a behavior to give a time-varying event
-- implementation.
switchE :: Behavior (Event a) -> Event a
-- | Unwrap a behavior inside another behavior to give a time-varying
-- behavior implementation.
switch :: Behavior (Behavior a) -> Reactive (Behavior a)
-- | Execute the specified Reactive action inside an event.
execute :: Event (Reactive a) -> Event a
-- | Obtain the current value of a behavior.
sample :: Behavior a -> Reactive a
-- | If there's more than one firing in a single transaction, combine them
-- into one using the specified combining function.
--
-- If the event firings are ordered, then the first will appear at the
-- left input of the combining function. In most common cases it's best
-- not to make any assumptions about the ordering, and the combining
-- function would ideally be commutative.
coalesce :: (a -> a -> a) -> Event a -> Event a
-- | Merge two streams of events of the same type, combining simultaneous
-- event occurrences.
--
-- In the case where multiple event occurrences are simultaneous (i.e.
-- all within the same transaction), they are combined using the supplied
-- function. The output event is guaranteed not to have more than one
-- event occurrence per transaction.
--
-- The combine function should be commutative, because simultaneous
-- events should be considered to be order-agnostic.
mergeWith :: (a -> a -> a) -> Event a -> Event a -> Event a
-- | Only keep event occurrences for which the predicate is true.
filterE :: (a -> Bool) -> Event a -> Event a
-- | Variant of snapshotWith that throws away the event's value and
-- captures the behavior's.
snapshot :: Event a -> Behavior b -> Event b
-- | Let event occurrences through only when the behavior's value is True.
-- Note that the behavior's value is as it was at the start of the
-- transaction, that is, no state changes from the current transaction
-- are taken into account.
gate :: Event a -> Behavior Bool -> Event a
-- | Transform an event with a generalized state loop (a mealy machine).
-- The function is passed the input and the old state and returns the new
-- state and output value.
collectE :: (a -> s -> (b, s)) -> s -> Event a -> Reactive (Event b)
-- | Transform a behavior with a generalized state loop (a mealy machine).
-- The function is passed the input and the old state and returns the new
-- state and output value.
collect :: (a -> s -> (b, s)) -> s -> Behavior a -> Reactive (Behavior b)
-- | Accumulate state changes given in the input event.
accum :: a -> Event (a -> a) -> Reactive (Behavior a)
-- | Count event occurrences, giving a behavior that starts with 0 before
-- the first occurrence.
count :: Event a -> Reactive (Behavior Int)
-- | Throw away all event occurrences except for the first one.
once :: Event a -> Event a