diff --git a/reflex.cabal b/reflex.cabal index 0a9f7a9b..bf439f2e 100644 --- a/reflex.cabal +++ b/reflex.cabal @@ -85,7 +85,6 @@ library monoidal-containers == 0.4.0.0 exposed-modules: - Control.Monad.ReaderIO Data.AppendMap, Data.FastMutableIntMap, Data.FastWeakBag, diff --git a/src/Control/Monad/ReaderIO.hs b/src/Control/Monad/ReaderIO.hs deleted file mode 100644 index fb5f60c7..00000000 --- a/src/Control/Monad/ReaderIO.hs +++ /dev/null @@ -1,60 +0,0 @@ -{-# language RoleAnnotations #-} -{-# language MultiParamTypeClasses #-} -{-# language FlexibleInstances #-} -{-# language CPP #-} -module Control.Monad.ReaderIO - ( - ReaderIO (..) - ) - where - -import Control.Monad.Fix -#if MIN_VERSION_base(4,10,0) -import Control.Applicative -#endif -import Control.Monad -import Control.Monad.Reader.Class -import Control.Monad.IO.Class - --- | An approximate clone of @RIO@ from the @rio@ package, but not based on --- @ReaderT@. The trouble with @ReaderT@ is that its third type argument has a --- @nominal@ role, so we can't coerce through it when it's wrapped in some --- other @data@ type. Ugh. -newtype ReaderIO e a = ReaderIO { runReaderIO :: e -> IO a } -type role ReaderIO representational representational - -instance Functor (ReaderIO e) where - fmap = liftM - {-# INLINE fmap #-} - a <$ m = m >> pure a - {-# INLINE (<$) #-} - -instance Applicative (ReaderIO e) where - pure a = ReaderIO $ \_ -> pure a - {-# INLINE pure #-} - (<*>) = ap - {-# INLINE (<*>) #-} -#if MIN_VERSION_base(4,10,0) - liftA2 = liftM2 - {-# INLINE liftA2 #-} -#endif - (*>) = (>>) - {-# INLINE (*>) #-} - -instance Monad (ReaderIO e) where - ReaderIO q >>= f = ReaderIO $ \e -> q e >>= \a -> runReaderIO (f a) e - {-# INLINE (>>=) #-} - -instance MonadFix (ReaderIO e) where - mfix f = ReaderIO $ \e -> mfix $ \r -> runReaderIO (f r) e - {-# INLINE mfix #-} - -instance MonadIO (ReaderIO e) where - liftIO m = ReaderIO $ \_ -> m - {-# INLINE liftIO #-} - -instance MonadReader e (ReaderIO e) where - ask = ReaderIO pure - {-# INLINE ask #-} - local f (ReaderIO m) = ReaderIO (m . f) - {-# INLINE local #-} diff --git a/src/Reflex/Class.hs b/src/Reflex/Class.hs index 6dd3100b..cd20f7aa 100644 --- a/src/Reflex/Class.hs +++ b/src/Reflex/Class.hs @@ -36,7 +36,6 @@ module Reflex.Class , coerceBehavior , coerceEvent , coerceDynamic - , coerceIncremental , MonadSample (..) , MonadHold (..) -- ** 'fan' related types @@ -317,10 +316,6 @@ class ( MonadHold t (PushM t) -- | Construct a 'Coercion' for a 'Dynamic' given an 'Coercion' for its -- occurrence type dynamicCoercion :: Coercion a b -> Coercion (Dynamic t a) (Dynamic t b) - -- | Construct a 'Coercion' for an 'Incremental' given 'Coercion's for its - -- patch target and patch types. - incrementalCoercion - :: Coercion (PatchTarget a) (PatchTarget b) -> Coercion a b -> Coercion (Incremental t a) (Incremental t b) mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a) fanInt :: Event t (IntMap a) -> EventSelectorInt t a @@ -342,12 +337,6 @@ coerceEvent = coerceWith $ eventCoercion Coercion coerceDynamic :: (Reflex t, Coercible a b) => Dynamic t a -> Dynamic t b coerceDynamic = coerceWith $ dynamicCoercion Coercion --- | Coerce an 'Incremental' between representationally-equivalent value types -coerceIncremental - :: (Reflex t, Coercible a b, Coercible (PatchTarget a) (PatchTarget b)) - => Incremental t a -> Incremental t b -coerceIncremental = coerceWith $ incrementalCoercion Coercion Coercion - -- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'. The 'Behavior' -- __must__ change when and only when the 'Event' fires, such that the -- 'Behavior''s value is always equal to the most recent firing of the 'Event'; diff --git a/src/Reflex/Profiled.hs b/src/Reflex/Profiled.hs index 7aafd867..72e973ba 100644 --- a/src/Reflex/Profiled.hs +++ b/src/Reflex/Profiled.hs @@ -9,7 +9,6 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE PolyKinds #-} -{-# LANGUAGE TypeApplications #-} {-# LANGUAGE RankNTypes #-} -- | -- Module: @@ -152,16 +151,13 @@ instance Reflex t => Reflex (ProfiledTimeline t) where currentIncremental (Incremental_Profiled i) = coerce $ currentIncremental i updatedIncremental (Incremental_Profiled i) = coerce $ profileEvent $ updatedIncremental i incrementalToDynamic (Incremental_Profiled i) = coerce $ incrementalToDynamic i - behaviorCoercion c = - Coercion `trans` behaviorCoercion @t c `trans` Coercion - eventCoercion c = - Coercion `trans` eventCoercion @t c `trans` Coercion - dynamicCoercion c = - Coercion `trans` dynamicCoercion @t c `trans` Coercion - incrementalCoercion c d = - Coercion `trans` incrementalCoercion @t c d `trans` Coercion - mergeIntIncremental = Event_Profiled . mergeIntIncremental . - coerceWith (Coercion `trans` incrementalCoercion Coercion Coercion `trans` Coercion) + behaviorCoercion (c :: Coercion a b) = case behaviorCoercion c :: Coercion (Behavior t a) (Behavior t b) of + Coercion -> unsafeCoerce (Coercion :: Coercion (Behavior (ProfiledTimeline t) a) (Behavior (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce + eventCoercion (c :: Coercion a b) = case eventCoercion c :: Coercion (Event t a) (Event t b) of + Coercion -> unsafeCoerce (Coercion :: Coercion (Event (ProfiledTimeline t) a) (Event (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce + dynamicCoercion (c :: Coercion a b) = case dynamicCoercion c :: Coercion (Dynamic t a) (Dynamic t b) of + Coercion -> unsafeCoerce (Coercion :: Coercion (Dynamic (ProfiledTimeline t) a) (Dynamic (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce + mergeIntIncremental = Event_Profiled . mergeIntIncremental . (unsafeCoerce :: Incremental (ProfiledTimeline t) (PatchIntMap (Event (ProfiledTimeline t) a)) -> Incremental t (PatchIntMap (Event t a))) fanInt (Event_Profiled e) = coerce $ fanInt $ profileEvent e deriving instance Functor (Dynamic t) => Functor (Dynamic (ProfiledTimeline t)) diff --git a/src/Reflex/Pure.hs b/src/Reflex/Pure.hs index 1d12aed9..ea2cbf99 100644 --- a/src/Reflex/Pure.hs +++ b/src/Reflex/Pure.hs @@ -128,7 +128,6 @@ instance (Enum t, HasTrie t, Ord t) => Reflex (Pure t) where behaviorCoercion Coercion = Coercion eventCoercion Coercion = Coercion dynamicCoercion Coercion = Coercion - incrementalCoercion Coercion Coercion = Coercion fanInt e = EventSelectorInt $ \k -> Event $ \t -> unEvent e t >>= IntMap.lookup k diff --git a/src/Reflex/Spider/Internal.hs b/src/Reflex/Spider/Internal.hs index f7267ea8..0e0ada95 100644 --- a/src/Reflex/Spider/Internal.hs +++ b/src/Reflex/Spider/Internal.hs @@ -17,8 +17,6 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE PolyKinds #-} -{-# LANGUAGE DeriveFunctor #-} -{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE InstanceSigs #-} #ifdef USE_REFLEX_OPTIMIZER {-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-} @@ -37,10 +35,7 @@ import Control.Monad hiding (forM, forM_, mapM, mapM_) import Control.Monad.Exception import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_) import Control.Monad.Primitive ---import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_) -import Control.Monad.Reader.Class -import Control.Monad.IO.Class -import Control.Monad.ReaderIO +import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_) import Control.Monad.Ref import Data.Align import Data.Coerce @@ -562,11 +557,6 @@ propagateFast a subscribers = withIncreasedDepth $ do toAny :: a -> Any toAny = unsafeCoerce --- Why do we use Any here, instead of just giving eventSubscribedRetained an --- existential type? Sadly, GHC does not currently know how to unbox types --- with existentially quantified fields. So instead we just coerce values --- to type Any on the way in. Since we never coerce them back, this is --- perfectly safe. data EventSubscribed x = EventSubscribed { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height) , eventSubscribedRetained :: {-# NOUNPACK #-} !Any @@ -690,7 +680,7 @@ behaviorPull !p = Behavior $ do wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull" parentsRef <- liftIO $ newIORef [] holdInits <- askBehaviorHoldInits - a <- liftIO $ runReaderIO (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits) + a <- liftIO $ runReaderT (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits) invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator parents <- liftIO $ readIORef parentsRef let subscribed = PullSubscribed @@ -725,46 +715,42 @@ readBehaviorUntracked b = do -- Dynamic -------------------------------------------------------------------------------- -type DynamicS x p = Dynamic x (PatchTarget p) p - -data Dynamic x target p = Dynamic - { dynamicCurrent :: !(Behavior x target) +data Dynamic x p = Dynamic + { dynamicCurrent :: !(Behavior x (PatchTarget p)) , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`? } -deriving instance (HasSpiderTimeline x) => Functor (Dynamic x target) - - - - -dynamicHold :: Hold x p -> DynamicS x p +dynamicHold :: Hold x p -> Dynamic x p dynamicHold !h = Dynamic { dynamicCurrent = behaviorHold h , dynamicUpdated = eventHold h } -dynamicHoldIdentity :: Hold x (Identity a) -> DynamicS x (Identity a) +dynamicHoldIdentity :: Hold x (Identity a) -> Dynamic x (Identity a) dynamicHoldIdentity = dynamicHold -dynamicConst :: PatchTarget p -> DynamicS x p +dynamicConst :: PatchTarget p -> Dynamic x p dynamicConst !a = Dynamic { dynamicCurrent = behaviorConst a , dynamicUpdated = eventNever } -dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> DynamicS x p +dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> Dynamic x p dynamicDyn !d = Dynamic { dynamicCurrent = behaviorDyn d , dynamicUpdated = eventDyn d } -dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> DynamicS x (Identity a) +dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> Dynamic x (Identity a) dynamicDynIdentity = dynamicDyn -------------------------------------------------------------------------------- -- Combinators -------------------------------------------------------------------------------- +--TODO: Figure out why certain things are not 'representational', then make them +--representational so we can use coerce + --type role Hold representational data Hold x p = Hold { holdValue :: !(IORef (PatchTarget p)) @@ -785,25 +771,20 @@ globalSpiderTimelineEnv = unsafePerformIO unsafeNewSpiderTimelineEnv -- | Stores all global data relevant to a particular Spider timeline; only one -- value should exist for each type @x@ -newtype SpiderTimelineEnv x = STE {unSTE :: SpiderTimelineEnv' x} --- We implement SpiderTimelineEnv with a newtype wrapper so --- we can get the coercions we want safely. -type role SpiderTimelineEnv nominal - -data SpiderTimelineEnv' x = SpiderTimelineEnv +data SpiderTimelineEnv x = SpiderTimelineEnv { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ()) , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x) #ifdef DEBUG , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int) #endif } -type role SpiderTimelineEnv' phantom +type role SpiderTimelineEnv nominal instance Eq (SpiderTimelineEnv x) where _ == _ = True -- Since only one exists of each type instance GEq SpiderTimelineEnv where - a `geq` b = if _spiderTimeline_lock (unSTE a) == _spiderTimeline_lock (unSTE b) + a `geq` b = if _spiderTimeline_lock a == _spiderTimeline_lock b then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments else Nothing @@ -826,7 +807,7 @@ runEventM :: EventM x a -> IO a runEventM = unEventM asksEventEnv :: forall x a. HasSpiderTimeline x => (EventEnv x -> a) -> EventM x a -asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (unSTE (spiderTimeline :: SpiderTimelineEnv x)) +asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x) class MonadIO m => Defer a m where getDeferralQueue :: m (IORef [a]) @@ -964,9 +945,9 @@ getHoldEventSubscription h = do type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x]) +--type role BehaviorM representational -- BehaviorM can sample behaviors -newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderIO (BehaviorEnv x) a } - deriving (Functor, Applicative, MonadIO, MonadFix, MonadReader (BehaviorEnv x)) +newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderT (BehaviorEnv x) IO a } deriving (Functor, Applicative, MonadIO, MonadFix) instance Monad (BehaviorM x) where {-# INLINE (>>=) #-} @@ -1183,11 +1164,11 @@ data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p) newtype Dyn (x :: Type) p = Dyn { unDyn :: IORef (DynType x p) } -newMapDyn :: HasSpiderTimeline x => (a -> b) -> DynamicS x (Identity a) -> DynamicS x (Identity b) +newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b) newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d) --TODO: Avoid the duplication between this and R.zipDynWith -zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> DynamicS x (Identity a) -> DynamicS x (Identity b) -> DynamicS x (Identity c) +zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c) zipDynWith f da db = let eab = align (dynamicUpdated da) (dynamicUpdated db) ec = flip push eab $ \o -> do @@ -1260,7 +1241,7 @@ run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> Res run roots after = do tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events" let t = spiderTimeline :: SpiderTimelineEnv x - result <- SpiderHost $ withMVar (_spiderTimeline_lock (unSTE t)) $ \_ -> unSpiderHost $ runFrame $ do + result <- SpiderHost $ withMVar (_spiderTimeline_lock t) $ \_ -> unSpiderHost $ runFrame $ do rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do occBefore <- liftIO $ do occBefore <- readIORef occRef @@ -1324,9 +1305,9 @@ type WeakList a = [Weak a] withIncreasedDepth :: CanTrace x m => m a -> m a withIncreasedDepth a = do spiderTimeline <- askSpiderTimelineEnv - liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) succ + liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) succ result <- a - liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) pred + liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) pred return result #else withIncreasedDepth :: m a -> m a @@ -1353,7 +1334,7 @@ traceMWhen _ b getMessage = when b $ do message <- getMessage #ifdef DEBUG spiderTimeline <- askSpiderTimelineEnv - d <- liftIO $ readIORef $ _spiderTimeline_depth $ unSTE spiderTimeline + d <- liftIO $ readIORef $ _spiderTimeline_depth spiderTimeline #else let d = 0 #endif @@ -1394,25 +1375,25 @@ propagateSubscriberHold h a = do data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset runBehaviorM :: BehaviorM x a -> Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]) -> IORef [SomeHoldInit x] -> IO a -runBehaviorM a mwi holdInits = runReaderIO (unBehaviorM a) (mwi, holdInits) +runBehaviorM a mwi holdInits = runReaderT (unBehaviorM a) (mwi, holdInits) askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x))) askInvalidator = do - (!m, _) <- ask + (!m, _) <- BehaviorM ask case m of Nothing -> return Nothing Just (!wi, _) -> return $ Just wi askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x])) askParentsRef = do - (!m, _) <- ask + (!m, _) <- BehaviorM ask case m of Nothing -> return Nothing Just (_, !p) -> return $ Just p askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x]) askBehaviorHoldInits = do - (_, !his) <- ask + (_, !his) <- BehaviorM ask return his {-# INLINE getDynHold #-} @@ -1730,20 +1711,20 @@ subscribeCoincidenceSubscribed subscribed sub = WeakBag.insert sub (coincidenceS {-# INLINE mergeG #-} mergeG :: forall k q x v. (HasSpiderTimeline x, GCompare k) => (forall a. q a -> Event x (v a)) - -> DynamicS x (PatchDMap k q) -> Event x (DMap k v) + -> Dynamic x (PatchDMap k q) -> Event x (DMap k v) mergeG nt d = cacheEvent (mergeCheap nt d) {-# INLINE mergeWithMove #-} mergeWithMove :: forall k v q x. (HasSpiderTimeline x, GCompare k) => (forall a. q a -> Event x (v a)) - -> DynamicS x (PatchDMapWithMove k q) -> Event x (DMap k v) + -> Dynamic x (PatchDMapWithMove k q) -> Event x (DMap k v) mergeWithMove nt d = cacheEvent (mergeCheapWithMove nt d) {-# INLINE [1] mergeCheap #-} mergeCheap :: forall k x q v. (HasSpiderTimeline x, GCompare k) => (forall a. q a -> Event x (v a)) - -> DynamicS x (PatchDMap k q) + -> Dynamic x (PatchDMap k q) -> Event x (DMap k v) mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy where @@ -1783,7 +1764,7 @@ mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy {-# INLINE [1] mergeCheapWithMove #-} mergeCheapWithMove :: forall k x v q. (HasSpiderTimeline x, GCompare k) => (forall a. q a -> Event x (v a)) - -> DynamicS x (PatchDMapWithMove k q) + -> Dynamic x (PatchDMapWithMove k q) -> Event x (DMap k v) mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy where @@ -1931,7 +1912,7 @@ updateMerge m updateFunc p = SomeMergeUpdate updateMe (invalidateMergeHeight m) {-# INLINE mergeGCheap' #-} mergeGCheap' :: forall k v x p s q. (HasSpiderTimeline x, GCompare k, PatchTarget p ~ DMap k q) - => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> DynamicS x p -> Event x (DMap k v) + => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> Dynamic x p -> Event x (DMap k v) mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do initialParents <- readBehaviorUntracked $ dynamicCurrent d accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized" @@ -1980,11 +1961,11 @@ mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do , occ ) -mergeInt :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a) +mergeInt :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a) mergeInt = cacheEvent . mergeIntCheap {-# INLINABLE mergeIntCheap #-} -mergeIntCheap :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a) +mergeIntCheap :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a) mergeIntCheap d = Event $ \sub -> do initialParents <- readBehaviorUntracked $ dynamicCurrent d accum <- liftIO $ FastMutableIntMap.newEmpty @@ -2142,7 +2123,7 @@ clearEventEnv (EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeI -- | Run an event action outside of a frame runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex runFrame a = SpiderHost $ do - let env = _spiderTimeline_eventEnv $ unSTE (spiderTimeline :: SpiderTimelineEnv x) + let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x) let go = do result <- a 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 @@ -2353,7 +2334,7 @@ instance HasSpiderTimeline x => Monad (Reflex.Class.Dynamic (SpiderTimeline x)) fail _ = error "Dynamic does not support 'fail'" {-# INLINABLE newJoinDyn #-} -newJoinDyn :: HasSpiderTimeline x => DynamicS x (Identity (DynamicS x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a) +newJoinDyn :: HasSpiderTimeline x => Reflex.Spider.Internal.Dynamic x (Identity (Reflex.Spider.Internal.Dynamic x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a) newJoinDyn d = let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d) eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d @@ -2503,7 +2484,7 @@ unsafeNewSpiderTimelineEnv = do #ifdef DEBUG depthRef <- newIORef 0 #endif - return $ STE $ SpiderTimelineEnv + return $ SpiderTimelineEnv { _spiderTimeline_lock = lock , _spiderTimeline_eventEnv = env #ifdef DEBUG @@ -2519,13 +2500,13 @@ data LocalSpiderTimeline (x :: Type) s instance Reifies s (SpiderTimelineEnv x) => HasSpiderTimeline (LocalSpiderTimeline x s) where - spiderTimeline = localSpiderTimeline Proxy $ reflect (Proxy :: Proxy s) + spiderTimeline = localSpiderTimeline (Proxy :: Proxy s) $ reflect (Proxy :: Proxy s) localSpiderTimeline - :: proxy s + :: Proxy s -> SpiderTimelineEnv x -> SpiderTimelineEnv (LocalSpiderTimeline x s) -localSpiderTimeline _ = coerce +localSpiderTimeline _ = unsafeCoerce -- | Pass a new timeline to the given function. withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r @@ -2543,8 +2524,8 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-} newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a } newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a } - newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: DynamicS x (Identity a) } -- deriving (Functor, Applicative, Monad) - newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: DynamicS x p } + newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: Dynamic x (Identity a) } -- deriving (Functor, Applicative, Monad) + newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: Dynamic x p } type PullM (SpiderTimeline x) = SpiderPullM x type PushM (SpiderTimeline x) = SpiderPushM x {-# INLINABLE never #-} @@ -2573,7 +2554,7 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where {-# INLINABLE current #-} current = SpiderBehavior . dynamicCurrent . unSpiderDynamic {-# INLINABLE updated #-} - updated = SpiderEvent #. dynamicUpdated .# fmap coerce . unSpiderDynamic + updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic {-# INLINABLE unsafeBuildDynamic #-} unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v' {-# INLINABLE unsafeBuildIncremental #-} @@ -2592,10 +2573,9 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply' eventCoercion Coercion = Coercion behaviorCoercion Coercion = Coercion - dynamicCoercion Coercion = Coercion - incrementalCoercion Coercion Coercion = Coercion + dynamicCoercion = unsafeCoerce --TODO: How can we avoid this unsafeCoerce? This is safe only because we know how Identity works as a Patch instance {-# INLINABLE mergeIntIncremental #-} - mergeIntIncremental = SpiderEvent . mergeInt . coerce + mergeIntIncremental = SpiderEvent . mergeInt . (unsafeCoerce :: Dynamic x (PatchIntMap (R.Event (SpiderTimeline x) a)) -> Dynamic x (PatchIntMap (Event x a))) . unSpiderIncremental {-# INLINABLE fanInt #-} fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e)) diff --git a/test/Reflex/Bench/Focused.hs b/test/Reflex/Bench/Focused.hs index cdfd5dd0..621ab5a5 100644 --- a/test/Reflex/Bench/Focused.hs +++ b/test/Reflex/Bench/Focused.hs @@ -130,16 +130,6 @@ mapDynChain = iterM (return . fmap (+1)) joinDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word) joinDynChain = iterM (\d -> return $ join $ fmap (const d) d) -holdDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word) -holdDynChain = iterM (\d -> sample (current d) >>= flip holdDyn (updated d)) - -buildDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word) -buildDynChain = iterM (\d -> do - let b = fmap (+1) (current d) - e = fmap (*2) (updated d) - buildDynamic (sample b) e) - - combineDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word) combineDynChain = iterM (\d -> return $ zipDynWith (+) d d) @@ -318,8 +308,6 @@ dynamics :: Word -> [(String, TestCase)] dynamics n = [ testE "mapDynChain" $ fmap updated $ mapDynChain n =<< d , testE "joinDynChain" $ fmap updated $ joinDynChain n =<< d - , testE "holdDynChain" $ fmap updated $ holdDynChain n =<< d - , testE "buildDynChain" $ fmap updated $ buildDynChain n =<< d , testE "combineDynChain" $ fmap updated $ combineDynChain n =<< d , testE "dense mergeTree" $ fmap (updated . mergeTreeDyn 8) dense , testE "sparse mergeTree" $ fmap (updated . mergeTreeDyn 8) sparse