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