-
Couldn't load subscription status.
- Fork 149
Open
Description
Let's say my website is waiting for two web requests:
evRequest1Done :: Event t () and evRequest2Done :: Event t ()
Now I want an event
evAllRequestsDone :: Event t ()
evAllRequestsDone = waitForAll [evRequest1Done, evRequest2Done]
that fires once all events in the list have fired at least once.
What is the best way to go about this?
I can offer two solutions, both with drawbacks:
Solution 1
EDIT: record instead of sumtype with Semigroup instance
data Done = Done
{ done1 :: Bool
, done2 :: Bool
}
setDone1 :: Done -> Done
setDone1 done = done { done1 = True }
setDone2 :: Done -> Done
setDone2 done = done { done2 = True }
waitForAll event1 event2 =
mapAccumMaybe_ accFunc (Done False False) $
mergeWith (.) [event1 $> setDone1, event2 $> setDone2]
where
accFunc done func =
let done'@(Done d1 d2) = func done
in (Just done', if d1 && d2 then Just () else Nothing)
Disadvantages:
- record
Oncerequired - bloated with helper functions (can me mitigated with lenses)
- gets more bloated for more then two events
Solution 2
waitFor :: Int -> Event t () -> Event t ()
waitFor n event =
mapAccumMaybe_ accFunc 0 event
where
accFunc x y = let z = x + y in (Just z, if z == n then Just () else Nothing)
-- use it like this
waitFor 2 $ mergeWith (+) $ fmap ($> 1) eventsDisadvantages:
- Doesn't actually solve the stated problem, when one of the events in the list can fire more then once
Metadata
Metadata
Assignees
Labels
No labels