on develop help sign in
Generalize fan following DMap (#318)
13e76bbDavid Feuer
ChangeLog.md+4
@@ -2,12 +2,16 @@
2
2
3## Unreleased
3## Unreleased
4
4
5+* Generalize `fan` to `fanG` to take a `DMap` with non-`Identity`
6+ values.
7+
5* Generalize merging functions:
8* Generalize merging functions:
6 `merge` to `mergeG`,
9 `merge` to `mergeG`,
7 `mergeIncremental` to `mergeIncrementalG`,
10 `mergeIncremental` to `mergeIncrementalG`,
8 `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`,
11 `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`,
9 `mergeIncrementalWithMove` to `mergeIncrementalWithMoveG`.
12 `mergeIncrementalWithMove` to `mergeIncrementalWithMoveG`.
10
13
14+
11## 0.6.2.0
15## 0.6.2.0
12
16
13* Fix `holdDyn` so that it is lazy in its event argument
17* Fix `holdDyn` so that it is lazy in its event argument
src/Reflex/Class.hs+31−3
@@ -41,6 +41,7 @@ module Reflex.Class
41 , MonadHold (..)
41 , MonadHold (..)
42 -- ** 'fan' related types
42 -- ** 'fan' related types
43 , EventSelector (..)
43 , EventSelector (..)
44+ , EventSelectorG (..)
44 , EventSelectorInt (..)
45 , EventSelectorInt (..)
45 -- * Convenience functions
46 -- * Convenience functions
46 , constDyn
47 , constDyn
@@ -64,6 +65,7 @@ module Reflex.Class
64 , alignEventWithMaybe
65 , alignEventWithMaybe
65 -- ** Breaking up 'Event's
66 -- ** Breaking up 'Event's
66 , splitE
67 , splitE
68+ , fan
67 , fanEither
69 , fanEither
68 , fanThese
70 , fanThese
69 , fanMap
71 , fanMap
@@ -260,13 +262,16 @@ class ( MonadHold t (PushM t)
260 -- | Merge a collection of events; the resulting 'Event' will only occur if at
262 -- | Merge a collection of events; the resulting 'Event' will only occur if at
261 -- least one input event is occurring, and will contain all of the input keys
263 -- least one input event is occurring, and will contain all of the input keys
262 -- that are occurring simultaneously
264 -- that are occurring simultaneously
265+
266+ --TODO: Generalize to get rid of DMap use --TODO: Provide a type-level guarantee that the result is not empty
263 mergeG :: GCompare k => (forall a. q a -> Event t (v a))
267 mergeG :: GCompare k => (forall a. q a -> Event t (v a))
264 -> DMap k q -> Event t (DMap k v)
268 -> DMap k q -> Event t (DMap k v)
265− --TODO: Generalize to get rid of DMap use --TODO: Provide a type-level guarantee that the result is not empty
269+
266 -- | Efficiently fan-out an event to many destinations. You should save the
270 -- | Efficiently fan-out an event to many destinations. You should save the
267− -- result in a @let@-binding, and then repeatedly 'select' on the result to
271+ -- result in a @let@-binding, and then repeatedly 'selectG' on the result to
268 -- create child events
272 -- create child events
269− fan :: GCompare k => Event t (DMap k Identity) -> EventSelector t k
273+ fanG :: GCompare k => Event t (DMap k v) -> EventSelectorG t k v
274+
270 -- | Create an 'Event' that will occur whenever the currently-selected input
275 -- | Create an 'Event' that will occur whenever the currently-selected input
271 -- 'Event' occurs
276 -- 'Event' occurs
272 switch :: Behavior t (Event t a) -> Event t a
277 switch :: Behavior t (Event t a) -> Event t a
@@ -310,6 +315,18 @@ class ( MonadHold t (PushM t)
310 mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a)
315 mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a)
311 fanInt :: Event t (IntMap a) -> EventSelectorInt t a
316 fanInt :: Event t (IntMap a) -> EventSelectorInt t a
312
317
318+-- | Efficiently fan-out an event to many destinations. You should save the
319+-- result in a @let@-binding, and then repeatedly 'select' on the result to
320+-- create child events
321+fan :: forall t k. (Reflex t, GCompare k)
322+ => Event t (DMap k Identity) -> EventSelector t k
323+ --TODO: Can we help enforce the partial application discipline here? The combinator is worthless without it
324+fan e = EventSelector (fixup (selectG (fanG e) :: k a -> Event t (Identity a)) :: forall a. k a -> Event t a)
325+ where
326+ fixup :: forall a. (k a -> Event t (Identity a)) -> k a -> Event t a
327+ fixup = case eventCoercion Coercion :: Coercion (Event t (Identity a)) (Event t a) of
328+ Coercion -> coerce
329+
313--TODO: Specialize this so that we can take advantage of knowing that there's no changing going on
330--TODO: Specialize this so that we can take advantage of knowing that there's no changing going on
314-- | Constructs a single 'Event' out of a map of events. The output event may fire with multiple
331-- | Constructs a single 'Event' out of a map of events. The output event may fire with multiple
315-- keys simultaneously.
332-- keys simultaneously.
@@ -497,6 +514,17 @@ newtype EventSelector t k = EventSelector
497 select :: forall a. k a -> Event t a
514 select :: forall a. k a -> Event t a
498 }
515 }
499
516
517+newtype EventSelectorG t k v = EventSelectorG
518+ { -- | Retrieve the 'Event' for the given key. The type of the 'Event' is
519+ -- determined by the type of the key, so this can be used to fan-out
520+ -- 'Event's whose sub-'Event's have different types.
521+ --
522+ -- Using 'EventSelector's and the 'fan' primitive is far more efficient than
523+ -- (but equivalent to) using 'mapMaybe' to select only the relevant
524+ -- occurrences of an 'Event'.
525+ selectG :: forall a. k a -> Event t (v a)
526+ }
527+
500-- | Efficiently select an 'Event' keyed on 'Int'. This is more efficient than manually
528-- | Efficiently select an 'Event' keyed on 'Int'. This is more efficient than manually
501-- filtering by key.
529-- filtering by key.
502newtype EventSelectorInt t a = EventSelectorInt { selectInt :: Int -> Event t a }
530newtype EventSelectorInt t a = EventSelectorInt { selectInt :: Int -> Event t a }
src/Reflex/Profiled.hs+1−1
@@ -135,11 +135,11 @@ instance Reflex t => Reflex (ProfiledTimeline t) where
135 push f (Event_Profiled e) = coerce $ push (coerce f) $ profileEvent e -- Profile before rather than after; this way fanout won't count against us
135 push f (Event_Profiled e) = coerce $ push (coerce f) $ profileEvent e -- Profile before rather than after; this way fanout won't count against us
136 pushCheap f (Event_Profiled e) = coerce $ pushCheap (coerce f) $ profileEvent e
136 pushCheap f (Event_Profiled e) = coerce $ pushCheap (coerce f) $ profileEvent e
137 pull = Behavior_Profiled . pull . coerce
137 pull = Behavior_Profiled . pull . coerce
138+ fanG (Event_Profiled e) = EventSelectorG $ coerce $ selectG (fanG $ profileEvent e)
138 mergeG :: forall (k :: z -> *) q v. GCompare k
139 mergeG :: forall (k :: z -> *) q v. GCompare k
139 => (forall a. q a -> Event (ProfiledTimeline t) (v a))
140 => (forall a. q a -> Event (ProfiledTimeline t) (v a))
140 -> DMap k q -> Event (ProfiledTimeline t) (DMap k v)
141 -> DMap k q -> Event (ProfiledTimeline t) (DMap k v)
141 mergeG nt = Event_Profiled #. mergeG (coerce nt)
142 mergeG nt = Event_Profiled #. mergeG (coerce nt)
142− fan (Event_Profiled e) = EventSelector $ coerce $ select (fan $ profileEvent e)
143 switch (Behavior_Profiled b) = coerce $ profileEvent $ switch (coerceBehavior b)
143 switch (Behavior_Profiled b) = coerce $ profileEvent $ switch (coerceBehavior b)
144 coincidence (Event_Profiled e) = coerce $ profileEvent $ coincidence (coerceEvent e)
144 coincidence (Event_Profiled e) = coerce $ profileEvent $ coincidence (coerceEvent e)
145 current (Dynamic_Profiled d) = coerce $ current d
145 current (Dynamic_Profiled d) = coerce $ current d
src/Reflex/Pure.hs+3−2
@@ -7,6 +7,7 @@
7{-# LANGUAGE TypeFamilies #-}
7{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE RankNTypes #-}
8{-# LANGUAGE RankNTypes #-}
9{-# LANGUAGE PolyKinds #-}
9{-# LANGUAGE PolyKinds #-}
10+
10#ifdef USE_REFLEX_OPTIMIZER
11#ifdef USE_REFLEX_OPTIMIZER
11{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
12{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
12#endif
13#endif
@@ -92,8 +93,8 @@ instance (Enum t, HasTrie t, Ord t) => Reflex (Pure t) where
92 then Nothing
93 then Nothing
93 else Just currentOccurrences
94 else Just currentOccurrences
94
95
95− fan :: GCompare k => Event (Pure t) (DMap k Identity) -> EventSelector (Pure t) k
96+ -- fanG :: GCompare k => Event (Pure t) (DMap k v) -> EventSelectorG (Pure t) k v
96− fan e = EventSelector $ \k -> Event $ \t -> unEvent e t >>= fmap runIdentity . DMap.lookup k
97+ fanG e = EventSelectorG $ \k -> Event $ \t -> unEvent e t >>= DMap.lookup k
97
98
98 switch :: Behavior (Pure t) (Event (Pure t) a) -> Event (Pure t) a
99 switch :: Behavior (Pure t) (Event (Pure t) a) -> Event (Pure t) a
99 switch b = Event $ memo $ \t -> unEvent (unBehavior b t) t
100 switch b = Event $ memo $ \t -> unEvent (unBehavior b t) t
src/Reflex/Spider/Internal.hs+26−24
@@ -19,6 +19,7 @@
19{-# LANGUAGE UndecidableInstances #-}
19{-# LANGUAGE UndecidableInstances #-}
20{-# LANGUAGE PolyKinds #-}
20{-# LANGUAGE PolyKinds #-}
21{-# LANGUAGE InstanceSigs #-}
21{-# LANGUAGE InstanceSigs #-}
22+
22#ifdef USE_REFLEX_OPTIMIZER
23#ifdef USE_REFLEX_OPTIMIZER
23{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
24{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
24#endif
25#endif
@@ -374,7 +375,7 @@ eventRoot !k !r = Event $ wrap eventSubscribedRoot $ liftIO . getRootSubscribed
374eventNever :: Event x a
375eventNever :: Event x a
375eventNever = Event $ \_ -> return (EventSubscription (return ()) eventSubscribedNever, Nothing)
376eventNever = Event $ \_ -> return (EventSubscription (return ()) eventSubscribedNever, Nothing)
376
377
377−eventFan :: (GCompare k, HasSpiderTimeline x) => k a -> Fan x k -> Event x a
378+eventFan :: (GCompare k, HasSpiderTimeline x) => k a -> Fan x k v -> Event x (v a)
378eventFan !k !f = Event $ wrap eventSubscribedFan $ getFanSubscribed k f
379eventFan !k !f = Event $ wrap eventSubscribedFan $ getFanSubscribed k f
379
380
380eventSwitch :: HasSpiderTimeline x => Switch x a -> Event x a
381eventSwitch :: HasSpiderTimeline x => Switch x a -> Event x a
@@ -426,14 +427,14 @@ newSubscriberHold h = return $ Subscriber
426 , subscriberRecalculateHeight = \_ -> return ()
427 , subscriberRecalculateHeight = \_ -> return ()
427 }
428 }
428
429
429−newSubscriberFan :: forall x k. (HasSpiderTimeline x, GCompare k) => FanSubscribed x k -> IO (Subscriber x (DMap k Identity))
430+newSubscriberFan :: forall x k v. (HasSpiderTimeline x, GCompare k) => FanSubscribed x k v -> IO (Subscriber x (DMap k v))
430newSubscriberFan subscribed = return $ Subscriber
431newSubscriberFan subscribed = return $ Subscriber
431 { subscriberPropagate = \a -> {-# SCC "traverseFan" #-} do
432 { subscriberPropagate = \a -> {-# SCC "traverseFan" #-} do
432 subs <- liftIO $ readIORef $ fanSubscribedSubscribers subscribed
433 subs <- liftIO $ readIORef $ fanSubscribedSubscribers subscribed
433 tracePropagate (Proxy :: Proxy x) $ "SubscriberFan" <> showNodeId subscribed <> ": " ++ show (DMap.size subs) ++ " keys subscribed, " ++ show (DMap.size a) ++ " keys firing"
434 tracePropagate (Proxy :: Proxy x) $ "SubscriberFan" <> showNodeId subscribed <> ": " ++ show (DMap.size subs) ++ " keys subscribed, " ++ show (DMap.size a) ++ " keys firing"
434 liftIO $ writeIORef (fanSubscribedOccurrence subscribed) $ Just a
435 liftIO $ writeIORef (fanSubscribedOccurrence subscribed) $ Just a
435 scheduleClear $ fanSubscribedOccurrence subscribed
436 scheduleClear $ fanSubscribedOccurrence subscribed
436− let f _ (Pair (Identity v) subsubs) = do
437+ let f _ (Pair v subsubs) = do
437 propagate v $ _fanSubscribedChildren_list subsubs
438 propagate v $ _fanSubscribedChildren_list subsubs
438 return $ Constant ()
439 return $ Constant ()
439 _ <- DMap.traverseWithKey f $ DMap.intersectionWithKey (\_ -> Pair) a subs --TODO: Would be nice to have DMap.traverse_
440 _ <- DMap.traverseWithKey f $ DMap.intersectionWithKey (\_ -> Pair) a subs --TODO: Would be nice to have DMap.traverse_
@@ -581,7 +582,7 @@ eventSubscribedNever = EventSubscribed
581#endif
582#endif
582 }
583 }
583
584
584−eventSubscribedFan :: FanSubscribed x k -> EventSubscribed x
585+eventSubscribedFan :: FanSubscribed x k v -> EventSubscribed x
585eventSubscribedFan !subscribed = EventSubscribed
586eventSubscribedFan !subscribed = EventSubscribed
586 { eventSubscribedHeightRef = eventSubscribedHeightRef $ _eventSubscription_subscribed $ fanSubscribedParent subscribed
587 { eventSubscribedHeightRef = eventSubscribedHeightRef $ _eventSubscription_subscribed $ fanSubscribedParent subscribed
587 , eventSubscribedRetained = toAny subscribed
588 , eventSubscribedRetained = toAny subscribed
@@ -990,7 +991,7 @@ data RootSubscribed x a = forall k. GCompare k => RootSubscribed
990#endif
991#endif
991 }
992 }
992
993
993−data Root x (k :: * -> *)
994+data Root x k
994 = Root { rootOccurrence :: !(IORef (DMap k Identity)) -- The currently-firing occurrence of this event
995 = Root { rootOccurrence :: !(IORef (DMap k Identity)) -- The currently-firing occurrence of this event
995 , rootSubscribed :: !(IORef (DMap k (RootSubscribed x)))
996 , rootSubscribed :: !(IORef (DMap k (RootSubscribed x)))
996 , rootInit :: !(forall a. k a -> RootTrigger x a -> IO (IO ()))
997 , rootInit :: !(forall a. k a -> RootTrigger x a -> IO (IO ()))
@@ -1060,25 +1061,25 @@ heightBagVerify b@(HeightBag s c) = if
1060heightBagVerify = id
1061heightBagVerify = id
1061#endif
1062#endif
1062
1063
1063−data FanSubscribedChildren (x :: *) k a = FanSubscribedChildren
1064+data FanSubscribedChildren x k v a = FanSubscribedChildren
1064− { _fanSubscribedChildren_list :: !(WeakBag (Subscriber x a))
1065+ { _fanSubscribedChildren_list :: !(WeakBag (Subscriber x (v a)))
1065− , _fanSubscribedChildren_self :: {-# NOUNPACK #-} !(k a, FanSubscribed x k)
1066+ , _fanSubscribedChildren_self :: {-# NOUNPACK #-} !(k a, FanSubscribed x k v)
1066− , _fanSubscribedChildren_weakSelf :: !(IORef (Weak (k a, FanSubscribed x k)))
1067+ , _fanSubscribedChildren_weakSelf :: !(IORef (Weak (k a, FanSubscribed x k v)))
1067 }
1068 }
1068
1069
1069−data FanSubscribed (x :: *) k
1070+data FanSubscribed x k v
1070− = FanSubscribed { fanSubscribedCachedSubscribed :: !(IORef (Maybe (FanSubscribed x k)))
1071+ = FanSubscribed { fanSubscribedCachedSubscribed :: !(IORef (Maybe (FanSubscribed x k v)))
1071− , fanSubscribedOccurrence :: !(IORef (Maybe (DMap k Identity)))
1072+ , fanSubscribedOccurrence :: !(IORef (Maybe (DMap k v)))
1072− , fanSubscribedSubscribers :: !(IORef (DMap k (FanSubscribedChildren x k))) -- This DMap should never be empty
1073+ , fanSubscribedSubscribers :: !(IORef (DMap k (FanSubscribedChildren x k v))) -- This DMap should never be empty
1073 , fanSubscribedParent :: !(EventSubscription x)
1074 , fanSubscribedParent :: !(EventSubscription x)
1074#ifdef DEBUG_NODEIDS
1075#ifdef DEBUG_NODEIDS
1075 , fanSubscribedNodeId :: Int
1076 , fanSubscribedNodeId :: Int
1076#endif
1077#endif
1077 }
1078 }
1078
1079
1079−data Fan x k
1080+data Fan x k v
1080− = Fan { fanParent :: !(Event x (DMap k Identity))
1081+ = Fan { fanParent :: !(Event x (DMap k v))
1081− , fanSubscribed :: !(IORef (Maybe (FanSubscribed x k)))
1082+ , fanSubscribed :: !(IORef (Maybe (FanSubscribed x k v)))
1082 }
1083 }
1083
1084
1084data SwitchSubscribed x a
1085data SwitchSubscribed x a
@@ -1525,7 +1526,7 @@ fanInt p =
1525 return (EventSubscription (FastWeakBag.remove t) $! EventSubscribed heightRef $! toAny (_fanInt_subscriptionRef self, t), IntMap.lookup k currentOcc)
1526 return (EventSubscription (FastWeakBag.remove t) $! EventSubscribed heightRef $! toAny (_fanInt_subscriptionRef self, t), IntMap.lookup k currentOcc)
1526
1527
1527{-# INLINABLE getFanSubscribed #-}
1528{-# INLINABLE getFanSubscribed #-}
1528−getFanSubscribed :: (HasSpiderTimeline x, GCompare k) => k a -> Fan x k -> Subscriber x a -> EventM x (WeakBagTicket, FanSubscribed x k, Maybe a)
1529+getFanSubscribed :: (HasSpiderTimeline x, GCompare k) => k a -> Fan x k v -> Subscriber x (v a) -> EventM x (WeakBagTicket, FanSubscribed x k v, Maybe (v a))
1529getFanSubscribed k f sub = do
1530getFanSubscribed k f sub = do
1530 mSubscribed <- liftIO $ readIORef $ fanSubscribed f
1531 mSubscribed <- liftIO $ readIORef $ fanSubscribed f
1531 case mSubscribed of
1532 case mSubscribed of
@@ -1559,7 +1560,7 @@ getFanSubscribed k f sub = do
1559 liftIO $ writeIORef (fanSubscribed f) $ Just subscribed
1560 liftIO $ writeIORef (fanSubscribed f) $ Just subscribed
1560 return (slnForSub, subscribed, coerce $ DMap.lookup k =<< parentOcc)
1561 return (slnForSub, subscribed, coerce $ DMap.lookup k =<< parentOcc)
1561
1562
1562−cleanupFanSubscribed :: GCompare k => (k a, FanSubscribed x k) -> IO ()
1563+cleanupFanSubscribed :: GCompare k => (k a, FanSubscribed x k v) -> IO ()
1563cleanupFanSubscribed (k, subscribed) = do
1564cleanupFanSubscribed (k, subscribed) = do
1564 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
1565 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
1565 let reducedSubscribers = DMap.delete k subscribers
1566 let reducedSubscribers = DMap.delete k subscribers
@@ -1571,7 +1572,7 @@ cleanupFanSubscribed (k, subscribed) = do
1571 else writeIORef (fanSubscribedSubscribers subscribed) $! reducedSubscribers
1572 else writeIORef (fanSubscribedSubscribers subscribed) $! reducedSubscribers
1572
1573
1573{-# INLINE subscribeFanSubscribed #-}
1574{-# INLINE subscribeFanSubscribed #-}
1574−subscribeFanSubscribed :: GCompare k => k a -> FanSubscribed x k -> Subscriber x a -> IO WeakBagTicket
1575+subscribeFanSubscribed :: GCompare k => k a -> FanSubscribed x k v -> Subscriber x (v a) -> IO WeakBagTicket
1575subscribeFanSubscribed k subscribed sub = do
1576subscribeFanSubscribed k subscribed sub = do
1576 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
1577 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
1577 case DMap.lookup k subscribers of
1578 case DMap.lookup k subscribers of
@@ -2047,14 +2048,15 @@ mergeIntCheap d = Event $ \sub -> do
2047 )
2048 )
2048
2049
2049newtype EventSelector x k = EventSelector { select :: forall a. k a -> Event x a }
2050newtype EventSelector x k = EventSelector { select :: forall a. k a -> Event x a }
2051+newtype EventSelectorG x k v = EventSelectorG { selectG :: forall a. k a -> Event x (v a) }
2050
2052
2051−fan :: (HasSpiderTimeline x, GCompare k) => Event x (DMap k Identity) -> EventSelector x k
2053+fanG :: (HasSpiderTimeline x, GCompare k) => Event x (DMap k v) -> EventSelectorG x k v
2052−fan e =
2054+fanG e =
2053 let f = Fan
2055 let f = Fan
2054 { fanParent = e
2056 { fanParent = e
2055 , fanSubscribed = unsafeNewIORef e Nothing
2057 , fanSubscribed = unsafeNewIORef e Nothing
2056 }
2058 }
2057− in EventSelector $ \k -> eventFan k f
2059+ in EventSelectorG $ \k -> eventFan k f
2058
2060
2059runHoldInits :: HasSpiderTimeline x => IORef [SomeHoldInit x] -> IORef [SomeDynInit x] -> IORef [SomeMergeInit x] -> EventM x ()
2061runHoldInits :: HasSpiderTimeline x => IORef [SomeHoldInit x] -> IORef [SomeDynInit x] -> IORef [SomeMergeInit x] -> EventM x ()
2060runHoldInits holdInitRef dynInitRef mergeInitRef = do
2062runHoldInits holdInitRef dynInitRef mergeInitRef = do
@@ -2523,6 +2525,8 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2523 pushCheap f = SpiderEvent . pushCheap (coerce f) . unSpiderEvent
2525 pushCheap f = SpiderEvent . pushCheap (coerce f) . unSpiderEvent
2524 {-# INLINABLE pull #-}
2526 {-# INLINABLE pull #-}
2525 pull = SpiderBehavior . pull . coerce
2527 pull = SpiderBehavior . pull . coerce
2528+ {-# INLINABLE fanG #-}
2529+ fanG e = R.EventSelectorG $ SpiderEvent . selectG (fanG (unSpiderEvent e))
2526 {-# INLINABLE mergeG #-}
2530 {-# INLINABLE mergeG #-}
2527 mergeG
2531 mergeG
2528 :: forall (k :: k2 -> *) q (v :: k2 -> *). GCompare k
2532 :: forall (k :: k2 -> *) q (v :: k2 -> *). GCompare k
@@ -2530,8 +2534,6 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2530 -> DMap k q
2534 -> DMap k q
2531 -> R.Event (SpiderTimeline x) (DMap k v)
2535 -> R.Event (SpiderTimeline x) (DMap k v)
2532 mergeG nt = SpiderEvent . mergeG (unSpiderEvent #. nt) . dynamicConst
2536 mergeG nt = SpiderEvent . mergeG (unSpiderEvent #. nt) . dynamicConst
2533− {-# INLINABLE fan #-}
2534− fan e = R.EventSelector $ SpiderEvent . select (fan (unSpiderEvent e))
2535 {-# INLINABLE switch #-}
2537 {-# INLINABLE switch #-}
2536 switch = SpiderEvent . switch . (coerce :: Behavior x (R.Event (SpiderTimeline x) a) -> Behavior x (Event x a)) . unSpiderBehavior
2538 switch = SpiderEvent . switch . (coerce :: Behavior x (R.Event (SpiderTimeline x) a) -> Behavior x (Event x a)) . unSpiderBehavior
2537 {-# INLINABLE coincidence #-}
2539 {-# INLINABLE coincidence #-}
test/GC.hs+2−2
@@ -56,8 +56,8 @@ hostPerf ref = S.runSpiderHost $ do
56 { S.subscriberPropagate = S.subscriberPropagate sub
56 { S.subscriberPropagate = S.subscriberPropagate sub
57 }
57 }
58 return (s, o))
58 return (s, o))
59− $ runIdentity <$> S.select
59+ $ runIdentity . runIdentity <$> S.selectG
60− (S.fan $ S.pushCheap (return . Just . mapKeyValuePairsMonotonic (\(t :=> e) -> WrapArg t :=> Identity e)) response)
60+ (S.fanG $ S.pushCheap (return . Just . mapKeyValuePairsMonotonic (\(t :=> e) -> WrapArg t :=> Identity e)) response)
61 (WrapArg Request)
61 (WrapArg Request)
62 return $ alignWith (mergeThese (<>))
62 return $ alignWith (mergeThese (<>))
63 (flip S.pushCheap eadd $ \_ -> return $ Just $ DMap.singleton Request $ do
63 (flip S.pushCheap eadd $ \_ -> return $ Just $ DMap.singleton Request $ do