-- | Sodium Reactive Programming (FRP) system. -- -- The @p@ type parameter determines the /partition/ that your FRP is running -- on. A thread is automatically created for each partition used in the system based -- on the unique concrete p type, which must be an instance of Typeable. FRP -- processing runs on this thread, but 'synchronously' will block the calling thread -- while it waits for FRP processing to complete. -- -- The 'cross' and 'crossE' functions are used to move events and behaviours between -- partitions. The separation thus created allows your FRP logic to be partitioned -- so that the different partitions can run in parallel, with more relaxed guarantees -- of consistency between partitions. -- -- Some functions are pure, and others need to run under the 'Reactive' monad via -- 'synchronously' or 'asynchronously'. -- -- In addition to the functions supplied here, note that you can use -- -- * Functor on 'Event' and 'Behaviour' -- -- * Applicative on 'behaviour', e.g. @let bsum = (+) \<$\> ba \<*\> bb@ -- -- * Applicative 'pure' is used to give a constant 'Behaviour'. -- -- * Recursive do (via DoRec) to make state loops with the @rec@ keyword. -- -- Here's an example of recursive do to write state-keeping loops. Note that -- attachWith will capture the /old/ value of the state /s/. -- -- > {-# LANGUAGE DoRec #-} -- > -- | Accumulate on input event, outputting the new state each time. -- > accumE :: (a -> s -> s) -> s -> Event p a -> Reactive p (Event p s) -- > accumE f z ea = do -- > rec -- > let es = attachWith f ea s -- > s <- hold z es -- > return es module FRP.Sodium ( -- * Running FRP code Reactive, synchronously, asynchronously, newEvent, listen, listenIO, listenValue, listenValueIO, -- * FRP language Event, never, merge, justE, filterE, Behaviour, Behavior, hold, valueEvent, attachWith, attach, tag, gate, collectE, collect, accumE, countE, count, switchE, switch, once, execute, sample, -- * Partitions crossE, cross ) where import FRP.Sodium.Impl