on develop help sign in
Merge pull request #416 from parenthetical/now-event
17ccde7Ryan Trinkle
ChangeLog.md+3
@@ -1,5 +1,8 @@
1# Revision history for reflex
1# Revision history for reflex
2
2
3+## Unreleased
4+* ([#416](https://github.com/reflex-frp/reflex/pull/416)) Add `now :: m (Event t ())` to `MonadHold`.
5+
3## 0.7.1.0
6## 0.7.1.0
4
7
5* ([#413](https://github.com/reflex-frp/reflex/pull/413), [#417](https://github.com/reflex-frp/reflex/pull/417)) Add `Reflex.Host.Headless` module which provides `runHeadlessApp` as an easy way to run a Reflex network in a "headless" environment.
8* ([#413](https://github.com/reflex-frp/reflex/pull/413), [#417](https://github.com/reflex-frp/reflex/pull/417)) Add `Reflex.Host.Headless` module which provides `runHeadlessApp` as an easy way to run a Reflex network in a "headless" environment.
src/Reflex/Class.hs+13
@@ -420,6 +420,13 @@ class MonadSample t m => MonadHold t m where
420 -- | Create a new 'Event' that only occurs only once, on the first occurrence of
420 -- | Create a new 'Event' that only occurs only once, on the first occurrence of
421 -- the supplied 'Event'.
421 -- the supplied 'Event'.
422 headE :: Event t a -> m (Event t a)
422 headE :: Event t a -> m (Event t a)
423+ -- | An event which only occurs at the current moment in time, such that:
424+ --
425+ -- > coincidence (pushAlways (\a -> (a <$) <$> now) e) = e
426+ --
427+ now :: m (Event t ())
428+ default now :: (m ~ f m', MonadTrans f, MonadHold t m') => m (Event t ())
429+ now = lift now
423
430
424-- | Accumulate an 'Incremental' with the supplied initial value and the firings of the provided 'Event',
431-- | Accumulate an 'Incremental' with the supplied initial value and the firings of the provided 'Event',
425-- using the combining function to produce a patch.
432-- using the combining function to produce a patch.
@@ -565,6 +572,7 @@ instance MonadHold t m => MonadHold t (ReaderT r m) where
565 holdIncremental a0 = lift . holdIncremental a0
572 holdIncremental a0 = lift . holdIncremental a0
566 buildDynamic a0 = lift . buildDynamic a0
573 buildDynamic a0 = lift . buildDynamic a0
567 headE = lift . headE
574 headE = lift . headE
575+ now = lift now
568
576
569instance (MonadSample t m, Monoid r) => MonadSample t (WriterT r m) where
577instance (MonadSample t m, Monoid r) => MonadSample t (WriterT r m) where
570 sample = lift . sample
578 sample = lift . sample
@@ -575,6 +583,7 @@ instance (MonadHold t m, Monoid r) => MonadHold t (WriterT r m) where
575 holdIncremental a0 = lift . holdIncremental a0
583 holdIncremental a0 = lift . holdIncremental a0
576 buildDynamic a0 = lift . buildDynamic a0
584 buildDynamic a0 = lift . buildDynamic a0
577 headE = lift . headE
585 headE = lift . headE
586+ now = lift now
578
587
579instance MonadSample t m => MonadSample t (StateT s m) where
588instance MonadSample t m => MonadSample t (StateT s m) where
580 sample = lift . sample
589 sample = lift . sample
@@ -585,6 +594,7 @@ instance MonadHold t m => MonadHold t (StateT s m) where
585 holdIncremental a0 = lift . holdIncremental a0
594 holdIncremental a0 = lift . holdIncremental a0
586 buildDynamic a0 = lift . buildDynamic a0
595 buildDynamic a0 = lift . buildDynamic a0
587 headE = lift . headE
596 headE = lift . headE
597+ now = lift now
588
598
589instance MonadSample t m => MonadSample t (ExceptT e m) where
599instance MonadSample t m => MonadSample t (ExceptT e m) where
590 sample = lift . sample
600 sample = lift . sample
@@ -595,6 +605,7 @@ instance MonadHold t m => MonadHold t (ExceptT e m) where
595 holdIncremental a0 = lift . holdIncremental a0
605 holdIncremental a0 = lift . holdIncremental a0
596 buildDynamic a0 = lift . buildDynamic a0
606 buildDynamic a0 = lift . buildDynamic a0
597 headE = lift . headE
607 headE = lift . headE
608+ now = lift now
598
609
599instance (MonadSample t m, Monoid w) => MonadSample t (RWST r w s m) where
610instance (MonadSample t m, Monoid w) => MonadSample t (RWST r w s m) where
600 sample = lift . sample
611 sample = lift . sample
@@ -605,6 +616,7 @@ instance (MonadHold t m, Monoid w) => MonadHold t (RWST r w s m) where
605 holdIncremental a0 = lift . holdIncremental a0
616 holdIncremental a0 = lift . holdIncremental a0
606 buildDynamic a0 = lift . buildDynamic a0
617 buildDynamic a0 = lift . buildDynamic a0
607 headE = lift . headE
618 headE = lift . headE
619+ now = lift now
608
620
609instance MonadSample t m => MonadSample t (ContT r m) where
621instance MonadSample t m => MonadSample t (ContT r m) where
610 sample = lift . sample
622 sample = lift . sample
@@ -615,6 +627,7 @@ instance MonadHold t m => MonadHold t (ContT r m) where
615 holdIncremental a0 = lift . holdIncremental a0
627 holdIncremental a0 = lift . holdIncremental a0
616 buildDynamic a0 = lift . buildDynamic a0
628 buildDynamic a0 = lift . buildDynamic a0
617 headE = lift . headE
629 headE = lift . headE
630+ now = lift now
618
631
619--------------------------------------------------------------------------------
632--------------------------------------------------------------------------------
620-- Convenience functions
633-- Convenience functions
src/Reflex/EventWriter/Base.hs+2
@@ -133,6 +133,8 @@ instance MonadHold t m => MonadHold t (EventWriterT t w m) where
133 buildDynamic a0 = lift . buildDynamic a0
133 buildDynamic a0 = lift . buildDynamic a0
134 {-# INLINABLE headE #-}
134 {-# INLINABLE headE #-}
135 headE = lift . headE
135 headE = lift . headE
136+ {-# INLINABLE now #-}
137+ now = lift now
136
138
137instance (Reflex t, Adjustable t m, MonadHold t m, Semigroup w) => Adjustable t (EventWriterT t w m) where
139instance (Reflex t, Adjustable t m, MonadHold t m, Semigroup w) => Adjustable t (EventWriterT t w m) where
138 runWithReplace = runWithReplaceEventWriterTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
140 runWithReplace = runWithReplaceEventWriterTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
src/Reflex/PerformEvent/Base.hs+2
@@ -164,6 +164,8 @@ instance (ReflexHost t, MonadHold t m) => MonadHold t (PerformEventT t m) where
164 buildDynamic getV0 v' = PerformEventT $ lift $ buildDynamic getV0 v'
164 buildDynamic getV0 v' = PerformEventT $ lift $ buildDynamic getV0 v'
165 {-# INLINABLE headE #-}
165 {-# INLINABLE headE #-}
166 headE = PerformEventT . lift . headE
166 headE = PerformEventT . lift . headE
167+ {-# INLINABLE now #-}
168+ now = PerformEventT . lift $ now
167
169
168instance (MonadRef (HostFrame t), ReflexHost t) => MonadRef (PerformEventT t m) where
170instance (MonadRef (HostFrame t), ReflexHost t) => MonadRef (PerformEventT t m) where
169 type Ref (PerformEventT t m) = Ref (HostFrame t)
171 type Ref (PerformEventT t m) = Ref (HostFrame t)
src/Reflex/PostBuild/Base.hs+2
@@ -84,6 +84,8 @@ instance MonadHold t m => MonadHold t (PostBuildT t m) where
84 buildDynamic a0 = lift . buildDynamic a0
84 buildDynamic a0 = lift . buildDynamic a0
85 {-# INLINABLE headE #-}
85 {-# INLINABLE headE #-}
86 headE = lift . headE
86 headE = lift . headE
87+ {-# INLINABLE now #-}
88+ now = lift now
87
89
88instance PerformEvent t m => PerformEvent t (PostBuildT t m) where
90instance PerformEvent t m => PerformEvent t (PostBuildT t m) where
89 type Performable (PostBuildT t m) = Performable m
91 type Performable (PostBuildT t m) = Performable m
src/Reflex/Profiled.hs+1
@@ -183,6 +183,7 @@ instance MonadHold t m => MonadHold (ProfiledTimeline t) (ProfiledM m) where
183 holdIncremental v0 (Event_Profiled v') = ProfiledM $ Incremental_Profiled <$> holdIncremental v0 v'
183 holdIncremental v0 (Event_Profiled v') = ProfiledM $ Incremental_Profiled <$> holdIncremental v0 v'
184 buildDynamic (ProfiledM v0) (Event_Profiled v') = ProfiledM $ Dynamic_Profiled <$> buildDynamic v0 v'
184 buildDynamic (ProfiledM v0) (Event_Profiled v') = ProfiledM $ Dynamic_Profiled <$> buildDynamic v0 v'
185 headE (Event_Profiled e) = ProfiledM $ Event_Profiled <$> headE e
185 headE (Event_Profiled e) = ProfiledM $ Event_Profiled <$> headE e
186+ now = ProfiledM $ Event_Profiled <$> now
186
187
187instance MonadSample t m => MonadSample (ProfiledTimeline t) (ProfiledM m) where
188instance MonadSample t m => MonadSample (ProfiledTimeline t) (ProfiledM m) where
188 sample (Behavior_Profiled b) = ProfiledM $ sample b
189 sample (Behavior_Profiled b) = ProfiledM $ sample b
src/Reflex/Pure.hs+4
@@ -210,3 +210,7 @@ instance (Enum t, HasTrie t, Ord t) => MonadHold (Pure t) ((->) t) where
210 Just x -> fromMaybe lastValue $ apply x lastValue
210 Just x -> fromMaybe lastValue $ apply x lastValue
211
211
212 headE = slowHeadE
212 headE = slowHeadE
213+ now t = Event $ guard . (t ==)
214+
215+
216+
src/Reflex/Spider/Internal.hs+36−1
@@ -306,7 +306,20 @@ data CacheSubscribed x a
306#endif
306#endif
307 }
307 }
308
308
309−
309+nowSpiderEventM :: (HasSpiderTimeline x) => EventM x (R.Event (SpiderTimeline x) ())
310+nowSpiderEventM =
311+ SpiderEvent <$> now
312+
313+now :: (MonadIO m, Defer (Some Clear) m, HasSpiderTimeline x
314+ ) => m (Event x ())
315+now = do
316+ nowOrNot <- liftIO $ newIORef $ Just ()
317+ scheduleClear nowOrNot
318+ return . Event $ \_ -> do
319+ occ <- liftIO . readIORef $ nowOrNot
320+ return ( EventSubscription (return ()) eventSubscribedNow
321+ , occ
322+ )
310
323
311-- | Construct an 'Event' whose value is guaranteed not to be recomputed
324-- | Construct an 'Event' whose value is guaranteed not to be recomputed
312-- repeatedly
325-- repeatedly
@@ -593,6 +606,16 @@ eventSubscribedNever = EventSubscribed
593 , eventSubscribedWhoCreated = return ["never"]
606 , eventSubscribedWhoCreated = return ["never"]
594#endif
607#endif
595 }
608 }
609+eventSubscribedNow :: EventSubscribed x
610+eventSubscribedNow = EventSubscribed
611+ { eventSubscribedHeightRef = zeroRef
612+ , eventSubscribedRetained = toAny ()
613+#ifdef DEBUG_CYCLES
614+ , eventSubscribedGetParents = return []
615+ , eventSubscribedHasOwnHeightRef = False
616+ , eventSubscribedWhoCreated = return ["now"]
617+#endif
618+ }
596
619
597eventSubscribedFan :: FanSubscribed x k v -> EventSubscribed x
620eventSubscribedFan :: FanSubscribed x k v -> EventSubscribed x
598eventSubscribedFan !subscribed = EventSubscribed
621eventSubscribedFan !subscribed = EventSubscribed
@@ -2496,6 +2519,8 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Event
2496 {-# INLINABLE headE #-}
2519 {-# INLINABLE headE #-}
2497 headE = R.slowHeadE
2520 headE = R.slowHeadE
2498-- headE (SpiderEvent e) = SpiderEvent <$> Reflex.Spider.Internal.headE e
2521-- headE (SpiderEvent e) = SpiderEvent <$> Reflex.Spider.Internal.headE e
2522+ {-# INLINABLE now #-}
2523+ now = nowSpiderEventM
2499
2524
2500instance Reflex.Class.MonadSample (SpiderTimeline x) (SpiderPullM x) where
2525instance Reflex.Class.MonadSample (SpiderTimeline x) (SpiderPullM x) where
2501 {-# INLINABLE sample #-}
2526 {-# INLINABLE sample #-}
@@ -2517,6 +2542,9 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Spide
2517 {-# INLINABLE headE #-}
2542 {-# INLINABLE headE #-}
2518 headE = R.slowHeadE
2543 headE = R.slowHeadE
2519-- headE (SpiderEvent e) = SpiderPushM $ SpiderEvent <$> Reflex.Spider.Internal.headE e
2544-- headE (SpiderEvent e) = SpiderPushM $ SpiderEvent <$> Reflex.Spider.Internal.headE e
2545+ {-# INLINABLE now #-}
2546+ now = SpiderPushM nowSpiderEventM
2547+
2520
2548
2521instance HasSpiderTimeline x => Monad (Reflex.Class.Dynamic (SpiderTimeline x)) where
2549instance HasSpiderTimeline x => Monad (Reflex.Class.Dynamic (SpiderTimeline x)) where
2522 {-# INLINE return #-}
2550 {-# INLINE return #-}
@@ -2580,6 +2608,9 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Spide
2580 buildDynamic getV0 e = runFrame . runSpiderHostFrame $ Reflex.Class.buildDynamic getV0 e
2608 buildDynamic getV0 e = runFrame . runSpiderHostFrame $ Reflex.Class.buildDynamic getV0 e
2581 {-# INLINABLE headE #-}
2609 {-# INLINABLE headE #-}
2582 headE e = runFrame . runSpiderHostFrame $ Reflex.Class.headE e
2610 headE e = runFrame . runSpiderHostFrame $ Reflex.Class.headE e
2611+ {-# INLINABLE now #-}
2612+ now = runFrame . runSpiderHostFrame $ Reflex.Class.now
2613+
2583
2614
2584instance HasSpiderTimeline x => Reflex.Class.MonadSample (SpiderTimeline x) (SpiderHostFrame x) where
2615instance HasSpiderTimeline x => Reflex.Class.MonadSample (SpiderTimeline x) (SpiderHostFrame x) where
2585 sample = SpiderHostFrame . readBehaviorUntracked . unSpiderBehavior --TODO: This can cause problems with laziness, so we should get rid of it if we can
2616 sample = SpiderHostFrame . readBehaviorUntracked . unSpiderBehavior --TODO: This can cause problems with laziness, so we should get rid of it if we can
@@ -2596,6 +2627,8 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Spide
2596 {-# INLINABLE headE #-}
2627 {-# INLINABLE headE #-}
2597 headE = R.slowHeadE
2628 headE = R.slowHeadE
2598-- headE (SpiderEvent e) = SpiderHostFrame $ SpiderEvent <$> Reflex.Spider.Internal.headE e
2629-- headE (SpiderEvent e) = SpiderHostFrame $ SpiderEvent <$> Reflex.Spider.Internal.headE e
2630+ {-# INLINABLE now #-}
2631+ now = SpiderHostFrame Reflex.Class.now
2599
2632
2600instance HasSpiderTimeline x => Reflex.Class.MonadSample (SpiderTimeline x) (SpiderHost x) where
2633instance HasSpiderTimeline x => Reflex.Class.MonadSample (SpiderTimeline x) (SpiderHost x) where
2601 {-# INLINABLE sample #-}
2634 {-# INLINABLE sample #-}
@@ -2616,6 +2649,8 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Refle
2616 buildDynamic getV0 e = Reflex.Spider.Internal.ReadPhase $ Reflex.Class.buildDynamic getV0 e
2649 buildDynamic getV0 e = Reflex.Spider.Internal.ReadPhase $ Reflex.Class.buildDynamic getV0 e
2617 {-# INLINABLE headE #-}
2650 {-# INLINABLE headE #-}
2618 headE e = Reflex.Spider.Internal.ReadPhase $ Reflex.Class.headE e
2651 headE e = Reflex.Spider.Internal.ReadPhase $ Reflex.Class.headE e
2652+ {-# INLINABLE now #-}
2653+ now = Reflex.Spider.Internal.ReadPhase Reflex.Class.now
2619
2654
2620--------------------------------------------------------------------------------
2655--------------------------------------------------------------------------------
2621-- Deprecated items
2656-- Deprecated items
src/Reflex/TriggerEvent/Base.hs+2
@@ -122,6 +122,8 @@ instance MonadHold t m => MonadHold t (TriggerEventT t m) where
122 buildDynamic a0 = lift . buildDynamic a0
122 buildDynamic a0 = lift . buildDynamic a0
123 {-# INLINABLE headE #-}
123 {-# INLINABLE headE #-}
124 headE = lift . headE
124 headE = lift . headE
125+ {-# INLINABLE now #-}
126+ now = lift now
125
127
126instance Adjustable t m => Adjustable t (TriggerEventT t m) where
128instance Adjustable t m => Adjustable t (TriggerEventT t m) where
127 {-# INLINABLE runWithReplace #-}
129 {-# INLINABLE runWithReplace #-}
test/Reflex/Plan/Pure.hs+1
@@ -41,6 +41,7 @@ instance MonadHold (Pure Int) PurePlan where
41 holdIncremental initial = liftPlan . holdIncremental initial
41 holdIncremental initial = liftPlan . holdIncremental initial
42 buildDynamic getInitial = liftPlan . buildDynamic getInitial
42 buildDynamic getInitial = liftPlan . buildDynamic getInitial
43 headE = liftPlan . headE
43 headE = liftPlan . headE
44+ now = liftPlan now
44
45
45instance MonadSample (Pure Int) PurePlan where
46instance MonadSample (Pure Int) PurePlan where
46 sample = liftPlan . sample
47 sample = liftPlan . sample
test/Reflex/Test/Micro.hs+8−2
@@ -322,8 +322,14 @@ testCases =
322 let e = never <$ switch b
322 let e = never <$ switch b
323 return $ void e
323 return $ void e
324 lazyHold
324 lazyHold
325−
325+ , testE "now-1" $ do
326−
326+ e1 <- events1
327+ switchHoldPromptly never . pushAlways (\a -> fmap (a <$) now) $ e1
328+ , testE "now-2" $ do
329+ e1 <- events1
330+ let e = pushAlways (\a -> if a == "a" then now else return never) e1
331+ x <- accumDyn (<>) never e
332+ return . coincidence $ updated x
327 ] where
333 ] where
328
334
329 events1, events2, events3 :: TestPlan t m => m (Event t String)
335 events1, events2, events3 :: TestPlan t m => m (Event t String)