@@ -21,9 +21,13 @@
21{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
21{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
24−-- | This module contains the Reflex interface, as well as a variety of
28+-- This module contains the Reflex interface, as well as a variety of
25−-- convenience functions for working with 'Event's, 'Behavior's, and other
29+-- convenience functions for working with 'Event's, 'Behavior's, and other
26−-- signals.
30+-- signals.
27module Reflex.Class
31module Reflex.Class
28 ( module Reflex.Patch
32 ( module Reflex.Patch
29 -- * Primitives
33 -- * Primitives
@@ -34,10 +38,9 @@ module Reflex.Class
34 , coerceDynamic
38 , coerceDynamic
35 , MonadSample (..)
39 , MonadSample (..)
36 , MonadHold (..)
40 , MonadHold (..)
37− -- ** 'fan'-related types
41+ -- ** 'fan' related types
38 , EventSelector (..)
42 , EventSelector (..)
39 , EventSelectorInt (..)
43 , EventSelectorInt (..)
40− -- ** 'Incremental'-related types
41 -- * Convenience functions
44 -- * Convenience functions
42 , constDyn
45 , constDyn
43 , pushAlways
46 , pushAlways
@@ -134,8 +137,10 @@ module Reflex.Class
134 -- * Unsafe functions
137 -- * Unsafe functions
135 , unsafeDynamic
138 , unsafeDynamic
136 , unsafeMapIncremental
139 , unsafeMapIncremental
137− -- * 'FunctorMaybe'
140+ -- * 'Filterable' convenience functions
138− , FunctorMaybe (..)
141+ , FunctorMaybe -- fmapMaybe is purposely not exported from deprecated 'FunctorMaybe' and the new alias is exported instead
142+ , mapMaybe -- Re-exported for convenience
139 , fforMaybe
144 , fforMaybe
140 , ffilter
145 , ffilter
141 , filterLeft
146 , filterLeft
@@ -145,10 +150,11 @@ module Reflex.Class
147 -- * Deprecated functions
152 -- * Deprecated functions
148− , appendEvents
153+ , switchPromptly
149− , onceE
154+ , switchPromptOnly
150− , sequenceThese
155+ -- * "Cheap" functions
151 , fmapMaybeCheap
156 , fmapMaybeCheap
152 , fmapCheap
158 , fmapCheap
153 , fforCheap
159 , fforCheap
154 , fforMaybeCheap
160 , fforMaybeCheap
@@ -156,8 +162,6 @@ module Reflex.Class
156 , tagCheap
162 , tagCheap
157 , mergeWithCheap
163 , mergeWithCheap
158 , mergeWithCheap'
164 , mergeWithCheap'
161 -- * Slow, but general, implementations
165 -- * Slow, but general, implementations
162 , slowHeadE
166 , slowHeadE
@@ -194,14 +198,17 @@ import qualified Data.Some as Some
194import Data.String
198import Data.String
195import Data.These
199import Data.These
196import Data.Type.Coercion
200import Data.Type.Coercion
201+import Data.Witherable (Filterable(..))
202+import qualified Data.Witherable as W
203+import Reflex.FunctorMaybe (FunctorMaybe)
197−import Reflex.FunctorMaybe
204+import qualified Reflex.FunctorMaybe
198import Reflex.Patch
205import Reflex.Patch
199import qualified Reflex.Patch.MapWithMove as PatchMapWithMove
206import qualified Reflex.Patch.MapWithMove as PatchMapWithMove
201import Debug.Trace (trace)
208import Debug.Trace (trace)
203-- | The 'Reflex' class contains all the primitive functionality needed for
210-- | 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
205-- which "timeline" is in use. Timelines are fully-independent FRP contexts,
212-- which "timeline" is in use. Timelines are fully-independent FRP contexts,
206-- and the type of the timeline determines the FRP engine to be used. For most
213-- and the type of the timeline determines the FRP engine to be used. For most
207-- purposes, the 'Reflex.Spider' implementation is recommended.
214-- purposes, the 'Reflex.Spider' implementation is recommended.
@@ -257,8 +264,7 @@ class ( MonadHold t (PushM t)
257 -- | Create an 'Event' that will occur whenever the currently-selected input
264 -- | Create an 'Event' that will occur whenever the currently-selected input
258 -- 'Event' occurs
265 -- 'Event' occurs
259 switch :: Behavior t (Event t a) -> Event t a
266 switch :: Behavior t (Event t a) -> Event t a
260− -- | Create an 'Event' that will occur whenever the input event is occurring
267+ -- | Create an 'Event' that will occur whenever the input event is occurring -- and its occurrence value, another 'Event', is also occurring
261− -- and its occurrence value, another 'Event', is also occurring
262 coincidence :: Event t (Event t a) -> Event t a
268 coincidence :: Event t (Event t a) -> Event t a
263 -- | Extract the 'Behavior' of a 'Dynamic'.
269 -- | Extract the 'Behavior' of a 'Dynamic'.
264 current :: Dynamic t a -> Behavior t a
270 current :: Dynamic t a -> Behavior t a
@@ -267,7 +273,7 @@ class ( MonadHold t (PushM t)
267 -- | Create a new 'Dynamic'. The given 'PullM' must always return the most
273 -- | Create a new 'Dynamic'. The given 'PullM' must always return the most
268 -- recent firing of the given 'Event', if any.
274 -- recent firing of the given 'Event', if any.
269 unsafeBuildDynamic :: PullM t a -> Event t a -> Dynamic t a
275 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
271 -- in the same way that the accumulated application of patches would change
277 -- in the same way that the accumulated application of patches would change
272 -- that value.
278 -- that value.
273 unsafeBuildIncremental :: Patch p => PullM t (PatchTarget p) -> Event t p -> Incremental t p
279 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
310coerceDynamic = coerceWith $ dynamicCoercion Coercion
316coerceDynamic = coerceWith $ dynamicCoercion Coercion
312-- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'. The 'Behavior'
318-- | 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
314-- 'Behavior''s value is always equal to the most recent firing of the 'Event';
320-- 'Behavior''s value is always equal to the most recent firing of the 'Event';
315-- if this is not the case, the resulting 'Dynamic' will behave
321-- if this is not the case, the resulting 'Dynamic' will behave
316-- nondeterministically.
322-- nondeterministically.
@@ -338,7 +344,7 @@ class MonadSample t m => MonadHold t m where
338 -- value and will be updated whenever the given 'Event' occurs. The update
344 -- value and will be updated whenever the given 'Event' occurs. The update
339 -- takes effect immediately after the 'Event' occurs; if the occurrence that
345 -- takes effect immediately after the 'Event' occurs; if the occurrence that
340 -- sets the 'Behavior' (or one that is simultaneous with it) is used to sample
346 -- 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
343 hold :: a -> Event t a -> m (Behavior t a)
349 hold :: a -> Event t a -> m (Behavior t a)
344 default hold :: (m ~ f m', MonadTrans f, MonadHold t m') => a -> Event t a -> m (Behavior t a)
350 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
389 return $ case result of
395 return $ case result of
390 (Nothing, Nothing) -> Nothing
396 (Nothing, Nothing) -> Nothing
391 _ -> Just result
397 _ -> Just result
392− d' <- holdIncremental z $ fmapMaybe fst e'
398+ d' <- holdIncremental z $ mapMaybe fst e'
393− return (d', fmapMaybe snd e')
399+ return (d', mapMaybe snd e')
395slowHeadE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
401slowHeadE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
396slowHeadE e = do
402slowHeadE e = do
@@ -400,14 +406,14 @@ slowHeadE e = do
401-- | An 'EventSelector' allows you to efficiently 'select' an 'Event' based on a
407-- | An 'EventSelector' allows you to efficiently 'select' an 'Event' based on a
402-- key. This is much more efficient than filtering for each key with
408-- key. This is much more efficient than filtering for each key with
403−-- 'fmapMaybe'.
409+-- 'mapMaybe'.
404newtype EventSelector t k = EventSelector
410newtype EventSelector t k = EventSelector
405 { -- | Retrieve the 'Event' for the given key. The type of the 'Event' is
411 { -- | Retrieve the 'Event' for the given key. The type of the 'Event' is
406 -- determined by the type of the key, so this can be used to fan-out
412 -- determined by the type of the key, so this can be used to fan-out
407 -- 'Event's whose sub-'Event's have different types.
413 -- 'Event's whose sub-'Event's have different types.
409 -- Using 'EventSelector's and the 'fan' primitive is far more efficient than
415 -- 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
411 -- occurrences of an 'Event'.
417 -- occurrences of an 'Event'.
412 select :: forall a. k a -> Event t a
418 select :: forall a. k a -> Event t a
@@ -542,6 +548,15 @@ instance (Reflex t, Num a) => Num (Behavior t a) where
542 negate = fmap negate
548 negate = fmap negate
543 signum = fmap signum
549 signum = fmap signum
551+instance (Num a, Reflex t) => Num (Dynamic t a) where
555+ signum = fmap signum
556+ fromInteger = pure . fromInteger
557+ negate = fmap negate
545instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
560instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
546 a <> b = pull $ liftM2 (<>) (sample a) (sample b)
561 a <> b = pull $ liftM2 (<>) (sample a) (sample b)
547 sconcat = pull . fmap sconcat . mapM sample
562 sconcat = pull . fmap sconcat . mapM sample
@@ -551,22 +566,25 @@ instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
551 times1p n = fmap $ times1p n
566 times1p n = fmap $ times1p n
569+-- | Alias for 'mapMaybe'
570+fmapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b
554−-- | Flipped version of 'fmapMaybe'.
573+-- | Flipped version of 'mapMaybe'.
555−fforMaybe :: FunctorMaybe f => f a -> (a -> Maybe b) -> f b
574+fforMaybe :: Filterable f => f a -> (a -> Maybe b) -> f b
556−fforMaybe = flip fmapMaybe
575+fforMaybe = flip mapMaybe
558-- | Filter 'f a' using the provided predicate.
577-- | Filter 'f a' using the provided predicate.
559−-- Relies on 'fforMaybe'.
560−ffilter :: FunctorMaybe f => (a -> Bool) -> f a -> f a
578+ffilter :: Filterable f => (a -> Bool) -> f a -> f a
561−ffilter f = fmapMaybe $ \x -> if f x then Just x else Nothing
579+ffilter = W.filter
563-- | Filter 'Left's from 'f (Either a b)' into 'a'.
581-- | Filter 'Left's from 'f (Either a b)' into 'a'.
564−filterLeft :: FunctorMaybe f => f (Either a b) -> f a
582+filterLeft :: Filterable f => f (Either a b) -> f a
565−filterLeft = fmapMaybe (either Just (const Nothing))
583+filterLeft = mapMaybe (either Just (const Nothing))
567-- | Filter 'Right's from 'f (Either a b)' into 'b'.
585-- | Filter 'Right's from 'f (Either a b)' into 'b'.
568−filterRight :: FunctorMaybe f => f (Either a b) -> f b
586+filterRight :: Filterable f => f (Either a b) -> f b
569−filterRight = fmapMaybe (either (const Nothing) Just)
587+filterRight = mapMaybe (either (const Nothing) Just)
571-- | Left-biased event union (prefers left event on simultaneous
589-- | Left-biased event union (prefers left event on simultaneous
572-- occurrence).
590-- occurrence).
@@ -584,13 +602,18 @@ instance Reflex t => Bind (Event t) where
585instance Reflex t => Functor (Event t) where
603instance Reflex t => Functor (Event t) where
586 {-# INLINE fmap #-}
604 {-# INLINE fmap #-}
587− fmap f = fmapMaybe $ Just . f
605+ fmap f = mapMaybe $ Just . f
588 {-# INLINE (<$) #-}
606 {-# INLINE (<$) #-}
589 x <$ e = fmapCheap (const x) e
607 x <$ e = fmapCheap (const x) e
609+-- TODO Remove this instance
591instance Reflex t => FunctorMaybe (Event t) where
610instance Reflex t => FunctorMaybe (Event t) where
592 {-# INLINE fmapMaybe #-}
611 {-# INLINE fmapMaybe #-}
612+ fmapMaybe = mapMaybe
614+instance Reflex t => Filterable (Event t) where
615+ {-# INLINE mapMaybe #-}
593− fmapMaybe f = push $ return . f
616+ mapMaybe f = push $ return . f
595-- | Never: @'zero' = 'never'@.
618-- | Never: @'zero' = 'never'@.
596instance Reflex t => Plus (Event t) where
619instance Reflex t => Plus (Event t) where
@@ -641,7 +664,7 @@ headTailE e = do
641-- event returns 'True'.
664-- event returns 'True'.
643-- Starting at the current time, fire all the occurrences of the 'Event' for
666-- 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,
645-- do not fire, and permanently stop firing, even if 'True' values would have
668-- do not fire, and permanently stop firing, even if 'True' values would have
646-- been encountered later.
669-- been encountered later.
647takeWhileE
670takeWhileE
@@ -656,7 +679,7 @@ takeWhileE f = takeWhileJustE $ \v -> guard (f v) $> v
656-- event returns 'Just b'.
679-- event returns 'Just b'.
658-- Starting at the current time, fire all the occurrences of the 'Event' for
681-- 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,
660-- do not fire, and permanently stop firing, even if 'Just b' values would have
683-- do not fire, and permanently stop firing, even if 'Just b' values would have
661-- been encountered later.
684-- been encountered later.
662takeWhileJustE
685takeWhileJustE
@@ -808,7 +831,7 @@ fanEither :: Reflex t => Event t (Either a b) -> (Event t a, Event t b)
808fanEither e =
831fanEither e =
809 let justLeft = either Just (const Nothing)
832 let justLeft = either Just (const Nothing)
810 justRight = either (const Nothing) Just
833 justRight = either (const Nothing) Just
811− in (fmapMaybe justLeft e, fmapMaybe justRight e)
834+ in (mapMaybe justLeft e, mapMaybe justRight e)
813-- | Split the event into separate events for 'This' and 'That' values,
836-- | Split the event into separate events for 'This' and 'That' values,
814-- allowing them to fire simultaneously when the input value is 'These'.
837-- allowing them to fire simultaneously when the input value is 'These'.
@@ -820,7 +843,7 @@ fanThese e =
820 that (That y) = Just y
843 that (That y) = Just y
821 that (These _ y) = Just y
844 that (These _ y) = Just y
822 that _ = Nothing
845 that _ = Nothing
823− in (fmapMaybe this e, fmapMaybe that e)
846+ in (mapMaybe this e, mapMaybe that e)
825-- | Split the event into an 'EventSelector' that allows efficient selection of
848-- | Split the event into an 'EventSelector' that allows efficient selection of
826-- the individual 'Event's.
849-- the individual 'Event's.
@@ -829,7 +852,7 @@ fanMap = fan . fmap mapToDMap
830-- | Switches to the new event whenever it receives one. Only the old event is
853-- | Switches to the new event whenever it receives one. Only the old event is
831-- considered the moment a new one is switched in; the output event will fire at
854-- 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.
834-- Because the simultaneous firing case is irrelevant, this function imposes
857-- Because the simultaneous firing case is irrelevant, this function imposes
835-- laxer "timing requirements" on the overall circuit, avoiding many potential
858-- laxer "timing requirements" on the overall circuit, avoiding many potential
@@ -875,13 +898,13 @@ coincidencePatchMap e = fmapCheap PatchMap $ coincidence $ ffor e $ \(PatchMap m
875 Nothing -> fmapCheap (const Nothing) e
898 Nothing -> fmapCheap (const Nothing) e
876 Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
899 Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
878−-- | See 'coincicencePatchMap'
901+-- | See 'coincidencePatchMap'
879coincidencePatchIntMap :: Reflex t => Event t (PatchIntMap (Event t v)) -> Event t (PatchIntMap v)
902coincidencePatchIntMap :: Reflex t => Event t (PatchIntMap (Event t v)) -> Event t (PatchIntMap v)
880coincidencePatchIntMap e = fmapCheap PatchIntMap $ coincidence $ ffor e $ \(PatchIntMap m) -> mergeIntMap $ ffor m $ \case
903coincidencePatchIntMap e = fmapCheap PatchIntMap $ coincidence $ ffor e $ \(PatchIntMap m) -> mergeIntMap $ ffor m $ \case
881 Nothing -> fmapCheap (const Nothing) e
904 Nothing -> fmapCheap (const Nothing) e
882 Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
905 Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
884−-- | See 'coincicencePatchMap'
907+-- | See 'coincidencePatchMap'
885coincidencePatchMapWithMove :: (Reflex t, Ord k) => Event t (PatchMapWithMove k (Event t v)) -> Event t (PatchMapWithMove k v)
908coincidencePatchMapWithMove :: (Reflex t, Ord k) => Event t (PatchMapWithMove k (Event t v)) -> Event t (PatchMapWithMove k v)
886coincidencePatchMapWithMove e = fmapCheap unsafePatchMapWithMove $ coincidence $ ffor e $ \p -> mergeMap $ ffor (unPatchMapWithMove p) $ \ni -> case PatchMapWithMove._nodeInfo_from ni of
909coincidencePatchMapWithMove e = fmapCheap unsafePatchMapWithMove $ coincidence $ ffor e $ \p -> mergeMap $ ffor (unPatchMapWithMove p) $ \ni -> case PatchMapWithMove._nodeInfo_from ni of
887 PatchMapWithMove.From_Delete -> fforCheap e $ \_ ->
910 PatchMapWithMove.From_Delete -> fforCheap e $ \_ ->
@@ -942,7 +965,7 @@ zipDyn = zipDynWith (,)
943-- | Combine two 'Dynamic's with a combining function. The result will change
966-- | Combine two 'Dynamic's with a combining function. The result will change
944-- whenever either (or both) input 'Dynamic' changes.
967-- whenever either (or both) input 'Dynamic' changes.
945−-- More efficient than liftA2.
968+-- More efficient than 'liftA2'.
946zipDynWith :: Reflex t => (a -> b -> c) -> Dynamic t a -> Dynamic t b -> Dynamic t c
969zipDynWith :: Reflex t => (a -> b -> c) -> Dynamic t a -> Dynamic t b -> Dynamic t c
947zipDynWith f da db =
970zipDynWith f da db =
948 let eab = align (updated da) (updated db)
971 let eab = align (updated da) (updated db)
@@ -973,7 +996,7 @@ instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where
974-- | This function converts a 'DMap' whose elements are 'Dynamic's into a
997-- | This function converts a 'DMap' whose elements are 'Dynamic's into a
975-- 'Dynamic' 'DMap'. Its implementation is more efficient than doing the same
998-- '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.
977distributeDMapOverDynPure :: forall t k. (Reflex t, GCompare k) => DMap k (Dynamic t) -> Dynamic t (DMap k Identity)
1000distributeDMapOverDynPure :: forall t k. (Reflex t, GCompare k) => DMap k (Dynamic t) -> Dynamic t (DMap k Identity)
978distributeDMapOverDynPure dm = case DMap.toList dm of
1001distributeDMapOverDynPure dm = case DMap.toList dm of
979 [] -> constDyn DMap.empty
1002 [] -> constDyn DMap.empty
@@ -999,14 +1022,16 @@ distributeListOverDynWith f = fmap (f . map (\(Const2 _ :=> Identity v) -> v) .
999difference :: Reflex t => Event t a -> Event t b -> Event t a
1022difference :: Reflex t => Event t a -> Event t b -> Event t a
1000difference = alignEventWithMaybe $ \case
1023difference = alignEventWithMaybe $ \case
1001 This a -> Just a
1024 This a -> Just a
1002− _ -> Nothing
1025+ _ -> Nothing
1027+-- | Zips two values by taking the union of their shapes and combining with the provided function.
1028+-- 'Nothing' values are dropped.
1004alignEventWithMaybe :: Reflex t => (These a b -> Maybe c) -> Event t a -> Event t b -> Event t c
1029alignEventWithMaybe :: Reflex t => (These a b -> Maybe c) -> Event t a -> Event t b -> Event t c
1005−alignEventWithMaybe f ea eb =
1030+alignEventWithMaybe f ea eb = mapMaybe (f <=< dmapToThese) $
1006− fmapMaybe (f <=< dmapToThese)
1008− $ DMap.fromList [LeftTag :=> ea, RightTag :=> eb]
1031+ merge $ DMap.fromList [LeftTag :=> ea, RightTag :=> eb]
1033+-- | Produces an 'Event' that fires only when the input event fires with a 'DSum' key that
1034+-- matches the provided key.
1010filterEventKey
1035filterEventKey
1011 :: forall t m k v a.
1036 :: forall t m k v a.
1012 ( Reflex t
1037 ( Reflex t
@@ -1024,7 +1049,10 @@ filterEventKey k kv' = do
1024 Nothing -> Nothing
1049 Nothing -> Nothing
1025 takeWhileJustE f kv'
1050 takeWhileJustE f kv'
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.
1028factorEvent
1056factorEvent
1029 :: forall t m k v a.
1057 :: forall t m k v a.
1030 ( Reflex t
1058 ( Reflex t
@@ -1074,26 +1102,94 @@ class Reflex t => Accumulator t f | f -> t where
1074 mapAccumMaybe f = mapAccumMaybeM $ \v o -> return $ f v o
1102 mapAccumMaybe f = mapAccumMaybeM $ \v o -> return $ f v o
1075 mapAccumMaybeM :: (MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (f a, Event t c)
1103 mapAccumMaybeM :: (MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (f a, Event t c)
1105+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1106+-- with the provided function. See 'foldDyn'.
1077−accumDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> a) -> a -> Event t b -> m (Dynamic t a)
1108+ :: (Reflex t, MonadHold t m, MonadFix m)
1078accumDyn f = accumMaybeDyn $ \v o -> Just $ f v o
1113accumDyn f = accumMaybeDyn $ \v o -> Just $ f v o
1115+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1116+-- with the provided 'PushM' action.
1079−accumMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t a) -> a -> Event t b -> m (Dynamic t a)
1118+ :: (Reflex t, MonadHold t m, MonadFix m)
1119+ => (a -> b -> PushM t a)
1080accumMDyn f = accumMaybeMDyn $ \v o -> Just <$> f v o
1123accumMDyn f = accumMaybeMDyn $ \v o -> Just <$> f v o
1125+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1126+-- with the provided function, discarding 'Nothing' results.
1081−accumMaybeDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> Maybe a) -> a -> Event t b -> m (Dynamic t a)
1128+ :: (Reflex t, MonadHold t m, MonadFix m)
1129+ => (a -> b -> Maybe a)
1082accumMaybeDyn f = accumMaybeMDyn $ \v o -> return $ f v o
1133accumMaybeDyn f = accumMaybeMDyn $ \v o -> return $ f v o
1135+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1136+-- with the provided 'PushM' action, discarding 'Nothing' results.
1083−accumMaybeMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Dynamic t a)
1138+ :: (Reflex t, MonadHold t m, MonadFix m)
1139+ => (a -> b -> PushM t (Maybe a))
1084accumMaybeMDyn f z e = do
1143accumMaybeMDyn f z e = do
1085 rec let e' = flip push e $ \o -> do
1144 rec let e' = flip push e $ \o -> do
1086 v <- sample $ current d'
1145 v <- sample $ current d'
1088 d' <- holdDyn z e'
1147 d' <- holdDyn z e'
1089 return d'
1148 return d'
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'.
1090−mapAccumDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (a, c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1154+ :: (Reflex t, MonadHold t m, MonadFix m)
1155+ => (a -> b -> (a, c))
1158+ -> m (Dynamic t a, Event t c)
1091mapAccumDyn f = mapAccumMaybeDyn $ \v o -> bimap Just Just $ f v o
1159mapAccumDyn f = mapAccumMaybeDyn $ \v o -> bimap Just Just $ f v o
1161+-- | Similar to 'mapAccumDyn' except that the combining function is a
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)
1164+ :: (Reflex t, MonadHold t m, MonadFix m)
1165+ => (a -> b -> PushM t (a, c))
1168+ -> m (Dynamic t a, Event t c)
1093mapAccumMDyn f = mapAccumMaybeMDyn $ \v o -> bimap Just Just <$> f v o
1169mapAccumMDyn f = mapAccumMaybeMDyn $ \v o -> bimap Just Just <$> f v o
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.
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)
1178+ :: (Reflex t, MonadHold t m, MonadFix m)
1179+ => (a -> b -> (Maybe a, Maybe c))
1182+ -> m (Dynamic t a, Event t c)
1095mapAccumMaybeDyn f = mapAccumMaybeMDyn $ \v o -> return $ f v o
1183mapAccumMaybeDyn f = mapAccumMaybeMDyn $ \v o -> return $ f v o
1185+-- | Like 'mapAccumMaybeDyn' except that the combining function is a
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)
1188+ :: (Reflex t, MonadHold t m, MonadFix m)
1189+ => (a -> b -> PushM t (Maybe a, Maybe c))
1192+ -> m (Dynamic t a, Event t c)
1097mapAccumMaybeMDyn f z e = do
1193mapAccumMaybeMDyn f z e = do
1098 rec let e' = flip push e $ \o -> do
1194 rec let e' = flip push e $ \o -> do
1099 v <- sample $ current d'
1195 v <- sample $ current d'
@@ -1101,18 +1197,42 @@ mapAccumMaybeMDyn f z e = do
1101 return $ case result of
1197 return $ case result of
1102 (Nothing, Nothing) -> Nothing
1198 (Nothing, Nothing) -> Nothing
1103 _ -> Just result
1199 _ -> Just result
1104− d' <- holdDyn z $ fmapMaybe fst e'
1200+ d' <- holdDyn z $ mapMaybe fst e'
1105− return (d', fmapMaybe snd e')
1201+ return (d', mapMaybe snd e')
1203+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1204+-- with the provided function.
1107{-# INLINE accumB #-}
1205{-# INLINE accumB #-}
1108−accumB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> a) -> a -> Event t b -> m (Behavior t a)
1207+ :: (Reflex t, MonadHold t m, MonadFix m)
1211+ -> m (Behavior t a)
1109accumB f = accumMaybeB $ \v o -> Just $ f v o
1212accumB f = accumMaybeB $ \v o -> Just $ f v o
1214+-- | Like 'accumB' except that the combining function is a 'PushM' action.
1110{-# INLINE accumMB #-}
1215{-# INLINE accumMB #-}
1111−accumMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t a) -> a -> Event t b -> m (Behavior t a)
1217+ :: (Reflex t, MonadHold t m, MonadFix m)
1218+ => (a -> b -> PushM t a)
1221+ -> m (Behavior t a)
1112accumMB f = accumMaybeMB $ \v o -> Just <$> f v o
1222accumMB f = accumMaybeMB $ \v o -> Just <$> f v o
1224+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1225+-- with the provided function, discarding 'Nothing' results.
1113{-# INLINE accumMaybeB #-}
1226{-# INLINE accumMaybeB #-}
1114−accumMaybeB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> Maybe a) -> a -> Event t b -> m (Behavior t a)
1228+ :: (Reflex t, MonadHold t m, MonadFix m)
1229+ => (a -> b -> Maybe a)
1232+ -> m (Behavior t a)
1115accumMaybeB f = accumMaybeMB $ \v o -> return $ f v o
1233accumMaybeB f = accumMaybeMB $ \v o -> return $ f v o
1235+-- | Like 'accumMaybeB' except that the combining function is a 'PushM' action.
1116{-# INLINE accumMaybeMB #-}
1236{-# INLINE accumMaybeMB #-}
1117accumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Behavior t a)
1237accumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Behavior t a)
1118accumMaybeMB f z e = do
1238accumMaybeMB f z e = do
@@ -1121,16 +1241,42 @@ accumMaybeMB f z e = do
1122 d' <- hold z e'
1242 d' <- hold z e'
1123 return d'
1243 return d'
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'.
1124{-# INLINE mapAccumB #-}
1248{-# 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)
1250+ :: (Reflex t, MonadHold t m, MonadFix m)
1251+ => (a -> b -> (a, c))
1254+ -> m (Behavior t a, Event t c)
1126mapAccumB f = mapAccumMaybeB $ \v o -> bimap Just Just $ f v o
1255mapAccumB f = mapAccumMaybeB $ \v o -> bimap Just Just $ f v o
1257+-- | Like 'mapAccumB' except that the combining function is a 'PushM' action.
1127{-# INLINE mapAccumMB #-}
1258{-# 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)
1260+ :: (Reflex t, MonadHold t m, MonadFix m)
1261+ => (a -> b -> PushM t (a, c))
1264+ -> m (Behavior t a, Event t c)
1129mapAccumMB f = mapAccumMaybeMB $ \v o -> bimap Just Just <$> f v o
1265mapAccumMB f = mapAccumMaybeMB $ \v o -> bimap Just Just <$> f v o
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.
1130{-# INLINE mapAccumMaybeB #-}
1270{-# 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)
1272+ :: (Reflex t, MonadHold t m, MonadFix m)
1273+ => (a -> b -> (Maybe a, Maybe c))
1276+ -> m (Behavior t a, Event t c)
1132mapAccumMaybeB f = mapAccumMaybeMB $ \v o -> return $ f v o
1277mapAccumMaybeB f = mapAccumMaybeMB $ \v o -> return $ f v o
1279+-- | LIke 'mapAccumMaybeB' except that the combining function is a 'PushM' action.
1134{-# INLINE mapAccumMaybeMB #-}
1280{-# INLINE mapAccumMaybeMB #-}
1135mapAccumMaybeMB :: (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)
1281mapAccumMaybeMB :: (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)
1136mapAccumMaybeMB f z e = do
1282mapAccumMaybeMB f z e = do
@@ -1140,8 +1286,8 @@ mapAccumMaybeMB f z e = do
1140 return $ case result of
1286 return $ case result of
1141 (Nothing, Nothing) -> Nothing
1287 (Nothing, Nothing) -> Nothing
1142 _ -> Just result
1288 _ -> Just result
1143− d' <- hold z $ fmapMaybe fst e'
1289+ d' <- hold z $ mapMaybe fst e'
1144− return (d', fmapMaybe snd e')
1290+ return (d', mapMaybe snd e')
1146-- | Accumulate occurrences of an 'Event', producing an output occurrence each
1292-- | Accumulate occurrences of an 'Event', producing an output occurrence each
1147-- time. Discard the underlying 'Accumulator'.
1293-- time. Discard the underlying 'Accumulator'.
@@ -1285,38 +1431,53 @@ infixl 4 <@
1285-- Cheap Functions
1431-- Cheap Functions
1286------------------
1432------------------
1434+-- | A "cheap" version of 'pushAlways'. See the performance note on 'pushCheap'.
1288{-# INLINE pushAlwaysCheap #-}
1435{-# INLINE pushAlwaysCheap #-}
1289pushAlwaysCheap :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
1436pushAlwaysCheap :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
1290pushAlwaysCheap f = pushCheap (fmap Just . f)
1437pushAlwaysCheap f = pushCheap (fmap Just . f)
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
1444+-- | An alias for 'mapMaybeCheap'
1292{-# INLINE fmapMaybeCheap #-}
1445{-# INLINE fmapMaybeCheap #-}
1293fmapMaybeCheap :: Reflex t => (a -> Maybe b) -> Event t a -> Event t b
1446fmapMaybeCheap :: Reflex t => (a -> Maybe b) -> Event t a -> Event t b
1294−fmapMaybeCheap f = pushCheap $ return . f
1447+fmapMaybeCheap = mapMaybeCheap
1450+-- | A "cheap" version of 'fforMaybe'. See the performance note on 'pushCheap'.
1296{-# INLINE fforMaybeCheap #-}
1451{-# INLINE fforMaybeCheap #-}
1297fforMaybeCheap :: Reflex t => Event t a -> (a -> Maybe b) -> Event t b
1452fforMaybeCheap :: Reflex t => Event t a -> (a -> Maybe b) -> Event t b
1298−fforMaybeCheap = flip fmapMaybeCheap
1453+fforMaybeCheap = flip mapMaybeCheap
1455+-- | A "cheap" version of 'ffor'. See the performance note on 'pushCheap'.
1300{-# INLINE fforCheap #-}
1456{-# INLINE fforCheap #-}
1301fforCheap :: Reflex t => Event t a -> (a -> b) -> Event t b
1457fforCheap :: Reflex t => Event t a -> (a -> b) -> Event t b
1302fforCheap = flip fmapCheap
1458fforCheap = flip fmapCheap
1460+-- | A "cheap" version of 'fmap'. See the performance note on 'pushCheap'.
1304{-# INLINE fmapCheap #-}
1461{-# INLINE fmapCheap #-}
1305fmapCheap :: Reflex t => (a -> b) -> Event t a -> Event t b
1462fmapCheap :: Reflex t => (a -> b) -> Event t a -> Event t b
1306fmapCheap f = pushCheap $ return . Just . f
1463fmapCheap f = pushCheap $ return . Just . f
1465+-- | A "cheap" version of 'tag'. See the performance note on 'pushCheap'.
1308{-# INLINE tagCheap #-}
1466{-# INLINE tagCheap #-}
1309tagCheap :: Reflex t => Behavior t b -> Event t a -> Event t b
1467tagCheap :: Reflex t => Behavior t b -> Event t a -> Event t b
1310tagCheap b = pushAlwaysCheap $ \_ -> sample b
1468tagCheap b = pushAlwaysCheap $ \_ -> sample b
1470+-- | A "cheap" version of 'mergeWithCheap'. See the performance note on 'pushCheap'.
1312{-# INLINE mergeWithCheap #-}
1471{-# INLINE mergeWithCheap #-}
1313mergeWithCheap :: Reflex t => (a -> a -> a) -> [Event t a] -> Event t a
1472mergeWithCheap :: Reflex t => (a -> a -> a) -> [Event t a] -> Event t a
1314mergeWithCheap = mergeWithCheap' id
1473mergeWithCheap = mergeWithCheap' id
1475+-- | A "cheap" version of 'mergeWithCheap''. See the performance note on 'pushCheap'.
1316{-# INLINE mergeWithCheap' #-}
1476{-# INLINE mergeWithCheap' #-}
1317mergeWithCheap' :: Reflex t => (a -> b) -> (b -> b -> b) -> [Event t a] -> Event t b
1477mergeWithCheap' :: Reflex t => (a -> b) -> (b -> b -> b) -> [Event t a] -> Event t b
1318mergeWithCheap' f g = mergeWithFoldCheap' $ foldl1 g . fmap f
1478mergeWithCheap' f g = mergeWithFoldCheap' $ foldl1 g . fmap f
1480+-- | A "cheap" version of 'mergeWithFoldCheap''. See the performance note on 'pushCheap'.
1320{-# INLINE mergeWithFoldCheap' #-}
1481{-# INLINE mergeWithFoldCheap' #-}
1321mergeWithFoldCheap' :: Reflex t => (NonEmpty a -> b) -> [Event t a] -> Event t b
1482mergeWithFoldCheap' :: Reflex t => (NonEmpty a -> b) -> [Event t a] -> Event t b
1322mergeWithFoldCheap' f es =
1483mergeWithFoldCheap' f es =
@@ -1329,28 +1490,6 @@ mergeWithFoldCheap' f es =
1329-- Deprecated functions
1490-- Deprecated functions
1330--------------------------------------------------------------------------------
1491--------------------------------------------------------------------------------
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
1338−-- | Alias for 'headE'
1339−{-# DEPRECATED onceE "Use 'headE' instead" #-}
1340−onceE :: MonadHold t m => Event t a -> m (Event t a)
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" #-}
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
1354{-# 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'. " #-}
1493{-# 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'. " #-}
1355switchPromptly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
1494switchPromptly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
1356switchPromptly = switchHoldPromptly
1495switchPromptly = switchHoldPromptly