on 75e8fd5 help sign in
21 files changed+81−300
since splitsnapshots
unifiedsplit
ChangeLog.md−26 Quickref.md−1 README.md+22−14 reflex.cabal+8−29 src/Reflex/BehaviorWriter/Base.hs+4−13 src/Reflex/Class.hs−13 src/Reflex/Dynamic.hs+1−1 src/Reflex/DynamicWriter/Base.hs+4−13 src/Reflex/EventWriter/Base.hs+4−14 src/Reflex/Host/Headless.hs+9−11 src/Reflex/PerformEvent/Base.hs−2 src/Reflex/PostBuild/Base.hs−2 src/Reflex/Profiled.hs−1 src/Reflex/Pure.hs−4 src/Reflex/Query/Base.hs−4 src/Reflex/Requester/Base.hs+26−95 src/Reflex/Spider/Internal.hs+1−36 src/Reflex/TriggerEvent/Base.hs−2 test/Headless.hs−10 test/Reflex/Plan/Pure.hs−1 test/Reflex/Test/Micro.hs+2−8
ChangeLog.md−26
@@ -1,33 +1,7 @@
11# Revision history for reflex
22
3−## 0.8.2.0
4−
5−* Add `matchResponseMapWithRequests`, which it similar to `matchResponsesWithRequests` but allows processing of multiple responses at once.
6−
7−## 0.8.1.1
8−
9−* Allow newer hlint for older GHCs, and add upper bound for newer GHCs
10−
11−## 0.8.1.0
12−
13−* Add support for GHC 8.10
14−* Drop support for GHC < 8.4
15−
16−## 0.8.0.0
17−
18−* Replace 0.7.2.0 with 0.8.0.0 to reflect the `MonadHold` interface change. Deprecates 0.7.2.0.
19−
20−## 0.7.2.0 -- *Deprecated*
21−
22−* ([#416](https://github.com/reflex-frp/reflex/pull/416)) Add `now :: m (Event t ())` to `MonadHold`.
23−* Extend some dependency version bounds
24−* Fix HLint 3 test
25−
263## 0.7.1.1
274
28−*Backport release*.
29−Changes do not carry forward to 0.7.2.0.
30−
315* Add support for GHC 8.10
326* Drop support for GHC < 8.4
337* Extend some dependency version bounds
Quickref.md−1
@@ -54,7 +54,6 @@ Since MonadHold depends on MonadSample, any [S] function also runs in [H] contex
5454[ ] difference :: Event a -> Event b -> Event a
5555[ ] align :: Event a -> Event b -> Event (These a b)
5656[ ] alignWith :: (These a b -> c) -> Event a -> Event b -> Event c
57− -- Note align functions from Data.Align in semialign package
5857[ ] mergeWith :: (a -> a -> a) -> [Event a] -> Event a
5958[ ] leftmost :: [Event a] -> Event a
6059[ ] mergeList :: [Event a] -> Event (NonEmpty a)
README.md+22−14
@@ -1,23 +1,31 @@
1−# [Reflex](https://reflex-frp.org/)
1+## [Reflex](https://reflex-frp.org/)
22
33[![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/reflex.svg)](https://hackage.haskell.org/package/reflex) [![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/reflex/badge)](https://matrix.hackage.haskell.org/#/package/reflex) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/reflex-frp/reflex/blob/master/LICENSE)
44
5−Interactive programs without callbacks or side-effects. Functional Reactive Programming (FRP) uses composable events and time-varying values to describe interactive systems as pure functions. Just like other pure functional code, functional reactive code is easier to get right on the first try, maintain, and reuse.
5+### Practical Functional Reactive Programming
66
7−Reflex is a fully-deterministic, higher-order Functional Reactive Programming interface and an engine that efficiently implements that interface.
7+Reflex is a fully-deterministic, higher-order Functional Reactive Programming (FRP) interface and an engine that efficiently implements that interface.
88
9−**Visit https://reflex-frp.org for more information, tutorials, documentation and [examples](https://examples.reflex-frp.org/).**
9+[Reflex-DOM](https://github.com/reflex-frp/reflex-dom) is a framework built on Reflex that facilitates the development of web pages, including highly-interactive single-page apps.
1010
11−## Resources
11+A summary of Reflex functions is available in the [quick reference](Quickref.md).
1212
13−* [Official Website](https://reflex-frp.org)
14−* [Quick Reference](Quickref.md)
15−* [Reflex-DOM](https://github.com/reflex-frp/reflex-dom): A framework built on Reflex that facilitates the development of web pages, including highly-interactive single-page apps.
16−* [Obelisk](https://github.com/obsidiansystems/obelisk#obelisk): A framework built on Reflex and Reflex-DOM for functional reactive web and mobile applications, with batteries included.
17−* [Get started with Reflex](https://github.com/reflex-frp/reflex-platform)
18−* [/r/reflexfrp](https://www.reddit.com/r/reflexfrp)
19−* [irc.freenode.net #reflex-frp](http://webchat.freenode.net?channels=%23reflex-frp&uio=d4)
13+**Visit https://reflex-frp.org/ for more information, tutorials, documentation and [examples](https://examples.reflex-frp.org/).**
2014
21−## Hacking
15+### Resources
16+[Get started with Reflex](https://github.com/reflex-frp/reflex-platform)
2217
23−From the root of a [Reflex Platform](https://github.com/reflex-frp/reflex-platform) checkout, run `./scripts/hack-on haskell-overlays/reflex-packages/dep/reflex`. This will check out the reflex source code into the `haskell-overlays/reflex-packages/dep/reflex` directory. You can then point that checkout at your fork, make changes, etc. Use the `./try-reflex` or `./scripts/work-on` scripts to start a shell in which you can test your changes.
18+[/r/reflexfrp](https://www.reddit.com/r/reflexfrp)
19+
20+[irc.freenode.net #reflex-frp](http://webchat.freenode.net?channels=%23reflex-frp&uio=d4)
21+
22+### Hacking
23+
24+From the root of a [Reflex
25+Platform](https://github.com/reflex-frp/reflex-platform) checkout, run
26+`./scripts/hack-on haskell-overlays/reflex-packages/dep/reflex`. This
27+will check out the reflex source code into the
28+`haskell-overlays/reflex-packages/dep/reflex` directory. You can then
29+point that checkout at your fork, make changes, etc. Use the
30+`./try-reflex` or `./scripts/work-on` scripts to start a shell in
31+which you can test your changes.
reflex.cabal+8−29
@@ -1,17 +1,7 @@
11Name: reflex
2−Version: 0.8.2.0
2+Version: 0.7.1.1
33Synopsis: Higher-order Functional Reactive Programming
4−Description:
5− Interactive programs without callbacks or side-effects.
6− Functional Reactive Programming (FRP) uses composable events and time-varying
7− values to describe interactive systems as pure functions.
8− Just like other pure functional code, functional reactive code is easier
9− to get right on the first try, maintain, and reuse.
10− .
11− Reflex is a fully-deterministic, higher-order Functional Reactive Programming
12− interface and an engine that efficiently implements that interface.
13− .
14− <https://reflex-frp.org>
4+Description: Reflex is a high-performance, deterministic, higher-order Functional Reactive Programming system
155License: BSD3
166License-file: LICENSE
177Author: Ryan Trinkle
@@ -74,7 +64,6 @@ library
7464 base >= 4.11 && < 4.15,
7565 bifunctors >= 5.2 && < 5.6,
7666 comonad >= 5.0.4 && < 5.1,
77− constraints >= 0.10 && <0.14,
7867 constraints-extras >= 0.3 && < 0.4,
7968 containers >= 0.6 && < 0.7,
8069 data-default >= 0.5 && < 0.8,
@@ -97,7 +86,7 @@ library
9786 time >= 1.4 && < 1.10,
9887 transformers >= 0.5.6.0 && < 0.6,
9988 unbounded-delays >= 0.1.0.0 && < 0.2,
100− witherable >= 0.3 && < 0.5
89+ witherable >= 0.3 && < 0.4
10190
10291 if flag(split-these)
10392 build-depends: these >= 1 && <1.2,
@@ -166,8 +155,7 @@ library
166155
167156 if flag(debug-trace-events)
168157 cpp-options: -DDEBUG_TRACE_EVENTS
169− build-depends:
170− bytestring >= 0.10.8 && < 0.11
158+ build-depends: bytestring
171159
172160 if flag(use-reflex-optimizer)
173161 cpp-options: -DUSE_REFLEX_OPTIMIZER
@@ -192,14 +180,13 @@ library
192180 other-extensions: TemplateHaskell
193181 else
194182 build-depends:
195− dependent-sum >= 0.6 && < 0.8
183+ dependent-sum >= 0.6 && < 0.7
196184
197185 if flag(fast-weak) && impl(ghcjs)
198186 cpp-options: -DGHCJS_FAST_WEAK
199187
200188 if impl(ghcjs)
201− build-depends:
202− ghcjs-base == 0.2.*
189+ build-depends: ghcjs-base
203190
204191test-suite semantics
205192 default-language: Haskell2010
@@ -259,9 +246,9 @@ test-suite hlint
259246 , filepath
260247 , filemanip
261248 if impl(ghc >= 8.8)
262− build-depends: hlint >= 3 && < 4
249+ build-depends: hlint >= 3
263250 else
264− build-depends: hlint (< 2.1 || >= 2.2.2) && < 4
251+ build-depends: hlint (< 2.1 || >= 2.2.2) && < 3
265252 if impl(ghcjs)
266253 buildable: False
267254
@@ -346,14 +333,6 @@ test-suite RequesterT
346333 Reflex.Plan.Pure
347334 Test.Run
348335
349−test-suite Headless
350− default-language: Haskell2010
351− type: exitcode-stdio-1.0
352− main-is: Headless.hs
353− hs-source-dirs: test
354− build-depends: base
355− , reflex
356−
357336test-suite Adjustable
358337 default-language: Haskell2010
359338 type: exitcode-stdio-1.0
src/Reflex/BehaviorWriter/Base.hs+4−13
@@ -24,7 +24,6 @@ module Reflex.BehaviorWriter.Base
2424import Control.Monad.Exception
2525import Control.Monad.Identity
2626import Control.Monad.IO.Class
27−import Control.Monad.Morph
2827import Control.Monad.Reader
2928import Control.Monad.Ref
3029import Control.Monad.State.Strict
@@ -49,18 +48,7 @@ import Reflex.TriggerEvent.Class
4948
5049-- | A basic implementation of 'BehaviorWriter'.
5150newtype BehaviorWriterT t w m a = BehaviorWriterT { unBehaviorWriterT :: StateT [Behavior t w] m a }
52− -- The list is kept in reverse order
53− deriving
54− ( Functor
55− , Applicative
56− , Monad
57− , MonadTrans
58− , MFunctor
59− , MonadIO
60− , MonadFix
61− , MonadAsyncException
62− , MonadException
63− )
51+ deriving (Functor, Applicative, Monad, MonadIO, MonadFix, MonadAsyncException, MonadException) -- The list is kept in reverse order
6452
6553-- | Run a 'BehaviorWriterT' action. The behavior writer output will be provided
6654-- along with the result of the action.
@@ -85,6 +73,9 @@ withBehaviorWriterT f dw = do
8573deriving instance MonadHold t m => MonadHold t (BehaviorWriterT t w m)
8674deriving instance MonadSample t m => MonadSample t (BehaviorWriterT t w m)
8775
76+instance MonadTrans (BehaviorWriterT t w) where
77+ lift = BehaviorWriterT . lift
78+
8879instance MonadRef m => MonadRef (BehaviorWriterT t w m) where
8980 type Ref (BehaviorWriterT t w m) = Ref m
9081 newRef = lift . newRef
src/Reflex/Class.hs−13
@@ -421,13 +421,6 @@ class MonadSample t m => MonadHold t m where
421421 -- | Create a new 'Event' that only occurs only once, on the first occurrence of
422422 -- the supplied 'Event'.
423423 headE :: Event t a -> m (Event t a)
424− -- | An event which only occurs at the current moment in time, such that:
425− --
426− -- > coincidence (pushAlways (\a -> (a <$) <$> now) e) = e
427− --
428− now :: m (Event t ())
429− default now :: (m ~ f m', MonadTrans f, MonadHold t m') => m (Event t ())
430− now = lift now
431424
432425-- | Accumulate an 'Incremental' with the supplied initial value and the firings of the provided 'Event',
433426-- using the combining function to produce a patch.
@@ -573,7 +566,6 @@ instance MonadHold t m => MonadHold t (ReaderT r m) where
573566 holdIncremental a0 = lift . holdIncremental a0
574567 buildDynamic a0 = lift . buildDynamic a0
575568 headE = lift . headE
576− now = lift now
577569
578570instance (MonadSample t m, Monoid r) => MonadSample t (WriterT r m) where
579571 sample = lift . sample
@@ -584,7 +576,6 @@ instance (MonadHold t m, Monoid r) => MonadHold t (WriterT r m) where
584576 holdIncremental a0 = lift . holdIncremental a0
585577 buildDynamic a0 = lift . buildDynamic a0
586578 headE = lift . headE
587− now = lift now
588579
589580instance MonadSample t m => MonadSample t (StateT s m) where
590581 sample = lift . sample
@@ -595,7 +586,6 @@ instance MonadHold t m => MonadHold t (StateT s m) where
595586 holdIncremental a0 = lift . holdIncremental a0
596587 buildDynamic a0 = lift . buildDynamic a0
597588 headE = lift . headE
598− now = lift now
599589
600590instance MonadSample t m => MonadSample t (ExceptT e m) where
601591 sample = lift . sample
@@ -606,7 +596,6 @@ instance MonadHold t m => MonadHold t (ExceptT e m) where
606596 holdIncremental a0 = lift . holdIncremental a0
607597 buildDynamic a0 = lift . buildDynamic a0
608598 headE = lift . headE
609− now = lift now
610599
611600instance (MonadSample t m, Monoid w) => MonadSample t (RWST r w s m) where
612601 sample = lift . sample
@@ -617,7 +606,6 @@ instance (MonadHold t m, Monoid w) => MonadHold t (RWST r w s m) where
617606 holdIncremental a0 = lift . holdIncremental a0
618607 buildDynamic a0 = lift . buildDynamic a0
619608 headE = lift . headE
620− now = lift now
621609
622610instance MonadSample t m => MonadSample t (ContT r m) where
623611 sample = lift . sample
@@ -628,7 +616,6 @@ instance MonadHold t m => MonadHold t (ContT r m) where
628616 holdIncremental a0 = lift . holdIncremental a0
629617 buildDynamic a0 = lift . buildDynamic a0
630618 headE = lift . headE
631− now = lift now
632619
633620--------------------------------------------------------------------------------
634621-- Convenience functions
src/Reflex/Dynamic.hs+1−1
@@ -348,7 +348,7 @@ factorDyn d = buildDynamic (sample (current d) >>= holdKey) update where
348348--
349349-- > demuxed (demux d) k === fmap (== k) d
350350--
351−-- However, when 'demuxed' is used multiple times, the complexity is only
351+-- However, when getDemuxed is used multiple times, the complexity is only
352352-- /O(log(n))/, rather than /O(n)/ for fmap.
353353data Demux t k = Demux { demuxValue :: Behavior t k
354354 , demuxSelector :: EventSelector t (Const2 k Bool)
src/Reflex/DynamicWriter/Base.hs+4−13
@@ -22,7 +22,6 @@ module Reflex.DynamicWriter.Base
2222import Control.Monad.Exception
2323import Control.Monad.Identity
2424import Control.Monad.IO.Class
25−import Control.Monad.Morph
2625import Control.Monad.Primitive
2726import Control.Monad.Reader
2827import Control.Monad.Ref
@@ -52,6 +51,9 @@ import Reflex.Query.Class
5251import Reflex.Requester.Class
5352import Reflex.TriggerEvent.Class
5453
54+instance MonadTrans (DynamicWriterT t w) where
55+ lift = DynamicWriterT . lift
56+
5557mapIncrementalMapValues :: (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')
5658mapIncrementalMapValues f = unsafeMapIncremental (fmap f) (fmap f)
5759
@@ -88,18 +90,7 @@ mergeDynIncrementalWithMove a = unsafeBuildIncremental (mapM (sample . current)
8890
8991-- | A basic implementation of 'DynamicWriter'.
9092newtype DynamicWriterT t w m a = DynamicWriterT { unDynamicWriterT :: StateT [Dynamic t w] m a }
91− -- The list is kept in reverse order
92− deriving
93− ( Functor
94− , Applicative
95− , Monad
96− , MonadTrans
97− , MFunctor
98− , MonadIO
99− , MonadFix
100− , MonadAsyncException
101− , MonadException
102− )
93+ deriving (Functor, Applicative, Monad, MonadIO, MonadFix, MonadAsyncException, MonadException) -- The list is kept in reverse order
10394
10495deriving instance MonadHold t m => MonadHold t (DynamicWriterT t w m)
10596deriving instance MonadSample t m => MonadSample t (DynamicWriterT t w m)
src/Reflex/EventWriter/Base.hs+4−14
@@ -35,7 +35,6 @@ import Reflex.TriggerEvent.Class
3535
3636import Control.Monad.Exception
3737import Control.Monad.Identity
38−import Control.Monad.Morph
3938import Control.Monad.Primitive
4039import Control.Monad.Reader
4140import Control.Monad.Ref
@@ -98,17 +97,7 @@ data EventWriterState t w = EventWriterState
9897
9998-- | A basic implementation of 'EventWriter'.
10099newtype EventWriterT t w m a = EventWriterT { unEventWriterT :: StateT (EventWriterState t w) m a }
101− deriving
102− ( Functor
103− , Applicative
104− , Monad
105− , MonadTrans
106− , MFunctor
107− , MonadFix
108− , MonadIO
109− , MonadException
110− , MonadAsyncException
111− )
100+ deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadException, MonadAsyncException)
112101
113102-- | Run a 'EventWriterT' action.
114103runEventWriterT :: forall t m w a. (Reflex t, Monad m, Semigroup w) => EventWriterT t w m a -> m (a, Event t w)
@@ -128,6 +117,9 @@ instance (Reflex t, Monad m, Semigroup w) => EventWriter t w (EventWriterT t w m
128117 , _eventWriterState_told = (tellId myId :=> w) : _eventWriterState_told old
129118 }
130119
120+instance MonadTrans (EventWriterT t w) where
121+ lift = EventWriterT . lift
122+
131123instance MonadSample t m => MonadSample t (EventWriterT t w m) where
132124 sample = lift . sample
133125
@@ -142,8 +134,6 @@ instance MonadHold t m => MonadHold t (EventWriterT t w m) where
142134 buildDynamic a0 = lift . buildDynamic a0
143135 {-# INLINABLE headE #-}
144136 headE = lift . headE
145− {-# INLINABLE now #-}
146− now = lift now
147137
148138instance (Reflex t, Adjustable t m, MonadHold t m, Semigroup w) => Adjustable t (EventWriterT t w m) where
149139 runWithReplace = runWithReplaceEventWriterTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
src/Reflex/Host/Headless.hs+9−11
@@ -7,7 +7,6 @@
77module Reflex.Host.Headless where
88
99import Control.Concurrent.Chan (newChan, readChan)
10−import Control.Monad (unless)
1110import Control.Monad.Fix (MonadFix, fix)
1211import Control.Monad.IO.Class (MonadIO, liftIO)
1312import Control.Monad.Primitive (PrimMonad)
@@ -16,7 +15,7 @@ import Data.Dependent.Sum (DSum (..), (==>))
1615import Data.Foldable (for_)
1716import Data.Functor.Identity (Identity(..))
1817import Data.IORef (IORef, readIORef)
19−import Data.Maybe (catMaybes, fromMaybe)
18+import Data.Maybe (catMaybes)
2019import Data.Traversable (for)
2120
2221import Reflex
@@ -83,33 +82,32 @@ runHeadlessApp guest =
8382 -- 'Nothing' if the guest application hasn't subscribed to this event.
8483 mPostBuildTrigger <- readRef postBuildTriggerRef
8584
85+ -- When there is a subscriber to the post-build event, fire the event.
86+ for_ mPostBuildTrigger $ \postBuildTrigger ->
87+ fire [postBuildTrigger :=> Identity ()] $ pure ()
88+
8689 -- Subscribe to an 'Event' of that the guest application can use to
8790 -- request application shutdown. We'll check whether this 'Event' is firing
8891 -- to determine whether to terminate.
8992 shutdown <- subscribeEvent result
9093
91− -- When there is a subscriber to the post-build event, fire the event.
92− soa <- for mPostBuildTrigger $ \postBuildTrigger ->
93− fire [postBuildTrigger :=> Identity ()] $ isFiring shutdown
94−
9594 -- The main application loop. We wait for new events and fire those that
9695 -- have subscribers. If we detect a shutdown request, the application
9796 -- terminates.
98− unless (or (fromMaybe [] soa)) $ fix $ \loop -> do
97+ fix $ \loop -> do
9998 -- Read the next event (blocking).
10099 ers <- liftIO $ readChan events
101100 stop <- do
102101 -- Fire events that have subscribers.
103102 fireEventTriggerRefs fc ers $
104103 -- Check if the shutdown 'Event' is firing.
105− isFiring shutdown
104+ readEvent shutdown >>= \case
105+ Nothing -> pure False
106+ Just _ -> pure True
106107 if or stop
107108 then pure ()
108109 else loop
109110 where
110− isFiring ev = readEvent ev >>= \case
111− Nothing -> pure False
112− Just _ -> pure True
113111 -- Use the given 'FireCommand' to fire events that have subscribers
114112 -- and call the callback for the 'TriggerInvocation' of each.
115113 fireEventTriggerRefs
src/Reflex/PerformEvent/Base.hs−2
@@ -164,8 +164,6 @@ instance (ReflexHost t, MonadHold t m) => MonadHold t (PerformEventT t m) where
164164 buildDynamic getV0 v' = PerformEventT $ lift $ buildDynamic getV0 v'
165165 {-# INLINABLE headE #-}
166166 headE = PerformEventT . lift . headE
167− {-# INLINABLE now #-}
168− now = PerformEventT . lift $ now
169167
170168instance (MonadRef (HostFrame t), ReflexHost t) => MonadRef (PerformEventT t m) where
171169 type Ref (PerformEventT t m) = Ref (HostFrame t)
src/Reflex/PostBuild/Base.hs−2
@@ -83,8 +83,6 @@ instance MonadHold t m => MonadHold t (PostBuildT t m) where
8383 buildDynamic a0 = lift . buildDynamic a0
8484 {-# INLINABLE headE #-}
8585 headE = lift . headE
86− {-# INLINABLE now #-}
87− now = lift now
8886
8987instance PerformEvent t m => PerformEvent t (PostBuildT t m) where
9088 type Performable (PostBuildT t m) = Performable m
src/Reflex/Profiled.hs−1
@@ -184,7 +184,6 @@ instance MonadHold t m => MonadHold (ProfiledTimeline t) (ProfiledM m) where
184184 holdIncremental v0 (Event_Profiled v') = ProfiledM $ Incremental_Profiled <$> holdIncremental v0 v'
185185 buildDynamic (ProfiledM v0) (Event_Profiled v') = ProfiledM $ Dynamic_Profiled <$> buildDynamic v0 v'
186186 headE (Event_Profiled e) = ProfiledM $ Event_Profiled <$> headE e
187− now = ProfiledM $ Event_Profiled <$> now
188187
189188instance MonadSample t m => MonadSample (ProfiledTimeline t) (ProfiledM m) where
190189 sample (Behavior_Profiled b) = ProfiledM $ sample b
src/Reflex/Pure.hs−4
@@ -211,7 +211,3 @@ instance (Enum t, HasTrie t, Ord t) => MonadHold (Pure t) ((->) t) where
211211 Just x -> fromMaybe lastValue $ apply x lastValue
212212
213213 headE = slowHeadE
214− now t = Event $ guard . (t ==)
215−
216−
217−
src/Reflex/Query/Base.hs−4
@@ -22,7 +22,6 @@ module Reflex.Query.Base
2222import Control.Applicative (liftA2)
2323import Control.Monad.Exception
2424import Control.Monad.Fix
25−import Control.Monad.Morph
2625import Control.Monad.Primitive
2726import Control.Monad.Reader
2827import Control.Monad.Ref
@@ -240,9 +239,6 @@ instance (Reflex t, MonadFix m, Group q, Additive q, Query q, Eq q, MonadHold t
240239instance MonadTrans (QueryT t q) where
241240 lift = QueryT . lift . lift . lift
242241
243−instance MFunctor (QueryT t q) where
244− hoist = mapQueryT
245−
246242instance PrimMonad m => PrimMonad (QueryT t q m) where
247243 type PrimState (QueryT t q m) = PrimState m
248244 primitive = lift . primitive
src/Reflex/Requester/Base.hs+26−95
@@ -1,7 +1,6 @@
11-- | This module provides 'RequesterT', the standard implementation of
22-- 'Requester'.
33{-# LANGUAGE AllowAmbiguousTypes #-}
4−{-# LANGUAGE ApplicativeDo #-}
54{-# LANGUAGE CPP #-}
65{-# LANGUAGE EmptyDataDecls #-}
76{-# LANGUAGE ExistentialQuantification #-}
@@ -33,7 +32,6 @@ module Reflex.Requester.Base
3332 , requesterDataToList
3433 , singletonRequesterData
3534 , matchResponsesWithRequests
36− , matchResponseMapWithRequests
3735 , multiEntry
3836 , unMultiEntry
3937 , requesting'
@@ -51,14 +49,12 @@ import Reflex.TriggerEvent.Class
5149import Control.Applicative (liftA2)
5250import Control.Monad.Exception
5351import Control.Monad.Identity
54−import Control.Monad.Morph
5552import Control.Monad.Primitive
5653import Control.Monad.Reader
5754import Control.Monad.Ref
5855import Control.Monad.State.Strict
5956import Data.Bits
6057import Data.Coerce
61−import Data.Constraint
6258import Data.Dependent.Map (DMap)
6359import qualified Data.Dependent.Map as DMap
6460import Data.Dependent.Sum (DSum (..))
@@ -84,51 +80,19 @@ newtype TagMap (f :: * -> *) = TagMap (IntMap Any)
8480
8581newtype RequesterData f = RequesterData (TagMap (Entry f))
8682
87−emptyRequesterData :: RequesterData f
88−emptyRequesterData = RequesterData $ TagMap IntMap.empty
89−
9083data RequesterDataKey a where
9184 RequesterDataKey_Single :: {-# UNPACK #-} !(MyTag (Single a)) -> RequesterDataKey a
9285 RequesterDataKey_Multi :: {-# UNPACK #-} !(MyTag Multi) -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a --TODO: Don't put a second Int here (or in the other Multis); use a single Int instead
93− RequesterDataKey_Multi2 :: GCompare k => {-# UNPACK #-} !(MyTag (Multi2 k)) -> !(Some k) -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a
86+ RequesterDataKey_Multi2 :: {-# UNPACK #-} !(MyTag (Multi2 k)) -> !(Some k) -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a
9487 RequesterDataKey_Multi3 :: {-# UNPACK #-} !(MyTag Multi3) -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a
9588
9689singletonRequesterData :: RequesterDataKey a -> f a -> RequesterData f
9790singletonRequesterData rdk v = case rdk of
9891 RequesterDataKey_Single k -> RequesterData $ singletonTagMap k $ Entry v
9992 RequesterDataKey_Multi k k' k'' -> RequesterData $ singletonTagMap k $ Entry $ IntMap.singleton k' $ singletonRequesterData k'' v
100− RequesterDataKey_Multi2 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ Multi2Contents
101− { _multi2Contents_values = Map.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v
102− , _multi2Contents_dict = Dict
103− }
93+ RequesterDataKey_Multi2 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ Map.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v
10494 RequesterDataKey_Multi3 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ IntMap.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v
10595
106−mergeRequesterData :: RequesterData f -> RequesterData f -> RequesterData f
107−mergeRequesterData (RequesterData a) (RequesterData b) = RequesterData $ mergeTagMap a b
108−
109−mergeTagMap :: forall f. TagMap (Entry f) -> TagMap (Entry f) -> TagMap (Entry f)
110−mergeTagMap (TagMap m) (TagMap n) =
111− TagMap $ IntMap.unionWithKey (g' combiner) m n
112− where
113− combiner :: forall a. MyTag a -> Entry f a -> Entry f a -> Entry f a
114− combiner k (Entry a) (Entry b) = Entry $ case myKeyType k of
115− MyTagType_Single -> a
116− MyTagType_Multi -> IntMap.unionWith mergeRequesterData a b
117− MyTagType_Multi2 -> case _multi2Contents_dict a of
118− Dict -> Multi2Contents
119− { _multi2Contents_values = Map.unionWith (IntMap.unionWith mergeRequesterData) (_multi2Contents_values a) (_multi2Contents_values b)
120− , _multi2Contents_dict = Dict
121− }
122− MyTagType_Multi3 -> IntMap.unionWith (IntMap.unionWith mergeRequesterData) a b
123− g' :: (forall a. MyTag a -> Entry f a -> Entry f a -> Entry f a) -> Int -> Any -> Any -> Any
124− g' f rawKey a b =
125− let k = MyTag rawKey :: MyTag a
126− fromAny :: Any -> Entry f a
127− fromAny = unsafeCoerce
128− toAny :: Entry f a -> Any
129− toAny = unsafeCoerce
130− in toAny $ f k (fromAny a) (fromAny b)
131−
13296requesterDataToList :: RequesterData f -> [DSum RequesterDataKey f]
13397requesterDataToList (RequesterData m) = do
13498 k :=> Entry e <- tagMapToList m
@@ -138,12 +102,11 @@ requesterDataToList (RequesterData m) = do
138102 (k', e') <- IntMap.toList e
139103 k'' :=> e'' <- requesterDataToList e'
140104 return $ RequesterDataKey_Multi k k' k'' :=> e''
141− MyTagType_Multi2 -> case _multi2Contents_dict e of
142− Dict -> do
143− (k', e') <- Map.toList $ _multi2Contents_values e
144− (k'', e'') <- IntMap.toList e'
145− k''' :=> e''' <- requesterDataToList e''
146− return $ RequesterDataKey_Multi2 k k' k'' k''' :=> e'''
105+ MyTagType_Multi2 -> do
106+ (k', e') <- Map.toList e
107+ (k'', e'') <- IntMap.toList e'
108+ k''' :=> e''' <- requesterDataToList e''
109+ return $ RequesterDataKey_Multi2 k k' k'' k''' :=> e'''
147110 MyTagType_Multi3 -> do
148111 (k', e') <- IntMap.toList e
149112 (k'', e'') <- IntMap.toList e'
@@ -171,13 +134,7 @@ traverseRequesterData f (RequesterData m) = RequesterData <$> traverseTagMapWith
171134 go k (Entry request) = Entry <$> case myKeyType k of
172135 MyTagType_Single -> f request
173136 MyTagType_Multi -> traverse (traverseRequesterData f) request
174− MyTagType_Multi2 -> case request of
175− Multi2Contents { _multi2Contents_values = request', _multi2Contents_dict = Dict } -> do
176− v <- traverse (traverse (traverseRequesterData f)) request'
177− pure $ Multi2Contents
178− { _multi2Contents_values = v
179− , _multi2Contents_dict = Dict
180− }
137+ MyTagType_Multi2 -> traverse (traverse (traverseRequesterData f)) request
181138 MyTagType_Multi3 -> traverse (traverse (traverseRequesterData f)) request
182139
183140-- | 'traverseRequesterData' with its arguments flipped
@@ -221,14 +178,9 @@ instance MyTagTypeOffset Multi3 where
221178type family EntryContents request a where
222179 EntryContents request (Single a) = request a
223180 EntryContents request Multi = IntMap (RequesterData request)
224− EntryContents request (Multi2 k) = Multi2Contents k request
181+ EntryContents request (Multi2 k) = Map (Some k) (IntMap (RequesterData request))
225182 EntryContents request Multi3 = IntMap (IntMap (RequesterData request))
226183
227−data Multi2Contents k request = Multi2Contents
228− { _multi2Contents_dict :: {-# UNPACK #-} !(Dict (GCompare k)) -- This is a Dict instead of an existential context because we only want to use it in certain circumstances
229− , _multi2Contents_values :: {-# UNPACK #-} !(Map (Some k) (IntMap (RequesterData request)))
230− }
231−
232184newtype Entry request x = Entry { unEntry :: EntryContents request x }
233185
234186{-# INLINE singleEntry #-}
@@ -357,7 +309,7 @@ tagRequest req = do
357309 return t
358310
359311{-# INLINE responseFromTag #-}
360−responseFromTag :: forall m t request response x. Monad m => MyTagWrap response (Entry response x) -> RequesterT t request response m (Event t (Entry response x))
312+responseFromTag :: Monad m => MyTagWrap response (Entry response x) -> RequesterT t request response m (Event t (Entry response x))
361313responseFromTag (MyTagWrap t) = do
362314 responses :: EventSelectorInt t Any <- RequesterT ask
363315 return $ (unsafeCoerce :: Event t Any -> Event t (Entry response x)) $ selectInt responses t
@@ -365,9 +317,6 @@ responseFromTag (MyTagWrap t) = do
365317instance MonadTrans (RequesterT t request response) where
366318 lift = RequesterT . lift . lift
367319
368−instance MFunctor (RequesterT t request response) where
369− hoist f = RequesterT . hoist (hoist f) . unRequesterT
370−
371320instance PerformEvent t m => PerformEvent t (RequesterT t request response m) where
372321 type Performable (RequesterT t request response m) = Performable m
373322 performEvent_ = lift . performEvent_
@@ -487,9 +436,9 @@ traverseDMapWithKeyWithAdjustRequesterTWith base mapPatch weakenPatchWith patchN
487436 let responses :: EventSelector t (Const2 (Some k) (IntMap (RequesterData response)))
488437 responses = fanMap $ fmapCheap unpack response
489438 unpack :: Entry response (Multi2 k) -> Map (Some k) (IntMap (RequesterData response))
490− unpack = _multi2Contents_values . unEntry
439+ unpack = unEntry
491440 pack :: Map (Some k) (IntMap (RequesterData request)) -> Entry request (Multi2 k)
492− pack m = Entry $ Multi2Contents { _multi2Contents_values = m, _multi2Contents_dict = Dict }
441+ pack = Entry
493442 f' :: forall a. k a -> Compose ((,) Int) v a -> m (Compose ((,) (Event t (IntMap (RequesterData request)))) v' a)
494443 f' k (Compose (n, v)) = do
495444 (result, myRequests) <- runRequesterT (f k v) $ mapMaybeCheap (IntMap.lookup n) $ select responses (Const2 (Some k))
@@ -510,30 +459,10 @@ traverseDMapWithKeyWithAdjustRequesterTWith base mapPatch weakenPatchWith patchN
510459data Decoder rawResponse response =
511460 forall a. Decoder (RequesterDataKey a) (rawResponse -> response a)
512461
513−matchResponsesWithRequests
514− :: forall t rawRequest rawResponse request response m.
515− ( MonadFix m
516− , MonadHold t m
517− , Reflex t
518− )
519− => (forall a. request a -> (rawRequest, rawResponse -> response a))
520− -- ^ Given a request (from 'Requester'), produces the wire format of the
521− -- request and a function used to process the associated response
522− -> Event t (RequesterData request)
523− -- ^ The outgoing requests
524− -> Event t (Int, rawResponse)
525− -- ^ The incoming responses, tagged by an identifying key
526− -> m ( Event t (Map Int rawRequest)
527− , Event t (RequesterData response)
528− )
529− -- ^ A map of outgoing wire-format requests and an event of responses keyed
530− -- by the 'RequesterData' key of the associated outgoing request
531−matchResponsesWithRequests f send recv = matchResponseMapWithRequests f send $ uncurry Map.singleton <$> recv
532−
533462-- | Matches incoming responses with previously-sent requests
534463-- and uses the provided request "decoder" function to process
535464-- incoming responses.
536−matchResponseMapWithRequests
465+matchResponsesWithRequests
537466 :: forall t rawRequest rawResponse request response m.
538467 ( MonadFix m
539468 , MonadHold t m
@@ -544,14 +473,14 @@ matchResponseMapWithRequests
544473 -- request and a function used to process the associated response
545474 -> Event t (RequesterData request)
546475 -- ^ The outgoing requests
547− -> Event t (Map Int rawResponse)
548− -- ^ A map of incoming responses, tagged by an identifying key
476+ -> Event t (Int, rawResponse)
477+ -- ^ The incoming responses, tagged by an identifying key
549478 -> m ( Event t (Map Int rawRequest)
550479 , Event t (RequesterData response)
551480 )
552481 -- ^ A map of outgoing wire-format requests and an event of responses keyed
553482 -- by the 'RequesterData' key of the associated outgoing request
554−matchResponseMapWithRequests f send recv = do
483+matchResponsesWithRequests f send recv = do
555484 rec nextId <- hold 1 $ fmap (\(next, _, _) -> next) outgoing
556485 waitingFor :: Incremental t (PatchMap Int (Decoder rawResponse response)) <-
557486 holdIncremental mempty $ leftmost
@@ -593,15 +522,17 @@ matchResponseMapWithRequests f send recv = do
593522 processIncoming
594523 :: Incremental t (PatchMap Int (Decoder rawResponse response))
595524 -- A map of outstanding expected responses
596− -> Event t (Map Int rawResponse)
525+ -> Event t (Int, rawResponse)
597526 -- A incoming response paired with its identifying key
598527 -> Event t (RequesterData response, PatchMap Int v)
599528 -- The decoded response and a patch that clears the outstanding responses queue
600− processIncoming waitingFor inc = flip push inc $ \rspMap -> do
529+ processIncoming waitingFor inc = flip push inc $ \(n, rawRsp) -> do
601530 wf <- sample $ currentIncremental waitingFor
602− let match rawRsp (Decoder k rspF) =
603− let rsp = rspF rawRsp
604− in singletonRequesterData k rsp
605− matches = Map.intersectionWith match rspMap wf
606− pure $ if Map.null matches then Nothing else Just
607− (Map.foldl' mergeRequesterData emptyRequesterData matches, PatchMap $ Nothing <$ matches)
531+ case Map.lookup n wf of
532+ Nothing -> return Nothing -- TODO How should lookup failures be handled here? They shouldn't ever happen..
533+ Just (Decoder k rspF) -> do
534+ let rsp = rspF rawRsp
535+ return $ Just
536+ ( singletonRequesterData k rsp
537+ , PatchMap $ Map.singleton n Nothing
538+ )
src/Reflex/Spider/Internal.hs+1−36
@@ -307,20 +307,7 @@ data CacheSubscribed x a
307307#endif
308308 }
309309
310−nowSpiderEventM :: (HasSpiderTimeline x) => EventM x (R.Event (SpiderTimeline x) ())
311−nowSpiderEventM =
312− SpiderEvent <$> now
313−
314−now :: (MonadIO m, Defer (Some Clear) m, HasSpiderTimeline x
315− ) => m (Event x ())
316−now = do
317− nowOrNot <- liftIO $ newIORef $ Just ()
318− scheduleClear nowOrNot
319− return . Event $ \_ -> do
320− occ <- liftIO . readIORef $ nowOrNot
321− return ( EventSubscription (return ()) eventSubscribedNow
322− , occ
323− )
310+
324311
325312-- | Construct an 'Event' whose value is guaranteed not to be recomputed
326313-- repeatedly
@@ -607,16 +594,6 @@ eventSubscribedNever = EventSubscribed
607594 , eventSubscribedWhoCreated = return ["never"]
608595#endif
609596 }
610−eventSubscribedNow :: EventSubscribed x
611−eventSubscribedNow = EventSubscribed
612− { eventSubscribedHeightRef = zeroRef
613− , eventSubscribedRetained = toAny ()
614−#ifdef DEBUG_CYCLES
615− , eventSubscribedGetParents = return []
616− , eventSubscribedHasOwnHeightRef = False
617− , eventSubscribedWhoCreated = return ["now"]
618−#endif
619− }
620597
621598eventSubscribedFan :: FanSubscribed x k v -> EventSubscribed x
622599eventSubscribedFan !subscribed = EventSubscribed
@@ -2520,8 +2497,6 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Event
25202497 {-# INLINABLE headE #-}
25212498 headE = R.slowHeadE
25222499-- headE (SpiderEvent e) = SpiderEvent <$> Reflex.Spider.Internal.headE e
2523− {-# INLINABLE now #-}
2524− now = nowSpiderEventM
25252500
25262501instance Reflex.Class.MonadSample (SpiderTimeline x) (SpiderPullM x) where
25272502 {-# INLINABLE sample #-}
@@ -2543,9 +2518,6 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Spide
25432518 {-# INLINABLE headE #-}
25442519 headE = R.slowHeadE
25452520-- headE (SpiderEvent e) = SpiderPushM $ SpiderEvent <$> Reflex.Spider.Internal.headE e
2546− {-# INLINABLE now #-}
2547− now = SpiderPushM nowSpiderEventM
2548−
25492521
25502522instance HasSpiderTimeline x => Monad (Reflex.Class.Dynamic (SpiderTimeline x)) where
25512523 {-# INLINE return #-}
@@ -2609,9 +2581,6 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Spide
26092581 buildDynamic getV0 e = runFrame . runSpiderHostFrame $ Reflex.Class.buildDynamic getV0 e
26102582 {-# INLINABLE headE #-}
26112583 headE e = runFrame . runSpiderHostFrame $ Reflex.Class.headE e
2612− {-# INLINABLE now #-}
2613− now = runFrame . runSpiderHostFrame $ Reflex.Class.now
2614−
26152584
26162585instance HasSpiderTimeline x => Reflex.Class.MonadSample (SpiderTimeline x) (SpiderHostFrame x) where
26172586 sample = SpiderHostFrame . readBehaviorUntracked . unSpiderBehavior --TODO: This can cause problems with laziness, so we should get rid of it if we can
@@ -2628,8 +2597,6 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Spide
26282597 {-# INLINABLE headE #-}
26292598 headE = R.slowHeadE
26302599-- headE (SpiderEvent e) = SpiderHostFrame $ SpiderEvent <$> Reflex.Spider.Internal.headE e
2631− {-# INLINABLE now #-}
2632− now = SpiderHostFrame Reflex.Class.now
26332600
26342601instance HasSpiderTimeline x => Reflex.Class.MonadSample (SpiderTimeline x) (SpiderHost x) where
26352602 {-# INLINABLE sample #-}
@@ -2650,8 +2617,6 @@ instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (Refle
26502617 buildDynamic getV0 e = Reflex.Spider.Internal.ReadPhase $ Reflex.Class.buildDynamic getV0 e
26512618 {-# INLINABLE headE #-}
26522619 headE e = Reflex.Spider.Internal.ReadPhase $ Reflex.Class.headE e
2653− {-# INLINABLE now #-}
2654− now = Reflex.Spider.Internal.ReadPhase Reflex.Class.now
26552620
26562621--------------------------------------------------------------------------------
26572622-- Deprecated items
src/Reflex/TriggerEvent/Base.hs−2
@@ -122,8 +122,6 @@ instance MonadHold t m => MonadHold t (TriggerEventT t m) where
122122 buildDynamic a0 = lift . buildDynamic a0
123123 {-# INLINABLE headE #-}
124124 headE = lift . headE
125− {-# INLINABLE now #-}
126− now = lift now
127125
128126instance Adjustable t m => Adjustable t (TriggerEventT t m) where
129127 {-# INLINABLE runWithReplace #-}
test/Headless.hsdeleted−10
@@ -1,10 +0,0 @@
1−module Main where
2−
3−import Reflex
4−import Reflex.Host.Headless (runHeadlessApp)
5−
6−main :: IO ()
7−main = do
8− runHeadlessApp $ do
9− pb <- getPostBuild
10− performEvent (pure <$> pb)
test/Reflex/Plan/Pure.hs−1
@@ -41,7 +41,6 @@ instance MonadHold (Pure Int) PurePlan where
4141 holdIncremental initial = liftPlan . holdIncremental initial
4242 buildDynamic getInitial = liftPlan . buildDynamic getInitial
4343 headE = liftPlan . headE
44− now = liftPlan now
4544
4645instance MonadSample (Pure Int) PurePlan where
4746 sample = liftPlan . sample
test/Reflex/Test/Micro.hs+2−8
@@ -322,14 +322,8 @@ testCases =
322322 let e = never <$ switch b
323323 return $ void e
324324 lazyHold
325− , testE "now-1" $ do
326− e1 <- events1
327− switchHoldPromptly never . pushAlways (\a -> fmap (a <$) now) $ e1
328− , testE "now-2" $ do
329− e1 <- events1
330− let e = pushAlways (\a -> if a == "a" then now else return never) e1
331− x <- accumDyn (<>) never e
332− return . coincidence $ updated x
325+
326+
333327 ] where
334328
335329 events1, events2, events3 :: TestPlan t m => m (Event t String)