@@ -17,6 +17,8 @@
1717{-# LANGUAGE TypeOperators #-}
1818{-# LANGUAGE UndecidableInstances #-}
1919{-# LANGUAGE PolyKinds #-}
20+{-# LANGUAGE DeriveFunctor #-}
21+{-# LANGUAGE StandaloneDeriving #-}
2022{-# LANGUAGE InstanceSigs #-}
2123
2224#ifdef USE_REFLEX_OPTIMIZER
@@ -36,7 +38,10 @@ import Control.Monad hiding (forM, forM_, mapM, mapM_)
3638import Control.Monad.Exception
3739import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_)
3840import Control.Monad.Primitive
39−import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)
41+--import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)
42+import Control.Monad.Reader.Class
43+import Control.Monad.IO.Class
44+import Control.Monad.ReaderIO
4045import Control.Monad.Ref
4146import Data.Align
4247import Data.Coerce
@@ -550,6 +555,11 @@ propagateFast a subscribers = withIncreasedDepth $ do
550555toAny :: a -> Any
551556toAny = unsafeCoerce
552557
558+-- Why do we use Any here, instead of just giving eventSubscribedRetained an
559+-- existential type? Sadly, GHC does not currently know how to unbox types
560+-- with existentially quantified fields. So instead we just coerce values
561+-- to type Any on the way in. Since we never coerce them back, this is
562+-- perfectly safe.
553563data EventSubscribed x = EventSubscribed
554564 { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height)
555565 , eventSubscribedRetained :: {-# NOUNPACK #-} !Any
@@ -673,7 +683,7 @@ behaviorPull !p = Behavior $ do
673683 wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull"
674684 parentsRef <- liftIO $ newIORef []
675685 holdInits <- askBehaviorHoldInits
676− a <- liftIO $ runReaderT (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
686+ a <- liftIO $ runReaderIO (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
677687 invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator
678688 parents <- liftIO $ readIORef parentsRef
679689 let subscribed = PullSubscribed
@@ -708,42 +718,46 @@ readBehaviorUntracked b = do
708718-- Dynamic
709719--------------------------------------------------------------------------------
710720
711−data Dynamic x p = Dynamic
712− { dynamicCurrent :: !(Behavior x (PatchTarget p))
721+type DynamicS x p = Dynamic x (PatchTarget p) p
722+
723+data Dynamic x target p = Dynamic
724+ { dynamicCurrent :: !(Behavior x target)
713725 , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`?
714726 }
715727
716−dynamicHold :: Hold x p -> Dynamic x p
728+deriving instance (HasSpiderTimeline x) => Functor (Dynamic x target)
729+
730+
731+
732+
733+dynamicHold :: Hold x p -> DynamicS x p
717734dynamicHold !h = Dynamic
718735 { dynamicCurrent = behaviorHold h
719736 , dynamicUpdated = eventHold h
720737 }
721738
722−dynamicHoldIdentity :: Hold x (Identity a) -> Dynamic x (Identity a)
739+dynamicHoldIdentity :: Hold x (Identity a) -> DynamicS x (Identity a)
723740dynamicHoldIdentity = dynamicHold
724741
725−dynamicConst :: PatchTarget p -> Dynamic x p
742+dynamicConst :: PatchTarget p -> DynamicS x p
726743dynamicConst !a = Dynamic
727744 { dynamicCurrent = behaviorConst a
728745 , dynamicUpdated = eventNever
729746 }
730747
731−dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> Dynamic x p
748+dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> DynamicS x p
732749dynamicDyn !d = Dynamic
733750 { dynamicCurrent = behaviorDyn d
734751 , dynamicUpdated = eventDyn d
735752 }
736753
737−dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> Dynamic x (Identity a)
754+dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> DynamicS x (Identity a)
738755dynamicDynIdentity = dynamicDyn
739756
740757--------------------------------------------------------------------------------
741758-- Combinators
742759--------------------------------------------------------------------------------
743760
744−--TODO: Figure out why certain things are not 'representational', then make them
745−--representational so we can use coerce
746−
747761--type role Hold representational
748762data Hold x p
749763 = Hold { holdValue :: !(IORef (PatchTarget p))
@@ -764,20 +778,25 @@ globalSpiderTimelineEnv = unsafePerformIO unsafeNewSpiderTimelineEnv
764778
765779-- | Stores all global data relevant to a particular Spider timeline; only one
766780-- value should exist for each type @x@
767−data SpiderTimelineEnv x = SpiderTimelineEnv
781+newtype SpiderTimelineEnv x = STE {unSTE :: SpiderTimelineEnv' x}
782+-- We implement SpiderTimelineEnv with a newtype wrapper so
783+-- we can get the coercions we want safely.
784+type role SpiderTimelineEnv nominal
785+
786+data SpiderTimelineEnv' x = SpiderTimelineEnv
768787 { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ())
769788 , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x)
770789#ifdef DEBUG
771790 , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int)
772791#endif
773792 }
774−type role SpiderTimelineEnv nominal
793+type role SpiderTimelineEnv' phantom
775794
776795instance Eq (SpiderTimelineEnv x) where
777796 _ == _ = True -- Since only one exists of each type
778797
779798instance GEq SpiderTimelineEnv where
780− a `geq` b = if _spiderTimeline_lock a == _spiderTimeline_lock b
799+ a `geq` b = if _spiderTimeline_lock (unSTE a) == _spiderTimeline_lock (unSTE b)
781800 then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments
782801 else Nothing
783802
@@ -800,7 +819,7 @@ runEventM :: EventM x a -> IO a
800819runEventM = unEventM
801820
802821asksEventEnv :: forall x a. HasSpiderTimeline x => (EventEnv x -> a) -> EventM x a
803−asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
822+asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (unSTE (spiderTimeline :: SpiderTimelineEnv x))
804823
805824class MonadIO m => Defer a m where
806825 getDeferralQueue :: m (IORef [a])
@@ -938,9 +957,9 @@ getHoldEventSubscription h = do
938957
939958type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x])
940959
941−--type role BehaviorM representational
942960-- BehaviorM can sample behaviors
943−newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderT (BehaviorEnv x) IO a } deriving (Functor, Applicative, MonadIO, MonadFix)
961+newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderIO (BehaviorEnv x) a }
962+ deriving (Functor, Applicative, MonadIO, MonadFix, MonadReader (BehaviorEnv x))
944963
945964instance Monad (BehaviorM x) where
946965 {-# INLINE (>>=) #-}
@@ -1154,11 +1173,11 @@ data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p)
11541173
11551174newtype Dyn (x :: Type) p = Dyn { unDyn :: IORef (DynType x p) }
11561175
1157−newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)
1176+newMapDyn :: HasSpiderTimeline x => (a -> b) -> DynamicS x (Identity a) -> DynamicS x (Identity b)
11581177newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
11591178
11601179--TODO: Avoid the duplication between this and R.zipDynWith
1161−zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c)
1180+zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> DynamicS x (Identity a) -> DynamicS x (Identity b) -> DynamicS x (Identity c)
11621181zipDynWith f da db =
11631182 let eab = align (dynamicUpdated da) (dynamicUpdated db)
11641183 ec = flip push eab $ \o -> do
@@ -1234,7 +1253,7 @@ run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> Res
12341253run roots after = do
12351254 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
12361255 let t = spiderTimeline :: SpiderTimelineEnv x
1237− result <- SpiderHost $ withMVar (_spiderTimeline_lock t) $ \_ -> unSpiderHost $ runFrame $ do
1256+ result <- SpiderHost $ withMVar (_spiderTimeline_lock (unSTE t)) $ \_ -> unSpiderHost $ runFrame $ do
12381257 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
12391258 occBefore <- liftIO $ do
12401259 occBefore <- readIORef occRef
@@ -1298,9 +1317,9 @@ type WeakList a = [Weak a]
12981317withIncreasedDepth :: CanTrace x m => m a -> m a
12991318withIncreasedDepth a = do
13001319 spiderTimeline <- askSpiderTimelineEnv
1301− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) succ
1320+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) succ
13021321 result <- a
1303− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) pred
1322+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) pred
13041323 return result
13051324#else
13061325withIncreasedDepth :: m a -> m a
@@ -1327,7 +1346,7 @@ traceMWhen _ b getMessage = when b $ do
13271346 message <- getMessage
13281347#ifdef DEBUG
13291348 spiderTimeline <- askSpiderTimelineEnv
1330− d <- liftIO $ readIORef $ _spiderTimeline_depth spiderTimeline
1349+ d <- liftIO $ readIORef $ _spiderTimeline_depth $ unSTE spiderTimeline
13311350#else
13321351 let d = 0
13331352#endif
@@ -1368,25 +1387,25 @@ propagateSubscriberHold h a = do
13681387data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset
13691388
13701389runBehaviorM :: BehaviorM x a -> Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]) -> IORef [SomeHoldInit x] -> IO a
1371−runBehaviorM a mwi holdInits = runReaderT (unBehaviorM a) (mwi, holdInits)
1390+runBehaviorM a mwi holdInits = runReaderIO (unBehaviorM a) (mwi, holdInits)
13721391
13731392askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x)))
13741393askInvalidator = do
1375− (!m, _) <- BehaviorM ask
1394+ (!m, _) <- ask
13761395 case m of
13771396 Nothing -> return Nothing
13781397 Just (!wi, _) -> return $ Just wi
13791398
13801399askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x]))
13811400askParentsRef = do
1382− (!m, _) <- BehaviorM ask
1401+ (!m, _) <- ask
13831402 case m of
13841403 Nothing -> return Nothing
13851404 Just (_, !p) -> return $ Just p
13861405
13871406askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x])
13881407askBehaviorHoldInits = do
1389− (_, !his) <- BehaviorM ask
1408+ (_, !his) <- ask
13901409 return his
13911410
13921411{-# INLINE getDynHold #-}
@@ -1710,20 +1729,20 @@ subscribeCoincidenceSubscribed subscribed sub = WeakBag.insert sub (coincidenceS
17101729{-# INLINE mergeG #-}
17111730mergeG :: forall k q x v. (HasSpiderTimeline x, GCompare k)
17121731 => (forall a. q a -> Event x (v a))
1713− -> Dynamic x (PatchDMap k q) -> Event x (DMap k v)
1732+ -> DynamicS x (PatchDMap k q) -> Event x (DMap k v)
17141733mergeG nt d = cacheEvent (mergeCheap nt d)
17151734
17161735{-# INLINE mergeWithMove #-}
17171736mergeWithMove :: forall k v q x. (HasSpiderTimeline x, GCompare k)
17181737 => (forall a. q a -> Event x (v a))
1719− -> Dynamic x (PatchDMapWithMove k q) -> Event x (DMap k v)
1738+ -> DynamicS x (PatchDMapWithMove k q) -> Event x (DMap k v)
17201739mergeWithMove nt d = cacheEvent (mergeCheapWithMove nt d)
17211740
17221741{-# INLINE [1] mergeCheap #-}
17231742mergeCheap
17241743 :: forall k x q v. (HasSpiderTimeline x, GCompare k)
17251744 => (forall a. q a -> Event x (v a))
1726− -> Dynamic x (PatchDMap k q)
1745+ -> DynamicS x (PatchDMap k q)
17271746 -> Event x (DMap k v)
17281747mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
17291748 where
@@ -1763,7 +1782,7 @@ mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
17631782{-# INLINE [1] mergeCheapWithMove #-}
17641783mergeCheapWithMove :: forall k x v q. (HasSpiderTimeline x, GCompare k)
17651784 => (forall a. q a -> Event x (v a))
1766− -> Dynamic x (PatchDMapWithMove k q)
1785+ -> DynamicS x (PatchDMapWithMove k q)
17671786 -> Event x (DMap k v)
17681787mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy
17691788 where
@@ -1911,7 +1930,7 @@ updateMerge m updateFunc p = SomeMergeUpdate updateMe (invalidateMergeHeight m)
19111930
19121931{-# INLINE mergeGCheap' #-}
19131932mergeGCheap' :: forall k v x p s q. (HasSpiderTimeline x, GCompare k, PatchTarget p ~ DMap k q)
1914− => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> Dynamic x p -> Event x (DMap k v)
1933+ => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> DynamicS x p -> Event x (DMap k v)
19151934mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
19161935 initialParents <- readBehaviorUntracked $ dynamicCurrent d
19171936 accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
@@ -1960,11 +1979,11 @@ mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
19601979 , occ
19611980 )
19621981
1963−mergeInt :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1982+mergeInt :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
19641983mergeInt = cacheEvent . mergeIntCheap
19651984
19661985{-# INLINABLE mergeIntCheap #-}
1967−mergeIntCheap :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1986+mergeIntCheap :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
19681987mergeIntCheap d = Event $ \sub -> do
19691988 initialParents <- readBehaviorUntracked $ dynamicCurrent d
19701989 accum <- liftIO $ FastMutableIntMap.newEmpty
@@ -2124,7 +2143,7 @@ clearEventEnv (EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeI
21242143-- | Run an event action outside of a frame
21252144runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
21262145runFrame a = SpiderHost $ do
2127− let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
2146+ let env = _spiderTimeline_eventEnv $ unSTE (spiderTimeline :: SpiderTimelineEnv x)
21282147 let go = do
21292148 result <- a
21302149 runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events
@@ -2335,7 +2354,7 @@ instance HasSpiderTimeline x => Monad (Reflex.Class.Dynamic (SpiderTimeline x))
23352354 fail _ = error "Dynamic does not support 'fail'"
23362355
23372356{-# INLINABLE newJoinDyn #-}
2338−newJoinDyn :: HasSpiderTimeline x => Reflex.Spider.Internal.Dynamic x (Identity (Reflex.Spider.Internal.Dynamic x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
2357+newJoinDyn :: HasSpiderTimeline x => DynamicS x (Identity (DynamicS x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
23392358newJoinDyn d =
23402359 let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d)
23412360 eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d
@@ -2485,7 +2504,7 @@ unsafeNewSpiderTimelineEnv = do
24852504#ifdef DEBUG
24862505 depthRef <- newIORef 0
24872506#endif
2488− return $ SpiderTimelineEnv
2507+ return $ STE $ SpiderTimelineEnv
24892508 { _spiderTimeline_lock = lock
24902509 , _spiderTimeline_eventEnv = env
24912510#ifdef DEBUG
@@ -2501,13 +2520,13 @@ data LocalSpiderTimeline (x :: Type) s
25012520
25022521instance Reifies s (SpiderTimelineEnv x) =>
25032522 HasSpiderTimeline (LocalSpiderTimeline x s) where
2504− spiderTimeline = localSpiderTimeline (Proxy :: Proxy s) $ reflect (Proxy :: Proxy s)
2523+ spiderTimeline = localSpiderTimeline Proxy $ reflect (Proxy :: Proxy s)
25052524
25062525localSpiderTimeline
2507− :: Proxy s
2526+ :: proxy s
25082527 -> SpiderTimelineEnv x
25092528 -> SpiderTimelineEnv (LocalSpiderTimeline x s)
2510−localSpiderTimeline _ = unsafeCoerce
2529+localSpiderTimeline _ = coerce
25112530
25122531-- | Pass a new timeline to the given function.
25132532withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r
@@ -2525,8 +2544,8 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
25252544 {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-}
25262545 newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
25272546 newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }
2528− newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: Dynamic x (Identity a) } -- deriving (Functor, Applicative, Monad)
2529− newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: Dynamic x p }
2547+ newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: DynamicS x (Identity a) } -- deriving (Functor, Applicative, Monad)
2548+ newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: DynamicS x p }
25302549 type PullM (SpiderTimeline x) = SpiderPullM x
25312550 type PushM (SpiderTimeline x) = SpiderPushM x
25322551 {-# INLINABLE never #-}
@@ -2555,7 +2574,7 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
25552574 {-# INLINABLE current #-}
25562575 current = SpiderBehavior . dynamicCurrent . unSpiderDynamic
25572576 {-# INLINABLE updated #-}
2558− updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic
2577+ updated = SpiderEvent #. dynamicUpdated .# fmap coerce . unSpiderDynamic
25592578 {-# INLINABLE unsafeBuildDynamic #-}
25602579 unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
25612580 {-# INLINABLE unsafeBuildIncremental #-}
@@ -2574,9 +2593,10 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
25742593 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
25752594 eventCoercion Coercion = Coercion
25762595 behaviorCoercion Coercion = Coercion
2577− dynamicCoercion = unsafeCoerce --TODO: How can we avoid this unsafeCoerce? This is safe only because we know how Identity works as a Patch instance
2596+ dynamicCoercion Coercion = Coercion
2597+ incrementalCoercion Coercion Coercion = Coercion
25782598 {-# INLINABLE mergeIntIncremental #-}
2579− mergeIntIncremental = SpiderEvent . mergeInt . (unsafeCoerce :: Dynamic x (PatchIntMap (R.Event (SpiderTimeline x) a)) -> Dynamic x (PatchIntMap (Event x a))) . unSpiderIncremental
2599+ mergeIntIncremental = SpiderEvent . mergeInt . coerce
25802600 {-# INLINABLE fanInt #-}
25812601 fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e))
25822602