@@ -4,12 +4,12 @@
4{-# LANGUAGE ExistentialQuantification #-}
4{-# LANGUAGE ExistentialQuantification #-}
5{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7−{-# LANGUAGE KindSignatures #-}
8{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
9{-# LANGUAGE Rank2Types #-}
8{-# LANGUAGE Rank2Types #-}
10{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE TypeFamilies #-}
12{-# LANGUAGE UndecidableInstances #-}
11{-# LANGUAGE UndecidableInstances #-}
12+{-# LANGUAGE StandaloneDeriving #-}
13#ifdef USE_REFLEX_OPTIMIZER
13#ifdef USE_REFLEX_OPTIMIZER
14{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
14{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
@@ -21,6 +21,7 @@ module Reflex.Requester.Base
23import Reflex.Class
23import Reflex.Class
24+import Reflex.EventWriter
24import Reflex.Host.Class
25import Reflex.Host.Class
25import Reflex.PerformEvent.Class
26import Reflex.PerformEvent.Class
26import Reflex.PostBuild.Class
27import Reflex.PostBuild.Class
@@ -33,31 +34,34 @@ import Control.Monad.Primitive
33import Control.Monad.Reader
34import Control.Monad.Reader
34import Control.Monad.Ref
35import Control.Monad.Ref
35import Control.Monad.State.Strict
36import Control.Monad.State.Strict
36import Data.Dependent.Map (DMap, DSum (..))
38import Data.Dependent.Map (DMap, DSum (..))
37import qualified Data.Dependent.Map as DMap
39import qualified Data.Dependent.Map as DMap
38import Data.Functor.Misc
40import Data.Functor.Misc
39−import qualified Data.List.NonEmpty as NonEmpty
41−import Data.Some (Some)
42−import qualified Data.Some as Some
44import Data.Unique.Tag
41import Data.Unique.Tag
46-- | A basic implementation of 'Requester'.
43-- | A basic implementation of 'Requester'.
47−newtype RequesterT t request response m a = RequesterT { unRequesterT :: StateT [Event t (DMap (Tag (PrimState m)) request)] (ReaderT (EventSelector t (WrapArg response (Tag (PrimState m)))) m) a }
44+newtype RequesterT t request response m a = RequesterT { unRequesterT :: EventWriterT t (DMap (Tag (PrimState m)) request) (ReaderT (EventSelector t (WrapArg response (Tag (PrimState m)))) m) a }
48 deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadException)
45 deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadException)
47+deriving instance MonadSample t m => MonadSample t (RequesterT t request response m)
48+deriving instance MonadHold t m => MonadHold t (RequesterT t request response m)
49+deriving instance PostBuild t m => PostBuild t (RequesterT t request response m)
50+deriving instance TriggerEvent t m => TriggerEvent t (RequesterT t request response m)
50-- | Run a 'RequesterT' action. The resulting 'Event' will fire whenever
52-- | Run a 'RequesterT' action. The resulting 'Event' will fire whenever
51-- requests are made, and responses should be provided in the input 'Event'.
53-- requests are made, and responses should be provided in the input 'Event'.
52-- The 'Tag' keys will be used to return the responses to the same place the
54-- The 'Tag' keys will be used to return the responses to the same place the
53-- requests were issued.
55-- requests were issued.
54runRequesterT :: (Reflex t, Monad m)
57runRequesterT :: (Reflex t, Monad m)
55 => RequesterT t request response m a
58 => RequesterT t request response m a
56 -> Event t (DMap (Tag (PrimState m)) response)
59 -> Event t (DMap (Tag (PrimState m)) response)
57 -> m (a, Event t (DMap (Tag (PrimState m)) request))
60 -> m (a, Event t (DMap (Tag (PrimState m)) request))
58runRequesterT (RequesterT a) responses = do
61runRequesterT (RequesterT a) responses = do
62+ (result, requests) <- runReaderT (runEventWriterT a) $ fan $
59− (result, requests) <- runReaderT (runStateT a mempty) $ fan $ mapKeyValuePairsMonotonic (\(t :=> e) -> WrapArg t :=> Identity e) <$> responses
63+ mapKeyValuePairsMonotonic (\(t :=> e) -> WrapArg t :=> Identity e) <$> responses
60− return (result, mergeWith DMap.union requests)
64+ return (result, requests)
62instance (Reflex t, PrimMonad m) => Requester t (RequesterT t request response m) where
66instance (Reflex t, PrimMonad m) => Requester t (RequesterT t request response m) where
63 type Request (RequesterT t request response m) = request
67 type Request (RequesterT t request response m) = request
@@ -66,96 +70,17 @@ instance (Reflex t, PrimMonad m) => Requester t (RequesterT t request response m
66 t <- lift newTag
70 t <- lift newTag
67 s <- RequesterT ask
71 s <- RequesterT ask
68 (req, result) <- a $ select s $ WrapArg t
72 (req, result) <- a $ select s $ WrapArg t
69− RequesterT $ modify $ (:) $ DMap.singleton t <$> req
73+ RequesterT $ tellEvent $ DMap.singleton t <$> req
70 return result
74 return result
72instance MonadTrans (RequesterT t request response) where
76instance MonadTrans (RequesterT t request response) where
73 lift = RequesterT . lift . lift
77 lift = RequesterT . lift . lift
75−instance MonadSample t m => MonadSample t (RequesterT t request response m) where
76− sample = lift . sample
78−instance MonadHold t m => MonadHold t (RequesterT t request response m) where
79− hold v0 = lift . hold v0
80− holdDyn v0 = lift . holdDyn v0
81− holdIncremental v0 = lift . holdIncremental v0
83−instance (Reflex t, MonadAdjust t m, MonadHold t m) => MonadAdjust t (RequesterT t request response m) where
84− runWithReplace = runWithReplaceRequesterTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
85− sequenceDMapWithAdjust = sequenceDMapWithAdjustRequesterTWith $ \dm0 dm' -> lift $ sequenceDMapWithAdjust dm0 dm'
87−-- | Given a function like 'runWithReplace' for the underlying monad, implement
88−-- 'runWithReplace' for 'RequesterT'. This is necessary when the underlying
89−-- monad doesn't have a 'MonadAdjust' instance or to override the default
90−-- 'MonadAdjust' behavior.
91−runWithReplaceRequesterTWith :: forall m t request response a b. (Reflex t, MonadHold t m)
95− -> RequesterT t request response m (a', Event t b')
97− -> RequesterT t request response m a
98− -> Event t (RequesterT t request response m b)
99− -> RequesterT t request response m (a, Event t b)
100−runWithReplaceRequesterTWith f a0 a' = do
101− response <- RequesterT ask
102− let g :: RequesterT t request response m c -> m (c, [Event t (DMap (Tag (PrimState m)) request)])
103− g (RequesterT r) = runReaderT (runStateT r mempty) response
104− (result0, result') <- f (g a0) $ g <$> a'
105− request <- holdDyn (fmap (mconcat . NonEmpty.toList) $ mergeList $ snd result0) $ fmap (mconcat . NonEmpty.toList) . mergeList . snd <$> result'
106− -- 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.)
107− RequesterT $ modify $ (:) $ coincidence $ updated request
108− RequesterT $ modify $ (:) $ switch $ current request
109− return (fst result0, fst <$> result')
111−-- | Like 'runWithReplaceRequesterTWith', but for 'sequenceDMapWithAdjust'.
112−sequenceDMapWithAdjustRequesterTWith :: (GCompare k, Reflex t, MonadHold t m)
113− => (forall k'. GCompare k'
115− -> Event t (PatchDMap k' m)
116− -> RequesterT t request response m (DMap k' Identity, Event t (PatchDMap k' Identity))
118− -> DMap k (RequesterT t request response m)
119− -> Event t (PatchDMap k (RequesterT t request response m))
120− -> RequesterT t request response m (DMap k Identity, Event t (PatchDMap k Identity))
121−sequenceDMapWithAdjustRequesterTWith f (dm0 :: DMap k (RequesterT t request response m)) dm' = do
122− response <- RequesterT ask
123− let inputTransform :: forall a. DMapTransform a k (WrapArg ((,) [Event t (DMap (Tag (PrimState m)) request)]) k) (RequesterT t request response m) m
124− inputTransform = DMapTransform WrapArg (\(RequesterT v) -> swap <$> runReaderT (runStateT v mempty) response)
125− (children0, children') <- f (mapKeysAndValuesMonotonic inputTransform dm0) $ mapPatchKeysAndValuesMonotonic inputTransform <$> dm'
126− let result0 = mapKeyValuePairsMonotonic (\(WrapArg k :=> Identity (_, v)) -> k :=> Identity v) children0
127− result' = ffor children' $ \(PatchDMap p) -> PatchDMap $
128− mapKeyValuePairsMonotonic (\(WrapArg k :=> ComposeMaybe mv) -> k :=> ComposeMaybe (fmap (Identity . snd . runIdentity) mv)) p
129− requests0 :: DMap (Const2 (Some k) (DMap (Tag (PrimState m)) request)) (Event t)
130− requests0 = mapKeyValuePairsMonotonic (\(WrapArg k :=> Identity (r, _)) -> Const2 (Some.This k) :=> mergeWith DMap.union r) children0
131− requests' :: Event t (PatchDMap (Const2 (Some k) (DMap (Tag (PrimState m)) request)) (Event t))
132− requests' = ffor children' $ \(PatchDMap p) -> PatchDMap $
133− mapKeyValuePairsMonotonic (\(WrapArg k :=> ComposeMaybe mv) -> Const2 (Some.This k) :=> ComposeMaybe (fmap (mergeWith DMap.union . fst . runIdentity) mv)) p
134− childRequestMap <- holdIncremental requests0 requests'
135− -- 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.)
136− RequesterT $ modify $ (:) $ coincidence $ ffor requests' $ \(PatchDMap p) -> mergeWith DMap.union $ catMaybes $ ffor (DMap.toList p) $ \(Const2 _ :=> ComposeMaybe me) -> me
137− RequesterT $ modify $ (:) $ ffor (mergeIncremental childRequestMap) $ \m ->
138− mconcat $ (\(Const2 _ :=> Identity reqs) -> reqs) <$> DMap.toList m
139− return (result0, result')
141instance PerformEvent t m => PerformEvent t (RequesterT t request response m) where
79instance PerformEvent t m => PerformEvent t (RequesterT t request response m) where
142 type Performable (RequesterT t request response m) = Performable m
80 type Performable (RequesterT t request response m) = Performable m
143 performEvent_ = lift . performEvent_
81 performEvent_ = lift . performEvent_
144 performEvent = lift . performEvent
82 performEvent = lift . performEvent
146−instance PostBuild t m => PostBuild t (RequesterT t request response m) where
147− getPostBuild = lift getPostBuild
149−instance TriggerEvent t m => TriggerEvent t (RequesterT t request response m) where
150− newTriggerEvent = lift newTriggerEvent
151− newTriggerEventWithOnComplete = lift newTriggerEventWithOnComplete
152− newEventWithLazyTriggerWithOnComplete = lift . newEventWithLazyTriggerWithOnComplete
154−instance MonadReader r m => MonadReader r (RequesterT t request response m) where
156− local f (RequesterT a) = RequesterT $ mapStateT (mapReaderT $ local f) a
157− reader = lift . reader
159instance MonadRef m => MonadRef (RequesterT t request response m) where
84instance MonadRef m => MonadRef (RequesterT t request response m) where
160 type Ref (RequesterT t request response m) = Ref m
85 type Ref (RequesterT t request response m) = Ref m
161 newRef = lift . newRef
86 newRef = lift . newRef
@@ -166,15 +91,43 @@ instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (RequesterT
166 newEventWithTrigger = lift . newEventWithTrigger
91 newEventWithTrigger = lift . newEventWithTrigger
167 newFanEventWithTrigger f = lift $ newFanEventWithTrigger f
92 newFanEventWithTrigger f = lift $ newFanEventWithTrigger f
169−--------------------------------------------------------------------------------
94+instance MonadReader r m => MonadReader r (RequesterT t request response m) where
170−-- Internal functions
95+ ask = lift ask
171−--------------------------------------------------------------------------------
96+ local f (RequesterT (EventWriterT a)) = RequesterT $ EventWriterT $ mapStateT (mapReaderT $ local f) a
97+ reader = lift . reader
173−data DMapTransform (a :: *) k k' v v' = forall (b :: *). DMapTransform !(k a -> k' b) !(v a -> v' b)
99+instance (Reflex t, MonadAdjust t m, MonadHold t m) => MonadAdjust t (RequesterT t request response m) where
100+ runWithReplace (RequesterT a) em = RequesterT $ runWithReplace a (coerceEvent em)
101+ sequenceDMapWithAdjust dm edm = RequesterT $ sequenceDMapWithAdjust (coerce dm) (coerceEvent edm)
175−mapPatchKeysAndValuesMonotonic :: (forall a. DMapTransform a k k' v v') -> PatchDMap k v -> PatchDMap k' v'
103+runWithReplaceRequesterTWith :: forall m t request response a b. (Reflex t, MonadHold t m)
176−mapPatchKeysAndValuesMonotonic x (PatchDMap p) = PatchDMap $ mapKeyValuePairsMonotonic (\(k :=> ComposeMaybe mv) -> case x of DMapTransform f g -> f k :=> ComposeMaybe (fmap g mv)) p
104+ => (forall a' b'. m a' -> Event t (m b') -> RequesterT t request response m (a', Event t b'))
105+ -> RequesterT t request response m a
106+ -> Event t (RequesterT t request response m b)
107+ -> RequesterT t request response m (a, Event t b)
108+runWithReplaceRequesterTWith f a0 a' =
109+ let f' :: forall a' b'. ReaderT (EventSelector t (WrapArg response (Tag (PrimState m)))) m a'
110+ -> Event t (ReaderT (EventSelector t (WrapArg response (Tag (PrimState m)))) m b')
111+ -> EventWriterT t (DMap (Tag (PrimState m)) request) (ReaderT (EventSelector t (WrapArg response (Tag (PrimState m)))) m) (a', Event t b')
113+ r <- EventWriterT $ ask
114+ unRequesterT (f (runReaderT x r) (fmap (`runReaderT` r) y))
115+ in RequesterT $ runWithReplaceEventWriterTWith f' (coerce a0) (coerceEvent a')
178−mapKeysAndValuesMonotonic :: (forall a. DMapTransform a k k' v v') -> DMap k v -> DMap k' v'
117+sequenceDMapWithAdjustRequesterTWith :: (GCompare k, Reflex t, MonadHold t m)
118+ => (forall k'. GCompare k' => DMap k' m -> Event t (PatchDMap k' m) -> RequesterT t request response m (DMap k' Identity, Event t (PatchDMap k' Identity)))
119+ -> DMap k (RequesterT t request response m)
120+ -> Event t (PatchDMap k (RequesterT t request response m))
121+ -> RequesterT t request response m (DMap k Identity, Event t (PatchDMap k Identity))
122+sequenceDMapWithAdjustRequesterTWith f (dm0 :: DMap k (RequesterT t request response m)) dm' =
179−mapKeysAndValuesMonotonic x = mapKeyValuePairsMonotonic $ \(k :=> v) -> case x of
123+ let dmapUnwrap r = mapKeyValuePairsMonotonic $ \(k :=> v) -> k :=> runReaderT v r
180− DMapTransform f g -> f k :=> g v
124+ patchDmapUnwrap r (PatchDMap p) = PatchDMap $ mapKeyValuePairsMonotonic
125+ (\(k :=> ComposeMaybe mv) -> k :=> ComposeMaybe (fmap (`runReaderT` r) mv)) p
126+ f' :: forall k'. GCompare k'
127+ => DMap k' (ReaderT (EventSelector t (WrapArg response (Tag (PrimState m)))) m)
128+ -> Event t (PatchDMap k' (ReaderT (EventSelector t (WrapArg response (Tag (PrimState m)))) m))
129+ -> EventWriterT t (DMap (Tag (PrimState m)) request) (ReaderT (EventSelector t (WrapArg response (Tag (PrimState m)))) m) (DMap k' Identity, Event t (PatchDMap k' Identity))
131+ r <- EventWriterT $ ask
132+ unRequesterT (f (dmapUnwrap r x) (fmap (patchDmapUnwrap r) y))
133+ in RequesterT $ sequenceDMapWithAdjustEventWriterTWith f' (coerce dm0) (coerceEvent dm')