on develop help sign in
Renames MonadAdjust and moves it to its own module.
71efa5fDave Laing
reflex.cabal+2
@@ -79,12 +79,14 @@ library
79
79
80 exposed-modules:
80 exposed-modules:
81 Data.AppendMap,
81 Data.AppendMap,
82+ Data.Map.Misc,
82 Data.Functor.Misc,
83 Data.Functor.Misc,
83 Data.WeakBag,
84 Data.WeakBag,
84 Data.FastWeakBag,
85 Data.FastWeakBag,
85 Data.FastMutableIntMap,
86 Data.FastMutableIntMap,
86 Reflex,
87 Reflex,
87 Reflex.Class,
88 Reflex.Class,
89+ Reflex.Collection,
88 Reflex.EventWriter,
90 Reflex.EventWriter,
89 Reflex.Dynamic,
91 Reflex.Dynamic,
90 Reflex.Dynamic.Uniq,
92 Reflex.Dynamic.Uniq,
src/Data/Map/Misc.hsnew file+55
@@ -0,0 +1,55 @@
1+{-# LANGUAGE LambdaCase #-}
2+module Data.Map.Misc
3+ (
4+ -- * Working with Maps
5+ diffMapNoEq
6+ , diffMap
7+ , applyMap
8+ , mapPartitionEithers
9+ , applyMapKeysSet
10+ ) where
11+
12+import Data.Align
13+import Data.Either
14+import Data.Map (Map)
15+import qualified Data.Map as Map
16+import Data.Maybe
17+import Data.Set (Set)
18+import qualified Data.Set as Set
19+import Data.These
20+
21+diffMapNoEq :: (Ord k) => Map k v -> Map k v -> Map k (Maybe v)
22+diffMapNoEq olds news = flip Map.mapMaybe (align olds news) $ \case
23+ This _ -> Just Nothing
24+ These _ new -> Just $ Just new
25+ That new -> Just $ Just new
26+
27+diffMap :: (Ord k, Eq v) => Map k v -> Map k v -> Map k (Maybe v)
28+diffMap olds news = flip Map.mapMaybe (align olds news) $ \case
29+ This _ -> Just Nothing
30+ These old new
31+ | old == new -> Nothing
32+ | otherwise -> Just $ Just new
33+ That new -> Just $ Just new
34+
35+applyMap :: Ord k => Map k (Maybe v) -> Map k v -> Map k v
36+applyMap patch old = insertions `Map.union` (old `Map.difference` deletions)
37+ where (deletions, insertions) = mapPartitionEithers $ maybeToEither <$> patch
38+ maybeToEither = \case
39+ Nothing -> Left ()
40+ Just r -> Right r
41+
42+mapPartitionEithers :: Map k (Either a b) -> (Map k a, Map k b)
43+mapPartitionEithers m = (fromLeft <$> ls, fromRight <$> rs)
44+ where (ls, rs) = Map.partition isLeft m
45+ fromLeft (Left l) = l
46+ fromLeft _ = error "mapPartitionEithers: fromLeft received a Right value; this should be impossible"
47+ fromRight (Right r) = r
48+ fromRight _ = error "mapPartitionEithers: fromRight received a Left value; this should be impossible"
49+
50+-- | Apply a map patch to a set
51+-- > applyMapKeysSet patch (Map.keysSet m) == Map.keysSet (applyMap patch m)
52+applyMapKeysSet :: Ord k => Map k (Maybe v) -> Set k -> Set k
53+applyMapKeysSet patch old = Map.keysSet insertions `Set.union` (old `Set.difference` Map.keysSet deletions)
54+ where (insertions, deletions) = Map.partition isJust patch
55+
src/Reflex.hs+1
@@ -6,6 +6,7 @@ module Reflex
6 ) where
6 ) where
7
7
8import Reflex.Class as X
8import Reflex.Class as X
9+import Reflex.Collection as X
9import Reflex.EventWriter as X
10import Reflex.EventWriter as X
10import Reflex.Dynamic as X
11import Reflex.Dynamic as X
11#ifdef USE_TEMPLATE_HASKELL
12#ifdef USE_TEMPLATE_HASKELL
src/Reflex/Adjustable/Class.hsnew file+166
@@ -0,0 +1,166 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE RankNTypes #-}
3+{-# LANGUAGE LambdaCase #-}
4+{-# LANGUAGE RecursiveDo #-}
5+{-# LANGUAGE ScopedTypeVariables #-}
6+{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE FunctionalDependencies #-}
8+{-# LANGUAGE FlexibleInstances #-}
9+{-# LANGUAGE TypeFamilies #-}
10+{-# LANGUAGE UndecidableInstances #-}
11+#ifdef USE_REFLEX_OPTIMIZER
12+{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
13+#endif
14+module Reflex.Adjustable.Class
15+ (
16+ -- * The Adjustable typeclass
17+ Adjustable(..)
18+ , sequenceDMapWithAdjust
19+ , sequenceDMapWithAdjustWithMove
20+ , mapMapWithAdjustWithMove
21+ -- * Widgets on Collections
22+ , listHoldWithKey
23+ , listWithKey
24+ , listWithKey'
25+ , listWithKeyShallowDiff
26+ , listViewWithKey
27+ , selectViewListWithKey
28+ , selectViewListWithKey_
29+ -- * List Utils
30+ , list
31+ , simpleList
32+ ) where
33+
34+import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
35+import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
36+import Data.Align
37+import Data.Map (Map)
38+import qualified Data.Map as Map
39+import Data.Dependent.Map (DMap, GCompare (..))
40+import Data.Functor.Constant
41+import Data.Functor.Misc
42+import Data.Map.Misc
43+import Data.These
44+
45+import Reflex.Class
46+import Reflex.Dynamic
47+import Reflex.PostBuild.Class
48+
49+-- | A 'Monad' that supports adjustment over time. After an action has been
50+-- run, if the given events fire, it will adjust itself so that its net effect
51+-- is as though it had originally been run with the new value. Note that there
52+-- is some issue here with persistent side-effects: obviously, IO (and some
53+-- other side-effects) cannot be undone, so it is up to the instance implementer
54+-- to determine what the best meaning for this class is in such cases.
55+class (Reflex t, Monad m) => Adjustable t m | m -> t where
56+ runWithReplace :: m a -> Event t (m b) -> m (a, Event t b)
57+ traverseIntMapWithKeyWithAdjust :: (IntMap.Key -> v -> m v') -> IntMap v -> Event t (PatchIntMap v) -> m (IntMap v', Event t (PatchIntMap v'))
58+ traverseDMapWithKeyWithAdjust :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMap k v) -> m (DMap k v', Event t (PatchDMap k v'))
59+ traverseDMapWithKeyWithAdjustWithMove :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMapWithMove k v) -> m (DMap k v', Event t (PatchDMapWithMove k v'))
60+
61+instance Adjustable t m => Adjustable t (ReaderT r m) where
62+ runWithReplace a0 a' = do
63+ r <- ask
64+ lift $ runWithReplace (runReaderT a0 r) $ fmap (`runReaderT` r) a'
65+ traverseIntMapWithKeyWithAdjust f dm0 dm' = do
66+ r <- ask
67+ lift $ traverseIntMapWithKeyWithAdjust (\k v -> runReaderT (f k v) r) dm0 dm'
68+ traverseDMapWithKeyWithAdjust f dm0 dm' = do
69+ r <- ask
70+ lift $ traverseDMapWithKeyWithAdjust (\k v -> runReaderT (f k v) r) dm0 dm'
71+ traverseDMapWithKeyWithAdjustWithMove f dm0 dm' = do
72+ r <- ask
73+ lift $ traverseDMapWithKeyWithAdjustWithMove (\k v -> runReaderT (f k v) r) dm0 dm'
74+
75+sequenceDMapWithAdjust :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMap k m) -> m (DMap k Identity, Event t (PatchDMap k Identity))
76+sequenceDMapWithAdjust = traverseDMapWithKeyWithAdjust $ \_ -> fmap Identity
77+
78+sequenceDMapWithAdjustWithMove :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMapWithMove k m) -> m (DMap k Identity, Event t (PatchDMapWithMove k Identity))
79+sequenceDMapWithAdjustWithMove = traverseDMapWithKeyWithAdjustWithMove $ \_ -> fmap Identity
80+
81+mapMapWithAdjustWithMove :: forall t m k v v'. (Adjustable t m, Ord k) => (k -> v -> m v') -> Map k v -> Event t (PatchMapWithMove k v) -> m (Map k v', Event t (PatchMapWithMove k v'))
82+mapMapWithAdjustWithMove f m0 m' = do
83+ (out0 :: DMap (Const2 k v) (Constant v'), out') <- traverseDMapWithKeyWithAdjustWithMove (\(Const2 k) (Identity v) -> Constant <$> f k v) (mapToDMap m0) (const2PatchDMapWithMoveWith Identity <$> m')
84+ return (dmapToMapWith (\(Constant v') -> v') out0, patchDMapWithMoveToPatchMapWithMoveWith (\(Constant v') -> v') <$> out')
85+
86+listHoldWithKey :: forall t m k v a. (Ord k, Adjustable t m, MonadHold t m) => Map k v -> Event t (Map k (Maybe v)) -> (k -> v -> m a) -> m (Dynamic t (Map k a))
87+listHoldWithKey m0 m' f = do
88+ let dm0 = mapWithFunctorToDMap $ Map.mapWithKey f m0
89+ dm' = fmap (PatchDMap . mapWithFunctorToDMap . Map.mapWithKey (\k v -> ComposeMaybe $ fmap (f k) v)) m'
90+ (a0, a') <- sequenceDMapWithAdjust dm0 dm'
91+ fmap dmapToMap . incrementalToDynamic <$> holdIncremental a0 a' --TODO: Move the dmapToMap to the righthand side so it doesn't get fully redone every time
92+
93+--TODO: Something better than Dynamic t (Map k v) - we want something where the Events carry diffs, not the whole value
94+listWithKey :: forall t k v m a. (Ord k, Adjustable t m, PostBuild t m, MonadFix m, MonadHold t m) => Dynamic t (Map k v) -> (k -> Dynamic t v -> m a) -> m (Dynamic t (Map k a))
95+listWithKey vals mkChild = do
96+ postBuild <- getPostBuild
97+ let childValChangedSelector = fanMap $ updated vals
98+ -- We keep track of changes to children values in the mkChild function we pass to listHoldWithKey
99+ -- The other changes we need to keep track of are child insertions and deletions. diffOnlyKeyChanges
100+ -- keeps track of insertions and deletions but ignores value changes, since they're already accounted for.
101+ diffOnlyKeyChanges olds news = flip Map.mapMaybe (align olds news) $ \case
102+ This _ -> Just Nothing
103+ These _ _ -> Nothing
104+ That new -> Just $ Just new
105+ rec sentVals :: Dynamic t (Map k v) <- foldDyn applyMap Map.empty changeVals
106+ let changeVals :: Event t (Map k (Maybe v))
107+ changeVals = attachWith diffOnlyKeyChanges (current sentVals) $ leftmost
108+ [ updated vals
109+ , tag (current vals) postBuild --TODO: This should probably be added to the attachWith, not to the updated; if we were using diffMap instead of diffMapNoEq, I think it might not work
110+ ]
111+ listHoldWithKey Map.empty changeVals $ \k v ->
112+ mkChild k =<< holdDyn v (select childValChangedSelector $ Const2 k)
113+
114+{-# DEPRECATED listWithKey' "listWithKey' has been renamed to listWithKeyShallowDiff; also, its behavior has changed to fix a bug where children were always rebuilt (never updated)" #-}
115+listWithKey' :: (Ord k, Adjustable t m, MonadFix m, MonadHold t m) => Map k v -> Event t (Map k (Maybe v)) -> (k -> v -> Event t v -> m a) -> m (Dynamic t (Map k a))
116+listWithKey' = listWithKeyShallowDiff
117+
118+-- | Display the given map of items (in key order) using the builder function provided, and update it with the given event. 'Nothing' update entries will delete the corresponding children, and 'Just' entries will create them if they do not exist or send an update event to them if they do.
119+listWithKeyShallowDiff :: (Ord k, Adjustable t m, MonadFix m, MonadHold t m) => Map k v -> Event t (Map k (Maybe v)) -> (k -> v -> Event t v -> m a) -> m (Dynamic t (Map k a))
120+listWithKeyShallowDiff initialVals valsChanged mkChild = do
121+ let childValChangedSelector = fanMap $ fmap (Map.mapMaybe id) valsChanged
122+ sentVals <- foldDyn applyMap Map.empty $ fmap (fmap void) valsChanged
123+ let relevantPatch patch _ = case patch of
124+ Nothing -> Just Nothing -- Even if we let a Nothing through when the element doesn't already exist, this doesn't cause a problem because it is ignored
125+ Just _ -> Nothing -- We don't want to let spurious re-creations of items through
126+ listHoldWithKey initialVals (attachWith (flip (Map.differenceWith relevantPatch)) (current sentVals) valsChanged) $ \k v ->
127+ mkChild k v $ select childValChangedSelector $ Const2 k
128+
129+--TODO: Something better than Dynamic t (Map k v) - we want something where the Events carry diffs, not the whole value
130+-- | Create a dynamically-changing set of Event-valued widgets.
131+-- This is like listWithKey, specialized for widgets returning (Event t a). listWithKey would return 'Dynamic t (Map k (Event t a))' in this scenario, but listViewWithKey flattens this to 'Event t (Map k a)' via 'switch'.
132+listViewWithKey :: (Ord k, Adjustable t m, PostBuild t m, MonadHold t m, MonadFix m) => Dynamic t (Map k v) -> (k -> Dynamic t v -> m (Event t a)) -> m (Event t (Map k a))
133+listViewWithKey vals mkChild = switch . fmap mergeMap <$> listViewWithKey' vals mkChild
134+
135+listViewWithKey' :: (Ord k, Adjustable t m, PostBuild t m, MonadHold t m, MonadFix m) => Dynamic t (Map k v) -> (k -> Dynamic t v -> m a) -> m (Behavior t (Map k a))
136+listViewWithKey' vals mkChild = current <$> listWithKey vals mkChild
137+
138+-- | Create a dynamically-changing set of widgets, one of which is selected at any time.
139+selectViewListWithKey :: forall t m k v a. (Adjustable t m, Ord k, PostBuild t m, MonadHold t m, MonadFix m)
140+ => Dynamic t k -- ^ Current selection key
141+ -> Dynamic t (Map k v) -- ^ Dynamic key/value map
142+ -> (k -> Dynamic t v -> Dynamic t Bool -> m (Event t a)) -- ^ Function to create a widget for a given key from Dynamic value and Dynamic Bool indicating if this widget is currently selected
143+ -> m (Event t (k, a)) -- ^ Event that fires when any child's return Event fires. Contains key of an arbitrary firing widget.
144+selectViewListWithKey selection vals mkChild = do
145+ let selectionDemux = demux selection -- For good performance, this value must be shared across all children
146+ selectChild <- listWithKey vals $ \k v -> do
147+ let selected = demuxed selectionDemux k
148+ selectSelf <- mkChild k v selected
149+ return $ fmap ((,) k) selectSelf
150+ return $ switchPromptlyDyn $ leftmost . Map.elems <$> selectChild
151+
152+selectViewListWithKey_ :: forall t m k v a. (Adjustable t m, Ord k, PostBuild t m, MonadHold t m, MonadFix m)
153+ => Dynamic t k -- ^ Current selection key
154+ -> Dynamic t (Map k v) -- ^ Dynamic key/value map
155+ -> (k -> Dynamic t v -> Dynamic t Bool -> m (Event t a)) -- ^ Function to create a widget for a given key from Dynamic value and Dynamic Bool indicating if this widget is currently selected
156+ -> m (Event t k) -- ^ Event that fires when any child's return Event fires. Contains key of an arbitrary firing widget.
157+selectViewListWithKey_ selection vals mkChild = fmap fst <$> selectViewListWithKey selection vals mkChild
158+
159+-- | Create a dynamically-changing set of widgets from a Dynamic key/value map.
160+-- Unlike the 'withKey' variants, the child widgets are insensitive to which key they're associated with.
161+list :: (Ord k, Adjustable t m, MonadHold t m, PostBuild t m, MonadFix m) => Dynamic t (Map k v) -> (Dynamic t v -> m a) -> m (Dynamic t (Map k a))
162+list dm mkChild = listWithKey dm (\_ dv -> mkChild dv)
163+
164+-- | Create a dynamically-changing set of widgets from a Dynamic list.
165+simpleList :: (Adjustable t m, MonadHold t m, PostBuild t m, MonadFix m) => Dynamic t [v] -> (Dynamic t v -> m a) -> m (Dynamic t [a])
166+simpleList xs mkChild = fmap (fmap (map snd . Map.toList)) $ flip list mkChild $ fmap (Map.fromList . zip [(1::Int)..]) xs
src/Reflex/Class.hs+18−8
@@ -1,3 +1,4 @@
1+{-# LANGUAGE ConstraintKinds #-}
1{-# LANGUAGE CPP #-}
2{-# LANGUAGE CPP #-}
2{-# LANGUAGE DefaultSignatures #-}
3{-# LANGUAGE DefaultSignatures #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleContexts #-}
@@ -120,13 +121,15 @@ module Reflex.Class
120 , ffilter
121 , ffilter
121 , filterLeft
122 , filterLeft
122 , filterRight
123 , filterRight
123− -- * Miscellaneous convenience functions
124+ -- * 'Adjustable'
124− , ffor
125+ , Adjustable(..)
125− , MonadAdjust (..)
126 , sequenceDMapWithAdjust
126 , sequenceDMapWithAdjust
127 , sequenceDMapWithAdjustWithMove
127 , sequenceDMapWithAdjustWithMove
128 , mapMapWithAdjustWithMove
128 , mapMapWithAdjustWithMove
129+ -- * Miscellaneous convenience functions
130+ , ffor
129 -- * Deprecated functions
131 -- * Deprecated functions
132+ , MonadAdjust
130 , appendEvents
133 , appendEvents
131 , onceE
134 , onceE
132 , sequenceThese
135 , sequenceThese
@@ -1154,19 +1157,23 @@ infixl 4 <@>
1154(<@) = tag
1157(<@) = tag
1155infixl 4 <@
1158infixl 4 <@
1156
1159
1160+------------------
1161+-- Adjustable
1162+------------------
1163+
1157-- | A 'Monad' that supports adjustment over time. After an action has been
1164-- | A 'Monad' that supports adjustment over time. After an action has been
1158-- run, if the given events fire, it will adjust itself so that its net effect
1165-- run, if the given events fire, it will adjust itself so that its net effect
1159-- is as though it had originally been run with the new value. Note that there
1166-- is as though it had originally been run with the new value. Note that there
1160-- is some issue here with persistent side-effects: obviously, IO (and some
1167-- is some issue here with persistent side-effects: obviously, IO (and some
1161-- other side-effects) cannot be undone, so it is up to the instance implementer
1168-- other side-effects) cannot be undone, so it is up to the instance implementer
1162-- to determine what the best meaning for this class is in such cases.
1169-- to determine what the best meaning for this class is in such cases.
1163−class (Reflex t, Monad m) => MonadAdjust t m | m -> t where
1170+class (Reflex t, Monad m) => Adjustable t m | m -> t where
1164 runWithReplace :: m a -> Event t (m b) -> m (a, Event t b)
1171 runWithReplace :: m a -> Event t (m b) -> m (a, Event t b)
1165 traverseIntMapWithKeyWithAdjust :: (IntMap.Key -> v -> m v') -> IntMap v -> Event t (PatchIntMap v) -> m (IntMap v', Event t (PatchIntMap v'))
1172 traverseIntMapWithKeyWithAdjust :: (IntMap.Key -> v -> m v') -> IntMap v -> Event t (PatchIntMap v) -> m (IntMap v', Event t (PatchIntMap v'))
1166 traverseDMapWithKeyWithAdjust :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMap k v) -> m (DMap k v', Event t (PatchDMap k v'))
1173 traverseDMapWithKeyWithAdjust :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMap k v) -> m (DMap k v', Event t (PatchDMap k v'))
1167 traverseDMapWithKeyWithAdjustWithMove :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMapWithMove k v) -> m (DMap k v', Event t (PatchDMapWithMove k v'))
1174 traverseDMapWithKeyWithAdjustWithMove :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMapWithMove k v) -> m (DMap k v', Event t (PatchDMapWithMove k v'))
1168
1175
1169−instance MonadAdjust t m => MonadAdjust t (ReaderT r m) where
1176+instance Adjustable t m => Adjustable t (ReaderT r m) where
1170 runWithReplace a0 a' = do
1177 runWithReplace a0 a' = do
1171 r <- ask
1178 r <- ask
1172 lift $ runWithReplace (runReaderT a0 r) $ fmap (`runReaderT` r) a'
1179 lift $ runWithReplace (runReaderT a0 r) $ fmap (`runReaderT` r) a'
@@ -1180,13 +1187,13 @@ instance MonadAdjust t m => MonadAdjust t (ReaderT r m) where
1180 r <- ask
1187 r <- ask
1181 lift $ traverseDMapWithKeyWithAdjustWithMove (\k v -> runReaderT (f k v) r) dm0 dm'
1188 lift $ traverseDMapWithKeyWithAdjustWithMove (\k v -> runReaderT (f k v) r) dm0 dm'
1182
1189
1183−sequenceDMapWithAdjust :: (GCompare k, MonadAdjust t m) => DMap k m -> Event t (PatchDMap k m) -> m (DMap k Identity, Event t (PatchDMap k Identity))
1190+sequenceDMapWithAdjust :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMap k m) -> m (DMap k Identity, Event t (PatchDMap k Identity))
1184sequenceDMapWithAdjust = traverseDMapWithKeyWithAdjust $ \_ -> fmap Identity
1191sequenceDMapWithAdjust = traverseDMapWithKeyWithAdjust $ \_ -> fmap Identity
1185
1192
1186−sequenceDMapWithAdjustWithMove :: (GCompare k, MonadAdjust t m) => DMap k m -> Event t (PatchDMapWithMove k m) -> m (DMap k Identity, Event t (PatchDMapWithMove k Identity))
1193+sequenceDMapWithAdjustWithMove :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMapWithMove k m) -> m (DMap k Identity, Event t (PatchDMapWithMove k Identity))
1187sequenceDMapWithAdjustWithMove = traverseDMapWithKeyWithAdjustWithMove $ \_ -> fmap Identity
1194sequenceDMapWithAdjustWithMove = traverseDMapWithKeyWithAdjustWithMove $ \_ -> fmap Identity
1188
1195
1189−mapMapWithAdjustWithMove :: forall t m k v v'. (MonadAdjust t m, Ord k) => (k -> v -> m v') -> Map k v -> Event t (PatchMapWithMove k v) -> m (Map k v', Event t (PatchMapWithMove k v'))
1196+mapMapWithAdjustWithMove :: forall t m k v v'. (Adjustable t m, Ord k) => (k -> v -> m v') -> Map k v -> Event t (PatchMapWithMove k v) -> m (Map k v', Event t (PatchMapWithMove k v'))
1190mapMapWithAdjustWithMove f m0 m' = do
1197mapMapWithAdjustWithMove f m0 m' = do
1191 (out0 :: DMap (Const2 k v) (Constant v'), out') <- traverseDMapWithKeyWithAdjustWithMove (\(Const2 k) (Identity v) -> Constant <$> f k v) (mapToDMap m0) (const2PatchDMapWithMoveWith Identity <$> m')
1198 (out0 :: DMap (Const2 k v) (Constant v'), out') <- traverseDMapWithKeyWithAdjustWithMove (\(Const2 k) (Identity v) -> Constant <$> f k v) (mapToDMap m0) (const2PatchDMapWithMoveWith Identity <$> m')
1192 return (dmapToMapWith (\(Constant v') -> v') out0, patchDMapWithMoveToPatchMapWithMoveWith (\(Constant v') -> v') <$> out')
1199 return (dmapToMapWith (\(Constant v') -> v') out0, patchDMapWithMoveToPatchMapWithMoveWith (\(Constant v') -> v') <$> out')
@@ -1239,6 +1246,9 @@ mergeWithFoldCheap' f es =
1239-- Deprecated functions
1246-- Deprecated functions
1240--------------------------------------------------------------------------------
1247--------------------------------------------------------------------------------
1241
1248
1249+{-# DEPRECATED MonadAdjust "Use Adjustable instead" #-}
1250+type MonadAdjust = Adjustable
1251+
1242-- | Create a new 'Event' that occurs if at least one of the supplied 'Event's
1252-- | Create a new 'Event' that occurs if at least one of the supplied 'Event's
1243-- occurs. If both occur at the same time they are combined using 'mappend'.
1253-- occurs. If both occur at the same time they are combined using 'mappend'.
1244{-# DEPRECATED appendEvents "If a 'Semigroup a' instance is available, use 'mappend'; otherwise, use 'alignWith (mergeThese mappend)' instead" #-}
1254{-# DEPRECATED appendEvents "If a 'Semigroup a' instance is available, use 'mappend'; otherwise, use 'alignWith (mergeThese mappend)' instead" #-}
src/Reflex/Collection.hsnew file+121
@@ -0,0 +1,121 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE RankNTypes #-}
3+{-# LANGUAGE LambdaCase #-}
4+{-# LANGUAGE RecursiveDo #-}
5+{-# LANGUAGE ScopedTypeVariables #-}
6+{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE FunctionalDependencies #-}
8+{-# LANGUAGE FlexibleInstances #-}
9+{-# LANGUAGE TypeFamilies #-}
10+{-# LANGUAGE UndecidableInstances #-}
11+#ifdef USE_REFLEX_OPTIMIZER
12+{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
13+#endif
14+module Reflex.Collection
15+ (
16+ -- * Widgets on Collections
17+ listHoldWithKey
18+ , listWithKey
19+ , listWithKey'
20+ , listWithKeyShallowDiff
21+ , listViewWithKey
22+ , selectViewListWithKey
23+ , selectViewListWithKey_
24+ -- * List Utils
25+ , list
26+ , simpleList
27+ ) where
28+
29+import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
30+import Data.Align
31+import Data.Map (Map)
32+import qualified Data.Map as Map
33+import Data.Functor.Misc
34+import Data.Map.Misc
35+import Data.These
36+
37+import Reflex.Class
38+import Reflex.Dynamic
39+import Reflex.PostBuild.Class
40+
41+listHoldWithKey :: forall t m k v a. (Ord k, Adjustable t m, MonadHold t m) => Map k v -> Event t (Map k (Maybe v)) -> (k -> v -> m a) -> m (Dynamic t (Map k a))
42+listHoldWithKey m0 m' f = do
43+ let dm0 = mapWithFunctorToDMap $ Map.mapWithKey f m0
44+ dm' = fmap (PatchDMap . mapWithFunctorToDMap . Map.mapWithKey (\k v -> ComposeMaybe $ fmap (f k) v)) m'
45+ (a0, a') <- sequenceDMapWithAdjust dm0 dm'
46+ fmap dmapToMap . incrementalToDynamic <$> holdIncremental a0 a' --TODO: Move the dmapToMap to the righthand side so it doesn't get fully redone every time
47+
48+--TODO: Something better than Dynamic t (Map k v) - we want something where the Events carry diffs, not the whole value
49+listWithKey :: forall t k v m a. (Ord k, Adjustable t m, PostBuild t m, MonadFix m, MonadHold t m) => Dynamic t (Map k v) -> (k -> Dynamic t v -> m a) -> m (Dynamic t (Map k a))
50+listWithKey vals mkChild = do
51+ postBuild <- getPostBuild
52+ let childValChangedSelector = fanMap $ updated vals
53+ -- We keep track of changes to children values in the mkChild function we pass to listHoldWithKey
54+ -- The other changes we need to keep track of are child insertions and deletions. diffOnlyKeyChanges
55+ -- keeps track of insertions and deletions but ignores value changes, since they're already accounted for.
56+ diffOnlyKeyChanges olds news = flip Map.mapMaybe (align olds news) $ \case
57+ This _ -> Just Nothing
58+ These _ _ -> Nothing
59+ That new -> Just $ Just new
60+ rec sentVals :: Dynamic t (Map k v) <- foldDyn applyMap Map.empty changeVals
61+ let changeVals :: Event t (Map k (Maybe v))
62+ changeVals = attachWith diffOnlyKeyChanges (current sentVals) $ leftmost
63+ [ updated vals
64+ , tag (current vals) postBuild --TODO: This should probably be added to the attachWith, not to the updated; if we were using diffMap instead of diffMapNoEq, I think it might not work
65+ ]
66+ listHoldWithKey Map.empty changeVals $ \k v ->
67+ mkChild k =<< holdDyn v (select childValChangedSelector $ Const2 k)
68+
69+{-# DEPRECATED listWithKey' "listWithKey' has been renamed to listWithKeyShallowDiff; also, its behavior has changed to fix a bug where children were always rebuilt (never updated)" #-}
70+listWithKey' :: (Ord k, Adjustable t m, MonadFix m, MonadHold t m) => Map k v -> Event t (Map k (Maybe v)) -> (k -> v -> Event t v -> m a) -> m (Dynamic t (Map k a))
71+listWithKey' = listWithKeyShallowDiff
72+
73+-- | Display the given map of items (in key order) using the builder function provided, and update it with the given event. 'Nothing' update entries will delete the corresponding children, and 'Just' entries will create them if they do not exist or send an update event to them if they do.
74+listWithKeyShallowDiff :: (Ord k, Adjustable t m, MonadFix m, MonadHold t m) => Map k v -> Event t (Map k (Maybe v)) -> (k -> v -> Event t v -> m a) -> m (Dynamic t (Map k a))
75+listWithKeyShallowDiff initialVals valsChanged mkChild = do
76+ let childValChangedSelector = fanMap $ fmap (Map.mapMaybe id) valsChanged
77+ sentVals <- foldDyn applyMap Map.empty $ fmap (fmap void) valsChanged
78+ let relevantPatch patch _ = case patch of
79+ Nothing -> Just Nothing -- Even if we let a Nothing through when the element doesn't already exist, this doesn't cause a problem because it is ignored
80+ Just _ -> Nothing -- We don't want to let spurious re-creations of items through
81+ listHoldWithKey initialVals (attachWith (flip (Map.differenceWith relevantPatch)) (current sentVals) valsChanged) $ \k v ->
82+ mkChild k v $ select childValChangedSelector $ Const2 k
83+
84+--TODO: Something better than Dynamic t (Map k v) - we want something where the Events carry diffs, not the whole value
85+-- | Create a dynamically-changing set of Event-valued widgets.
86+-- This is like listWithKey, specialized for widgets returning (Event t a). listWithKey would return 'Dynamic t (Map k (Event t a))' in this scenario, but listViewWithKey flattens this to 'Event t (Map k a)' via 'switch'.
87+listViewWithKey :: (Ord k, Adjustable t m, PostBuild t m, MonadHold t m, MonadFix m) => Dynamic t (Map k v) -> (k -> Dynamic t v -> m (Event t a)) -> m (Event t (Map k a))
88+listViewWithKey vals mkChild = switch . fmap mergeMap <$> listViewWithKey' vals mkChild
89+
90+listViewWithKey' :: (Ord k, Adjustable t m, PostBuild t m, MonadHold t m, MonadFix m) => Dynamic t (Map k v) -> (k -> Dynamic t v -> m a) -> m (Behavior t (Map k a))
91+listViewWithKey' vals mkChild = current <$> listWithKey vals mkChild
92+
93+-- | Create a dynamically-changing set of widgets, one of which is selected at any time.
94+selectViewListWithKey :: forall t m k v a. (Adjustable t m, Ord k, PostBuild t m, MonadHold t m, MonadFix m)
95+ => Dynamic t k -- ^ Current selection key
96+ -> Dynamic t (Map k v) -- ^ Dynamic key/value map
97+ -> (k -> Dynamic t v -> Dynamic t Bool -> m (Event t a)) -- ^ Function to create a widget for a given key from Dynamic value and Dynamic Bool indicating if this widget is currently selected
98+ -> m (Event t (k, a)) -- ^ Event that fires when any child's return Event fires. Contains key of an arbitrary firing widget.
99+selectViewListWithKey selection vals mkChild = do
100+ let selectionDemux = demux selection -- For good performance, this value must be shared across all children
101+ selectChild <- listWithKey vals $ \k v -> do
102+ let selected = demuxed selectionDemux k
103+ selectSelf <- mkChild k v selected
104+ return $ fmap ((,) k) selectSelf
105+ return $ switchPromptlyDyn $ leftmost . Map.elems <$> selectChild
106+
107+selectViewListWithKey_ :: forall t m k v a. (Adjustable t m, Ord k, PostBuild t m, MonadHold t m, MonadFix m)
108+ => Dynamic t k -- ^ Current selection key
109+ -> Dynamic t (Map k v) -- ^ Dynamic key/value map
110+ -> (k -> Dynamic t v -> Dynamic t Bool -> m (Event t a)) -- ^ Function to create a widget for a given key from Dynamic value and Dynamic Bool indicating if this widget is currently selected
111+ -> m (Event t k) -- ^ Event that fires when any child's return Event fires. Contains key of an arbitrary firing widget.
112+selectViewListWithKey_ selection vals mkChild = fmap fst <$> selectViewListWithKey selection vals mkChild
113+
114+-- | Create a dynamically-changing set of widgets from a Dynamic key/value map.
115+-- Unlike the 'withKey' variants, the child widgets are insensitive to which key they're associated with.
116+list :: (Ord k, Adjustable t m, MonadHold t m, PostBuild t m, MonadFix m) => Dynamic t (Map k v) -> (Dynamic t v -> m a) -> m (Dynamic t (Map k a))
117+list dm mkChild = listWithKey dm (\_ dv -> mkChild dv)
118+
119+-- | Create a dynamically-changing set of widgets from a Dynamic list.
120+simpleList :: (Adjustable t m, MonadHold t m, PostBuild t m, MonadFix m) => Dynamic t [v] -> (Dynamic t v -> m a) -> m (Dynamic t [a])
121+simpleList xs mkChild = fmap (fmap (map snd . Map.toList)) $ flip list mkChild $ fmap (Map.fromList . zip [(1::Int)..]) xs
src/Reflex/DynamicWriter.hs+2−2
@@ -135,9 +135,9 @@ instance MonadState s m => MonadState s (DynamicWriterT t w m) where
135newtype DynamicWriterTLoweredResult t w v a = DynamicWriterTLoweredResult (v a, Dynamic t w)
135newtype DynamicWriterTLoweredResult t w v a = DynamicWriterTLoweredResult (v a, Dynamic t w)
136
136
137-- | When the execution of a 'DynamicWriterT' action is adjusted using
137-- | When the execution of a 'DynamicWriterT' action is adjusted using
138−-- 'MonadAdjust', the 'Dynamic' output of that action will also be updated to
138+-- 'Adjustable', the 'Dynamic' output of that action will also be updated to
139-- match.
139-- match.
140−instance (MonadAdjust t m, MonadFix m, Monoid w, MonadHold t m, Reflex t) => MonadAdjust t (DynamicWriterT t w m) where
140+instance (Adjustable t m, MonadFix m, Monoid w, MonadHold t m, Reflex t) => Adjustable t (DynamicWriterT t w m) where
141 runWithReplace a0 a' = do
141 runWithReplace a0 a' = do
142 (result0, result') <- lift $ runWithReplace (runDynamicWriterT a0) $ runDynamicWriterT <$> a'
142 (result0, result') <- lift $ runWithReplace (runDynamicWriterT a0) $ runDynamicWriterT <$> a'
143 tellDyn . join =<< holdDyn (snd result0) (snd <$> result')
143 tellDyn . join =<< holdDyn (snd result0) (snd <$> result')
src/Reflex/EventWriter.hs+3−3
@@ -140,7 +140,7 @@ instance MonadHold t m => MonadHold t (EventWriterT t w m) where
140 {-# INLINABLE headE #-}
140 {-# INLINABLE headE #-}
141 headE = lift . headE
141 headE = lift . headE
142
142
143−instance (Reflex t, MonadAdjust t m, MonadHold t m, Semigroup w) => MonadAdjust t (EventWriterT t w m) where
143+instance (Reflex t, Adjustable t m, MonadHold t m, Semigroup w) => Adjustable t (EventWriterT t w m) where
144 runWithReplace = runWithReplaceEventWriterTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
144 runWithReplace = runWithReplaceEventWriterTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
145 traverseIntMapWithKeyWithAdjust = sequenceIntMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseIntMapWithKeyWithAdjust f dm0 dm') patchIntMapNewElements mergeIntIncremental
145 traverseIntMapWithKeyWithAdjust = sequenceIntMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseIntMapWithKeyWithAdjust f dm0 dm') patchIntMapNewElements mergeIntIncremental
146 traverseDMapWithKeyWithAdjust = sequenceDMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseDMapWithKeyWithAdjust f dm0 dm') mapPatchDMap weakenPatchDMapWith patchMapNewElements mergeMapIncremental
146 traverseDMapWithKeyWithAdjust = sequenceDMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseDMapWithKeyWithAdjust f dm0 dm') mapPatchDMap weakenPatchDMapWith patchMapNewElements mergeMapIncremental
@@ -154,8 +154,8 @@ instance Requester t m => Requester t (EventWriterT t w m) where
154
154
155-- | Given a function like 'runWithReplace' for the underlying monad, implement
155-- | Given a function like 'runWithReplace' for the underlying monad, implement
156-- 'runWithReplace' for 'EventWriterT'. This is necessary when the underlying
156-- 'runWithReplace' for 'EventWriterT'. This is necessary when the underlying
157−-- monad doesn't have a 'MonadAdjust' instance or to override the default
157+-- monad doesn't have a 'Adjustable' instance or to override the default
158−-- 'MonadAdjust' behavior.
158+-- 'Adjustable' behavior.
159runWithReplaceEventWriterTWith :: forall m t w a b. (Reflex t, MonadHold t m, Semigroup w)
159runWithReplaceEventWriterTWith :: forall m t w a b. (Reflex t, MonadHold t m, Semigroup w)
160 => (forall a' b'. m a' -> Event t (m b') -> EventWriterT t w m (a', Event t b'))
160 => (forall a' b'. m a' -> Event t (m b') -> EventWriterT t w m (a', Event t b'))
161 -> EventWriterT t w m a
161 -> EventWriterT t w m a
src/Reflex/PerformEvent/Base.hs+1−1
@@ -72,7 +72,7 @@ instance (ReflexHost t, Ref m ~ Ref IO, PrimMonad (HostFrame t)) => PerformEvent
72 {-# INLINABLE performEvent #-}
72 {-# INLINABLE performEvent #-}
73 performEvent = PerformEventT . requestingIdentity
73 performEvent = PerformEventT . requestingIdentity
74
74
75−instance (ReflexHost t, PrimMonad (HostFrame t)) => MonadAdjust t (PerformEventT t m) where
75+instance (ReflexHost t, PrimMonad (HostFrame t)) => Adjustable t (PerformEventT t m) where
76 runWithReplace outerA0 outerA' = PerformEventT $ runWithReplaceRequesterTWith f (coerce outerA0) (coerceEvent outerA')
76 runWithReplace outerA0 outerA' = PerformEventT $ runWithReplaceRequesterTWith f (coerce outerA0) (coerceEvent outerA')
77 where f :: HostFrame t a -> Event t (HostFrame t b) -> RequesterT t (HostFrame t) Identity (HostFrame t) (a, Event t b)
77 where f :: HostFrame t a -> Event t (HostFrame t b) -> RequesterT t (HostFrame t) Identity (HostFrame t) (a, Event t b)
78 f a0 a' = do
78 f a0 a' = do
src/Reflex/PostBuild/Base.hs+1−1
@@ -107,7 +107,7 @@ instance MonadAtomicRef m => MonadAtomicRef (PostBuildT t m) where
107 {-# INLINABLE atomicModifyRef #-}
107 {-# INLINABLE atomicModifyRef #-}
108 atomicModifyRef r = lift . atomicModifyRef r
108 atomicModifyRef r = lift . atomicModifyRef r
109
109
110−instance (Reflex t, MonadHold t m, MonadFix m, MonadAdjust t m, PerformEvent t m) => MonadAdjust t (PostBuildT t m) where
110+instance (Reflex t, MonadHold t m, MonadFix m, Adjustable t m, PerformEvent t m) => Adjustable t (PostBuildT t m) where
111 runWithReplace a0 a' = do
111 runWithReplace a0 a' = do
112 postBuild <- getPostBuild
112 postBuild <- getPostBuild
113 lift $ do
113 lift $ do
src/Reflex/Query/Base.hs+1−1
@@ -70,7 +70,7 @@ let sampleBs :: forall m'. MonadSample t m' => [Behavior t q] -> m' q
70 return (Just (AdditivePatch p))
70 return (Just (AdditivePatch p))
71-}
71-}
72
72
73−instance (Reflex t, MonadFix m, Group q, Additive q, Query q, MonadHold t m, MonadAdjust t m) => MonadAdjust t (QueryT t q m) where
73+instance (Reflex t, MonadFix m, Group q, Additive q, Query q, MonadHold t m, Adjustable t m) => Adjustable t (QueryT t q m) where
74 runWithReplace (QueryT a0) a' = do
74 runWithReplace (QueryT a0) a' = do
75 ((r0, bs0), r') <- QueryT $ lift $ runWithReplace (runStateT a0 []) $ fmapCheap (flip runStateT [] . unQueryT) a'
75 ((r0, bs0), r') <- QueryT $ lift $ runWithReplace (runStateT a0 []) $ fmapCheap (flip runStateT [] . unQueryT) a'
76 let sampleBs :: forall m'. MonadSample t m' => [Behavior t q] -> m' q
76 let sampleBs :: forall m'. MonadSample t m' => [Behavior t q] -> m' q
src/Reflex/Requester/Base.hs+2−2
@@ -299,7 +299,7 @@ instance MonadReader r m => MonadReader r (RequesterT t request response m) wher
299 local f (RequesterT a) = RequesterT $ mapStateT (mapReaderT $ local f) a
299 local f (RequesterT a) = RequesterT $ mapStateT (mapReaderT $ local f) a
300 reader = lift . reader
300 reader = lift . reader
301
301
302−instance (Reflex t, MonadAdjust t m, MonadHold t m, MonadFix m) => MonadAdjust t (RequesterT t request response m) where
302+instance (Reflex t, Adjustable t m, MonadHold t m, MonadFix m) => Adjustable t (RequesterT t request response m) where
303 runWithReplace = runWithReplaceRequesterTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
303 runWithReplace = runWithReplaceRequesterTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
304 traverseIntMapWithKeyWithAdjust = traverseIntMapWithKeyWithAdjustRequesterTWith (\f dm0 dm' -> lift $ traverseIntMapWithKeyWithAdjust f dm0 dm') patchIntMapNewElementsMap mergeIntIncremental
304 traverseIntMapWithKeyWithAdjust = traverseIntMapWithKeyWithAdjustRequesterTWith (\f dm0 dm' -> lift $ traverseIntMapWithKeyWithAdjust f dm0 dm') patchIntMapNewElementsMap mergeIntIncremental
305 {-# INLINABLE traverseDMapWithKeyWithAdjust #-}
305 {-# INLINABLE traverseDMapWithKeyWithAdjust #-}
@@ -358,7 +358,7 @@ traverseIntMapWithKeyWithAdjustRequesterTWith base patchNewElements mergePatchIn
358 (result, myRequests) <- runRequesterT (f k v) $ fmapMaybeCheap (IntMap.lookup n) $ selectInt responses k --TODO: Instead of doing fmapMaybeCheap, can we share a fanInt across all instances of a given key, or at least the ones that are adjacent in time?
358 (result, myRequests) <- runRequesterT (f k v) $ fmapMaybeCheap (IntMap.lookup n) $ selectInt responses k --TODO: Instead of doing fmapMaybeCheap, can we share a fanInt across all instances of a given key, or at least the ones that are adjacent in time?
359 return (fmapCheap (IntMap.singleton n) myRequests, result)
359 return (fmapCheap (IntMap.singleton n) myRequests, result)
360 ndm' <- numberOccurrencesFrom 1 dm'
360 ndm' <- numberOccurrencesFrom 1 dm'
361− (children0, children') <- base f' (fmap ((,) 0) dm0) $ fmap (\(n, dm) -> fmap ((,) n) dm) ndm' --TODO: Avoid this somehow, probably by adding some sort of per-cohort information passing to MonadAdjust
361+ (children0, children') <- base f' (fmap ((,) 0) dm0) $ fmap (\(n, dm) -> fmap ((,) n) dm) ndm' --TODO: Avoid this somehow, probably by adding some sort of per-cohort information passing to Adjustable
362 let result0 = fmap snd children0
362 let result0 = fmap snd children0
363 result' = fforCheap children' $ fmap snd
363 result' = fforCheap children' $ fmap snd
364 requests0 :: IntMap (Event t (IntMap (RequesterData request)))
364 requests0 :: IntMap (Event t (IntMap (RequesterData request)))
src/Reflex/TriggerEvent/Base.hs+1−1
@@ -119,7 +119,7 @@ instance MonadHold t m => MonadHold t (TriggerEventT t m) where
119 {-# INLINABLE headE #-}
119 {-# INLINABLE headE #-}
120 headE = lift . headE
120 headE = lift . headE
121
121
122−instance MonadAdjust t m => MonadAdjust t (TriggerEventT t m) where
122+instance Adjustable t m => Adjustable t (TriggerEventT t m) where
123 {-# INLINABLE runWithReplace #-}
123 {-# INLINABLE runWithReplace #-}
124 runWithReplace (TriggerEventT a0) a' = TriggerEventT $ runWithReplace a0 (coerceEvent a')
124 runWithReplace (TriggerEventT a0) a' = TriggerEventT $ runWithReplace a0 (coerceEvent a')
125 {-# INLINABLE traverseIntMapWithKeyWithAdjust #-}
125 {-# INLINABLE traverseIntMapWithKeyWithAdjust #-}
src/Reflex/Widget/Basic.hs+1−1
@@ -30,7 +30,7 @@ import Reflex.Patch.MapWithMove
30-- > (\k v -> text $ "\n" ++ show k ++ " " ++ v) -- show each element on a new line
30-- > (\k v -> text $ "\n" ++ show k ++ " " ++ v) -- show each element on a new line
31-- > (Map.fromList $ zip [0..] [(3, "a"), (2, "b"), (1, "c")])
31-- > (Map.fromList $ zip [0..] [(3, "a"), (2, "b"), (1, "c")])
32-- > sortEvent
32-- > sortEvent
33−sortableList :: forall t m k v a. (MonadHold t m, MonadFix m, MonadAdjust t m, Ord k)
33+sortableList :: forall t m k v a. (MonadHold t m, MonadFix m, Adjustable t m, Ord k)
34 => (k -> v -> m a) -- ^ Function to render the content for each key/value pair
34 => (k -> v -> m a) -- ^ Function to render the content for each key/value pair
35 -> Map k v -- ^ The sortable list with an initial ordering determined by the @Map@ keys in ascending order
35 -> Map k v -- ^ The sortable list with an initial ordering determined by the @Map@ keys in ascending order
36 -> Event t (v -> v -> Ordering) -- ^ An event carrying a sort function for the list
36 -> Event t (v -> v -> Ordering) -- ^ An event carrying a sort function for the list
test/EventWriterT.hs+1−1
@@ -35,7 +35,7 @@ testOrdering pulse = do
35 forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse)
35 forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse)
36 return ()
36 return ()
37
37
38−testSimultaneous :: (Reflex t, MonadAdjust t m, MonadHold t m) => Event t (These () ()) -> EventWriterT t [Int] m ()
38+testSimultaneous :: (Reflex t, Adjustable t m, MonadHold t m) => Event t (These () ()) -> EventWriterT t [Int] m ()
39testSimultaneous pulse = do
39testSimultaneous pulse = do
40 let e0 = fmapMaybe (^? here) pulse
40 let e0 = fmapMaybe (^? here) pulse
41 e1 = fmapMaybe (^? there) pulse
41 e1 = fmapMaybe (^? there) pulse
test/QueryT.hs+4−12
@@ -81,7 +81,7 @@ testQueryT w (AppIn _ pulse) = do
81 }
81 }
82
82
83testRunWithReplace :: ( Reflex t
83testRunWithReplace :: ( Reflex t
84− , MonadAdjust t m
84+ , Adjustable t m
85 , MonadHold t m
85 , MonadHold t m
86 , MonadFix m
86 , MonadFix m
87 , MonadQuery t (Selector Int MyQuery) m)
87 , MonadQuery t (Selector Int MyQuery) m)
@@ -96,7 +96,7 @@ testRunWithReplace replace increment = do
96 return ()
96 return ()
97
97
98testSequenceDMapWithAdjust :: ( Reflex t
98testSequenceDMapWithAdjust :: ( Reflex t
99− , MonadAdjust t m
99+ , Adjustable t m
100 , MonadHold t m
100 , MonadHold t m
101 , MonadFix m
101 , MonadFix m
102 , MonadQuery t (Selector Int MyQuery) m)
102 , MonadQuery t (Selector Int MyQuery) m)
@@ -110,7 +110,7 @@ testSequenceDMapWithAdjust replace increment = do
110 return ()
110 return ()
111
111
112testSequenceDMapWithAdjustWithMove :: ( Reflex t
112testSequenceDMapWithAdjustWithMove :: ( Reflex t
113− , MonadAdjust t m
113+ , Adjustable t m
114 , MonadHold t m
114 , MonadHold t m
115 , MonadFix m
115 , MonadFix m
116 , MonadQuery t (Selector Int MyQuery) m)
116 , MonadQuery t (Selector Int MyQuery) m)
@@ -123,16 +123,8 @@ testSequenceDMapWithAdjustWithMove replace increment = do
123 queryDyn $ zipDynWith (\x y -> Selector (AMap.singleton (x :: Int) y)) n $ pure $ MyQuery $ SelectedCount 1
123 queryDyn $ zipDynWith (\x y -> Selector (AMap.singleton (x :: Int) y)) n $ pure $ MyQuery $ SelectedCount 1
124 return ()
124 return ()
125
125
126−listHoldWithKey :: forall t m k v a. (Ord k, MonadHold t m, MonadAdjust t m) => Map k v -> Event t (Map k (Maybe v)) -> (k -> v -> m a) -> m (Dynamic t (Map k a))
127−listHoldWithKey m0 m' f = do
128− let dm0 = mapWithFunctorToDMap $ Map.mapWithKey f m0
129− dm' = fmap (PatchDMap . mapWithFunctorToDMap . Map.mapWithKey (\k v -> ComposeMaybe $ fmap (f k) v)) m'
130− (a0, a') <- sequenceDMapWithAdjust dm0 dm'
131− fmap dmapToMap . incrementalToDynamic <$> holdIncremental a0 a'
132−
133−
134-- scam it out to test traverseDMapWithAdjustWithMove
126-- scam it out to test traverseDMapWithAdjustWithMove
135−listHoldWithKeyWithMove :: forall t m k v a. (Ord k, MonadHold t m, MonadAdjust t m) => Map k v -> Event t (Map k (Maybe v)) -> (k -> v -> m a) -> m (Dynamic t (Map k a))
127+listHoldWithKeyWithMove :: forall t m k v a. (Ord k, MonadHold t m, Adjustable t m) => Map k v -> Event t (Map k (Maybe v)) -> (k -> v -> m a) -> m (Dynamic t (Map k a))
136listHoldWithKeyWithMove m0 m' f = do
128listHoldWithKeyWithMove m0 m' f = do
137 (n0, n') <- mapMapWithAdjustWithMove f m0 $ ffor m' $ PatchMapWithMove . Map.map (\v -> NodeInfo (maybe From_Delete From_Insert v) Nothing)
129 (n0, n') <- mapMapWithAdjustWithMove f m0 $ ffor m' $ PatchMapWithMove . Map.map (\v -> NodeInfo (maybe From_Delete From_Insert v) Nothing)
138 incrementalToDynamic <$> holdIncremental n0 n'
130 incrementalToDynamic <$> holdIncremental n0 n'
test/RequesterT.hs+2−2
@@ -45,7 +45,7 @@ unwrapApp x appIn = do
45testOrdering :: ( Response m ~ Identity
45testOrdering :: ( Response m ~ Identity
46 , Request m ~ RequestInt
46 , Request m ~ RequestInt
47 , Requester t m
47 , Requester t m
48− , MonadAdjust t m)
48+ , Adjustable t m)
49 => Event t ()
49 => Event t ()
50 -> m ()
50 -> m ()
51testOrdering pulse = do
51testOrdering pulse = do
@@ -55,7 +55,7 @@ testOrdering pulse = do
55testSimultaneous :: ( Response m ~ Identity
55testSimultaneous :: ( Response m ~ Identity
56 , Request m ~ RequestInt
56 , Request m ~ RequestInt
57 , Requester t m
57 , Requester t m
58− , MonadAdjust t m)
58+ , Adjustable t m)
59 => Event t (These () ())
59 => Event t (These () ())
60 -> m ()
60 -> m ()
61testSimultaneous pulse = do
61testSimultaneous pulse = do