Debounce instead of delay

This commit is contained in:
2026-08-25 10:47:38 +03:00
parent d341270ed1
commit 2664ca67c0
2 changed files with 30 additions and 6 deletions
+27 -4
View File
@@ -28,6 +28,7 @@ module AFRP
, rollup , rollup
, sliding , sliding
, fixed , fixed
, debounce
) where ) where
import Control.Category (Category(..), (>>>)) import Control.Category (Category(..), (>>>))
@@ -150,9 +151,9 @@ mapAccumRequest f x extract = go x
let next = f t b a let next = f t b a
in pure (extract next, go next) in pure (extract next, go next)
data DelayState a = DelayState data DelayState x a = DelayState
{ pending :: [(UTCTime, a)] { pending :: x
, output :: Event a , output :: !(Event a)
} }
@@ -178,6 +179,21 @@ delayEvent delay =
_ -> _ ->
DelayState queued Tick DelayState queued Tick
debounce :: NominalDiffTime -> Mealy eff (Event a) (Event a)
debounce delay =
mapAccumRequest step initial output
where
initial = DelayState Nothing Tick
step req st input =
let now = requestTime req
held = case input of
Tick -> pending st
Event x -> Just (delay `addUTCTime` now, x)
in case held of
Just (due, x)
| due <= now -> DelayState Nothing (Event x)
_ -> DelayState held Tick
changes :: Eq a => Mealy eff a (Event a) changes :: Eq a => Mealy eff a (Event a)
changes = mapAccum go Nothing (maybe Tick snd) changes = mapAccum go Nothing (maybe Tick snd)
where where
@@ -230,7 +246,14 @@ duration = mapAccumRequest go (Nothing @(UTCTime, NominalDiffTime)) (maybe 0 snd
rollup :: Int -> Int -> Mealy eff (Event a) (Event [a]) -- | Rollup, hold back bursty messages
--
-- Consider a case where you have a bursty set of data. You care to get an immediate response,
-- but don't want to spam the output
rollup
:: Int -- ^ How many items to pass through before burst protection
-> Int -- ` How many seconds to collect the bursty data
-> Mealy eff (Event a) (Event [a])
rollup limit seconds = mapAccumRequest go (Left Tick) (either id (\(_, _, _, ev) -> ev)) rollup limit seconds = mapAccumRequest go (Left Tick) (either id (\(_, _, _, ev) -> ev))
where where
e a = Endo ([a] ++) e a = Endo ([a] ++)
+3 -2
View File
@@ -133,8 +133,9 @@ waitFor n = duration >>> arr (> n) >>> edge
delayedDoor :: HASS (Event Value) (Event DoorState) delayedDoor :: HASS (Event Value) (Event DoorState)
delayedDoor = door delayedDoor = door
>>> (AFRP.hold Open &&& AFRP.delayEvent 15) >>> AFRP.debounce 15
>>> AFRP.sample >>> AFRP.hold Open
>>> AFRP.changes
>>> traceEvent >>> traceEvent
humidifierController :: HASS (Event Value) () humidifierController :: HASS (Event Value) ()