on develop help sign in
wip
adfc860Ryan Trinkle
.gitignore+2
@@ -32,3 +32,5 @@ hsenv.log
32.#*
32.#*
33/shell.nix
33/shell.nix
34/ghci-tmp
34/ghci-tmp
35+*.dump-*
36+*.verbose-core2core
default.nix+4
@@ -4,6 +4,7 @@
4, monad-control, mtl, primitive, ref-tf, semigroupoids
4, monad-control, mtl, primitive, ref-tf, semigroupoids
5, semigroups, split, stdenv, stm, syb, template-haskell
5, semigroups, split, stdenv, stm, syb, template-haskell
6, these, transformers, transformers-compat, prim-uniq
6, these, transformers, transformers-compat, prim-uniq
7+, ghc_reflex ? null
7}:
8}:
8mkDerivation {
9mkDerivation {
9 pname = "reflex";
10 pname = "reflex";
@@ -20,6 +21,9 @@ mkDerivation {
20 base bifunctors containers deepseq dependent-map dependent-sum
21 base bifunctors containers deepseq dependent-map dependent-sum
21 hlint mtl ref-tf split transformers
22 hlint mtl ref-tf split transformers
22 ];
23 ];
24+ buildDepends = [
25+ ghc_reflex
26+ ];
23 homepage = "https://github.com/reflex-frp/reflex";
27 homepage = "https://github.com/reflex-frp/reflex";
24 description = "Higher-order Functional Reactive Programming";
28 description = "Higher-order Functional Reactive Programming";
25 license = stdenv.lib.licenses.bsd3;
29 license = stdenv.lib.licenses.bsd3;
src/Reflex/DynamicWriter.hs+7−8
@@ -19,6 +19,7 @@ import Control.Monad.Reader
19import Control.Monad.Ref
19import Control.Monad.Ref
20import Control.Monad.State.Strict
20import Control.Monad.State.Strict
21import Data.Dependent.Map (DMap, DSum (..))
21import Data.Dependent.Map (DMap, DSum (..))
22+import qualified Data.Dependent.Map as DMap
22import Data.Functor.Misc
23import Data.Functor.Misc
23import Data.Map (Map)
24import Data.Map (Map)
24import qualified Data.Map as Map
25import qualified Data.Map as Map
@@ -166,15 +167,13 @@ instance (MonadAdjust t m, MonadFix m, Monoid w, MonadHold t m, Reflex t) => Mon
166 liftedResult0 = mapKeyValuePairsMonotonic (\(WrapArg k :=> Identity r) -> k :=> Identity (getValue r)) result0
167 liftedResult0 = mapKeyValuePairsMonotonic (\(WrapArg k :=> Identity r) -> k :=> Identity (getValue r)) result0
167 liftedResult' = ffor result' $ \(PatchDMap p) -> PatchDMap $
168 liftedResult' = ffor result' $ \(PatchDMap p) -> PatchDMap $
168 mapKeyValuePairsMonotonic (\(WrapArg k :=> ComposeMaybe mr) -> k :=> ComposeMaybe (fmap (Identity . getValue . runIdentity) mr)) p
169 mapKeyValuePairsMonotonic (\(WrapArg k :=> ComposeMaybe mr) -> k :=> ComposeMaybe (fmap (Identity . getValue . runIdentity) mr)) p
169− liftedWritten0 :: DMap (Const2 (Some k) (Dynamic t w)) Identity
170+ liftedWritten0 :: Map (Some k) (Dynamic t w)
170− liftedWritten0 = mapKeyValuePairsMonotonic (\(WrapArg k :=> Identity r) -> Const2 (Some.This k) :=> Identity (getWritten r)) result0
171+ liftedWritten0 = Map.fromDistinctAscList $ fmap (\(WrapArg k :=> Identity r) -> (Some.This k, getWritten r)) $ DMap.toList result0
171− liftedWritten' = ffor result' $ \(PatchDMap p) -> PatchDMap $
172+ liftedWritten' = ffor result' $ \(PatchDMap p) -> PatchMap $
172− mapKeyValuePairsMonotonic (\(WrapArg k :=> ComposeMaybe mr) -> Const2 (Some.This k) :=> ComposeMaybe (fmap (Identity . getWritten . runIdentity) mr)) p
173+ Map.fromDistinctAscList $ fmap (\(WrapArg k :=> ComposeMaybe mr) -> (Some.This k, fmap (getWritten . runIdentity) mr)) $ DMap.toList p
173− --TODO: We should be able to improve the performance here in two ways
174+ --TODO: We should be able to improve the performance here by incrementally updating the mconcat of the merged Dynamics
174− -- 1. Incrementally merging the Dynamics
175− -- 2. Incrementally updating the mconcat of the merged Dynamics
176 i <- holdIncremental liftedWritten0 liftedWritten'
175 i <- holdIncremental liftedWritten0 liftedWritten'
177− tellDyn $ join $ mconcat . Map.elems . dmapToMap <$> incrementalToDynamic i
176+ tellDyn $ fmap (mconcat . Map.elems) $ incrementalToDynamic $ mergeDynIncremental i
178 return (liftedResult0, liftedResult')
177 return (liftedResult0, liftedResult')
179
178
180withDynamicWriterT :: (Monoid w, Reflex t, MonadHold t m, MonadFix m)
179withDynamicWriterT :: (Monoid w, Reflex t, MonadHold t m, MonadFix m)
src/Reflex/Optimizer.hsnew file+33
@@ -0,0 +1,33 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE LambdaCase #-}
3+module Reflex.Optimizer (plugin) where
4+
5+#ifndef ghcjs_HOST_OS
6+
7+import GhcPlugins
8+import Control.Arrow
9+
10+plugin :: Plugin
11+plugin = defaultPlugin { installCoreToDos = install }
12+
13+install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
14+install [] p = return $ makeInlinable : p
15+
16+makeInlinable :: CoreToDo
17+makeInlinable = CoreDoPluginPass "MakeInlinable" $ \modGuts -> do
18+ let f v = setIdInfo v $ let i = idInfo v in
19+ setInlinePragInfo i $ let p = inlinePragInfo i in
20+ if isDefaultInlinePragma p
21+ then defaultInlinePragma { inl_inline = Inlinable }
22+ else p
23+ newBinds = flip map (mg_binds modGuts) $ \case
24+ NonRec b e -> NonRec (f b) e
25+ Rec bes -> Rec $ map (first f) bes
26+ return $ modGuts { mg_binds = newBinds }
27+
28+#else
29+
30+plugin :: ()
31+plugin = ()
32+
33+#endif
src/Reflex/PerformEvent/Base.hs+2−1
@@ -32,6 +32,7 @@ import Data.Dependent.Map (DMap, GCompare (..), Some)
32import qualified Data.Dependent.Map as DMap
32import qualified Data.Dependent.Map as DMap
33import Data.Dependent.Sum
33import Data.Dependent.Sum
34import Data.Functor.Misc
34import Data.Functor.Misc
35+import Data.Maybe
35import Data.Semigroup
36import Data.Semigroup
36import qualified Data.Some as Some
37import qualified Data.Some as Some
37import Data.These
38import Data.These
@@ -211,7 +212,7 @@ sequenceDMapWithAdjustRequestTWith f (dm0 :: DMap k (RequestT t request response
211 childRequestMap <- holdIncremental requests0 requests'
212 childRequestMap <- holdIncremental requests0 requests'
212 RequestT $ modify $ (:) $ ffor (mergeIncremental childRequestMap) $ \m ->
213 RequestT $ modify $ (:) $ ffor (mergeIncremental childRequestMap) $ \m ->
213 mconcat $ (\(Const2 _ :=> Identity reqs) -> reqs) <$> DMap.toList m
214 mconcat $ (\(Const2 _ :=> Identity reqs) -> reqs) <$> DMap.toList m
214−-- RequestT $ modify $ (:) $ coincidence $ ffor requests' $ \(PatchDMap p) -> mergeWith DMap.union $ catMaybes $ ffor (DMap.toList p) $ \(Const2 _ :=> ComposeMaybe me) -> me -- We could make it prompt like this, but this seems to be slower than just delaying the PostBuild event to allow this stuff to settle (which is more similar to the previous behavior anyway)
215+ RequestT $ modify $ (:) $ coincidence $ ffor requests' $ \(PatchDMap p) -> mergeWith DMap.union $ catMaybes $ ffor (DMap.toList p) $ \(Const2 _ :=> ComposeMaybe me) -> me
215 return (result0, result')
216 return (result0, result')
216
217
217instance PerformEvent t m => PerformEvent t (RequestT t request response m) where
218instance PerformEvent t m => PerformEvent t (RequestT t request response m) where
src/Reflex/PostBuild/Class.hs+1−2
@@ -98,7 +98,6 @@ instance (Reflex t, MonadHold t m, MonadFix m, MonadAdjust t m, PerformEvent t m
98 postBuild <- getPostBuild
98 postBuild <- getPostBuild
99 let loweredDm0 = DMap.map (`runPostBuildT` postBuild) dm0
99 let loweredDm0 = DMap.map (`runPostBuildT` postBuild) dm0
100 rec (result0, result') <- lift $ sequenceDMapWithAdjust loweredDm0 loweredDm'
100 rec (result0, result') <- lift $ sequenceDMapWithAdjust loweredDm0 loweredDm'
101− delayedResult' <- performEvent $ return () <$ result' -- Delaying this result seems to be faster than making RequestT (and thus PerformEvent) more prompt
102 let loweredDm' = ffor dm' $ \(PatchDMap p) -> PatchDMap $
101 let loweredDm' = ffor dm' $ \(PatchDMap p) -> PatchDMap $
103− DMap.map (ComposeMaybe . fmap (\v -> runPostBuildT v =<< headE (void delayedResult')) . getComposeMaybe) p --TODO: Avoid doing this headE so many times; once per loweredDm' firing ought to be OK, but it's not totally trivial to do because result' might be firing at the same time, and we don't want *that* to be the postBuild occurrence
102+ DMap.map (ComposeMaybe . fmap (\v -> runPostBuildT v =<< headE (void result')) . getComposeMaybe) p --TODO: Avoid doing this headE so many times; once per loweredDm' firing ought to be OK, but it's not totally trivial to do because result' might be firing at the same time, and we don't want *that* to be the postBuild occurrence
104 return (result0, result')
103 return (result0, result')
src/Reflex/Spider/Internal.hs+34−25
@@ -17,6 +17,7 @@
17{-# LANGUAGE TypeFamilies #-}
17{-# LANGUAGE TypeFamilies #-}
18{-# LANGUAGE TypeOperators #-}
18{-# LANGUAGE TypeOperators #-}
19{-# LANGUAGE UndecidableInstances #-}
19{-# LANGUAGE UndecidableInstances #-}
20+{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
20-- | This module is the implementation of the 'Spider' 'Reflex' engine. It uses
21-- | This module is the implementation of the 'Spider' 'Reflex' engine. It uses
21-- a graph traversal algorithm to propagate 'Event's and 'Behavior's.
22-- a graph traversal algorithm to propagate 'Event's and 'Behavior's.
22module Reflex.Spider.Internal where
23module Reflex.Spider.Internal where
@@ -180,12 +181,23 @@ unsafeNodeId a = unsafePerformIO $ do
180-- Event
181-- Event
181--------------------------------------------------------------------------------
182--------------------------------------------------------------------------------
182
183
184+newtype Event x a = Event { unEvent :: Subscriber x a -> EventM x (EventSubscription x, Maybe a) }
185+
186+{-# INLINE subscribeAndRead #-}
183−newtype Event x a = Event { subscribeAndRead :: Subscriber x a -> EventM x (EventSubscription x, Maybe a) }
187+subscribeAndRead :: Event x a -> Subscriber x a -> EventM x (EventSubscription x, Maybe a)
188+subscribeAndRead = unEvent
189+
190+{-# RULES "pushCheap/cacheEvent" forall f e. pushCheap f (cacheEvent e) = pushCheap f e #-}
191+{-# RULES "hold/cacheEvent" forall f e. hold f (cacheEvent e) = hold f e #-}
192+{- RULES
193+ "subscribeAndRead/cacheEvent" forall e. subscribeAndRead (cacheEvent e) = subscribeAndRead e
194+ #-}
184
195
185-- | Construct an 'Event' equivalent to that constructed by 'push', but with no
196-- | Construct an 'Event' equivalent to that constructed by 'push', but with no
186-- caching; if the computation function is very cheap, this is (much) more
197-- caching; if the computation function is very cheap, this is (much) more
187-- efficient than 'push'
198-- efficient than 'push'
188−{-# INLINABLE pushCheap #-}
199+{- INLINABLE pushCheap #-}
200+{-# INLINE [1] pushCheap #-}
189pushCheap :: HasSpiderTimeline x => (a -> ComputeM x (Maybe b)) -> Event x a -> Event x b
201pushCheap :: HasSpiderTimeline x => (a -> ComputeM x (Maybe b)) -> Event x a -> Event x b
190pushCheap f e = Event $ \sub -> do
202pushCheap f e = Event $ \sub -> do
191 (subscription, occ) <- subscribeAndRead e $ sub
203 (subscription, occ) <- subscribeAndRead e $ sub
@@ -210,7 +222,7 @@ data CacheSubscribed x a
210--TODO: Try a caching strategy where we subscribe directly to the parent when
222--TODO: Try a caching strategy where we subscribe directly to the parent when
211--there's only one subscriber, and then build our own WeakBag only when a second
223--there's only one subscriber, and then build our own WeakBag only when a second
212--subscriber joins
224--subscriber joins
213−{-# INLINABLE cacheEvent #-}
225+{-# NOINLINE [1] cacheEvent #-}
214cacheEvent :: HasSpiderTimeline x => Event x a -> Event x a
226cacheEvent :: HasSpiderTimeline x => Event x a -> Event x a
215cacheEvent e = Event $ \sub -> {-# SCC "cacheEvent" #-} do
227cacheEvent e = Event $ \sub -> {-# SCC "cacheEvent" #-} do
216 let !mSubscribedRef = unsafeNewIORef e Nothing
228 let !mSubscribedRef = unsafeNewIORef e Nothing
@@ -588,7 +600,7 @@ behaviorPull !p = Behavior $ do
588 askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (BehaviorSubscribedPull subscribed) :))
600 askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (BehaviorSubscribedPull subscribed) :))
589 return a
601 return a
590
602
591−behaviorDyn :: (HasSpiderTimeline x, R.Patch p) => Dyn x p -> Behavior x (R.PatchTarget p)
603+behaviorDyn :: R.Patch p => Dyn x p -> Behavior x (R.PatchTarget p)
592behaviorDyn !d = Behavior $ readHoldTracked =<< getDynHold d
604behaviorDyn !d = Behavior $ readHoldTracked =<< getDynHold d
593
605
594{-# INLINE readHoldTracked #-}
606{-# INLINE readHoldTracked #-}
@@ -599,7 +611,7 @@ readHoldTracked h = do
599 askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (BehaviorSubscribedHold h) :))
611 askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (BehaviorSubscribedHold h) :))
600 return result
612 return result
601
613
602−{-# SPECIALIZE readBehaviorUntracked :: HasSpiderTimeline x => Behavior x a -> BehaviorM x a #-}
614+{-# SPECIALIZE readBehaviorUntracked :: Behavior x a -> BehaviorM x a #-}
603{-# SPECIALIZE readBehaviorUntracked :: HasSpiderTimeline x => Behavior x a -> EventM x a #-}
615{-# SPECIALIZE readBehaviorUntracked :: HasSpiderTimeline x => Behavior x a -> EventM x a #-}
604readBehaviorUntracked :: Defer (SomeHoldInit x) m => Behavior x a -> m a
616readBehaviorUntracked :: Defer (SomeHoldInit x) m => Behavior x a -> m a
605readBehaviorUntracked b = do
617readBehaviorUntracked b = do
@@ -693,7 +705,7 @@ instance HasSpiderTimeline x => Defer (SomeHoldInit x) (EventM x) where
693 {-# INLINE getDeferralQueue #-}
705 {-# INLINE getDeferralQueue #-}
694 getDeferralQueue = asksEventEnv eventEnvHoldInits
706 getDeferralQueue = asksEventEnv eventEnvHoldInits
695
707
696−instance HasSpiderTimeline x => Defer (SomeHoldInit x) (BehaviorM x) where
708+instance Defer (SomeHoldInit x) (BehaviorM x) where
697 {-# INLINE getDeferralQueue #-}
709 {-# INLINE getDeferralQueue #-}
698 getDeferralQueue = BehaviorM $ asks snd
710 getDeferralQueue = BehaviorM $ asks snd
699
711
@@ -752,8 +764,8 @@ instance HasSpiderTimeline x => Defer (SomeResetCoincidence x) (EventM x) where
752 getDeferralQueue = asksEventEnv eventEnvResetCoincidences
764 getDeferralQueue = asksEventEnv eventEnvResetCoincidences
753
765
754-- Note: hold cannot examine its event until after the phase is over
766-- Note: hold cannot examine its event until after the phase is over
755−{-# SPECIALIZE hold :: (HasSpiderTimeline x, R.Patch p) => R.PatchTarget p -> Event x p -> EventM x (Hold x p) #-}
767+{- SPECIALIZE hold :: (HasSpiderTimeline x, R.Patch p) => R.PatchTarget p -> Event x p -> EventM x (Hold x p) #-}
756−{- SPECIALIZE hold :: (HasSpiderTimeline x, R.Patch p) => R.PatchTarget p -> Event x p -> ComputeM x (Hold x p) #-}
768+{-# INLINE [1] hold #-}
757hold :: (R.Patch p, Defer (SomeHoldInit x) m) => R.PatchTarget p -> Event x p -> m (Hold x p)
769hold :: (R.Patch p, Defer (SomeHoldInit x) m) => R.PatchTarget p -> Event x p -> m (Hold x p)
758hold v0 e = do
770hold v0 e = do
759 valRef <- liftIO $ newIORef v0
771 valRef <- liftIO $ newIORef v0
@@ -1050,17 +1062,9 @@ instance HasSpiderTimeline x => Functor (Event x) where
1050instance Functor (Behavior x) where
1062instance Functor (Behavior x) where
1051 fmap f = pull . fmap f . readBehaviorTracked
1063 fmap f = pull . fmap f . readBehaviorTracked
1052
1064
1053−{-# INLINABLE push #-} --TODO: If this is helpful, we can get rid of the unsafeNewIORef and use unsafePerformIO directly
1065+{-# INLINE push #-}
1054push :: HasSpiderTimeline x => (a -> ComputeM x (Maybe b)) -> Event x a -> Event x b
1066push :: HasSpiderTimeline x => (a -> ComputeM x (Maybe b)) -> Event x a -> Event x b
1055push f e = cacheEvent (pushCheap f e)
1067push f e = cacheEvent (pushCheap f e)
1056−{-
1057−push f e = eventPush $ Push
1058− { pushCompute = f
1059− , pushParent = e
1060− , pushSubscribed = unsafeNewIORef (f, e) Nothing --TODO: Does the use of the tuple here create unnecessary overhead?
1061− }
1062−-- DISABLED: {- RULES "push/push" forall f g e. push f (push g e) = push (maybe (return Nothing) f <=< g) e #-}
1063−-}
1064
1068
1065{-# INLINABLE pull #-}
1069{-# INLINABLE pull #-}
1066pull :: BehaviorM x a -> Behavior x a
1070pull :: BehaviorM x a -> Behavior x a
@@ -1089,8 +1093,8 @@ coincidence a = eventCoincidence $ Coincidence
1089run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> ResultM x b -> SpiderHost x b
1093run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> ResultM x b -> SpiderHost x b
1090run roots after = do
1094run roots after = do
1091 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
1095 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
1092− spiderTimeline <- SpiderHost ask
1096+ t <- SpiderHost ask
1093− result <- SpiderHost $ lift $ withMVar (_spiderTimeline_lock spiderTimeline) $ \_ -> flip runReaderT spiderTimeline $ unSpiderHost $ runFrame $ do
1097+ result <- SpiderHost $ lift $ withMVar (_spiderTimeline_lock t) $ \_ -> flip runReaderT t $ unSpiderHost $ runFrame $ do
1094 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
1098 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
1095 occBefore <- liftIO $ do
1099 occBefore <- liftIO $ do
1096 occBefore <- readIORef occRef
1100 occBefore <- readIORef occRef
@@ -1485,7 +1489,11 @@ subscribeCoincidenceSubscribed subscribed sub = WeakBag.insert sub (coincidenceS
1485
1489
1486{-# INLINE merge #-}
1490{-# INLINE merge #-}
1487merge :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (R.PatchDMap k (Event x)) -> Event x (DMap k Identity)
1491merge :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (R.PatchDMap k (Event x)) -> Event x (DMap k Identity)
1488−merge d = cacheEvent $ Event $ \sub -> do
1492+merge d = cacheEvent (mergeCheap d)
1493+
1494+{-# INLINE [1] mergeCheap #-}
1495+mergeCheap :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (R.PatchDMap k (Event x)) -> Event x (DMap k Identity)
1496+mergeCheap d = Event $ \sub -> do
1489 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1497 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1490 accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
1498 accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
1491 heightRef <- liftIO $ newIORef $ error "merge: heightRef not yet initialized"
1499 heightRef <- liftIO $ newIORef $ error "merge: heightRef not yet initialized"
@@ -1660,7 +1668,7 @@ clearEventEnv (EventEnv toAssignRef holdInitRef mergeUpdateRef mergeInitRef toCl
1660
1668
1661-- | Run an event action outside of a frame
1669-- | Run an event action outside of a frame
1662runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
1670runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
1663−runFrame a = SpiderHost $ ask >>= \spiderTimeline -> lift $ do
1671+runFrame a = SpiderHost $ ask >>= \_ -> lift $ do
1664 let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimeline x)
1672 let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimeline x)
1665 let go = do
1673 let go = do
1666 result <- a
1674 result <- a
@@ -1822,7 +1830,7 @@ data Global
1822
1830
1823{-# NOINLINE globalSpiderTimeline #-}
1831{-# NOINLINE globalSpiderTimeline #-}
1824globalSpiderTimeline :: SpiderTimeline Global
1832globalSpiderTimeline :: SpiderTimeline Global
1825−globalSpiderTimeline = unsafePerformIO unsafeNewSpiderTimeline
1833+!globalSpiderTimeline = unsafePerformIO unsafeNewSpiderTimeline
1826
1834
1827-- | Stores all global data relevant to a particular Spider timeline; only one
1835-- | Stores all global data relevant to a particular Spider timeline; only one
1828-- value should exist for each type @x@
1836-- value should exist for each type @x@
@@ -1887,6 +1895,7 @@ instance HasSpiderTimeline x => Monad (R.Dynamic (SpiderTimeline x)) where
1887 fail _ = error "Dynamic does not support 'fail'"
1895 fail _ = error "Dynamic does not support 'fail'"
1888
1896
1889instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
1897instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
1898+ {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-}
1890 newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
1899 newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
1891 newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }
1900 newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }
1892 newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: Dynamic x (Identity a) } -- deriving (Functor, Applicative, Monad)
1901 newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: Dynamic x (Identity a) } -- deriving (Functor, Applicative, Monad)
@@ -1897,7 +1906,7 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
1897 never = SpiderEvent eventNever
1906 never = SpiderEvent eventNever
1898 {-# INLINABLE constant #-}
1907 {-# INLINABLE constant #-}
1899 constant = SpiderBehavior . behaviorConst
1908 constant = SpiderBehavior . behaviorConst
1900− {-# INLINABLE push #-}
1909+ {-# INLINE push #-}
1901 push f = SpiderEvent . push (coerce f) . unSpiderEvent
1910 push f = SpiderEvent . push (coerce f) . unSpiderEvent
1902 {-# INLINABLE pull #-}
1911 {-# INLINABLE pull #-}
1903 pull = SpiderBehavior . pull . coerce
1912 pull = SpiderBehavior . pull . coerce
@@ -1964,11 +1973,11 @@ instance HasSpiderTimeline x => R.MonadSample (SpiderTimeline x) (SpiderHost x)
1964 {-# INLINABLE sample #-}
1973 {-# INLINABLE sample #-}
1965 sample = runFrame . readBehaviorUntracked . unSpiderBehavior
1974 sample = runFrame . readBehaviorUntracked . unSpiderBehavior
1966
1975
1967−instance HasSpiderTimeline x => R.MonadSample (SpiderTimeline x) (SpiderPullM x) where
1976+instance R.MonadSample (SpiderTimeline x) (SpiderPullM x) where
1968 {-# INLINABLE sample #-}
1977 {-# INLINABLE sample #-}
1969 sample = coerce . readBehaviorTracked . unSpiderBehavior
1978 sample = coerce . readBehaviorTracked . unSpiderBehavior
1970
1979
1971−instance HasSpiderTimeline x => R.MonadSample (SpiderTimeline x) (SpiderPushM x) where
1980+instance R.MonadSample (SpiderTimeline x) (SpiderPushM x) where
1972 {-# INLINABLE sample #-}
1981 {-# INLINABLE sample #-}
1973 sample (SpiderBehavior b) = SpiderPushM $ readBehaviorUntracked b
1982 sample (SpiderBehavior b) = SpiderPushM $ readBehaviorUntracked b
1974
1983