- type Step = EvalNetwork (IO ())
- data Network
- emptyNetwork :: Network
- type Build = ReaderWriterIOT BuildR BuildW IO
- liftIOLater :: IO () -> Build ()
- type BuildIO = Build
- liftBuild :: Build a -> BuildIO a
- buildLater :: Build () -> Build ()
- buildLaterReadNow :: Build a -> Build a
- compile :: BuildIO a -> Network -> IO (a, Network)
- module Control.Monad.IO.Class
- module Reactive.Banana.Prim.Cached
- interpret :: (Pulse a -> BuildIO (Pulse b)) -> [Maybe a] -> IO [Maybe b]
- mapAccumM :: Monad m => (a -> s -> m (b, s)) -> s -> [a] -> m [b]
- mapAccumM_ :: Monad m => (a -> s -> m (b, s)) -> s -> [a] -> m ()
- runSpaceProfile :: Show b => (Pulse a -> BuildIO (Pulse b)) -> [a] -> IO ()
- newInput :: Build (Pulse a, a -> Step)
- addHandler :: Pulse (Future a) -> (a -> IO ()) -> Build ()
- readLatch :: Latch a -> Build a
- type Pulse a = Ref (Pulse' a)
- neverP :: Build (Pulse a)
- alwaysP :: Build (Pulse ())
- mapP :: (a -> b) -> Pulse a -> Build (Pulse b)
- type Future = IO
- tagFuture :: Latch a -> Pulse b -> Build (Pulse (Future a))
- unsafeMapIOP :: (a -> IO b) -> Pulse a -> Build (Pulse b)
- filterJustP :: Pulse (Maybe a) -> Build (Pulse a)
- unionWithP :: (a -> a -> a) -> Pulse a -> Pulse a -> Build (Pulse a)
- type Latch a = Ref (Latch' a)
- pureL :: a -> Latch a
- mapL :: (a -> b) -> Latch a -> Latch b
- applyL :: Latch (a -> b) -> Latch a -> Latch b
- accumL :: a -> Pulse (a -> a) -> Build (Latch a, Pulse a)
- applyP :: Latch (a -> b) -> Pulse a -> Build (Pulse b)
- switchL :: Latch a -> Pulse (Latch a) -> Build (Latch a)
- executeP :: Pulse (b -> Build a) -> b -> Build (Pulse a)
- switchP :: Pulse (Pulse a) -> Build (Pulse a)
This is an internal module, useful if you want to implemented your own FRP library. If you just want to use FRP in your project, have a look at Reactive.Banana instead.
Build FRP networks
Pretend to return a value right now, but do not actually calculate it until later.
NOTE: Accessing the value before it's written leads to an error.
FIXME: Is there a way to have the value calculate on demand?
Simple interpreter for pulse/latch networks.
Mainly useful for testing functionality
Note: The result is not computed lazily, for similar reasons
sequence function does not compute its result lazily.
mapAccum for a monad. Discards results.
Execute an FRP network with a sequence of inputs. Make sure that outputs are evaluated, but don't display their values.
Mainly useful for testing whether there are space leaks.
Create a new pulse in the network and a function to trigger it.
addHandler, this function can be used to operate with
pulses as with standard callback-based events.
Register a handler to be executed whenever a pulse occurs.
The pulse may refer to future latch values.
Dynamic event switching
The main rule for value recursion in the
IO monad is that the action
to be performed must be known in advance. For instance, the following snippet
will not work, because
putStrLn cannot complete its action without
x, which is not defined until later.
mdo putStrLn x let x = "Hello recursion"
On the other hand, whenever the sequence of
IO actions can be known
before inspecting any later arguments, the recursion works.
For instance the snippet
mdo p1 <- mapP p2 p2 <- neverP return p1
With this issue in mind, almost all operations that build
Pulse values have been carefully implemented to not inspect
In conjunction with the
Cached mechanism for observable sharing,
this allows us to build combinators that can be used recursively.
One notable exception is the
readLatch function, which must
inspect its argument in order to be able to read its value.