Skip to content

Commit e549ebb

Browse files
author
Ryan Trinkle
authored
Merge pull request #190 from reflex-frp/eac-split-base-class
Split out Base and Class for DynamicWriter/EventWriter
2 parents 9f3356f + 4602fe7 commit e549ebb

File tree

11 files changed

+557
-506
lines changed

11 files changed

+557
-506
lines changed

reflex.cabal

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,13 @@ library
8888
Reflex.Class,
8989
Reflex.Collection,
9090
Reflex.EventWriter,
91+
Reflex.EventWriter.Base,
92+
Reflex.EventWriter.Class,
9193
Reflex.Dynamic,
9294
Reflex.Dynamic.Uniq,
9395
Reflex.DynamicWriter,
96+
Reflex.DynamicWriter.Base,
97+
Reflex.DynamicWriter.Class,
9498
Reflex.FastWeak,
9599
Reflex.FunctorMaybe,
96100
Reflex.Host.Class,

src/Reflex.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ module Reflex
77

88
import Reflex.Class as X
99
import Reflex.Collection as X
10-
import Reflex.EventWriter as X
10+
import Reflex.EventWriter.Base as X
11+
import Reflex.EventWriter.Class as X
1112
import Reflex.Dynamic as X
1213
#ifdef USE_TEMPLATE_HASKELL
1314
import Reflex.Dynamic.TH as X
1415
#endif
1516
import Reflex.Dynamic.Uniq as X
16-
import Reflex.DynamicWriter as X
17+
import Reflex.DynamicWriter.Base as X
18+
import Reflex.DynamicWriter.Class as X
1719
import Reflex.PerformEvent.Base as X
1820
import Reflex.PerformEvent.Class as X
1921
import Reflex.PostBuild.Base as X

src/Reflex/DynamicWriter.hs

Lines changed: 4 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -1,224 +1,7 @@
1-
-- | This module defines 'MonadDynamicWriter' and 'DynamicWriterT', its standard
2-
-- implementation.
3-
{-# LANGUAGE CPP #-}
4-
{-# LANGUAGE FlexibleInstances #-}
5-
{-# LANGUAGE FunctionalDependencies #-}
6-
{-# LANGUAGE GADTs #-}
7-
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
8-
{-# LANGUAGE LambdaCase #-}
9-
{-# LANGUAGE MultiParamTypeClasses #-}
10-
{-# LANGUAGE RankNTypes #-}
11-
{-# LANGUAGE ScopedTypeVariables #-}
12-
{-# LANGUAGE TypeFamilies #-}
13-
{-# LANGUAGE UndecidableInstances #-}
14-
#ifdef USE_REFLEX_OPTIMIZER
15-
{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
16-
#endif
171
module Reflex.DynamicWriter
18-
( MonadDynamicWriter (..)
19-
, DynamicWriterT (..)
20-
, runDynamicWriterT
21-
, withDynamicWriterT
2+
{-# DEPRECATED "Use 'Reflex.DynamicWriter.Class' and 'Reflex.DynamicWrite.Base' instead, or just import 'Reflex'" #-}
3+
( module X
224
) where
235

24-
import Control.Monad.Exception
25-
import Control.Monad.Identity
26-
import Control.Monad.IO.Class
27-
import Control.Monad.Reader
28-
import Control.Monad.Ref
29-
import Control.Monad.State.Strict
30-
import Data.Align
31-
import Data.Dependent.Map (DMap)
32-
import qualified Data.Dependent.Map as DMap
33-
import Data.FastMutableIntMap
34-
import Data.Functor.Misc
35-
import Data.IntMap (IntMap)
36-
import qualified Data.IntMap as IntMap
37-
import Data.Map (Map)
38-
import qualified Data.Map as Map
39-
import Data.Semigroup
40-
import Data.Some (Some)
41-
import Data.These
42-
import Reflex.Class
43-
import Reflex.Host.Class
44-
import qualified Reflex.Patch.MapWithMove as MapWithMove
45-
import Reflex.PerformEvent.Class
46-
import Reflex.PostBuild.Class
47-
import Reflex.Requester.Class
48-
import Reflex.TriggerEvent.Class
49-
50-
instance MonadTrans (DynamicWriterT t w) where
51-
lift = DynamicWriterT . lift
52-
53-
mapIncrementalMapValues :: (Reflex t, Patch (p v), Patch (p v'), PatchTarget (p v) ~ f v, PatchTarget (p v') ~ f v', Functor p, Functor f) => (v -> v') -> Incremental t (p v) -> Incremental t (p v')
54-
mapIncrementalMapValues f = unsafeMapIncremental (fmap f) (fmap f)
55-
56-
mergeDynIncremental :: (Reflex t, Ord k) => Incremental t (PatchMap k (Dynamic t v)) -> Incremental t (PatchMap k v)
57-
mergeDynIncremental a = unsafeBuildIncremental (mapM (sample . current) =<< sample (currentIncremental a)) $ addedAndRemovedValues <> changedValues
58-
where changedValues = fmap (PatchMap . fmap Just) $ mergeMapIncremental $ mapIncrementalMapValues updated a
59-
addedAndRemovedValues = flip pushAlways (updatedIncremental a) $ \(PatchMap m) -> PatchMap <$> mapM (mapM (sample . current)) m
60-
61-
mergeIntMapDynIncremental :: Reflex t => Incremental t (PatchIntMap (Dynamic t v)) -> Incremental t (PatchIntMap v)
62-
mergeIntMapDynIncremental a = unsafeBuildIncremental (mapM (sample . current) =<< sample (currentIncremental a)) $ addedAndRemovedValues <> changedValues
63-
where changedValues = fmap (PatchIntMap . fmap Just) $ mergeIntMapIncremental $ mapIncrementalMapValues updated a
64-
addedAndRemovedValues = flip pushAlways (updatedIncremental a) $ \(PatchIntMap m) -> PatchIntMap <$> mapM (mapM (sample . current)) m
65-
66-
mergeDynIncrementalWithMove :: forall t k v. (Reflex t, Ord k) => Incremental t (PatchMapWithMove k (Dynamic t v)) -> Incremental t (PatchMapWithMove k v)
67-
mergeDynIncrementalWithMove a = unsafeBuildIncremental (mapM (sample . current) =<< sample (currentIncremental a)) $ alignWith f addedAndRemovedValues changedValues
68-
where changedValues = mergeMapIncrementalWithMove $ mapIncrementalMapValues updated a
69-
addedAndRemovedValues = flip pushAlways (updatedIncremental a) $ fmap unsafePatchMapWithMove . mapM (mapM (sample . current)) . unPatchMapWithMove
70-
f :: These (PatchMapWithMove k v) (Map k v) -> PatchMapWithMove k v
71-
f x = unsafePatchMapWithMove $
72-
let (p, changed) = case x of
73-
This p_ -> (unPatchMapWithMove p_, mempty)
74-
That c -> (mempty, c)
75-
These p_ c -> (unPatchMapWithMove p_, c)
76-
(pWithNewVals, noLongerMoved) = flip runState [] $ forM p $ MapWithMove.nodeInfoMapMFrom $ \case
77-
MapWithMove.From_Insert v -> return $ MapWithMove.From_Insert v
78-
MapWithMove.From_Delete -> return $ MapWithMove.From_Delete
79-
MapWithMove.From_Move k -> case Map.lookup k changed of
80-
Nothing -> return $ MapWithMove.From_Move k
81-
Just v -> do
82-
modify (k:)
83-
return $ MapWithMove.From_Insert v
84-
noLongerMovedMap = Map.fromList $ fmap (\k -> (k, ())) noLongerMoved
85-
in Map.differenceWith (\e _ -> Just $ MapWithMove.nodeInfoSetTo Nothing e) pWithNewVals noLongerMovedMap --TODO: Check if any in the second map are not covered?
86-
87-
-- | A basic implementation of 'MonadDynamicWriter'.
88-
newtype DynamicWriterT t w m a = DynamicWriterT { unDynamicWriterT :: StateT [Dynamic t w] m a } deriving (Functor, Applicative, Monad, MonadIO, MonadFix, MonadHold t, MonadSample t, MonadAsyncException, MonadException) -- The list is kept in reverse order
89-
90-
instance MonadRef m => MonadRef (DynamicWriterT t w m) where
91-
type Ref (DynamicWriterT t w m) = Ref m
92-
newRef = lift . newRef
93-
readRef = lift . readRef
94-
writeRef r = lift . writeRef r
95-
96-
instance MonadAtomicRef m => MonadAtomicRef (DynamicWriterT t w m) where
97-
atomicModifyRef r = lift . atomicModifyRef r
98-
99-
instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (DynamicWriterT t w m) where
100-
newEventWithTrigger = lift . newEventWithTrigger
101-
newFanEventWithTrigger f = lift $ newFanEventWithTrigger f
102-
103-
-- | Run a 'DynamicWriterT' action. The dynamic writer output will be provided
104-
-- along with the result of the action.
105-
runDynamicWriterT :: (MonadFix m, Reflex t, Monoid w) => DynamicWriterT t w m a -> m (a, Dynamic t w)
106-
runDynamicWriterT (DynamicWriterT a) = do
107-
(result, ws) <- runStateT a []
108-
return (result, mconcat $ reverse ws)
109-
110-
-- | 'MonadDynamicWriter' efficiently collects 'Dynamic' values using 'tellDyn'
111-
-- and combines them monoidally to provide a 'Dynamic' result.
112-
class (Monad m, Monoid w) => MonadDynamicWriter t w m | m -> t w where
113-
tellDyn :: Dynamic t w -> m ()
114-
115-
instance (Monad m, Monoid w, Reflex t) => MonadDynamicWriter t w (DynamicWriterT t w m) where
116-
tellDyn w = DynamicWriterT $ modify (w :)
117-
118-
instance MonadReader r m => MonadReader r (DynamicWriterT t w m) where
119-
ask = lift ask
120-
local f (DynamicWriterT a) = DynamicWriterT $ mapStateT (local f) a
121-
reader = lift . reader
122-
123-
instance PerformEvent t m => PerformEvent t (DynamicWriterT t w m) where
124-
type Performable (DynamicWriterT t w m) = Performable m
125-
performEvent_ = lift . performEvent_
126-
performEvent = lift . performEvent
127-
128-
instance TriggerEvent t m => TriggerEvent t (DynamicWriterT t w m) where
129-
newTriggerEvent = lift newTriggerEvent
130-
newTriggerEventWithOnComplete = lift newTriggerEventWithOnComplete
131-
newEventWithLazyTriggerWithOnComplete = lift . newEventWithLazyTriggerWithOnComplete
132-
133-
instance PostBuild t m => PostBuild t (DynamicWriterT t w m) where
134-
getPostBuild = lift getPostBuild
135-
136-
instance MonadDynamicWriter t w m => MonadDynamicWriter t w (ReaderT r m) where
137-
tellDyn = lift . tellDyn
138-
139-
instance MonadState s m => MonadState s (DynamicWriterT t w m) where
140-
get = lift get
141-
put = lift . put
142-
143-
newtype DynamicWriterTLoweredResult t w v a = DynamicWriterTLoweredResult (v a, Dynamic t w)
144-
145-
-- | When the execution of a 'DynamicWriterT' action is adjusted using
146-
-- 'Adjustable', the 'Dynamic' output of that action will also be updated to
147-
-- match.
148-
instance (Adjustable t m, MonadFix m, Monoid w, MonadHold t m, Reflex t) => Adjustable t (DynamicWriterT t w m) where
149-
runWithReplace a0 a' = do
150-
(result0, result') <- lift $ runWithReplace (runDynamicWriterT a0) $ runDynamicWriterT <$> a'
151-
tellDyn . join =<< holdDyn (snd result0) (snd <$> result')
152-
return (fst result0, fst <$> result')
153-
traverseIntMapWithKeyWithAdjust = traverseIntMapWithKeyWithAdjustImpl traverseIntMapWithKeyWithAdjust mergeIntMapDynIncremental
154-
traverseDMapWithKeyWithAdjust = traverseDMapWithKeyWithAdjustImpl traverseDMapWithKeyWithAdjust mapPatchDMap weakenPatchDMapWith mergeDynIncremental
155-
traverseDMapWithKeyWithAdjustWithMove = traverseDMapWithKeyWithAdjustImpl traverseDMapWithKeyWithAdjustWithMove mapPatchDMapWithMove weakenPatchDMapWithMoveWith mergeDynIncrementalWithMove
156-
157-
traverseDMapWithKeyWithAdjustImpl :: forall t w k v' p p' v m. (PatchTarget (p' (Some k) (Dynamic t w)) ~ Map (Some k) (Dynamic t w), PatchTarget (p' (Some k) w) ~ Map (Some k) w, Patch (p' (Some k) w), Patch (p' (Some k) (Dynamic t w)), MonadFix m, Monoid w, Reflex t, MonadHold t m)
158-
=> ( (forall a. k a -> v a -> m (DynamicWriterTLoweredResult t w v' a))
159-
-> DMap k v
160-
-> Event t (p k v)
161-
-> m (DMap k (DynamicWriterTLoweredResult t w v'), Event t (p k (DynamicWriterTLoweredResult t w v')))
162-
)
163-
-> ((forall a. DynamicWriterTLoweredResult t w v' a -> v' a) -> p k (DynamicWriterTLoweredResult t w v') -> p k v')
164-
-> ((forall a. DynamicWriterTLoweredResult t w v' a -> Dynamic t w) -> p k (DynamicWriterTLoweredResult t w v') -> p' (Some k) (Dynamic t w))
165-
-> (Incremental t (p' (Some k) (Dynamic t w)) -> Incremental t (p' (Some k) w))
166-
-> (forall a. k a -> v a -> DynamicWriterT t w m (v' a))
167-
-> DMap k v
168-
-> Event t (p k v)
169-
-> DynamicWriterT t w m (DMap k v', Event t (p k v'))
170-
traverseDMapWithKeyWithAdjustImpl base mapPatch weakenPatchWith mergeMyDynIncremental f (dm0 :: DMap k v) dm' = do
171-
(result0, result') <- lift $ base (\k v -> fmap DynamicWriterTLoweredResult $ runDynamicWriterT $ f k v) dm0 dm'
172-
let getValue (DynamicWriterTLoweredResult (v, _)) = v
173-
getWritten (DynamicWriterTLoweredResult (_, w)) = w
174-
liftedResult0 = DMap.map getValue result0
175-
liftedResult' = ffor result' $ mapPatch getValue
176-
liftedWritten0 :: Map (Some k) (Dynamic t w)
177-
liftedWritten0 = weakenDMapWith getWritten result0
178-
liftedWritten' = ffor result' $ weakenPatchWith getWritten
179-
--TODO: We should be able to improve the performance here by incrementally updating the mconcat of the merged Dynamics
180-
i <- holdIncremental liftedWritten0 liftedWritten'
181-
tellDyn $ fmap (mconcat . Map.elems) $ incrementalToDynamic $ mergeMyDynIncremental i
182-
return (liftedResult0, liftedResult')
183-
184-
traverseIntMapWithKeyWithAdjustImpl :: forall t w v' p p' v m. (PatchTarget (p' (Dynamic t w)) ~ IntMap (Dynamic t w), PatchTarget (p' w) ~ IntMap w, Patch (p' w), Patch (p' (Dynamic t w)), MonadFix m, Monoid w, Reflex t, MonadHold t m, Functor p, p ~ p')
185-
=> ( (IntMap.Key -> v -> m ((v', Dynamic t w)))
186-
-> IntMap v
187-
-> Event t (p v)
188-
-> m (IntMap (v', Dynamic t w), Event t (p (v', Dynamic t w)))
189-
)
190-
-> (Incremental t (p' (Dynamic t w)) -> Incremental t (p' w))
191-
-> (IntMap.Key -> v -> DynamicWriterT t w m v')
192-
-> IntMap v
193-
-> Event t (p v)
194-
-> DynamicWriterT t w m (IntMap v', Event t (p v'))
195-
traverseIntMapWithKeyWithAdjustImpl base mergeMyDynIncremental f (dm0 :: IntMap v) dm' = do
196-
(result0, result') <- lift $ base (\k v -> runDynamicWriterT $ f k v) dm0 dm'
197-
let liftedResult0 = fmap fst result0
198-
liftedResult' = fmap (fmap fst) result'
199-
liftedWritten0 :: IntMap (Dynamic t w)
200-
liftedWritten0 = fmap snd result0
201-
liftedWritten' = fmap (fmap snd) result'
202-
--TODO: We should be able to improve the performance here by incrementally updating the mconcat of the merged Dynamics
203-
i <- holdIncremental liftedWritten0 liftedWritten'
204-
tellDyn $ fmap (mconcat . IntMap.elems) $ incrementalToDynamic $ mergeMyDynIncremental i
205-
return (liftedResult0, liftedResult')
206-
207-
-- | Map a function over the output of a 'DynamicWriterT'.
208-
withDynamicWriterT :: (Monoid w, Monoid w', Reflex t, MonadHold t m, MonadFix m)
209-
=> (w -> w')
210-
-> DynamicWriterT t w m a
211-
-> DynamicWriterT t w' m a
212-
withDynamicWriterT f dw = do
213-
(r, d) <- lift $ do
214-
(r, d) <- runDynamicWriterT dw
215-
let d' = fmap f d
216-
return (r, d')
217-
tellDyn d
218-
return r
219-
220-
instance Requester t m => Requester t (DynamicWriterT t w m) where
221-
type Request (DynamicWriterT t w m) = Request m
222-
type Response (DynamicWriterT t w m) = Response m
223-
requesting = lift . requesting
224-
requesting_ = lift . requesting_
6+
import Reflex.DynamicWriter.Base as X
7+
import Reflex.DynamicWriter.Class as X

0 commit comments

Comments
 (0)