@@ -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
@@ -256,8 +260,7 @@ class ( MonadHold t (PushM t)
256 -- | Create an 'Event' that will occur whenever the currently-selected input
260 -- | Create an 'Event' that will occur whenever the currently-selected input
257 -- 'Event' occurs
261 -- 'Event' occurs
258 switch :: Behavior t (Event t a) -> Event t a
262 switch :: Behavior t (Event t a) -> Event t a
259− -- | Create an 'Event' that will occur whenever the input event is occurring
263+ -- | Create an 'Event' that will occur whenever the input event is occurring -- and its occurrence value, another 'Event', is also occurring
260− -- and its occurrence value, another 'Event', is also occurring
261 coincidence :: Event t (Event t a) -> Event t a
264 coincidence :: Event t (Event t a) -> Event t a
262 -- | Extract the 'Behavior' of a 'Dynamic'.
265 -- | Extract the 'Behavior' of a 'Dynamic'.
263 current :: Dynamic t a -> Behavior t a
266 current :: Dynamic t a -> Behavior t a
@@ -998,14 +1001,16 @@ distributeListOverDynWith f = fmap (f . map (\(Const2 _ :=> Identity v) -> v) .
998difference :: Reflex t => Event t a -> Event t b -> Event t a
1001difference :: Reflex t => Event t a -> Event t b -> Event t a
999difference = alignEventWithMaybe $ \case
1002difference = alignEventWithMaybe $ \case
1000 This a -> Just a
1003 This a -> Just a
1001− _ -> Nothing
1004+ _ -> Nothing
1006+-- | Zips two values by taking the union of their shapes and combining with the provided function.
1007+-- 'Nothing' values are dropped.
1003alignEventWithMaybe :: Reflex t => (These a b -> Maybe c) -> Event t a -> Event t b -> Event t c
1008alignEventWithMaybe :: Reflex t => (These a b -> Maybe c) -> Event t a -> Event t b -> Event t c
1004−alignEventWithMaybe f ea eb =
1009+alignEventWithMaybe f ea eb = fmapMaybe (f <=< dmapToThese) $
1005− fmapMaybe (f <=< dmapToThese)
1007− $ DMap.fromList [LeftTag :=> ea, RightTag :=> eb]
1010+ merge $ DMap.fromList [LeftTag :=> ea, RightTag :=> eb]
1012+-- | Produces an 'Event' that fires only when the input event fires with a 'DSum' key that
1013+-- matches the provided key.
1009filterEventKey
1014filterEventKey
1010 :: forall t m k v a.
1015 :: forall t m k v a.
1011 ( Reflex t
1016 ( Reflex t
@@ -1023,7 +1028,10 @@ filterEventKey k kv' = do
1023 Nothing -> Nothing
1028 Nothing -> Nothing
1024 takeWhileJustE f kv'
1029 takeWhileJustE f kv'
1026−
1031+-- | "Factor" the input 'DSum' 'Event' to produce an 'Event' which
1032+-- fires when the 'DSum' key changes and contains both the value of the
1033+-- 'DSum' at switchover and an 'Event' of values produced by subsequent
1034+-- firings of the input 'Event' that do not change the 'DSum' key.
1027factorEvent
1035factorEvent
1028 :: forall t m k v a.
1036 :: forall t m k v a.
1029 ( Reflex t
1037 ( Reflex t
@@ -1073,26 +1081,94 @@ class Reflex t => Accumulator t f | f -> t where
1073 mapAccumMaybe f = mapAccumMaybeM $ \v o -> return $ f v o
1081 mapAccumMaybe f = mapAccumMaybeM $ \v o -> return $ f v o
1074 mapAccumMaybeM :: (MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (f a, Event t c)
1082 mapAccumMaybeM :: (MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (f a, Event t c)
1084+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1085+-- with the provided function. See 'foldDyn'.
1076−accumDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> a) -> a -> Event t b -> m (Dynamic t a)
1087+ :: (Reflex t, MonadHold t m, MonadFix m)
1077accumDyn f = accumMaybeDyn $ \v o -> Just $ f v o
1092accumDyn f = accumMaybeDyn $ \v o -> Just $ f v o
1094+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1095+-- with the provided 'PushM' action.
1078−accumMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t a) -> a -> Event t b -> m (Dynamic t a)
1097+ :: (Reflex t, MonadHold t m, MonadFix m)
1098+ => (a -> b -> PushM t a)
1079accumMDyn f = accumMaybeMDyn $ \v o -> Just <$> f v o
1102accumMDyn f = accumMaybeMDyn $ \v o -> Just <$> f v o
1104+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1105+-- with the provided function, discarding 'Nothing' results.
1080−accumMaybeDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> Maybe a) -> a -> Event t b -> m (Dynamic t a)
1107+ :: (Reflex t, MonadHold t m, MonadFix m)
1108+ => (a -> b -> Maybe a)
1081accumMaybeDyn f = accumMaybeMDyn $ \v o -> return $ f v o
1112accumMaybeDyn f = accumMaybeMDyn $ \v o -> return $ f v o
1114+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1115+-- with the provided 'PushM' action, discarding 'Nothing' results.
1082−accumMaybeMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Dynamic t a)
1117+ :: (Reflex t, MonadHold t m, MonadFix m)
1118+ => (a -> b -> PushM t (Maybe a))
1083accumMaybeMDyn f z e = do
1122accumMaybeMDyn f z e = do
1084 rec let e' = flip push e $ \o -> do
1123 rec let e' = flip push e $ \o -> do
1085 v <- sample $ current d'
1124 v <- sample $ current d'
1087 d' <- holdDyn z e'
1126 d' <- holdDyn z e'
1088 return d'
1127 return d'
1129+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1130+-- with a function that both accumulates and produces a value to fire
1131+-- as an 'Event'. Returns both the accumulated value and an 'Event'.
1089−mapAccumDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (a, c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1133+ :: (Reflex t, MonadHold t m, MonadFix m)
1134+ => (a -> b -> (a, c))
1137+ -> m (Dynamic t a, Event t c)
1090mapAccumDyn f = mapAccumMaybeDyn $ \v o -> bimap Just Just $ f v o
1138mapAccumDyn f = mapAccumMaybeDyn $ \v o -> bimap Just Just $ f v o
1140+-- | Similar to 'mapAccumDyn' except that the combining function is a
1091−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)
1143+ :: (Reflex t, MonadHold t m, MonadFix m)
1144+ => (a -> b -> PushM t (a, c))
1147+ -> m (Dynamic t a, Event t c)
1092mapAccumMDyn f = mapAccumMaybeMDyn $ \v o -> bimap Just Just <$> f v o
1148mapAccumMDyn f = mapAccumMaybeMDyn $ \v o -> bimap Just Just <$> f v o
1150+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event' with
1151+-- a function that both optionally accumulates and optionally produces
1152+-- a value to fire as a separate output 'Event'.
1153+-- Note that because 'Nothing's are discarded in both cases, the output
1154+-- 'Event' may fire even though the output 'Dynamic' has not changed, and
1155+-- the output 'Dynamic' may update even when the output 'Event' is not firing.
1093−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)
1157+ :: (Reflex t, MonadHold t m, MonadFix m)
1158+ => (a -> b -> (Maybe a, Maybe c))
1161+ -> m (Dynamic t a, Event t c)
1094mapAccumMaybeDyn f = mapAccumMaybeMDyn $ \v o -> return $ f v o
1162mapAccumMaybeDyn f = mapAccumMaybeMDyn $ \v o -> return $ f v o
1164+-- | Like 'mapAccumMaybeDyn' except that the combining function is a
1095−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)
1167+ :: (Reflex t, MonadHold t m, MonadFix m)
1168+ => (a -> b -> PushM t (Maybe a, Maybe c))
1171+ -> m (Dynamic t a, Event t c)
1096mapAccumMaybeMDyn f z e = do
1172mapAccumMaybeMDyn f z e = do
1097 rec let e' = flip push e $ \o -> do
1173 rec let e' = flip push e $ \o -> do
1098 v <- sample $ current d'
1174 v <- sample $ current d'
@@ -1103,15 +1179,39 @@ mapAccumMaybeMDyn f z e = do
1103 d' <- holdDyn z $ fmapMaybe fst e'
1179 d' <- holdDyn z $ fmapMaybe fst e'
1104 return (d', fmapMaybe snd e')
1180 return (d', fmapMaybe snd e')
1182+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1183+-- with the provided function.
1106{-# INLINE accumB #-}
1184{-# INLINE accumB #-}
1107−accumB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> a) -> a -> Event t b -> m (Behavior t a)
1186+ :: (Reflex t, MonadHold t m, MonadFix m)
1190+ -> m (Behavior t a)
1108accumB f = accumMaybeB $ \v o -> Just $ f v o
1191accumB f = accumMaybeB $ \v o -> Just $ f v o
1193+-- | Like 'accumB' except that the combining function is a 'PushM' action.
1109{-# INLINE accumMB #-}
1194{-# INLINE accumMB #-}
1110−accumMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t a) -> a -> Event t b -> m (Behavior t a)
1196+ :: (Reflex t, MonadHold t m, MonadFix m)
1197+ => (a -> b -> PushM t a)
1200+ -> m (Behavior t a)
1111accumMB f = accumMaybeMB $ \v o -> Just <$> f v o
1201accumMB f = accumMaybeMB $ \v o -> Just <$> f v o
1203+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1204+-- with the provided function, discarding 'Nothing' results.
1112{-# INLINE accumMaybeB #-}
1205{-# INLINE accumMaybeB #-}
1113−accumMaybeB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> Maybe a) -> a -> Event t b -> m (Behavior t a)
1207+ :: (Reflex t, MonadHold t m, MonadFix m)
1208+ => (a -> b -> Maybe a)
1211+ -> m (Behavior t a)
1114accumMaybeB f = accumMaybeMB $ \v o -> return $ f v o
1212accumMaybeB f = accumMaybeMB $ \v o -> return $ f v o
1214+-- | Like 'accumMaybeB' except that the combining function is a 'PushM' action.
1115{-# INLINE accumMaybeMB #-}
1215{-# INLINE accumMaybeMB #-}
1116accumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Behavior t a)
1216accumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Behavior t a)
1117accumMaybeMB f z e = do
1217accumMaybeMB f z e = do
@@ -1120,16 +1220,42 @@ accumMaybeMB f z e = do
1121 d' <- hold z e'
1221 d' <- hold z e'
1122 return d'
1222 return d'
1224+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1225+-- with a function that both accumulates and produces a value to fire
1226+-- as an 'Event'. Returns both the accumulated value and an 'Event'.
1123{-# INLINE mapAccumB #-}
1227{-# INLINE mapAccumB #-}
1124−mapAccumB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (a, c)) -> a -> Event t b -> m (Behavior t a, Event t c)
1229+ :: (Reflex t, MonadHold t m, MonadFix m)
1230+ => (a -> b -> (a, c))
1233+ -> m (Behavior t a, Event t c)
1125mapAccumB f = mapAccumMaybeB $ \v o -> bimap Just Just $ f v o
1234mapAccumB f = mapAccumMaybeB $ \v o -> bimap Just Just $ f v o
1236+-- | Like 'mapAccumB' except that the combining function is a 'PushM' action.
1126{-# INLINE mapAccumMB #-}
1237{-# INLINE mapAccumMB #-}
1127−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)
1239+ :: (Reflex t, MonadHold t m, MonadFix m)
1240+ => (a -> b -> PushM t (a, c))
1243+ -> m (Behavior t a, Event t c)
1128mapAccumMB f = mapAccumMaybeMB $ \v o -> bimap Just Just <$> f v o
1244mapAccumMB f = mapAccumMaybeMB $ \v o -> bimap Just Just <$> f v o
1246+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event' with
1247+-- a function that both optionally accumulates and optionally produces
1248+-- a value to fire as a separate output 'Event'. 'Nothing's are discarded.
1129{-# INLINE mapAccumMaybeB #-}
1249{-# INLINE mapAccumMaybeB #-}
1130−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)
1251+ :: (Reflex t, MonadHold t m, MonadFix m)
1252+ => (a -> b -> (Maybe a, Maybe c))
1255+ -> m (Behavior t a, Event t c)
1131mapAccumMaybeB f = mapAccumMaybeMB $ \v o -> return $ f v o
1256mapAccumMaybeB f = mapAccumMaybeMB $ \v o -> return $ f v o
1258+-- | LIke 'mapAccumMaybeB' except that the combining function is a 'PushM' action.
1133{-# INLINE mapAccumMaybeMB #-}
1259{-# INLINE mapAccumMaybeMB #-}
1134mapAccumMaybeMB :: (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)
1260mapAccumMaybeMB :: (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)
1135mapAccumMaybeMB f z e = do
1261mapAccumMaybeMB f z e = do
@@ -1284,38 +1410,47 @@ infixl 4 <@
1284-- Cheap Functions
1410-- Cheap Functions
1285------------------
1411------------------
1413+-- | A "cheap" version of 'pushAlways'. See the performance note on 'pushCheap'.
1287{-# INLINE pushAlwaysCheap #-}
1414{-# INLINE pushAlwaysCheap #-}
1288pushAlwaysCheap :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
1415pushAlwaysCheap :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
1289pushAlwaysCheap f = pushCheap (fmap Just . f)
1416pushAlwaysCheap f = pushCheap (fmap Just . f)
1418+-- | A "cheap" version of 'fmapMaybe'. See the performance note on 'pushCheap'.
1291{-# INLINE fmapMaybeCheap #-}
1419{-# INLINE fmapMaybeCheap #-}
1292fmapMaybeCheap :: Reflex t => (a -> Maybe b) -> Event t a -> Event t b
1420fmapMaybeCheap :: Reflex t => (a -> Maybe b) -> Event t a -> Event t b
1293fmapMaybeCheap f = pushCheap $ return . f
1421fmapMaybeCheap f = pushCheap $ return . f
1423+-- | A "cheap" version of 'fforMaybe'. See the performance note on 'pushCheap'.
1295{-# INLINE fforMaybeCheap #-}
1424{-# INLINE fforMaybeCheap #-}
1296fforMaybeCheap :: Reflex t => Event t a -> (a -> Maybe b) -> Event t b
1425fforMaybeCheap :: Reflex t => Event t a -> (a -> Maybe b) -> Event t b
1297fforMaybeCheap = flip fmapMaybeCheap
1426fforMaybeCheap = flip fmapMaybeCheap
1428+-- | A "cheap" version of 'ffor'. See the performance note on 'pushCheap'.
1299{-# INLINE fforCheap #-}
1429{-# INLINE fforCheap #-}
1300fforCheap :: Reflex t => Event t a -> (a -> b) -> Event t b
1430fforCheap :: Reflex t => Event t a -> (a -> b) -> Event t b
1301fforCheap = flip fmapCheap
1431fforCheap = flip fmapCheap
1433+-- | A "cheap" version of 'fmap'. See the performance note on 'pushCheap'.
1303{-# INLINE fmapCheap #-}
1434{-# INLINE fmapCheap #-}
1304fmapCheap :: Reflex t => (a -> b) -> Event t a -> Event t b
1435fmapCheap :: Reflex t => (a -> b) -> Event t a -> Event t b
1305fmapCheap f = pushCheap $ return . Just . f
1436fmapCheap f = pushCheap $ return . Just . f
1438+-- | A "cheap" version of 'tag'. See the performance note on 'pushCheap'.
1307{-# INLINE tagCheap #-}
1439{-# INLINE tagCheap #-}
1308tagCheap :: Reflex t => Behavior t b -> Event t a -> Event t b
1440tagCheap :: Reflex t => Behavior t b -> Event t a -> Event t b
1309tagCheap b = pushAlwaysCheap $ \_ -> sample b
1441tagCheap b = pushAlwaysCheap $ \_ -> sample b
1443+-- | A "cheap" version of 'mergeWithCheap'. See the performance note on 'pushCheap'.
1311{-# INLINE mergeWithCheap #-}
1444{-# INLINE mergeWithCheap #-}
1312mergeWithCheap :: Reflex t => (a -> a -> a) -> [Event t a] -> Event t a
1445mergeWithCheap :: Reflex t => (a -> a -> a) -> [Event t a] -> Event t a
1313mergeWithCheap = mergeWithCheap' id
1446mergeWithCheap = mergeWithCheap' id
1448+-- | A "cheap" version of 'mergeWithCheap''. See the performance note on 'pushCheap'.
1315{-# INLINE mergeWithCheap' #-}
1449{-# INLINE mergeWithCheap' #-}
1316mergeWithCheap' :: Reflex t => (a -> b) -> (b -> b -> b) -> [Event t a] -> Event t b
1450mergeWithCheap' :: Reflex t => (a -> b) -> (b -> b -> b) -> [Event t a] -> Event t b
1317mergeWithCheap' f g = mergeWithFoldCheap' $ foldl1 g . fmap f
1451mergeWithCheap' f g = mergeWithFoldCheap' $ foldl1 g . fmap f
1453+-- | A "cheap" version of 'mergeWithFoldCheap''. See the performance note on 'pushCheap'.
1319{-# INLINE mergeWithFoldCheap' #-}
1454{-# INLINE mergeWithFoldCheap' #-}
1320mergeWithFoldCheap' :: Reflex t => (NonEmpty a -> b) -> [Event t a] -> Event t b
1455mergeWithFoldCheap' :: Reflex t => (NonEmpty a -> b) -> [Event t a] -> Event t b
1321mergeWithFoldCheap' f es =
1456mergeWithFoldCheap' f es =