Strange drive behavior with event (UI a & # 8594; UI a)

I am experimenting with trpenny-gui trying to learn FRP interface. I want to avoid all explicit shared states by using the accumE / accumB method rather than IORef: s. I have four different signals (start, stop, timer, reset) that affect global state and UI. I use accumE w $ concatenate <$> unions [e0, e1, e2, e3]

to make the events have the same state w

. Here's a short snippet that captures its gist (with only one signal):

data World = World { intW :: Int , runW :: UI () }

main :: IO ()
main = startGUI defaultConfig setup

setup :: Window -> UI ()
setup _ = do
    (e0, fire) <- liftIO  UI.newEvent
    let e0' = action <$ e0
    e <- accumE (World 0 (return ())) e0'
    onEvent e $ \w -> void $ runW w
    replicateM_ 5 . liftIO $ fire ()
    where
        action :: World -> World
        action w = w { intW = succ $ intW w
                     , runW = liftIO . print $ intW w }

      

Everything seems to be working fine (although I think it is ok). However, if I instead change the event to be of type Event (UI World -> UI World)

(and remove the runW field), things look similar:

data World = World { intW :: Int } deriving (Show)

main :: IO ()
main = startGUI defaultConfig setup

setup :: Window -> UI ()
setup _ = do
    (e0, fire) <- liftIO UI.newEvent
    let e0' = action <$ e0
    e <- accumE (return (World 0)) e0'
    onEvent e void
    replicateM_ 5 . liftIO $ fire ()
    where
        action :: UI World -> UI World
        action world = do
            w <- world
            let w' = w { intW = succ $ intW w }
            liftIO $ print w'
            return w'

      

It seems that all UI actions are somehow accumulating and getting executed more and more with each event! I thought accE was like a fold where the accumulating state is replaced if not explicitly accumulating. What's the correct / best way to deal with this problem in general?

+3


source to share





All Articles