@@ -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 qualified Data.List.NonEmpty as NonEmpty
35import Data.Maybe
36import Data.Maybe
36import Data.Semigroup
37import Data.Semigroup
37import qualified Data.Some as Some
38import qualified Data.Some as Some
@@ -64,6 +65,12 @@ instance (ReflexHost t, Ref m ~ Ref IO, PrimMonad (HostFrame t)) => PerformEvent
64 performEvent = PerformEventT . fmap (fmap runIdentity) . requesting
65 performEvent = PerformEventT . fmap (fmap runIdentity) . requesting
66instance (ReflexHost t, PrimMonad (HostFrame t)) => MonadAdjust t (PerformEventT t m) where
67instance (ReflexHost t, PrimMonad (HostFrame t)) => MonadAdjust t (PerformEventT t m) where
68+ runWithReplace outerA0 outerA' = PerformEventT $ runWithReplaceRequestTWith f (coerce outerA0) (coerceEvent outerA')
69+ where f :: HostFrame t a -> Event t (HostFrame t b) -> RequestT t (HostFrame t) Identity (HostFrame t) (a, Event t b)
72+ result' <- requesting a'
73+ return (result0, fmap runIdentity result')
67 sequenceDMapWithAdjust (outerDm0 :: DMap k (PerformEventT t m)) outerDm' = PerformEventT $ sequenceDMapWithAdjustRequestTWith f (coerce outerDm0) (coerceEvent outerDm')
74 sequenceDMapWithAdjust (outerDm0 :: DMap k (PerformEventT t m)) outerDm' = PerformEventT $ sequenceDMapWithAdjustRequestTWith f (coerce outerDm0) (coerceEvent outerDm')
68 where f :: DMap k' (HostFrame t) -> Event t (PatchDMap k' (HostFrame t)) -> RequestT t (HostFrame t) Identity (HostFrame t) (DMap k' Identity, Event t (PatchDMap k' Identity))
75 where f :: DMap k' (HostFrame t) -> Event t (PatchDMap k' (HostFrame t)) -> RequestT t (HostFrame t) Identity (HostFrame t) (DMap k' Identity, Event t (PatchDMap k' Identity))
69 f dm0 dm' = do
76 f dm0 dm' = do
@@ -185,9 +192,30 @@ instance MonadHold t m => MonadHold t (RequestT t request response m) where
185 holdIncremental v0 = lift . holdIncremental v0
192 holdIncremental v0 = lift . holdIncremental v0
187instance (Reflex t, MonadAdjust t m, MonadHold t m) => MonadAdjust t (RequestT t request response m) where
194instance (Reflex t, MonadAdjust t m, MonadHold t m) => MonadAdjust t (RequestT t request response m) where
195+ runWithReplace = runWithReplaceRequestTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
188 sequenceDMapWithAdjust = sequenceDMapWithAdjustRequestTWith $ \dm0 dm' -> lift $ sequenceDMapWithAdjust dm0 dm'
196 sequenceDMapWithAdjust = sequenceDMapWithAdjustRequestTWith $ \dm0 dm' -> lift $ sequenceDMapWithAdjust dm0 dm'
198+runWithReplaceRequestTWith :: forall m t request response a b. (Reflex t, MonadHold t m)
202+ -> RequestT t request response m (a', Event t b')
204+ -> RequestT t request response m a
205+ -> Event t (RequestT t request response m b)
206+ -> RequestT t request response m (a, Event t b)
207+runWithReplaceRequestTWith f a0 a' = do
208+ response <- RequestT ask
209+ let g :: RequestT t request response m c -> m (c, [Event t (DMap (Tag (PrimState m)) request)])
210+ g (RequestT r) = runReaderT (runStateT r mempty) response
211+ (result0, result') <- f (g a0) $ g <$> a'
212+ request <- holdDyn (fmap (mconcat . NonEmpty.toList) $ mergeList $ snd result0) $ fmap (mconcat . NonEmpty.toList) . mergeList . snd <$> result'
213+ -- We add these two separately to take advantage of the free merge being done later. The coincidence case must come first so that it has precedence if both fire simultaneously. (Really, we should probably block the 'switch' whenever 'updated' fires, but switchPromptlyDyn has the same issue.)
214+ RequestT $ modify $ (:) $ coincidence $ updated request
215+ RequestT $ modify $ (:) $ switch $ current request
216+ return (fst result0, fst <$> result')
190−sequenceDMapWithAdjustRequestTWith :: (GCompare k, Monad m, Reflex t, MonadHold t m)
218+sequenceDMapWithAdjustRequestTWith :: (GCompare k, Reflex t, MonadHold t m)
191 => (forall k'. GCompare k'
219 => (forall k'. GCompare k'
192 => DMap k' m
220 => DMap k' m
193 -> Event t (PatchDMap k' m)
221 -> Event t (PatchDMap k' m)
@@ -210,9 +238,10 @@ sequenceDMapWithAdjustRequestTWith f (dm0 :: DMap k (RequestT t request response
210 requests' = ffor children' $ \(PatchDMap p) -> PatchDMap $
238 requests' = ffor children' $ \(PatchDMap p) -> PatchDMap $
211 mapKeyValuePairsMonotonic (\(WrapArg k :=> ComposeMaybe mv) -> Const2 (Some.This k) :=> ComposeMaybe (fmap (mergeWith DMap.union . fst . runIdentity) mv)) p
239 mapKeyValuePairsMonotonic (\(WrapArg k :=> ComposeMaybe mv) -> Const2 (Some.This k) :=> ComposeMaybe (fmap (mergeWith DMap.union . fst . runIdentity) mv)) p
212 childRequestMap <- holdIncremental requests0 requests'
240 childRequestMap <- holdIncremental requests0 requests'
241+ -- We add these two separately to take advantage of the free merge being done later. The coincidence case must come first so that it has precedence if both fire simultaneously. (Really, we should probably block the 'switch' whenever 'updated' fires, but switchPromptlyDyn has the same issue.)
242+ RequestT $ modify $ (:) $ coincidence $ ffor requests' $ \(PatchDMap p) -> mergeWith DMap.union $ catMaybes $ ffor (DMap.toList p) $ \(Const2 _ :=> ComposeMaybe me) -> me
213 RequestT $ modify $ (:) $ ffor (mergeIncremental childRequestMap) $ \m ->
243 RequestT $ modify $ (:) $ ffor (mergeIncremental childRequestMap) $ \m ->
214 mconcat $ (\(Const2 _ :=> Identity reqs) -> reqs) <$> DMap.toList m
244 mconcat $ (\(Const2 _ :=> Identity reqs) -> reqs) <$> DMap.toList m
215− RequestT $ modify $ (:) $ coincidence $ ffor requests' $ \(PatchDMap p) -> mergeWith DMap.union $ catMaybes $ ffor (DMap.toList p) $ \(Const2 _ :=> ComposeMaybe me) -> me
216 return (result0, result')
245 return (result0, result')
218instance PerformEvent t m => PerformEvent t (RequestT t request response m) where
247instance PerformEvent t m => PerformEvent t (RequestT t request response m) where