@@ -21,9 +21,13 @@
2121{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
2222#endif
2323
24−-- | This module contains the Reflex interface, as well as a variety of
25−-- convenience functions for working with 'Event's, 'Behavior's, and other
26−-- signals.
24+-- |
25+-- Module:
26+-- Reflex.Class
27+-- Description:
28+-- This module contains the Reflex interface, as well as a variety of
29+-- convenience functions for working with 'Event's, 'Behavior's, and other
30+-- signals.
2731module Reflex.Class
2832 ( module Reflex.Patch
2933 -- * Primitives
@@ -34,10 +38,9 @@ module Reflex.Class
3438 , coerceDynamic
3539 , MonadSample (..)
3640 , MonadHold (..)
37− -- ** 'fan'-related types
41+ -- ** 'fan' related types
3842 , EventSelector (..)
3943 , EventSelectorInt (..)
40− -- ** 'Incremental'-related types
4144 -- * Convenience functions
4245 , constDyn
4346 , pushAlways
@@ -134,8 +137,10 @@ module Reflex.Class
134137 -- * Unsafe functions
135138 , unsafeDynamic
136139 , unsafeMapIncremental
137− -- * 'FunctorMaybe'
138− , FunctorMaybe (..)
140+ -- * 'Filterable' convenience functions
141+ , FunctorMaybe -- fmapMaybe is purposely not exported from deprecated 'FunctorMaybe' and the new alias is exported instead
142+ , mapMaybe -- Re-exported for convenience
143+ , fmapMaybe
139144 , fforMaybe
140145 , ffilter
141146 , filterLeft
@@ -145,10 +150,11 @@ module Reflex.Class
145150 , ffor2
146151 , ffor3
147152 -- * Deprecated functions
148− , appendEvents
149− , onceE
150− , sequenceThese
153+ , switchPromptly
154+ , switchPromptOnly
155+ -- * "Cheap" functions
151156 , fmapMaybeCheap
157+ , mapMaybeCheap
152158 , fmapCheap
153159 , fforCheap
154160 , fforMaybeCheap
@@ -156,8 +162,6 @@ module Reflex.Class
156162 , tagCheap
157163 , mergeWithCheap
158164 , mergeWithCheap'
159− , switchPromptly
160− , switchPromptOnly
161165 -- * Slow, but general, implementations
162166 , slowHeadE
163167 ) where
@@ -194,14 +198,17 @@ import qualified Data.Some as Some
194198import Data.String
195199import Data.These
196200import Data.Type.Coercion
197−import Reflex.FunctorMaybe
201+import Data.Witherable (Filterable(..))
202+import qualified Data.Witherable as W
203+import Reflex.FunctorMaybe (FunctorMaybe)
204+import qualified Reflex.FunctorMaybe
198205import Reflex.Patch
199206import qualified Reflex.Patch.MapWithMove as PatchMapWithMove
200207
201208import Debug.Trace (trace)
202209
203210-- | The 'Reflex' class contains all the primitive functionality needed for
204−-- Functional Reactive Programming (FRP). The @t@ type parameter indicates
211+-- Functional Reactive Programming (FRP). The @/t/@ type parameter indicates
205212-- which "timeline" is in use. Timelines are fully-independent FRP contexts,
206213-- and the type of the timeline determines the FRP engine to be used. For most
207214-- purposes, the 'Reflex.Spider' implementation is recommended.
@@ -257,8 +264,7 @@ class ( MonadHold t (PushM t)
257264 -- | Create an 'Event' that will occur whenever the currently-selected input
258265 -- 'Event' occurs
259266 switch :: Behavior t (Event t a) -> Event t a
260− -- | Create an 'Event' that will occur whenever the input event is occurring
261− -- and its occurrence value, another 'Event', is also occurring
267+ -- | Create an 'Event' that will occur whenever the input event is occurring -- and its occurrence value, another 'Event', is also occurring
262268 coincidence :: Event t (Event t a) -> Event t a
263269 -- | Extract the 'Behavior' of a 'Dynamic'.
264270 current :: Dynamic t a -> Behavior t a
@@ -267,7 +273,7 @@ class ( MonadHold t (PushM t)
267273 -- | Create a new 'Dynamic'. The given 'PullM' must always return the most
268274 -- recent firing of the given 'Event', if any.
269275 unsafeBuildDynamic :: PullM t a -> Event t a -> Dynamic t a
270− -- | Create a new 'Incremental'. The given 'PullM''s value must always change
276+ -- | Create a new 'Incremental'. The given "PullM"'s value must always change
271277 -- in the same way that the accumulated application of patches would change
272278 -- that value.
273279 unsafeBuildIncremental :: Patch p => PullM t (PatchTarget p) -> Event t p -> Incremental t p
@@ -310,7 +316,7 @@ coerceDynamic :: (Reflex t, Coercible a b) => Dynamic t a -> Dynamic t b
310316coerceDynamic = coerceWith $ dynamicCoercion Coercion
311317
312318-- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'. The 'Behavior'
313−-- _must_ change when and only when the 'Event' fires, such that the
319+-- __must__ change when and only when the 'Event' fires, such that the
314320-- 'Behavior''s value is always equal to the most recent firing of the 'Event';
315321-- if this is not the case, the resulting 'Dynamic' will behave
316322-- nondeterministically.
@@ -338,7 +344,7 @@ class MonadSample t m => MonadHold t m where
338344 -- value and will be updated whenever the given 'Event' occurs. The update
339345 -- takes effect immediately after the 'Event' occurs; if the occurrence that
340346 -- sets the 'Behavior' (or one that is simultaneous with it) is used to sample
341− -- the 'Behavior', it will see the _old_ value of the 'Behavior', not the new
347+ -- the 'Behavior', it will see the __old__ value of the 'Behavior', not the new
342348 -- one.
343349 hold :: a -> Event t a -> m (Behavior t a)
344350 default hold :: (m ~ f m', MonadTrans f, MonadHold t m') => a -> Event t a -> m (Behavior t a)
@@ -389,8 +395,8 @@ mapAccumMaybeMIncremental f z e = do
389395 return $ case result of
390396 (Nothing, Nothing) -> Nothing
391397 _ -> Just result
392− d' <- holdIncremental z $ fmapMaybe fst e'
393− return (d', fmapMaybe snd e')
398+ d' <- holdIncremental z $ mapMaybe fst e'
399+ return (d', mapMaybe snd e')
394400
395401slowHeadE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
396402slowHeadE e = do
@@ -400,14 +406,14 @@ slowHeadE e = do
400406
401407-- | An 'EventSelector' allows you to efficiently 'select' an 'Event' based on a
402408-- key. This is much more efficient than filtering for each key with
403−-- 'fmapMaybe'.
409+-- 'mapMaybe'.
404410newtype EventSelector t k = EventSelector
405411 { -- | Retrieve the 'Event' for the given key. The type of the 'Event' is
406412 -- determined by the type of the key, so this can be used to fan-out
407413 -- 'Event's whose sub-'Event's have different types.
408414 --
409415 -- Using 'EventSelector's and the 'fan' primitive is far more efficient than
410− -- (but equivalent to) using 'fmapMaybe' to select only the relevant
416+ -- (but equivalent to) using 'mapMaybe' to select only the relevant
411417 -- occurrences of an 'Event'.
412418 select :: forall a. k a -> Event t a
413419 }
@@ -542,6 +548,15 @@ instance (Reflex t, Num a) => Num (Behavior t a) where
542548 negate = fmap negate
543549 signum = fmap signum
544550
551+instance (Num a, Reflex t) => Num (Dynamic t a) where
552+ (+) = liftA2 (+)
553+ (*) = liftA2 (*)
554+ abs = fmap abs
555+ signum = fmap signum
556+ fromInteger = pure . fromInteger
557+ negate = fmap negate
558+ (-) = liftA2 (-)
559+
545560instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
546561 a <> b = pull $ liftM2 (<>) (sample a) (sample b)
547562 sconcat = pull . fmap sconcat . mapM sample
@@ -551,22 +566,25 @@ instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
551566 times1p n = fmap $ times1p n
552567#endif
553568
554−-- | Flipped version of 'fmapMaybe'.
555−fforMaybe :: FunctorMaybe f => f a -> (a -> Maybe b) -> f b
556−fforMaybe = flip fmapMaybe
569+-- | Alias for 'mapMaybe'
570+fmapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b
571+fmapMaybe = mapMaybe
572+
573+-- | Flipped version of 'mapMaybe'.
574+fforMaybe :: Filterable f => f a -> (a -> Maybe b) -> f b
575+fforMaybe = flip mapMaybe
557576
558577-- | Filter 'f a' using the provided predicate.
559−-- Relies on 'fforMaybe'.
560−ffilter :: FunctorMaybe f => (a -> Bool) -> f a -> f a
561−ffilter f = fmapMaybe $ \x -> if f x then Just x else Nothing
578+ffilter :: Filterable f => (a -> Bool) -> f a -> f a
579+ffilter = W.filter
562580
563581-- | Filter 'Left's from 'f (Either a b)' into 'a'.
564−filterLeft :: FunctorMaybe f => f (Either a b) -> f a
565−filterLeft = fmapMaybe (either Just (const Nothing))
582+filterLeft :: Filterable f => f (Either a b) -> f a
583+filterLeft = mapMaybe (either Just (const Nothing))
566584
567585-- | Filter 'Right's from 'f (Either a b)' into 'b'.
568−filterRight :: FunctorMaybe f => f (Either a b) -> f b
569−filterRight = fmapMaybe (either (const Nothing) Just)
586+filterRight :: Filterable f => f (Either a b) -> f b
587+filterRight = mapMaybe (either (const Nothing) Just)
570588
571589-- | Left-biased event union (prefers left event on simultaneous
572590-- occurrence).
@@ -584,13 +602,18 @@ instance Reflex t => Bind (Event t) where
584602
585603instance Reflex t => Functor (Event t) where
586604 {-# INLINE fmap #-}
587− fmap f = fmapMaybe $ Just . f
605+ fmap f = mapMaybe $ Just . f
588606 {-# INLINE (<$) #-}
589607 x <$ e = fmapCheap (const x) e
590608
609+-- TODO Remove this instance
591610instance Reflex t => FunctorMaybe (Event t) where
592611 {-# INLINE fmapMaybe #-}
593− fmapMaybe f = push $ return . f
612+ fmapMaybe = mapMaybe
613+
614+instance Reflex t => Filterable (Event t) where
615+ {-# INLINE mapMaybe #-}
616+ mapMaybe f = push $ return . f
594617
595618-- | Never: @'zero' = 'never'@.
596619instance Reflex t => Plus (Event t) where
@@ -641,7 +664,7 @@ headTailE e = do
641664-- event returns 'True'.
642665--
643666-- Starting at the current time, fire all the occurrences of the 'Event' for
644−-- which the given predicate returns 'True'. When 'False' first is returned,
667+-- which the given predicate returns 'True'. When first 'False' is returned,
645668-- do not fire, and permanently stop firing, even if 'True' values would have
646669-- been encountered later.
647670takeWhileE
@@ -656,7 +679,7 @@ takeWhileE f = takeWhileJustE $ \v -> guard (f v) $> v
656679-- event returns 'Just b'.
657680--
658681-- Starting at the current time, fire all the occurrences of the 'Event' for
659−-- which the given predicate returns 'Just b'. When 'Nothing' first is returned,
682+-- which the given predicate returns 'Just b'. When first 'Nothing' is returned,
660683-- do not fire, and permanently stop firing, even if 'Just b' values would have
661684-- been encountered later.
662685takeWhileJustE
@@ -808,7 +831,7 @@ fanEither :: Reflex t => Event t (Either a b) -> (Event t a, Event t b)
808831fanEither e =
809832 let justLeft = either Just (const Nothing)
810833 justRight = either (const Nothing) Just
811− in (fmapMaybe justLeft e, fmapMaybe justRight e)
834+ in (mapMaybe justLeft e, mapMaybe justRight e)
812835
813836-- | Split the event into separate events for 'This' and 'That' values,
814837-- allowing them to fire simultaneously when the input value is 'These'.
@@ -820,7 +843,7 @@ fanThese e =
820843 that (That y) = Just y
821844 that (These _ y) = Just y
822845 that _ = Nothing
823− in (fmapMaybe this e, fmapMaybe that e)
846+ in (mapMaybe this e, mapMaybe that e)
824847
825848-- | Split the event into an 'EventSelector' that allows efficient selection of
826849-- the individual 'Event's.
@@ -829,7 +852,7 @@ fanMap = fan . fmap mapToDMap
829852
830853-- | Switches to the new event whenever it receives one. Only the old event is
831854-- considered the moment a new one is switched in; the output event will fire at
832−-- that moment if only if the old event does.
855+-- that moment only if the old event does.
833856--
834857-- Because the simultaneous firing case is irrelevant, this function imposes
835858-- laxer "timing requirements" on the overall circuit, avoiding many potential
@@ -875,13 +898,13 @@ coincidencePatchMap e = fmapCheap PatchMap $ coincidence $ ffor e $ \(PatchMap m
875898 Nothing -> fmapCheap (const Nothing) e
876899 Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
877900
878−-- | See 'coincicencePatchMap'
901+-- | See 'coincidencePatchMap'
879902coincidencePatchIntMap :: Reflex t => Event t (PatchIntMap (Event t v)) -> Event t (PatchIntMap v)
880903coincidencePatchIntMap e = fmapCheap PatchIntMap $ coincidence $ ffor e $ \(PatchIntMap m) -> mergeIntMap $ ffor m $ \case
881904 Nothing -> fmapCheap (const Nothing) e
882905 Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
883906
884−-- | See 'coincicencePatchMap'
907+-- | See 'coincidencePatchMap'
885908coincidencePatchMapWithMove :: (Reflex t, Ord k) => Event t (PatchMapWithMove k (Event t v)) -> Event t (PatchMapWithMove k v)
886909coincidencePatchMapWithMove e = fmapCheap unsafePatchMapWithMove $ coincidence $ ffor e $ \p -> mergeMap $ ffor (unPatchMapWithMove p) $ \ni -> case PatchMapWithMove._nodeInfo_from ni of
887910 PatchMapWithMove.From_Delete -> fforCheap e $ \_ ->
@@ -942,7 +965,7 @@ zipDyn = zipDynWith (,)
942965
943966-- | Combine two 'Dynamic's with a combining function. The result will change
944967-- whenever either (or both) input 'Dynamic' changes.
945−-- More efficient than liftA2.
968+-- More efficient than 'liftA2'.
946969zipDynWith :: Reflex t => (a -> b -> c) -> Dynamic t a -> Dynamic t b -> Dynamic t c
947970zipDynWith f da db =
948971 let eab = align (updated da) (updated db)
@@ -973,7 +996,7 @@ instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where
973996
974997-- | This function converts a 'DMap' whose elements are 'Dynamic's into a
975998-- 'Dynamic' 'DMap'. Its implementation is more efficient than doing the same
976−-- through the use of multiple uses of 'zipWithDyn' or 'Applicative' operators.
999+-- through the use of multiple uses of 'zipDynWith' or 'Applicative' operators.
9771000distributeDMapOverDynPure :: forall t k. (Reflex t, GCompare k) => DMap k (Dynamic t) -> Dynamic t (DMap k Identity)
9781001distributeDMapOverDynPure dm = case DMap.toList dm of
9791002 [] -> constDyn DMap.empty
@@ -999,14 +1022,16 @@ distributeListOverDynWith f = fmap (f . map (\(Const2 _ :=> Identity v) -> v) .
9991022difference :: Reflex t => Event t a -> Event t b -> Event t a
10001023difference = alignEventWithMaybe $ \case
10011024 This a -> Just a
1002− _ -> Nothing
1025+ _ -> Nothing
10031026
1027+-- | Zips two values by taking the union of their shapes and combining with the provided function.
1028+-- 'Nothing' values are dropped.
10041029alignEventWithMaybe :: Reflex t => (These a b -> Maybe c) -> Event t a -> Event t b -> Event t c
1005−alignEventWithMaybe f ea eb =
1006− fmapMaybe (f <=< dmapToThese)
1007− $ merge
1008− $ DMap.fromList [LeftTag :=> ea, RightTag :=> eb]
1030+alignEventWithMaybe f ea eb = mapMaybe (f <=< dmapToThese) $
1031+ merge $ DMap.fromList [LeftTag :=> ea, RightTag :=> eb]
10091032
1033+-- | Produces an 'Event' that fires only when the input event fires with a 'DSum' key that
1034+-- matches the provided key.
10101035filterEventKey
10111036 :: forall t m k v a.
10121037 ( Reflex t
@@ -1024,7 +1049,10 @@ filterEventKey k kv' = do
10241049 Nothing -> Nothing
10251050 takeWhileJustE f kv'
10261051
1027−
1052+-- | "Factor" the input 'DSum' 'Event' to produce an 'Event' which
1053+-- fires when the 'DSum' key changes and contains both the value of the
1054+-- 'DSum' at switchover and an 'Event' of values produced by subsequent
1055+-- firings of the input 'Event' that do not change the 'DSum' key.
10281056factorEvent
10291057 :: forall t m k v a.
10301058 ( Reflex t
@@ -1074,26 +1102,94 @@ class Reflex t => Accumulator t f | f -> t where
10741102 mapAccumMaybe f = mapAccumMaybeM $ \v o -> return $ f v o
10751103 mapAccumMaybeM :: (MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (f a, Event t c)
10761104
1077−accumDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> a) -> a -> Event t b -> m (Dynamic t a)
1105+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1106+-- with the provided function. See 'foldDyn'.
1107+accumDyn
1108+ :: (Reflex t, MonadHold t m, MonadFix m)
1109+ => (a -> b -> a)
1110+ -> a
1111+ -> Event t b
1112+ -> m (Dynamic t a)
10781113accumDyn f = accumMaybeDyn $ \v o -> Just $ f v o
1079−accumMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t a) -> a -> Event t b -> m (Dynamic t a)
1114+
1115+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1116+-- with the provided 'PushM' action.
1117+accumMDyn
1118+ :: (Reflex t, MonadHold t m, MonadFix m)
1119+ => (a -> b -> PushM t a)
1120+ -> a
1121+ -> Event t b
1122+ -> m (Dynamic t a)
10801123accumMDyn f = accumMaybeMDyn $ \v o -> Just <$> f v o
1081−accumMaybeDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> Maybe a) -> a -> Event t b -> m (Dynamic t a)
1124+
1125+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1126+-- with the provided function, discarding 'Nothing' results.
1127+accumMaybeDyn
1128+ :: (Reflex t, MonadHold t m, MonadFix m)
1129+ => (a -> b -> Maybe a)
1130+ -> a
1131+ -> Event t b
1132+ -> m (Dynamic t a)
10821133accumMaybeDyn f = accumMaybeMDyn $ \v o -> return $ f v o
1083−accumMaybeMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Dynamic t a)
1134+
1135+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1136+-- with the provided 'PushM' action, discarding 'Nothing' results.
1137+accumMaybeMDyn
1138+ :: (Reflex t, MonadHold t m, MonadFix m)
1139+ => (a -> b -> PushM t (Maybe a))
1140+ -> a
1141+ -> Event t b
1142+ -> m (Dynamic t a)
10841143accumMaybeMDyn f z e = do
10851144 rec let e' = flip push e $ \o -> do
10861145 v <- sample $ current d'
10871146 f v o
10881147 d' <- holdDyn z e'
10891148 return d'
1090−mapAccumDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (a, c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1149+
1150+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1151+-- with a function that both accumulates and produces a value to fire
1152+-- as an 'Event'. Returns both the accumulated value and an 'Event'.
1153+mapAccumDyn
1154+ :: (Reflex t, MonadHold t m, MonadFix m)
1155+ => (a -> b -> (a, c))
1156+ -> a
1157+ -> Event t b
1158+ -> m (Dynamic t a, Event t c)
10911159mapAccumDyn f = mapAccumMaybeDyn $ \v o -> bimap Just Just $ f v o
1092−mapAccumMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (a, c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1160+
1161+-- | Similar to 'mapAccumDyn' except that the combining function is a
1162+-- 'PushM' action.
1163+mapAccumMDyn
1164+ :: (Reflex t, MonadHold t m, MonadFix m)
1165+ => (a -> b -> PushM t (a, c))
1166+ -> a
1167+ -> Event t b
1168+ -> m (Dynamic t a, Event t c)
10931169mapAccumMDyn f = mapAccumMaybeMDyn $ \v o -> bimap Just Just <$> f v o
1094−mapAccumMaybeDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (Maybe a, Maybe c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1170+
1171+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event' with
1172+-- a function that both optionally accumulates and optionally produces
1173+-- a value to fire as a separate output 'Event'.
1174+-- Note that because 'Nothing's are discarded in both cases, the output
1175+-- 'Event' may fire even though the output 'Dynamic' has not changed, and
1176+-- the output 'Dynamic' may update even when the output 'Event' is not firing.
1177+mapAccumMaybeDyn
1178+ :: (Reflex t, MonadHold t m, MonadFix m)
1179+ => (a -> b -> (Maybe a, Maybe c))
1180+ -> a
1181+ -> Event t b
1182+ -> m (Dynamic t a, Event t c)
10951183mapAccumMaybeDyn f = mapAccumMaybeMDyn $ \v o -> return $ f v o
1096−mapAccumMaybeMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1184+
1185+-- | Like 'mapAccumMaybeDyn' except that the combining function is a
1186+-- 'PushM' action.
1187+mapAccumMaybeMDyn
1188+ :: (Reflex t, MonadHold t m, MonadFix m)
1189+ => (a -> b -> PushM t (Maybe a, Maybe c))
1190+ -> a
1191+ -> Event t b
1192+ -> m (Dynamic t a, Event t c)
10971193mapAccumMaybeMDyn f z e = do
10981194 rec let e' = flip push e $ \o -> do
10991195 v <- sample $ current d'
@@ -1101,18 +1197,42 @@ mapAccumMaybeMDyn f z e = do
11011197 return $ case result of
11021198 (Nothing, Nothing) -> Nothing
11031199 _ -> Just result
1104− d' <- holdDyn z $ fmapMaybe fst e'
1105− return (d', fmapMaybe snd e')
1200+ d' <- holdDyn z $ mapMaybe fst e'
1201+ return (d', mapMaybe snd e')
11061202
1203+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1204+-- with the provided function.
11071205{-# INLINE accumB #-}
1108−accumB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> a) -> a -> Event t b -> m (Behavior t a)
1206+accumB
1207+ :: (Reflex t, MonadHold t m, MonadFix m)
1208+ => (a -> b -> a)
1209+ -> a
1210+ -> Event t b
1211+ -> m (Behavior t a)
11091212accumB f = accumMaybeB $ \v o -> Just $ f v o
1213+
1214+-- | Like 'accumB' except that the combining function is a 'PushM' action.
11101215{-# INLINE accumMB #-}
1111−accumMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t a) -> a -> Event t b -> m (Behavior t a)
1216+accumMB
1217+ :: (Reflex t, MonadHold t m, MonadFix m)
1218+ => (a -> b -> PushM t a)
1219+ -> a
1220+ -> Event t b
1221+ -> m (Behavior t a)
11121222accumMB f = accumMaybeMB $ \v o -> Just <$> f v o
1223+
1224+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1225+-- with the provided function, discarding 'Nothing' results.
11131226{-# INLINE accumMaybeB #-}
1114−accumMaybeB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> Maybe a) -> a -> Event t b -> m (Behavior t a)
1227+accumMaybeB
1228+ :: (Reflex t, MonadHold t m, MonadFix m)
1229+ => (a -> b -> Maybe a)
1230+ -> a
1231+ -> Event t b
1232+ -> m (Behavior t a)
11151233accumMaybeB f = accumMaybeMB $ \v o -> return $ f v o
1234+
1235+-- | Like 'accumMaybeB' except that the combining function is a 'PushM' action.
11161236{-# INLINE accumMaybeMB #-}
11171237accumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Behavior t a)
11181238accumMaybeMB f z e = do
@@ -1121,16 +1241,42 @@ accumMaybeMB f z e = do
11211241 f v o
11221242 d' <- hold z e'
11231243 return d'
1244+
1245+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1246+-- with a function that both accumulates and produces a value to fire
1247+-- as an 'Event'. Returns both the accumulated value and an 'Event'.
11241248{-# INLINE mapAccumB #-}
1125−mapAccumB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (a, c)) -> a -> Event t b -> m (Behavior t a, Event t c)
1249+mapAccumB
1250+ :: (Reflex t, MonadHold t m, MonadFix m)
1251+ => (a -> b -> (a, c))
1252+ -> a
1253+ -> Event t b
1254+ -> m (Behavior t a, Event t c)
11261255mapAccumB f = mapAccumMaybeB $ \v o -> bimap Just Just $ f v o
1256+
1257+-- | Like 'mapAccumB' except that the combining function is a 'PushM' action.
11271258{-# INLINE mapAccumMB #-}
1128−mapAccumMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (a, c)) -> a -> Event t b -> m (Behavior t a, Event t c)
1259+mapAccumMB
1260+ :: (Reflex t, MonadHold t m, MonadFix m)
1261+ => (a -> b -> PushM t (a, c))
1262+ -> a
1263+ -> Event t b
1264+ -> m (Behavior t a, Event t c)
11291265mapAccumMB f = mapAccumMaybeMB $ \v o -> bimap Just Just <$> f v o
1266+
1267+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event' with
1268+-- a function that both optionally accumulates and optionally produces
1269+-- a value to fire as a separate output 'Event'. 'Nothing's are discarded.
11301270{-# INLINE mapAccumMaybeB #-}
1131−mapAccumMaybeB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (Maybe a, Maybe c)) -> a -> Event t b -> m (Behavior t a, Event t c)
1271+mapAccumMaybeB
1272+ :: (Reflex t, MonadHold t m, MonadFix m)
1273+ => (a -> b -> (Maybe a, Maybe c))
1274+ -> a
1275+ -> Event t b
1276+ -> m (Behavior t a, Event t c)
11321277mapAccumMaybeB f = mapAccumMaybeMB $ \v o -> return $ f v o
11331278
1279+-- | LIke 'mapAccumMaybeB' except that the combining function is a 'PushM' action.
11341280{-# INLINE mapAccumMaybeMB #-}
11351281mapAccumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (Behavior t a, Event t c)
11361282mapAccumMaybeMB f z e = do
@@ -1140,8 +1286,8 @@ mapAccumMaybeMB f z e = do
11401286 return $ case result of
11411287 (Nothing, Nothing) -> Nothing
11421288 _ -> Just result
1143− d' <- hold z $ fmapMaybe fst e'
1144− return (d', fmapMaybe snd e')
1289+ d' <- hold z $ mapMaybe fst e'
1290+ return (d', mapMaybe snd e')
11451291
11461292-- | Accumulate occurrences of an 'Event', producing an output occurrence each
11471293-- time. Discard the underlying 'Accumulator'.
@@ -1285,38 +1431,53 @@ infixl 4 <@
12851431-- Cheap Functions
12861432------------------
12871433
1434+-- | A "cheap" version of 'pushAlways'. See the performance note on 'pushCheap'.
12881435{-# INLINE pushAlwaysCheap #-}
12891436pushAlwaysCheap :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
12901437pushAlwaysCheap f = pushCheap (fmap Just . f)
12911438
1439+-- | A "cheap" version of 'mapMaybe'. See the performance note on 'pushCheap'.
1440+{-# INLINE mapMaybeCheap #-}
1441+mapMaybeCheap :: Reflex t => (a -> Maybe b) -> Event t a -> Event t b
1442+mapMaybeCheap f = pushCheap $ return . f
1443+
1444+-- | An alias for 'mapMaybeCheap'
12921445{-# INLINE fmapMaybeCheap #-}
12931446fmapMaybeCheap :: Reflex t => (a -> Maybe b) -> Event t a -> Event t b
1294−fmapMaybeCheap f = pushCheap $ return . f
1447+fmapMaybeCheap = mapMaybeCheap
1448+
12951449
1450+-- | A "cheap" version of 'fforMaybe'. See the performance note on 'pushCheap'.
12961451{-# INLINE fforMaybeCheap #-}
12971452fforMaybeCheap :: Reflex t => Event t a -> (a -> Maybe b) -> Event t b
1298−fforMaybeCheap = flip fmapMaybeCheap
1453+fforMaybeCheap = flip mapMaybeCheap
12991454
1455+-- | A "cheap" version of 'ffor'. See the performance note on 'pushCheap'.
13001456{-# INLINE fforCheap #-}
13011457fforCheap :: Reflex t => Event t a -> (a -> b) -> Event t b
13021458fforCheap = flip fmapCheap
13031459
1460+-- | A "cheap" version of 'fmap'. See the performance note on 'pushCheap'.
13041461{-# INLINE fmapCheap #-}
13051462fmapCheap :: Reflex t => (a -> b) -> Event t a -> Event t b
13061463fmapCheap f = pushCheap $ return . Just . f
13071464
1465+-- | A "cheap" version of 'tag'. See the performance note on 'pushCheap'.
13081466{-# INLINE tagCheap #-}
13091467tagCheap :: Reflex t => Behavior t b -> Event t a -> Event t b
13101468tagCheap b = pushAlwaysCheap $ \_ -> sample b
13111469
1470+-- | A "cheap" version of 'mergeWithCheap'. See the performance note on 'pushCheap'.
13121471{-# INLINE mergeWithCheap #-}
13131472mergeWithCheap :: Reflex t => (a -> a -> a) -> [Event t a] -> Event t a
13141473mergeWithCheap = mergeWithCheap' id
13151474
1475+-- | A "cheap" version of 'mergeWithCheap''. See the performance note on 'pushCheap'.
13161476{-# INLINE mergeWithCheap' #-}
13171477mergeWithCheap' :: Reflex t => (a -> b) -> (b -> b -> b) -> [Event t a] -> Event t b
13181478mergeWithCheap' f g = mergeWithFoldCheap' $ foldl1 g . fmap f
13191479
1480+-- | A "cheap" version of 'mergeWithFoldCheap''. See the performance note on 'pushCheap'.
13201481{-# INLINE mergeWithFoldCheap' #-}
13211482mergeWithFoldCheap' :: Reflex t => (NonEmpty a -> b) -> [Event t a] -> Event t b
13221483mergeWithFoldCheap' f es =
@@ -1329,28 +1490,6 @@ mergeWithFoldCheap' f es =
13291490-- Deprecated functions
13301491--------------------------------------------------------------------------------
13311492
1332−-- | Create a new 'Event' that occurs if at least one of the supplied 'Event's
1333−-- occurs. If both occur at the same time they are combined using 'mappend'.
1334−{-# DEPRECATED appendEvents "If a 'Semigroup a' instance is available, use 'mappend'; otherwise, use 'alignWith (mergeThese mappend)' instead" #-}
1335−appendEvents :: (Reflex t, Monoid a) => Event t a -> Event t a -> Event t a
1336−appendEvents = alignWith $ mergeThese mappend
1337−
1338−-- | Alias for 'headE'
1339−{-# DEPRECATED onceE "Use 'headE' instead" #-}
1340−onceE :: MonadHold t m => Event t a -> m (Event t a)
1341−onceE = headE
1342−
1343−-- | Run both sides of a 'These' monadically, combining the results.
1344−{-# DEPRECATED sequenceThese "Use bisequenceA or bisequence from the bifunctors package instead" #-}
1345−#ifdef USE_TEMPLATE_HASKELL
1346−{-# ANN sequenceThese "HLint: ignore Use fmap" #-}
1347−#endif
1348−sequenceThese :: Monad m => These (m a) (m b) -> m (These a b)
1349−sequenceThese t = case t of
1350− This ma -> fmap This ma
1351− These ma mb -> liftM2 These ma mb
1352− That mb -> fmap That mb
1353−
13541493{-# 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'. " #-}
13551494switchPromptly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
13561495switchPromptly = switchHoldPromptly