From 06cbb02c3d0efbfcde6474ebabe5ea49adcfb290 Mon Sep 17 00:00:00 2001 From: Ollie Charles Date: Thu, 11 Aug 2022 08:32:10 +0100 Subject: [PATCH] Implement `accumL` with `newPulse` (#260) Currently `accumL` uses `mapL` to read the previous state whenever the state update `Pulse` fires. This is problematic, because when the previous state is read in `mapL` (and transformed into a `(a -> a) -> a` function), this is cached into the `Latch`. This means that when the state update `Pulse` fires, we'll update one latch to the new state, while also retaining the previous state. This commit redefines `accumL` as a call to `newLatch` (as before) and creates a new `Pulse` with `newPulse` whose evaluation function reads the `Pulse` containing the `a -> a` endmorphism, and also reads the current state from its latch. With this implementation, no historic values are leaked by `accumL`. --- reactive-banana/src/Reactive/Banana/Prim/Mid/Combinators.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/reactive-banana/src/Reactive/Banana/Prim/Mid/Combinators.hs b/reactive-banana/src/Reactive/Banana/Prim/Mid/Combinators.hs index 26dcd41b..1a9f18d0 100644 --- a/reactive-banana/src/Reactive/Banana/Prim/Mid/Combinators.hs +++ b/reactive-banana/src/Reactive/Banana/Prim/Mid/Combinators.hs @@ -98,7 +98,11 @@ applyL lf lx = cachedLatch accumL :: a -> Pulse (a -> a) -> Build (Latch a, Pulse a) accumL a p1 = do (updateOn, x) <- newLatch a - p2 <- applyP (mapL (\x f -> f x) x) p1 + p2 <- newPulse "accumL" $ do + a <- readLatchP x + f <- readPulseP p1 + return $ fmap (\g -> g a) f + p2 `dependOn` p1 updateOn p2 return (x,p2)