on develop help sign in
WIP
commit531cc28876212b1f01272892f07329c7011b95ca authorRyan Trinkle <ryan.trinkle@gmail.com> dateSun 15 Sep 2019, 19:29 (7 years ago) parent55a1e29
8 files changed+297−34
reflex.cabal+1 src/Data/TagMap.hs+31 src/Data/Unique/Tag/Local.hs+11 src/Data/Unique/Tag/Local/Internal.hs+51 src/Reflex/FanTag.hs+23 src/Reflex/PerformEvent/Base.hs+27−1 src/Reflex/Requester/Base.hs+152−32 src/Reflex/Requester/Class.hs+1−1
reflex.cabal+1
@@ -57,6 +57,7 @@ library
5757 containers >= 0.6 && < 0.7,
5858 data-default >= 0.5 && < 0.8,
5959 dependent-map >= 0.3 && < 0.4,
60+ dlist == 0.8.*,
6061 exception-transformers == 0.4.*,
6162 profunctors >= 5.3 && < 5.5,
6263 lens >= 4.7 && < 5,
src/Data/TagMap.hsnew file+31
@@ -0,0 +1,31 @@
1+{-# LANGUAGE PolyKinds #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+module Data.TagMap
4+ ( TagMap
5+ , unTagMap
6+ , fromDMap
7+ , toDMap
8+ , insert
9+ ) where
10+
11+import Data.IntMap (IntMap)
12+import qualified Data.IntMap as IntMap
13+import Data.Dependent.Map (DMap)
14+import qualified Data.Dependent.Map as DMap
15+import Data.Dependent.Sum (DSum (..))
16+import Data.Unique.Tag.Local
17+
18+import GHC.Exts (Any)
19+import Unsafe.Coerce
20+
21+-- | Like DMap, but with 'Data.Unique.Tag.Tag' as the keys. Implemented using 'Data.IntMap.IntMap' under the hood.
22+newtype TagMap x (v :: k -> *) = TagMap { unTagMap :: IntMap Any }
23+
24+fromDMap :: forall k x (v :: k -> *). DMap (Tag x) v -> TagMap x v
25+fromDMap = TagMap . IntMap.fromDistinctAscList . fmap (\((k :: Tag x (a :: k)) :=> v) -> (tagId k, (unsafeCoerce :: v a -> Any) v)) . DMap.toAscList
26+
27+toDMap :: forall x v. TagMap x v -> DMap (Tag x) v
28+toDMap = DMap.fromDistinctAscList . fmap (\(k, v) -> (unsafeTagFromId k :=> (unsafeCoerce :: Any -> v a) v)) . IntMap.toAscList . unTagMap
29+
30+insert :: forall x a v. Tag x a -> v a -> TagMap x v -> TagMap x v
31+insert k v = TagMap . IntMap.insert (tagId k) ((unsafeCoerce :: v a -> Any) v) . unTagMap
src/Data/Unique/Tag/Local.hsnew file+11
@@ -0,0 +1,11 @@
1+module Data.Unique.Tag.Local
2+ ( Tag
3+ , TagGen (..)
4+ , TagGenT
5+ , tagId
6+ , unsafeTagFromId
7+ , runTagGenT
8+ , mapTagGenT
9+ ) where
10+
11+import Data.Unique.Tag.Local.Internal
src/Data/Unique/Tag/Local/Internal.hsnew file+51
@@ -0,0 +1,51 @@
1+{-# LANGUAGE EmptyDataDecls #-}
2+{-# LANGUAGE DeriveFunctor #-}
3+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+{-# LANGUAGE TypeFamilies #-}
5+{-# LANGUAGE PolyKinds #-}
6+{-# LANGUAGE RankNTypes #-}
7+{-# LANGUAGE ScopedTypeVariables #-}
8+module Data.Unique.Tag.Local.Internal where
9+
10+import Control.Monad.Exception
11+import Control.Monad.Primitive
12+import Control.Monad.Reader
13+import Data.Primitive.MutVar
14+
15+newtype Tag x a = Tag Int
16+
17+tagId :: Tag x a -> Int
18+tagId (Tag n) = n
19+
20+-- | WARNING: If you construct a tag with the wrong type, it will result in
21+-- incorrect unsafeCoerce applications, which can segfault or cause arbitrary
22+-- other damage to your program
23+unsafeTagFromId :: Int -> Tag x a
24+unsafeTagFromId n = Tag n
25+
26+class TagGen m where
27+ type TagScope m :: *
28+ -- | Note: this will throw an exception if its internal counter would wrap around
29+ mkTag :: m (Tag (TagScope m) a)
30+
31+newtype TagGenT (s :: *) m a = TagGenT { unTagGenT :: ReaderT (MutVar (PrimState m) Int) m a }
32+ deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadException)
33+
34+instance MonadTrans (TagGenT s) where
35+ lift = TagGenT . lift
36+
37+data TagGenTScope (ps :: *) (s :: *)
38+
39+instance PrimMonad m => TagGen (TagGenT s m) where
40+ type TagScope (TagGenT s m) = s
41+ mkTag = TagGenT $ ReaderT $ \r -> do
42+ n <- atomicModifyMutVar' r $ \x -> (succ x, x)
43+ pure $ Tag n
44+
45+runTagGenT :: forall m a. PrimMonad m => (forall s. TagGenT s m a) -> m a
46+runTagGenT (TagGenT a :: TagGenT (TagGenTScope (PrimState m) ()) m a) = do
47+ r <- newMutVar minBound
48+ runReaderT a r
49+
50+mapTagGenT :: PrimState m ~ PrimState n => (m a -> n b) -> TagGenT s m a -> TagGenT s n b
51+mapTagGenT f (TagGenT a) = TagGenT $ mapReaderT f a
src/Reflex/FanTag.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# LANGUAGE PolyKinds #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+module Reflex.FanTag
4+ ( EventSelectorTag
5+ , unEventSelectorTag
6+ , fanTag
7+ , selectTag
8+ ) where
9+
10+import Data.Unique.Tag.Local
11+import Data.TagMap
12+import Reflex.Class
13+
14+import GHC.Exts (Any)
15+import Unsafe.Coerce
16+
17+newtype EventSelectorTag t x (v :: k -> *) = EventSelectorTag { unEventSelectorTag :: EventSelectorInt t Any }
18+
19+fanTag :: Reflex t => Event t (TagMap x v) -> EventSelectorTag t x v
20+fanTag = EventSelectorTag . fanInt . fmapCheap unTagMap
21+
22+selectTag :: forall t x v a. Reflex t => EventSelectorTag t x v -> Tag x a -> Event t (v a)
23+selectTag (EventSelectorTag s) = fmapCheap (unsafeCoerce :: Any -> v a) . selectInt s . tagId
src/Reflex/PerformEvent/Base.hs+27−1
@@ -68,13 +68,37 @@ instance (PrimMonad (HostFrame t), ReflexHost t) => PrimMonad (PerformEventT t m
6868 type PrimState (PerformEventT t m) = PrimState (HostFrame t)
6969 primitive = PerformEventT . lift . primitive
7070
71−instance (ReflexHost t, Ref m ~ Ref IO) => PerformEvent t (PerformEventT t m) where
71+instance (ReflexHost t, Ref m ~ Ref IO, PrimMonad (HostFrame t)) => PerformEvent t (PerformEventT t m) where
7272 type Performable (PerformEventT t m) = HostFrame t
7373 {-# INLINABLE performEvent_ #-}
7474 performEvent_ = PerformEventT . requesting_
7575 {-# INLINABLE performEvent #-}
7676 performEvent = PerformEventT . requestingIdentity
7777
78+-- | An Adjustable instance where "adjusting" just runs the new thing - nothing is done with the old thing
79+newtype NullAdjustable t m a = NullAdjustable { unNullAdjustable :: m a }
80+ deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadException)
81+
82+instance PrimMonad m => PrimMonad (NullAdjustable t m) where
83+ type PrimState (NullAdjustable t m) = PrimState m
84+
85+instance Adjustable t (PerformEvent t m) where
86+ runWithReplace a0 a' = PerformEventT $ do
87+ runWithReplace (unPerformEventT a0) a'
88+
89+{-
90+instance Adjustable t (NullAdjustable t m) where
91+ runWithReplace a0 a' = NullAdjustable $ do
92+ result0 <- lift a0
93+ result' <- requestingIdentity a'
94+ return (result0, result')
95+ traverseDMapWithKeyWithAdjust = defaultAdjustBase traversePatchDMapWithKey
96+ traverseDMapWithKeyWithAdjustWithMove = defaultAdjustBase traversePatchDMapWithMoveWithKey
97+-}
98+{-
99+ traverseIntMapWithKeyWithAdjust = defaultAdjustIntBase traverseIntMapPatchWithKey
100+-}
101+
78102instance (ReflexHost t, PrimMonad (HostFrame t)) => Adjustable t (PerformEventT t m) where
79103 runWithReplace outerA0 outerA' = PerformEventT $ runWithReplaceRequesterTWith f (coerce outerA0) (coerceEvent outerA')
80104 where f :: HostFrame t a -> Event t (HostFrame t b) -> RequesterT t (HostFrame t) Identity (HostFrame t) (a, Event t b)
@@ -82,9 +106,11 @@ instance (ReflexHost t, PrimMonad (HostFrame t)) => Adjustable t (PerformEventT
82106 result0 <- lift a0
83107 result' <- requestingIdentity a'
84108 return (result0, result')
109+ {-
85110 traverseIntMapWithKeyWithAdjust f outerDm0 outerDm' = PerformEventT $ traverseIntMapWithKeyWithAdjustRequesterTWith (defaultAdjustIntBase traverseIntMapPatchWithKey) patchIntMapNewElementsMap mergeIntIncremental (\k v -> unPerformEventT $ f k v) (coerce outerDm0) (coerceEvent outerDm')
86111 traverseDMapWithKeyWithAdjust f outerDm0 outerDm' = PerformEventT $ traverseDMapWithKeyWithAdjustRequesterTWith (defaultAdjustBase traversePatchDMapWithKey) mapPatchDMap weakenPatchDMapWith patchMapNewElementsMap mergeMapIncremental (\k v -> unPerformEventT $ f k v) (coerce outerDm0) (coerceEvent outerDm')
87112 traverseDMapWithKeyWithAdjustWithMove f outerDm0 outerDm' = PerformEventT $ traverseDMapWithKeyWithAdjustRequesterTWith (defaultAdjustBase traversePatchDMapWithMoveWithKey) mapPatchDMapWithMove weakenPatchDMapWithMoveWith patchMapWithMoveNewElementsMap mergeMapIncrementalWithMove (\k v -> unPerformEventT $ f k v) (coerce outerDm0) (coerceEvent outerDm')
113+-}
88114
89115defaultAdjustBase :: forall t v v2 k' p. (Monad (HostFrame t), PrimMonad (HostFrame t), Reflex t)
90116 => ((forall a. k' a -> v a -> HostFrame t (v2 a)) -> p k' v -> HostFrame t (p k' v2))
src/Reflex/Requester/Base.hs+152−32
@@ -15,26 +15,24 @@
1515{-# LANGUAGE TypeFamilies #-}
1616{-# LANGUAGE TypeOperators #-}
1717{-# LANGUAGE UndecidableInstances #-}
18+{-# LANGUAGE InstanceSigs #-}
1819#ifdef USE_REFLEX_OPTIMIZER
1920{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
2021#endif
2122module Reflex.Requester.Base
2223 ( RequesterT (..)
2324 , runRequesterT
24− , withRequesterT
25− , runWithReplaceRequesterTWith
26− , traverseIntMapWithKeyWithAdjustRequesterTWith
27− , traverseDMapWithKeyWithAdjustRequesterTWith
28− , RequesterData
29− , RequesterDataKey
30− , traverseRequesterData
31− , forRequesterData
32− , requesterDataToList
33− , singletonRequesterData
34− , matchResponsesWithRequests
35− , multiEntry
36− , unMultiEntry
37− , requesting'
25+-- , withRequesterT
26+-- , RequesterData
27+-- , RequesterDataKey
28+-- , traverseRequesterData
29+-- , forRequesterData
30+-- , requesterDataToList
31+-- , singletonRequesterData
32+-- , matchResponsesWithRequests
33+-- , multiEntry
34+-- , unMultiEntry
35+-- , requesting'
3836 ) where
3937
4038import Reflex.Class
@@ -45,6 +43,8 @@ import Reflex.PerformEvent.Class
4543import Reflex.PostBuild.Class
4644import Reflex.Requester.Class
4745import Reflex.TriggerEvent.Class
46+import Reflex.EventWriter.Base
47+import Reflex.EventWriter.Class
4848
4949import Control.Applicative (liftA2)
5050import Control.Monad.Exception
@@ -68,8 +68,144 @@ import Data.Proxy
6868import qualified Data.Semigroup as S
6969import Data.Some (Some(Some))
7070import Data.Type.Equality
71−import Data.Unique.Tag
71+import Data.Sequence (Seq)
72+import qualified Data.Sequence as Seq
73+import Data.TagMap
74+import Reflex.FanTag
75+import Data.Unique.Tag.Local
76+import qualified Data.Unique.Tag as Global
77+import Data.GADT.Compare
78+
79+data RequestData m request = forall s. RequestData !(Global.Tag (PrimState m) s) !(Seq (RequestEnvelope s request))
80+data ResponseData m response = forall s. ResponseData !(Global.Tag (PrimState m) s) !(TagMap s response)
81+
82+runRequesterT :: forall t request response m a
83+ . ( Reflex t
84+ , PrimMonad m
85+ , MonadFix m
86+ )
87+ => RequesterT t request response m a
88+ -> Event t (ResponseData m response)
89+ -> m (a, Event t (RequestData m request))
90+runRequesterT (RequesterT a) wrappedResponses = withRequesterInternalT $ \(requests :: Event t (Seq (RequestEnvelope s request))) -> do
91+ t :: Global.Tag (PrimState m) s <- lift Global.newTag
92+ result <- a
93+ let responses = fforMaybe wrappedResponses $ \(ResponseData s m) -> case s `geq` t of
94+ Nothing -> Nothing --TODO: Warn somehow
95+ Just Refl -> Just m
96+ pure (responses, (result, fmap (RequestData t) requests))
97+
98+instance MonadTrans (RequesterInternalT s t request response) where
99+ lift = RequesterInternalT . lift . lift . lift
100+
101+instance MonadTrans (RequesterT t request response) where
102+ lift a = RequesterT $ RequesterInternalT $ lift $ lift $ lift a
103+
104+-- | Run a 'RequesterT' action. The resulting 'Event' will fire whenever
105+-- requests are made, and responses should be provided in the input 'Event'.
106+-- The 'Tag' keys will be used to return the responses to the same place the
107+-- requests were issued.
108+withRequesterInternalT :: (Reflex t, PrimMonad m, MonadFix m)
109+ => (forall s. Event t (Seq (RequestEnvelope s request)) -> RequesterInternalT s t request response m (Event t (TagMap s response), a))
110+ -> m a
111+withRequesterInternalT f = runTagGenT $ do
112+ rec let RequesterInternalT a = f requests
113+ ((responses, result), requests) <- runEventWriterT $ runReaderT a (fanTag responses)
114+ pure result
115+
116+data RequestEnvelope s request = forall a. RequestEnvelope {-# UNPACK #-} !(Maybe (Tag s a)) !(request a)
117+
118+newtype RequesterT t (request :: * -> *) (response :: * -> *) m a = RequesterT { unRequesterT :: forall s. RequesterInternalT s t request response m a }
119+
120+instance Functor m => Functor (RequesterT t request response m) where
121+ fmap f (RequesterT x) = RequesterT $ fmap f x
122+
123+instance Monad m => Applicative (RequesterT t request response m) where
124+ pure x = RequesterT $ pure x
125+ RequesterT f <*> RequesterT x = RequesterT $ f <*> x
126+ liftA2 f (RequesterT a) (RequesterT b) = RequesterT $ liftA2 f a b
127+ RequesterT f <* RequesterT x = RequesterT $ f <* x
128+ RequesterT f *> RequesterT x = RequesterT $ f *> x
129+
130+instance Monad m => Monad (RequesterT t request response m) where
131+ return = pure
132+ RequesterT mx >>= f = RequesterT $ mx >>= \x -> case f x of
133+ RequesterT y -> y
134+
135+instance MonadFix m => MonadFix (RequesterT t request response m) where
136+ mfix f = RequesterT $ mfix $ \x -> case f x of
137+ RequesterT a -> a
138+
139+instance MonadIO m => MonadIO (RequesterT t request respnose m) where
140+ liftIO a = RequesterT $ liftIO a
141+
142+instance MonadException m => MonadException (RequesterT t request respnose m) where
143+ throw e = RequesterT $ throw e
144+
145+newtype RequesterInternalT s t request response m a = RequesterInternalT { unRequesterInternalT :: ReaderT (EventSelectorTag t s response) (EventWriterT t (Seq (RequestEnvelope s request)) (TagGenT s m)) a }
146+ deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadException)
147+
148+instance MonadSample t m => MonadSample t (RequesterT t request response m)
149+instance MonadHold t m => MonadHold t (RequesterT t request response m)
150+instance PostBuild t m => PostBuild t (RequesterT t request response m)
151+instance TriggerEvent t m => TriggerEvent t (RequesterT t request response m)
152+
153+instance PrimMonad m => PrimMonad (RequesterT t request response m) where
154+ type PrimState (RequesterT t request response m) = PrimState m
155+ primitive = lift . primitive
156+
157+-- TODO: Monoid and Semigroup can likely be derived once StateT has them.
158+instance (Monoid a, Monad m) => Monoid (RequesterT t request response m a) where
159+ mempty = pure mempty
160+ mappend = liftA2 mappend
72161
162+instance (S.Semigroup a, Monad m) => S.Semigroup (RequesterT t request response m a) where
163+ (<>) = liftA2 (S.<>)
164+
165+instance PerformEvent t m => PerformEvent t (RequesterT t request response m) where
166+ type Performable (RequesterT t request response m) = Performable m
167+ performEvent_ = lift . performEvent_
168+ performEvent = lift . performEvent
169+
170+instance MonadRef m => MonadRef (RequesterT t request response m) where
171+ type Ref (RequesterT t request response m) = Ref m
172+ newRef = lift . newRef
173+ readRef = lift . readRef
174+ writeRef r = lift . writeRef r
175+
176+instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (RequesterT t request response m) where
177+ newEventWithTrigger = lift . newEventWithTrigger
178+ newFanEventWithTrigger f = lift $ newFanEventWithTrigger f
179+
180+instance MonadReader r m => MonadReader r (RequesterT t request response m) where
181+ ask = lift ask
182+ local f (RequesterT a) = RequesterT $ RequesterInternalT $ mapReaderT (mapEventWriterT $ mapTagGenT $ local f) $ unRequesterInternalT a
183+ reader = lift . reader
184+
185+instance (Reflex t, PrimMonad m) => Requester t (RequesterT t request response m) where
186+ type Request (RequesterT t request response m) = request
187+ type Response (RequesterT t request response m) = response
188+ requesting e = RequesterT $ RequesterInternalT $ do
189+ t <- lift $ lift mkTag
190+ tellEvent $ fmapCheap (Seq.singleton . RequestEnvelope (Just t)) e
191+ s <- ask
192+ pure $ selectTag s t
193+ requesting_ e = RequesterT $ RequesterInternalT $ do
194+ tellEvent $ fmapCheap (Seq.singleton . RequestEnvelope Nothing) e
195+
196+
197+{-# INLINABLE runWithReplaceRequesterTWith #-}
198+runWithReplaceRequesterTWith :: forall m t request response a b. (Reflex t, MonadHold t m
199+ , MonadFix m
200+ )
201+ => (forall a' b'. m a' -> Event t (m b') -> RequesterT t request response m (a', Event t b'))
202+ -> RequesterT t request response m a
203+ -> Event t (RequesterT t request response m b)
204+ -> RequesterT t request response m (a, Event t b)
205+runWithReplaceRequesterTWith f (RequesterT a0) a' = RequesterT $ do
206+ pure undefined
207+
208+{-
73209import GHC.Exts (Any)
74210import Unsafe.Coerce
75211
@@ -244,23 +380,6 @@ newtype RequesterT t request (response :: * -> *) m a = RequesterT { unRequester
244380#endif
245381 )
246382
247−deriving instance MonadSample t m => MonadSample t (RequesterT t request response m)
248−deriving instance MonadHold t m => MonadHold t (RequesterT t request response m)
249−deriving instance PostBuild t m => PostBuild t (RequesterT t request response m)
250−deriving instance TriggerEvent t m => TriggerEvent t (RequesterT t request response m)
251−
252−instance PrimMonad m => PrimMonad (RequesterT t request response m) where
253− type PrimState (RequesterT t request response m) = PrimState m
254− primitive = lift . primitive
255−
256−-- TODO: Monoid and Semigroup can likely be derived once StateT has them.
257−instance (Monoid a, Monad m) => Monoid (RequesterT t request response m a) where
258− mempty = pure mempty
259− mappend = liftA2 mappend
260−
261−instance (S.Semigroup a, Monad m) => S.Semigroup (RequesterT t request response m a) where
262− (<>) = liftA2 (S.<>)
263−
264383
265384-- | Run a 'RequesterT' action. The resulting 'Event' will fire whenever
266385-- requests are made, and responses should be provided in the input 'Event'.
@@ -535,3 +654,4 @@ matchResponsesWithRequests f send recv = do
535654 ( singletonRequesterData k rsp
536655 , PatchMap $ Map.singleton n Nothing
537656 )
657+-}
src/Reflex/Requester/Class.hs+1−1
@@ -40,7 +40,7 @@ class (Reflex t, Monad m) => Requester t m | m -> t where
4040 requesting :: Event t (Request m a) -> m (Event t (Response m a))
4141 -- | Emit a request whenever the given 'Event' fires, and ignore all responses.
4242 requesting_ :: Event t (Request m a) -> m ()
43−
43+--TODO: Make Requester polykinded, where Request m and Response m both take an argument of the same kind
4444
4545instance Requester t m => Requester t (ReaderT r m) where
4646 type Request (ReaderT r m) = Request m