@@ -47,6 +47,8 @@ import Data.GADT.Compare (GCompare (..), GEq (..), GOrdering (..))
47import Data.IntMap.Strict (IntMap)
47import Data.IntMap.Strict (IntMap)
48import qualified Data.IntMap.Strict as IntMap
48import qualified Data.IntMap.Strict as IntMap
49import Data.List.NonEmpty (NonEmpty (..))
49import Data.List.NonEmpty (NonEmpty (..))
50+import Data.List.NonEmpty.Deferred (NonEmptyDeferred)
51+import qualified Data.List.NonEmpty.Deferred as NonEmptyDeferred
50import Data.Map (Map)
52import Data.Map (Map)
51import qualified Data.Map as Map
53import qualified Data.Map as Map
52import Data.Semigroup
54import Data.Semigroup
@@ -54,45 +56,7 @@ import Data.Some (Some)
54import Data.Tuple
56import Data.Tuple
55import Data.Type.Equality
57import Data.Type.Equality
59−{-# DEPRECATED TellId "Do not construct this directly; use tellId instead" #-}
61− = TellId Int -- ^ WARNING: Do not construct this directly; use 'tellId' instead
62− deriving (Show, Eq, Ord, Enum)
64−tellId :: Int -> TellId w w
68−tellIdRefl :: TellId w x -> w :~: x
69−tellIdRefl _ = unsafeCoerce Refl
71−withTellIdRefl :: TellId w x -> (w ~ x => r) -> r
72−withTellIdRefl tid r = case tellIdRefl tid of
75−instance GEq (TellId w) where
83−instance GCompare (TellId w) where
87− case a `compare` b of
92−data EventWriterState t w = EventWriterState
59+type EventWriterState t w = Maybe (NonEmptyDeferred (Event t w))
93− { _eventWriterState_nextId :: {-# UNPACK #-} !Int -- Always negative (and decreasing over time)
94− , _eventWriterState_told :: ![DSum (TellId w) (Event t)] -- In increasing order
97-- | A basic implementation of 'EventWriter'.
61-- | A basic implementation of 'EventWriter'.
98newtype EventWriterT t w m a = EventWriterT { unEventWriterT :: StateT (EventWriterState t w) m a }
62newtype EventWriterT t w m a = EventWriterT { unEventWriterT :: StateT (EventWriterState t w) m a }
@@ -101,20 +65,11 @@ newtype EventWriterT t w m a = EventWriterT { unEventWriterT :: StateT (EventWri
101-- | Run a 'EventWriterT' action.
65-- | Run a 'EventWriterT' action.
102runEventWriterT :: forall t m w a. (Reflex t, Monad m, Semigroup w) => EventWriterT t w m a -> m (a, Event t w)
66runEventWriterT :: forall t m w a. (Reflex t, Monad m, Semigroup w) => EventWriterT t w m a -> m (a, Event t w)
103runEventWriterT (EventWriterT a) = do
67runEventWriterT (EventWriterT a) = do
104− (result, requests) <- runStateT a $ EventWriterState (-1) []
68+ (result, requests) <- runStateT a Nothing
105− let combineResults :: DMap (TellId w) Identity -> w
69+ return (result, maybe never (sconcat . NonEmptyDeferred.toNonEmpty) requests)
106− combineResults = sconcat
107− . (\(h : t) -> h :| t) -- Unconditional; 'merge' guarantees that it will only fire with non-empty DMaps
108− . DMap.foldlWithKey (\vs tid (Identity v) -> withTellIdRefl tid $ v : vs) [] -- This is where we finally reverse the DMap to get things in the correct order
109− return (result, fmap combineResults $ merge $ DMap.fromDistinctAscList $ _eventWriterState_told requests) --TODO: We can probably make this fromDistinctAscList more efficient by knowing the length in advance, but this will require exposing internals of DMap; also converting it to use a strict list might help
111instance (Reflex t, Monad m, Semigroup w) => EventWriter t w (EventWriterT t w m) where
71instance (Reflex t, Monad m, Semigroup w) => EventWriter t w (EventWriterT t w m) where
112− tellEvent w = EventWriterT $ modify $ \old ->
72+ tellEvent w = EventWriterT $ modify (<> Just (NonEmptyDeferred.singleton w))
113− let myId = _eventWriterState_nextId old
115− { _eventWriterState_nextId = pred myId
116− , _eventWriterState_told = (tellId myId :=> w) : _eventWriterState_told old
119instance MonadTrans (EventWriterT t w) where
74instance MonadTrans (EventWriterT t w) where
120 lift = EventWriterT . lift
75 lift = EventWriterT . lift