@@ -300,6 +300,8 @@ class ( MonadHold t (PushM t)
300300 fanInt :: Event t (IntMap a) -> EventSelectorInt t a
301301
302302--TODO: Specialize this so that we can take advantage of knowing that there's no changing going on
303+-- | Constructs a single 'Event' out of a map of events. The output event may fire with multiple
304+-- keys simultaneously.
303305mergeInt :: Reflex t => IntMap (Event t a) -> Event t (IntMap a)
304306mergeInt m = mergeIntIncremental $ unsafeBuildIncremental (return m) never
305307
@@ -368,26 +370,91 @@ class MonadSample t m => MonadHold t m where
368370 -- the supplied 'Event'.
369371 headE :: Event t a -> m (Event t a)
370372
371−accumIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> p) -> PatchTarget p -> Event t b -> m (Incremental t p)
373+-- | Accumulate an 'Incremental' with the supplied initial value and the firings of the provided 'Event',
374+-- using the combining function to produce a patch.
375+accumIncremental
376+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
377+ => (PatchTarget p -> b -> p)
378+ -> PatchTarget p
379+ -> Event t b
380+ -> m (Incremental t p)
372381accumIncremental f = accumMaybeIncremental $ \v o -> Just $ f v o
373−accumMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t p) -> PatchTarget p -> Event t b -> m (Incremental t p)
382+
383+-- | Similar to 'accumIncremental' but the combining function runs in 'PushM'
384+accumMIncremental
385+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
386+ => (PatchTarget p -> b -> PushM t p)
387+ -> PatchTarget p
388+ -> Event t b
389+ -> m (Incremental t p)
374390accumMIncremental f = accumMaybeMIncremental $ \v o -> Just <$> f v o
375−accumMaybeIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> Maybe p) -> PatchTarget p -> Event t b -> m (Incremental t p)
391+
392+-- | Similar to 'accumIncremental' but allows filtering of updates (by dropping updates when the
393+-- combining function produces @Nothing@)
394+accumMaybeIncremental
395+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
396+ => (PatchTarget p -> b -> Maybe p)
397+ -> PatchTarget p
398+ -> Event t b
399+ -> m (Incremental t p)
376400accumMaybeIncremental f = accumMaybeMIncremental $ \v o -> return $ f v o
377−accumMaybeMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t (Maybe p)) -> PatchTarget p -> Event t b -> m (Incremental t p)
401+
402+-- | Similar to 'accumMaybeMIncremental' but the combining function runs in 'PushM'
403+accumMaybeMIncremental
404+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
405+ => (PatchTarget p -> b -> PushM t (Maybe p))
406+ -> PatchTarget p
407+ -> Event t b
408+ -> m (Incremental t p)
378409accumMaybeMIncremental f z e = do
379410 rec let e' = flip push e $ \o -> do
380411 v <- sample $ currentIncremental d'
381412 f v o
382413 d' <- holdIncremental z e'
383414 return d'
384−mapAccumIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> (p, c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
415+
416+-- | Accumulate an 'Incremental' by folding occurrences of an 'Event'
417+-- with a function that both accumulates and produces a value to fire
418+-- as an 'Event'. Returns both the accumulated value and the constructed
419+-- 'Event'.
420+mapAccumIncremental
421+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
422+ => (PatchTarget p -> b -> (p, c))
423+ -> PatchTarget p
424+ -> Event t b
425+ -> m (Incremental t p, Event t c)
385426mapAccumIncremental f = mapAccumMaybeIncremental $ \v o -> bimap Just Just $ f v o
386−mapAccumMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t (p, c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
427+
428+-- | Like 'mapAccumIncremental' but the combining function runs in 'PushM'
429+mapAccumMIncremental
430+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
431+ => (PatchTarget p -> b -> PushM t (p, c))
432+ -> PatchTarget p
433+ -> Event t b
434+ -> m (Incremental t p, Event t c)
387435mapAccumMIncremental f = mapAccumMaybeMIncremental $ \v o -> bimap Just Just <$> f v o
388−mapAccumMaybeIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> (Maybe p, Maybe c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
436+
437+-- | Accumulate an 'Incremental' by folding occurrences of an 'Event' with
438+-- a function that both optionally accumulates and optionally produces
439+-- a value to fire as a separate output 'Event'.
440+-- Note that because 'Nothing's are discarded in both cases, the output
441+-- 'Event' may fire even though the output 'Incremental' has not changed, and
442+-- the output 'Incremental' may update even when the output 'Event' is not firing.
443+mapAccumMaybeIncremental
444+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
445+ => (PatchTarget p -> b -> (Maybe p, Maybe c))
446+ -> PatchTarget p
447+ -> Event t b
448+ -> m (Incremental t p, Event t c)
389449mapAccumMaybeIncremental f = mapAccumMaybeMIncremental $ \v o -> return $ f v o
390−mapAccumMaybeMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t (Maybe p, Maybe c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
450+
451+-- | Like 'mapAccumMaybeIncremental' but the combining function is a 'PushM' action
452+mapAccumMaybeMIncremental
453+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
454+ => (PatchTarget p -> b -> PushM t (Maybe p, Maybe c))
455+ -> PatchTarget p
456+ -> Event t b
457+ -> m (Incremental t p, Event t c)
391458mapAccumMaybeMIncremental f z e = do
392459 rec let e' = flip push e $ \o -> do
393460 v <- sample $ currentIncremental d'
@@ -398,6 +465,7 @@ mapAccumMaybeMIncremental f z e = do
398465 d' <- holdIncremental z $ mapMaybe fst e'
399466 return (d', mapMaybe snd e')
400467
468+-- | A somewhat slow implementation of 'headE'
401469slowHeadE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
402470slowHeadE e = do
403471 rec be <- hold e $ fmapCheap (const never) e'
@@ -418,6 +486,8 @@ newtype EventSelector t k = EventSelector
418486 select :: forall a. k a -> Event t a
419487 }
420488
489+-- | Efficiently select an 'Event' keyed on 'Int'. This is more efficient than manually
490+-- filtering by key.
421491newtype EventSelectorInt t a = EventSelectorInt { selectInt :: Int -> Event t a }
422492
423493--------------------------------------------------------------------------------
@@ -801,7 +871,12 @@ mergeList :: Reflex t => [Event t a] -> Event t (NonEmpty a)
801871mergeList [] = never
802872mergeList es = mergeWithFoldCheap' id es
803873
804−unsafeMapIncremental :: (Reflex t, Patch p, Patch p') => (PatchTarget p -> PatchTarget p') -> (p -> p') -> Incremental t p -> Incremental t p'
874+unsafeMapIncremental
875+ :: (Reflex t, Patch p, Patch p')
876+ => (PatchTarget p -> PatchTarget p')
877+ -> (p -> p')
878+ -> Incremental t p
879+ -> Incremental t p'
805880unsafeMapIncremental f g a = unsafeBuildIncremental (fmap f $ sample $ currentIncremental a) $ g <$> updatedIncremental a
806881
807882-- | Create a new 'Event' combining the map of 'Event's into an 'Event' that
@@ -918,6 +993,9 @@ coincidencePatchMapWithMove e = fmapCheap unsafePatchMapWithMove $ coincidence $
918993 ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Delete }
919994 ]
920995
996+-- | Given a 'PatchTarget' of events (e.g., a 'Map' with 'Event' values) and an event of 'Patch'es
997+-- (e.g., a 'PatchMap' with 'Event' values), produce an 'Event' of the 'PatchTarget' type that
998+-- fires with the patched value.
921999switchHoldPromptOnlyIncremental
9221000 :: forall t m p pt w
9231001 . ( Reflex t
@@ -942,8 +1020,12 @@ switchHoldPromptOnlyIncremental mergePatchIncremental coincidencePatch e0 e' = d
9421020
9431021instance Reflex t => Align (Event t) where
9441022 nil = never
1023+#if MIN_VERSION_these(0, 8, 0)
1024+instance Reflex t => Semialign (Event t) where
1025+#endif
9451026 align = alignEventWithMaybe Just
9461027
1028+
9471029-- | Create a new 'Event' that only occurs if the supplied 'Event' occurs and
9481030-- the 'Behavior' is true at the time of occurrence.
9491031gate :: Reflex t => Behavior t Bool -> Event t a -> Event t a
@@ -1015,7 +1097,16 @@ distributeListOverDyn = distributeListOverDynWith id
10151097
10161098-- | Create a new 'Dynamic' by applying a combining function to a list of 'Dynamic's
10171099distributeListOverDynWith :: Reflex t => ([a] -> b) -> [Dynamic t a] -> Dynamic t b
1018−distributeListOverDynWith f = fmap (f . map (\(Const2 _ :=> Identity v) -> v) . DMap.toList) . distributeDMapOverDynPure . DMap.fromList . map (\(k, v) -> Const2 k :=> v) . zip [0 :: Int ..]
1100+distributeListOverDynWith f =
1101+ fmap (f . map fromDSum . DMap.toAscList) .
1102+ distributeDMapOverDynPure .
1103+ DMap.fromDistinctAscList .
1104+ zipWith toDSum [0..]
1105+ where
1106+ toDSum :: Int -> Dynamic t a -> DSum (Const2 Int a) (Dynamic t)
1107+ toDSum k v = Const2 k :=> v
1108+ fromDSum :: DSum (Const2 Int a) Identity -> a
1109+ fromDSum (Const2 _ :=> Identity v) = v
10191110
10201111-- | Create a new 'Event' that occurs when the first supplied 'Event' occurs
10211112-- unless the second supplied 'Event' occurs simultaneously.
@@ -1491,8 +1582,10 @@ mergeWithFoldCheap' f es =
14911582--------------------------------------------------------------------------------
14921583
14931584{-# DEPRECATED switchPromptly "Use 'switchHoldPromptly' instead. The 'switchHold*' naming convention was chosen because those functions are more closely related to each other than they are to 'switch'. " #-}
1585+-- | See 'switchHoldPromptly'
14941586switchPromptly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
14951587switchPromptly = switchHoldPromptly
14961588{-# DEPRECATED switchPromptOnly "Use 'switchHoldPromptOnly' instead. The 'switchHold*' naming convention was chosen because those functions are more closely related to each other than they are to 'switch'. " #-}
1589+-- | See 'switchHoldPromptOnly'
14971590switchPromptOnly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
14981591switchPromptOnly = switchHoldPromptOnly