on develop help sign in
Merge branch 'develop' into queryt-optimization
commit512e4eacb80e61ac7b03e7b0e06130d93928be0f authorLuigy Leon <luichi.19@gmail.com> dateWed 16 Jan 2019, 19:01 (8 years ago) parent7494f05fc68de9
50 files changed+1326−602
.travis.yml−16 Quickref.md+25 bench-cbits/checkCapability.c+11−12 bench/Main.hs+7−6 bench/RunAll.hs+1−1 default.nix+1−1 hydra.json+29 jobsets.nix+70 reflex-platform.nix+8 reflex.cabal+79−15 release.nix+9 src/Data/AppendMap.hs+9−298 src/Reflex.hs+3 src/Reflex/Adjustable/Class.hs+52−10 src/Reflex/BehaviorWriter/Base.hs+202 src/Reflex/BehaviorWriter/Class.hs+26 src/Reflex/Class.hs+252−77 src/Reflex/Collection.hs+1 src/Reflex/Dynamic.hs+18−24 src/Reflex/Dynamic/TH.hs+2−2 src/Reflex/DynamicWriter/Base.hs+19−1 src/Reflex/EventWriter/Base.hs+75−58 src/Reflex/FunctorMaybe.hs+12−2 src/Reflex/Network.hs+1 src/Reflex/Optimizer.hs+5 src/Reflex/Patch/Class.hs+12 src/Reflex/Patch/DMapWithMove.hs+16−20 src/Reflex/Patch/MapWithMove.hs+77−5 src/Reflex/PerformEvent/Base.hs+1 src/Reflex/PostBuild/Base.hs+1 src/Reflex/Profiled.hs+3−1 src/Reflex/Query/Base.hs+65−8 src/Reflex/Query/Class.hs+23 src/Reflex/Requester/Base.hs+1 src/Reflex/Spider/Internal.hs+35−19 src/Reflex/Time.hs+2−2 src/Reflex/TriggerEvent/Base.hs+1 src/Reflex/Widget/Basic.hs+2 src/Reflex/Workflow.hs+1 test/EventWriterT.hs+69 test/QueryT.hs+12−6 test/Reflex/Bench/Focused.hs+1−1 test/Reflex/Plan/Pure.hs+4−4 test/Reflex/Plan/Reflex.hs+2−2 test/Reflex/Test/CrossImpl.hs+6−4 test/Reflex/Test/Micro.hs+64−3 test/Reflex/TestPlan.hs+2−2 test/Test/Run.hs+8 test/hlint.hs+1 test/semantics.hs−2
.travis.ymldeleted−16
@@ -1,16 +0,0 @@
1−# Cache Buster: 0
2−language: nix
3−cache:
4− directories:
5− - /nix
6−matrix:
7− include:
8− - env: COMPILER=ghc7103
9− - env: COMPILER=ghc821
10− - env: COMPILER=ghc802
11− - env: COMPILER=ghcjs
12−script:
13− - set -e
14− - nix-build -E "with (import <nixpkgs> {}); pkgs.haskell.packages.$COMPILER.callPackage ./default.nix { }"
15− - nix-collect-garbage -d # This is important to do right before 'script' ends so the cache gets GCed
16−
Quickref.md+25
@@ -98,6 +98,10 @@ Since MonadHold depends on MonadSample, any [S] function also runs in [H] contex
9898[ ] <> :: Monoid a => Behavior a -> Behavior a -> Behavior a
9999-- ... plus many more due to typeclass membership
100100
101+-- Combine multiple behaviors via applicative instance
102+[ ] ffor2 :: Behavior a -> Behavior b -> (a -> b -> c) -> Behavior c
103+[ ] ffor3 :: Behavior a -> Behavior b -> Behavior c -> (a -> b -> c -> d) -> Behavior d
104+
101105-- Behavior to Behavior by sampling current values
102106[S] sample :: Behavior a -> m a
103107[ ] pull :: m a -> Behavior a
@@ -135,6 +139,10 @@ Since MonadHold depends on MonadSample, any [S] function also runs in [H] contex
135139[ ] >>= :: Dynamic a -> (a -> Dynamic b) -> Dynamic b
136140[ ] zipDynWith :: (a -> b -> c) -> Dynamic a -> Dynamic b -> Dynamic c
137141
142+-- Combine multiple dynamics via applicative instance
143+[ ] ffor2 :: Dynamic a -> Dynamic b -> (a -> b -> c) -> Dynamic c
144+[ ] ffor3 :: Dynamic a -> Dynamic b -> Dynamic c -> (a -> b -> c -> d) -> Dynamic d
145+
138146-- Efficient one-to-many fanout
139147[ ] demux :: Ord k => Dynamic k -> Demux k
140148[ ] demuxed :: Eq k => Demux k -> k -> Dynamic Bool
@@ -284,3 +292,20 @@ Th typeclasses and their associated annotations include:
284292[P,T] delay :: NominalDiffTime -> Event t a -> m (Event t a)
285293```
286294
295+## Networks
296+
297+```haskell
298+-- Functions from Reflex.Network used to deal with Dynamics/Events carrying (m a)
299+
300+-- Given a Dynamic of network-creating actions, create a network that is recreated whenever the Dynamic updates.
301+-- The returned Event of network results occurs when the Dynamic does. Note: Often, the type a is an Event,
302+-- in which case the return value is an Event-of-Events that would typically be flattened (via switchHold).
303+[P,A] networkView :: Dynamic (m a) -> m (Event a)
304+
305+-- Given an initial network and an Event of network-creating actions, create a network that is recreated whenever the
306+-- Event fires. The returned Dynamic of network results occurs when the Event does. Note: Often, the type a is an
307+-- Event, in which case the return value is a Dynamic-of-Events that would typically be flattened.
308+[H,A] networkHold :: m a -> Event (m a) -> m (Dynamic a)
309+
310+-- Render a placeholder network to be shown while another network is not yet done building
311+[P,A] untilReady :: m a -> m b -> m (a, Event b)
bench-cbits/checkCapability.c+11−12
@@ -42,7 +42,7 @@ typedef struct Task_ {
4242 // or just continue immediately. It's a workaround for the fact
4343 // that signalling a condition variable doesn't do anything if the
4444 // thread is already running, but we want it to be sticky.
45− rtsBool wakeup;
45+ HsBool wakeup;
4646#endif
4747
4848 // This points to the Capability that the Task "belongs" to. If
@@ -62,14 +62,14 @@ typedef struct Task_ {
6262 // The current top-of-stack InCall
6363 struct InCall_ *incall;
6464
65− nat n_spare_incalls;
65+ uint32_t n_spare_incalls;
6666 struct InCall_ *spare_incalls;
6767
68− rtsBool worker; // == rtsTrue if this is a worker Task
69− rtsBool stopped; // this task has stopped or exited Haskell
68+ HsBool worker; // == rtsTrue if this is a worker Task
69+ HsBool stopped; // this task has stopped or exited Haskell
7070
7171 // So that we can detect when a finalizer illegally calls back into Haskell
72− rtsBool running_finalizers;
72+ HsBool running_finalizers;
7373
7474 // Links tasks on the returning_tasks queue of a Capability, and
7575 // on spare_workers.
@@ -88,7 +88,7 @@ struct Capability_ {
8888 StgFunTable f;
8989 StgRegTable r;
9090
91− nat no; // capability number.
91+ uint32_t no; // capability number.
9292
9393 // The Task currently holding this Capability. This task has
9494 // exclusive access to the contents of this Capability (apart from
@@ -98,12 +98,12 @@ struct Capability_ {
9898
9999 // true if this Capability is running Haskell code, used for
100100 // catching unsafe call-ins.
101− rtsBool in_haskell;
101+ HsBool in_haskell;
102102
103103 // Has there been any activity on this Capability since the last GC?
104− nat idle;
104+ uint32_t idle;
105105
106− rtsBool disabled;
106+ HsBool disabled;
107107
108108 // The run queue. The Task owning this Capability has exclusive
109109 // access to its run queue, so can wake up threads without
@@ -159,7 +159,7 @@ struct Capability_ {
159159#if defined(THREADED_RTS)
160160 // Worker Tasks waiting in the wings. Singly-linked.
161161 Task *spare_workers;
162− nat n_spare_workers; // count of above
162+ uint32_t n_spare_workers; // count of above
163163
164164 // This lock protects:
165165 // running_task
@@ -192,10 +192,9 @@ struct Capability_ {
192192
193193 // Per-capability STM-related data
194194 StgTVarWatchQueue *free_tvar_watch_queues;
195− StgInvariantCheckQueue *free_invariant_check_queues;
196195 StgTRecChunk *free_trec_chunks;
197196 StgTRecHeader *free_trec_headers;
198− nat transaction_tokens;
197+ uint32_t transaction_tokens;
199198} // typedef Capability is defined in RtsAPI.h
200199 // We never want a Capability to overlap a cache line with anything
201200 // else, so round it up to a cache line size:
bench/Main.hs+7−6
@@ -20,6 +20,7 @@ import qualified Data.Dependent.Map as DMap
2020import Data.Dependent.Sum
2121import Data.Functor.Misc
2222import Data.IORef
23+import Data.Maybe (fromJust)
2324import Reflex
2425import Reflex.Host.Class
2526
@@ -70,7 +71,7 @@ micros =
7071 , withSetupWHNF "fireEventsOnly"
7172 (newEventWithTriggerRef >>= subscribePair)
7273 (\(_, trigger) -> do
73− Just key <- liftIO $ readIORef trigger
74+ key <- fromJust <$> liftIO (readIORef trigger)
7475 fireEvents [key :=> Identity (42 :: Int)])
7576 , withSetupWHNF "fireEventsAndRead(head/merge1)"
7677 (setupMerge 1 >>= subscribePair)
@@ -84,14 +85,14 @@ micros =
8485 , withSetupWHNF "fireEventsOnly(head/merge100)"
8586 (setupMerge 100 >>= subscribePair)
8687 (\(_, t:_) -> do
87− Just key <- liftIO $ readIORef t
88+ key <- fromJust <$> liftIO (readIORef t)
8889 fireEvents [key :=> Identity (42 :: Int)])
8990 , withSetupWHNF "hold" newEventWithTriggerRef $ \(ev, _) -> hold (42 :: Int) ev
9091 , withSetupWHNF "sample" (newEventWithTriggerRef >>= hold (42 :: Int) . fst) sample
9192 ]
9293
9394setupMerge :: Int
94− -> SpiderHost Global ( Event (SpiderEnv Global) (DMap (Const2 Int a) Identity)
95+ -> SpiderHost Global ( Event (SpiderTimeline Global) (DMap (Const2 Int a) Identity)
9596 , [IORef (Maybe (EventTrigger Spider a))]
9697 )
9798setupMerge num = do
@@ -99,11 +100,11 @@ setupMerge num = do
99100 let !m = DMap.fromList [Const2 i :=> v | (i,v) <- zip [0..] evs]
100101 pure (merge m, triggers)
101102
102−subscribePair :: (Event (SpiderEnv Global) a, b) -> SpiderHost Global (EventHandle (SpiderEnv Global) a, b)
103+subscribePair :: (Event (SpiderTimeline Global) a, b) -> SpiderHost Global (EventHandle (SpiderTimeline Global) a, b)
103104subscribePair (ev, b) = (,b) <$> subscribeEvent ev
104105
105−fireAndRead :: IORef (Maybe (EventTrigger (SpiderEnv Global) a)) -> a -> EventHandle (SpiderEnv Global) b
106+fireAndRead :: IORef (Maybe (EventTrigger (SpiderTimeline Global) a)) -> a -> EventHandle (SpiderTimeline Global) b
106107 -> SpiderHost Global (Maybe b)
107108fireAndRead trigger val subd = do
108− Just key <- liftIO $ readIORef trigger
109+ key <- fromJust <$> liftIO (readIORef trigger)
109110 fireEventsAndRead [key :=> Identity val] $ readEvent subd >>= sequence
bench/RunAll.hs+1−1
@@ -136,7 +136,7 @@ benchmarks = implGroup "spider" runSpiderHost cases
136136pattern RunTestCaseFlag = "--run-test-case"
137137
138138spawnBenchmark :: String -> Benchmark
139−spawnBenchmark name = Benchmark name $ Benchmarkable $ \n -> do
139+spawnBenchmark name = bench name . toBenchmarkable $ \n -> do
140140 self <- getExecutablePath
141141 callProcess self [RunTestCaseFlag, name, show n, "+RTS", "-N1"]
142142
default.nix+1−1
@@ -11,7 +11,7 @@
1111}:
1212mkDerivation {
1313 pname = "reflex";
14− version = "0.5.0";
14+ version = "0.5";
1515 src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".git" "dist" ])) ./.;
1616 libraryHaskellDepends = [
1717 base bifunctors containers dependent-map dependent-sum
hydra.jsonnew file+29
@@ -0,0 +1,29 @@
1+{
2+ "enabled": 1,
3+ "hidden": true,
4+ "description": "Jobsets",
5+ "nixexprinput": "src",
6+ "nixexprpath": "jobsets.nix",
7+ "checkinterval": 300,
8+ "schedulingshares": 100,
9+ "enableemail": false,
10+ "emailoverride": "",
11+ "keepnr": 10,
12+ "inputs": {
13+ "src": {
14+ "type": "git",
15+ "value": "https://github.com/reflex-frp/reflex.git develop",
16+ "emailresponsible": false
17+ },
18+ "nixpkgs": {
19+ "type": "git",
20+ "value": "https://github.com/NixOS/nixpkgs-channels nixos-unstable",
21+ "emailresponsible": false
22+ },
23+ "prs": {
24+ "type": "githubpulls",
25+ "value": "reflex-frp reflex",
26+ "emailresponsible": false
27+ }
28+ }
29+}
jobsets.nixnew file+70
@@ -0,0 +1,70 @@
1+{ prs }:
2+
3+let
4+ pkgs = (import ./reflex-platform.nix {}).nixpkgs;
5+ mkFetchGithub = value: {
6+ inherit value;
7+ type = "git";
8+ emailresponsible = false;
9+ };
10+in
11+with pkgs.lib;
12+let
13+ defaults = jobs: {
14+ inherit (jobs) description;
15+ enabled = 1;
16+ hidden = false;
17+ keepnr = 10;
18+ schedulingshares = 100;
19+ checkinterval = 120;
20+ enableemail = false;
21+ emailoverride = "";
22+ nixexprinput = "reflex";
23+ nixexprpath = "release.nix";
24+ inputs = jobs.inputs // {
25+ nixpkgs = {
26+ type = "git";
27+ value = "https://github.com/NixOS/nixpkgs-channels nixos-unstable";
28+ emailresponsible = false;
29+ };
30+ config = {
31+ type = "nix";
32+ value = "{ android_sdk.accept_license = true; }";
33+ emailresponsible = false;
34+ };
35+ };
36+ };
37+ branchJobset = branch: defaults {
38+ description = "reflex-${branch}";
39+ inputs = {
40+ reflex = {
41+ value = "https://github.com/reflex-frp/reflex ${branch}";
42+ type = "git";
43+ emailresponsible = false;
44+ };
45+ };
46+ };
47+ makePr = num: info: {
48+ name = "reflex-pr-${num}";
49+ value = defaults {
50+ description = "#${num}: ${info.title}";
51+ inputs = {
52+ reflex = {
53+ #NOTE: This should really use "pull/${num}/merge"; however, GitHub's
54+ #status checks only operate on PR heads. This creates a race
55+ #condition, which can currently only be solved by requiring PRs to be
56+ #up to date before they're merged. See
57+ #https://github.com/isaacs/github/issues/1002
58+ value = "https://github.com/reflex-frp/reflex pull/${num}/head";
59+ type = "git";
60+ emailresponsible = false;
61+ };
62+ };
63+ };
64+ };
65+ processedPrs = mapAttrs' makePr (builtins.fromJSON (builtins.readFile prs));
66+ jobsetsAttrs = processedPrs //
67+ genAttrs ["develop"] branchJobset;
68+in {
69+ jobsets = pkgs.writeText "spec.json" (builtins.toJSON jobsetsAttrs);
70+}
reflex-platform.nixnew file+8
@@ -0,0 +1,8 @@
1+let
2+ reflex-platform-src = (import <nixpkgs> {}).fetchFromGitHub {
3+ owner = "reflex-frp";
4+ repo = "reflex-platform";
5+ rev = "384cd850f3adf1d404bced2424b5f6efb0f415f2";
6+ sha256 = "1ws77prqx8khmp8j6br1ij4k2v4dlgv170r9fmg0p1jivfbn8y9d";
7+ };
8+in import reflex-platform-src
reflex.cabal+79−15
@@ -37,16 +37,16 @@ library
3737 hs-source-dirs: src
3838 build-depends:
3939 MemoTrie == 0.6.*,
40− base >= 4.7 && < 4.12,
40+ base >= 4.7 && < 4.13,
4141 bifunctors >= 5.2 && < 5.6,
4242 comonad,
43− containers == 0.5.*,
43+ containers >= 0.5 && < 0.7,
4444 data-default >= 0.5 && < 0.8,
4545 dependent-map >= 0.2.4 && < 0.3,
4646 exception-transformers == 0.4.*,
4747 lens >= 4.7 && < 5,
4848 monad-control >= 1.0.1 && < 1.1,
49− monoidal-containers >= 0.3.0.2 && < 0.4,
49+ monoidal-containers == 0.4.*,
5050 mtl >= 2.1 && < 2.3,
5151 prim-uniq >= 0.1.0.1 && < 0.2,
5252 primitive >= 0.5 && < 0.7,
@@ -55,7 +55,7 @@ library
5555 reflection == 2.1.*,
5656 semigroupoids >= 4.0 && < 6,
5757 semigroups >= 0.16 && < 0.19,
58− stm == 2.4.*,
58+ stm >= 2.4 && < 2.6,
5959 syb >= 0.5 && < 0.8,
6060 these >= 0.4 && < 0.8,
6161 time >= 1.4 && < 1.9,
@@ -72,6 +72,9 @@ library
7272 Data.WeakBag,
7373 Reflex,
7474 Reflex.Class,
75+ Reflex.Adjustable.Class,
76+ Reflex.BehaviorWriter.Base,
77+ Reflex.BehaviorWriter.Class,
7578 Reflex.Collection,
7679 Reflex.Dynamic,
7780 Reflex.Dynamic.Uniq,
@@ -111,8 +114,7 @@ library
111114 Reflex.Widget.Basic,
112115 Reflex.Workflow
113116
114− ghc-options: -Wall -fwarn-redundant-constraints -fwarn-tabs -funbox-strict-fields -O2 -fspecialise-aggressively -ddump-simpl -ddump-to-file -dsuppress-coercions -dsuppress-idinfo
115− ghc-prof-options: -fprof-auto
117+ ghc-options: -Wall -fwarn-redundant-constraints -fwarn-tabs -funbox-strict-fields -O2 -fspecialise-aggressively
116118
117119 if flag(debug-trace-events)
118120 cpp-options: -DDEBUG_TRACE_EVENTS
@@ -129,7 +131,7 @@ library
129131 dependent-sum >= 0.3 && < 0.5,
130132 haskell-src-exts >= 1.16 && < 1.21,
131133 haskell-src-meta >= 0.6 && < 0.9,
132− template-haskell >= 2.9 && < 2.14
134+ template-haskell >= 2.9 && < 2.15
133135 exposed-modules:
134136 Reflex.Dynamic.TH
135137 other-extensions: TemplateHaskell
@@ -138,7 +140,7 @@ library
138140 dependent-sum == 0.4.*
139141
140142 if flag(fast-weak) && impl(ghcjs)
141− ghc-options: -DGHCJS_FAST_WEAK
143+ cpp-options: -DGHCJS_FAST_WEAK
142144
143145 if impl(ghcjs)
144146 build-depends: ghcjs-base
@@ -160,19 +162,34 @@ test-suite semantics
160162 reflex,
161163 split,
162164 transformers >= 0.3
165+ other-modules:
166+ Reflex.Bench.Focused
167+ Reflex.Plan.Pure
168+ Reflex.Plan.Reflex
169+ Reflex.Test
170+ Reflex.Test.Micro
171+ Reflex.TestPlan
163172
164173test-suite CrossImpl
165174 type: exitcode-stdio-1.0
166175 main-is: Reflex/Test/CrossImpl.hs
167176 hs-source-dirs: test
168− ghc-options: -O2 -Wall -rtsopts -main-is Reflex.Test.CrossImpl.test
177+ ghc-options: -O2 -Wall -rtsopts
169178 build-depends:
170179 base,
171180 containers,
172181 dependent-map,
182+ dependent-sum,
183+ deepseq >= 1.3 && < 1.5,
173184 mtl,
185+ transformers,
174186 ref-tf,
175187 reflex
188+ other-modules:
189+ Reflex.Test
190+ Reflex.TestPlan
191+ Reflex.Plan.Reflex
192+ Reflex.Plan.Pure
176193
177194test-suite hlint
178195 type: exitcode-stdio-1.0
@@ -191,12 +208,22 @@ test-suite EventWriterT
191208 main-is: EventWriterT.hs
192209 hs-source-dirs: test
193210 build-depends: base
211+ , containers
212+ , deepseq >= 1.3 && < 1.5
213+ , dependent-map
194214 , dependent-sum
195215 , lens
216+ , mtl
196217 , these
197218 , transformers
198219 , reflex
199220 , ref-tf
221+ other-modules:
222+ Reflex.Test
223+ Reflex.TestPlan
224+ Reflex.Plan.Reflex
225+ Reflex.Plan.Pure
226+ Test.Run
200227
201228test-suite RequesterT
202229 type: exitcode-stdio-1.0
@@ -211,6 +238,9 @@ test-suite RequesterT
211238 , reflex
212239 , ref-tf
213240 buildable: False
241+ other-modules:
242+ Reflex.TestPlan
243+ Reflex.Plan.Pure
214244
215245test-suite QueryT
216246 type: exitcode-stdio-1.0
@@ -220,52 +250,83 @@ test-suite QueryT
220250 , containers
221251 , dependent-map
222252 , dependent-sum
253+ , deepseq >= 1.3 && < 1.5
223254 , lens
224255 , monoidal-containers
256+ , mtl
225257 , ref-tf
226258 , reflex
227259 , semigroups
228260 , these
229261 , transformers
230− other-modules: Test.Run
262+ other-modules:
263+ Test.Run
264+ Reflex.TestPlan
265+ Reflex.Plan.Reflex
266+ Reflex.Plan.Pure
231267
232268test-suite GC-Semantics
233269 type: exitcode-stdio-1.0
234270 main-is: GC.hs
235271 hs-source-dirs: test
236272 build-depends: base
273+ , containers
237274 , dependent-sum
238275 , dependent-map
276+ , deepseq >= 1.3 && < 1.5
277+ , mtl
239278 , these
240279 , transformers
241280 , reflex
242281 , ref-tf
243282 if impl(ghc < 8)
244283 build-depends: semigroups
284+ other-modules:
285+ Reflex.Plan.Pure
286+ Reflex.Plan.Reflex
287+ Reflex.TestPlan
288+ Test.Run
245289
246290test-suite rootCleanup
247291 type: exitcode-stdio-1.0
248292 main-is: rootCleanup.hs
249293 hs-source-dirs: test
250294 build-depends: base
295+ , containers
296+ , deepseq >= 1.3 && < 1.5
297+ , dependent-sum
298+ , mtl
251299 , reflex
300+ , ref-tf
301+ , these
302+ other-modules:
303+ Reflex.Plan.Pure
304+ Reflex.TestPlan
305+ Test.Run
252306
253307benchmark spider-bench
254308 type: exitcode-stdio-1.0
255− hs-source-dirs: bench
309+ hs-source-dirs: bench test
256310 main-is: Main.hs
257311 ghc-options: -Wall -O2 -rtsopts
258312 build-depends:
259313 base,
260− criterion == 1.1.*,
314+ containers,
315+ criterion >= 1.1 && < 1.6,
261316 deepseq >= 1.3 && < 1.5,
262317 dependent-map,
263318 dependent-sum,
319+ ref-tf,
264320 mtl,
265321 primitive,
266322 reflex,
323+ split,
267324 stm,
268325 transformers >= 0.3
326+ other-modules:
327+ Reflex.TestPlan
328+ Reflex.Plan.Reflex
329+ Reflex.Bench.Focused
269330
270331benchmark saulzar-bench
271332 type: exitcode-stdio-1.0
@@ -273,11 +334,10 @@ benchmark saulzar-bench
273334 c-sources: bench-cbits/checkCapability.c
274335 main-is: RunAll.hs
275336 ghc-options: -Wall -O2 -rtsopts -threaded
276− ghc-prof-options: -fprof-auto
277337 build-depends:
278338 base,
279− containers == 0.5.*,
280− criterion == 1.1.*,
339+ containers >= 0.5 && < 0.7,
340+ criterion >= 1.1 && < 1.6,
281341 deepseq >= 1.3 && < 1.5,
282342 dependent-map,
283343 dependent-sum,
@@ -291,6 +351,10 @@ benchmark saulzar-bench
291351 stm,
292352 time,
293353 transformers >= 0.3
354+ other-modules:
355+ Reflex.TestPlan
356+ Reflex.Plan.Reflex
357+ Reflex.Bench.Focused
294358
295359source-repository head
296360 type: git
release.nixnew file+9
@@ -0,0 +1,9 @@
1+{ rp ? import ./reflex-platform.nix {}
2+}:
3+let
4+ inherit (rp.nixpkgs) lib;
5+ compilers = ["ghc8_4" "ghc8_0" "ghcjs8_4" "ghcjs8_0"];
6+in lib.genAttrs compilers (ghc: {
7+ reflex-useTemplateHaskell = rp.${ghc}.callPackage ./. { useTemplateHaskell = true; };
8+ reflex = rp.${ghc}.callPackage ./. { useTemplateHaskell = false; };
9+})
src/Data/AppendMap.hs+9−298
@@ -21,16 +21,17 @@ module Data.AppendMap
2121 , module Data.Map.Monoidal
2222 ) where
2323
24−import Prelude hiding (map)
24+import Prelude hiding (map, null)
2525
26−import Data.Align
2726import Data.Coerce
2827import Data.Default
2928import Data.Map (Map)
30−import qualified Data.Map as Map
29+#if MIN_VERSION_containers(0,5,11)
30+import qualified Data.Map.Internal.Debug as Map (showTree, showTreeWith)
31+#else
32+import qualified Data.Map as Map (showTree, showTreeWith)
33+#endif
3134import Data.Map.Monoidal
32−import Data.Semigroup
33−import Data.Set (Set)
3435import Reflex.Class (FunctorMaybe (..))
3536import Reflex.Patch (Additive, Group (..))
3637
@@ -44,8 +45,6 @@ _unAppendMap = getMonoidalMap
4445pattern AppendMap :: Map k v -> MonoidalMap k v
4546pattern AppendMap m = MonoidalMap m
4647
47−deriving instance Ord k => Align (MonoidalMap k)
48−
4948instance FunctorMaybe (MonoidalMap k) where
5049 fmapMaybe = mapMaybe
5150
@@ -53,7 +52,7 @@ instance FunctorMaybe (MonoidalMap k) where
5352nonEmptyDelete :: Ord k => k -> MonoidalMap k a -> Maybe (MonoidalMap k a)
5453nonEmptyDelete k vs =
5554 let deleted = delete k vs
56− in if Data.AppendMap.null deleted
55+ in if null deleted
5756 then Nothing
5857 else Just deleted
5958
@@ -62,309 +61,21 @@ mapMaybeNoNull :: (a -> Maybe b)
6261 -> Maybe (MonoidalMap token b)
6362mapMaybeNoNull f as =
6463 let bs = fmapMaybe f as
65− in if Data.AppendMap.null bs
64+ in if null bs
6665 then Nothing
6766 else Just bs
6867
69−#if !MIN_VERSION_monoidal_containers(0,3,1)
70−instance (Ord k, Semigroup v) => Semigroup (MonoidalMap k v) where
71− MonoidalMap a <> MonoidalMap b = MonoidalMap $ Map.unionWith (<>) a b
72−#endif
73−
68+-- TODO: Move instances to `Reflex.Patch`
7469instance (Ord k, Group q) => Group (MonoidalMap k q) where
7570 negateG = map negateG
7671
7772instance (Ord k, Additive q) => Additive (MonoidalMap k q)
7873
79−(!) :: forall k a. Ord k => MonoidalMap k a -> k -> a
80−(!) = coerce ((Map.!) :: Map k a -> k -> a)
81−infixl 9 !
82−
83−(\\) :: forall k a b. Ord k => MonoidalMap k a -> MonoidalMap k b -> MonoidalMap k a
84−(\\) = coerce ((Map.\\) :: Map k a -> Map k b -> Map k a)
85−infixl 9 {-"-} \\ {-"-} --These comments prevent the C preprocssor from complaining
86−
87−null :: forall k a. MonoidalMap k a -> Bool
88−null = coerce (Map.null :: Map k a -> Bool)
89−
90−lookup :: forall k a. Ord k => k -> MonoidalMap k a -> Maybe a
91−lookup = coerce (Map.lookup :: k -> Map k a -> Maybe a)
92−
93−lookupLT :: forall k a. Ord k => k -> MonoidalMap k a -> Maybe (k, a)
94−lookupLT = coerce (Map.lookupLT :: k -> Map k a -> Maybe (k,a))
95−
96−lookupGT :: forall k a. Ord k => k -> MonoidalMap k a -> Maybe (k, a)
97−lookupGT = coerce (Map.lookupGT :: k -> Map k a -> Maybe (k,a))
98−
99−lookupLE :: forall k a. Ord k => k -> MonoidalMap k a -> Maybe (k, a)
100−lookupLE = coerce (Map.lookupLE :: k -> Map k a -> Maybe (k,a))
101−
102−lookupGE :: forall k a. Ord k => k -> MonoidalMap k a -> Maybe (k, a)
103−lookupGE = coerce (Map.lookupGE :: k -> Map k a -> Maybe (k,a))
104−
105−empty :: forall k a. MonoidalMap k a
106−empty = coerce (Map.empty :: Map k a)
107−
108−insert :: forall k a. Ord k => k -> a -> MonoidalMap k a -> MonoidalMap k a
109−insert = coerce (Map.insert :: k -> a -> Map k a -> Map k a)
110−
111−insertWith :: forall k a. Ord k => (a -> a -> a) -> k -> a -> MonoidalMap k a -> MonoidalMap k a
112−insertWith = coerce (Map.insertWith :: (a -> a -> a) -> k -> a -> Map k a -> Map k a)
113−
114−insertWithKey :: forall k a. Ord k => (k -> a -> a -> a) -> k -> a -> MonoidalMap k a -> MonoidalMap k a
115−insertWithKey = coerce (Map.insertWithKey :: (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a)
116−
117−insertLookupWithKey :: forall k a. Ord k => (k -> a -> a -> a) -> k -> a -> MonoidalMap k a -> (Maybe a, MonoidalMap k a)
118−insertLookupWithKey = coerce (Map.insertLookupWithKey :: (k -> a -> a -> a) -> k -> a -> Map k a -> (Maybe a, Map k a))
119−
120−delete :: forall k a. Ord k => k -> MonoidalMap k a -> MonoidalMap k a
121−delete = coerce (Map.delete :: k -> Map k a -> Map k a)
122−
123−adjust :: forall k a. Ord k => (a -> a) -> k -> MonoidalMap k a -> MonoidalMap k a
124−adjust = coerce (Map.adjust :: (a -> a) -> k -> Map k a -> Map k a)
125−
126−adjustWithKey :: forall k a. Ord k => (k -> a -> a) -> k -> MonoidalMap k a -> MonoidalMap k a
127−adjustWithKey = coerce (Map.adjustWithKey :: (k -> a -> a) -> k -> Map k a -> Map k a)
128−
129−update :: forall k a. Ord k => (a -> Maybe a) -> k -> MonoidalMap k a -> MonoidalMap k a
130−update = coerce (Map.update :: (a -> Maybe a) -> k -> Map k a -> Map k a)
131−
132−updateWithKey :: forall k a. Ord k => (k -> a -> Maybe a) -> k -> MonoidalMap k a -> MonoidalMap k a
133−updateWithKey = coerce (Map.updateWithKey :: (k -> a -> Maybe a) -> k -> Map k a -> Map k a)
134−
135−updateLookupWithKey :: forall k a. Ord k => (k -> a -> Maybe a) -> k -> MonoidalMap k a -> (Maybe a, MonoidalMap k a)
136−updateLookupWithKey = coerce (Map.updateLookupWithKey :: (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a, Map k a))
137−
138−alter :: forall k a. Ord k => (Maybe a -> Maybe a) -> k -> MonoidalMap k a -> MonoidalMap k a
139−alter = coerce (Map.alter :: (Maybe a -> Maybe a) -> k -> Map k a -> Map k a)
140−
141−unionWith :: forall k a. Ord k => (a -> a -> a) -> MonoidalMap k a -> MonoidalMap k a -> MonoidalMap k a
142−unionWith = coerce (Map.unionWith :: (a -> a -> a) -> Map k a -> Map k a -> Map k a)
143−
144−unionWithKey :: forall k a. Ord k => (k -> a -> a -> a) -> MonoidalMap k a -> MonoidalMap k a -> MonoidalMap k a
145−unionWithKey = coerce (Map.unionWithKey :: (k -> a -> a -> a) -> Map k a -> Map k a -> Map k a)
146−
147−unionsWith :: forall k a. Ord k => (a -> a -> a) -> [MonoidalMap k a] -> MonoidalMap k a
148−unionsWith = coerce (Map.unionsWith :: (a -> a -> a) -> [Map k a] -> Map k a)
149−
150−difference :: forall k a b. Ord k => MonoidalMap k a -> MonoidalMap k b -> MonoidalMap k a
151−difference = (\\)
152−
153−differenceWith :: forall k a b. Ord k => (a -> b -> Maybe a) -> MonoidalMap k a -> MonoidalMap k b -> MonoidalMap k a
154−differenceWith = coerce (Map.differenceWith :: (a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a)
155−
156−differenceWithKey :: forall k a b. Ord k => (k -> a -> b -> Maybe a) -> MonoidalMap k a -> MonoidalMap k b -> MonoidalMap k a
157−differenceWithKey = coerce (Map.differenceWithKey :: (k -> a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a)
158−
159−intersectionWith :: forall k a b c. Ord k => (a -> b -> c) -> MonoidalMap k a -> MonoidalMap k b -> MonoidalMap k c
160−intersectionWith = coerce (Map.intersectionWith :: (a -> b -> c) -> Map k a -> Map k b -> Map k c)
161−
162−intersectionWithKey :: forall k a b c. Ord k => (k -> a -> b -> c) -> MonoidalMap k a -> MonoidalMap k b -> MonoidalMap k c
163−intersectionWithKey = coerce (Map.intersectionWithKey :: (k -> a -> b -> c) -> Map k a -> Map k b -> Map k c)
164−
165−mergeWithKey :: forall k a b c. Ord k => (k -> a -> b -> Maybe c) -> (MonoidalMap k a -> MonoidalMap k c) -> (MonoidalMap k b -> MonoidalMap k c) -> MonoidalMap k a -> MonoidalMap k b -> MonoidalMap k c
166−mergeWithKey = coerce (Map.mergeWithKey :: (k -> a -> b -> Maybe c) -> (Map k a -> Map k c) -> (Map k b -> Map k c) -> Map k a -> Map k b -> Map k c)
167−
168−map :: (a -> b) -> MonoidalMap k a -> MonoidalMap k b
169−map = fmap
170−
171−mapWithKey :: (k -> a -> b) -> MonoidalMap k a -> MonoidalMap k b
172−mapWithKey f (MonoidalMap m) = MonoidalMap $ Map.mapWithKey f m
173−
174−traverseWithKey :: Applicative t => (k -> a -> t b) -> MonoidalMap k a -> t (MonoidalMap k b)
175−traverseWithKey f (MonoidalMap m) = MonoidalMap <$> Map.traverseWithKey f m
176−
177−mapAccum :: forall k a b c. (a -> b -> (a, c)) -> a -> MonoidalMap k b -> (a, MonoidalMap k c)
178−mapAccum = coerce (Map.mapAccum :: (a -> b -> (a, c)) -> a -> Map k b -> (a, Map k c))
179−
180−mapAccumWithKey :: forall k a b c. (a -> k -> b -> (a, c)) -> a -> MonoidalMap k b -> (a, MonoidalMap k c)
181−mapAccumWithKey = coerce (Map.mapAccumWithKey :: (a -> k -> b -> (a, c)) -> a -> Map k b -> (a, Map k c))
182−
183−mapAccumRWithKey :: forall k a b c. (a -> k -> b -> (a, c)) -> a -> MonoidalMap k b -> (a, MonoidalMap k c)
184−mapAccumRWithKey = coerce (Map.mapAccumRWithKey :: (a -> k -> b -> (a, c)) -> a -> Map k b -> (a, Map k c))
185−
186−mapKeys :: forall k1 k2 a. Ord k2 => (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
187−mapKeys = coerce (Map.mapKeys :: (k1 -> k2) -> Map k1 a -> Map k2 a)
188−
189−mapKeysWith :: forall k1 k2 a. Ord k2 => (a -> a -> a) -> (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
190−mapKeysWith = coerce (Map.mapKeysWith :: (a -> a -> a) -> (k1 -> k2) -> Map k1 a -> Map k2 a)
191−
192−mapKeysMonotonic :: forall k1 k2 a. (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
193−mapKeysMonotonic = coerce (Map.mapKeysMonotonic :: (k1 -> k2) -> Map k1 a -> Map k2 a)
194−
195−foldr :: forall k a b. (a -> b -> b) -> b -> MonoidalMap k a -> b
196−foldr = coerce (Map.foldr :: (a -> b -> b) -> b -> Map k a -> b)
197−
198−foldl :: forall k a b. (a -> b -> a) -> a -> MonoidalMap k b -> a
199−foldl = coerce (Map.foldl :: (a -> b -> a) -> a -> Map k b -> a)
200−
201−foldrWithKey :: forall k a b. (k -> a -> b -> b) -> b -> MonoidalMap k a -> b
202−foldrWithKey = coerce (Map.foldrWithKey :: (k -> a -> b -> b) -> b -> Map k a -> b)
203−
204−foldlWithKey :: forall k a b. (a -> k -> b -> a) -> a -> MonoidalMap k b -> a
205−foldlWithKey = coerce (Map.foldlWithKey :: (a -> k -> b -> a) -> a -> Map k b -> a)
206−
207−foldMapWithKey :: forall k a m. Monoid m => (k -> a -> m) -> MonoidalMap k a -> m
208−foldMapWithKey = coerce (Map.foldMapWithKey :: (k -> a -> m) -> Map k a -> m)
209−
210−foldr' :: forall k a b. (a -> b -> b) -> b -> MonoidalMap k a -> b
211−foldr' = coerce (Map.foldr' :: (a -> b -> b) -> b -> Map k a -> b)
212−
213−foldl' :: forall k a b. (a -> b -> a) -> a -> MonoidalMap k b -> a
214−foldl' = coerce (Map.foldl' :: (a -> b -> a) -> a -> Map k b -> a)
215−
216−foldrWithKey' :: forall k a b. (k -> a -> b -> b) -> b -> MonoidalMap k a -> b
217−foldrWithKey' = coerce (Map.foldrWithKey' :: (k -> a -> b -> b) -> b -> Map k a -> b)
218−
219−foldlWithKey' :: forall k a b. (a -> k -> b -> a) -> a -> MonoidalMap k b -> a
220−foldlWithKey' = coerce (Map.foldlWithKey' :: (a -> k -> b -> a) -> a -> Map k b -> a)
221−
222−keysSet :: forall k a. MonoidalMap k a -> Set k
223−keysSet = coerce (Map.keysSet :: Map k a -> Set k)
224−
225−fromSet :: forall k a. (k -> a) -> Set k -> MonoidalMap k a
226−fromSet = coerce (Map.fromSet :: (k -> a) -> Set k -> Map k a)
227−
228−toList :: forall k a. MonoidalMap k a -> [(k, a)]
229−toList = coerce (Map.toList :: Map k a -> [(k, a)])
230−
231−fromList :: forall k a. Ord k => [(k, a)] -> MonoidalMap k a
232−fromList = coerce (Map.fromList :: [(k, a)] -> Map k a)
233−
234−fromListWith :: forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> MonoidalMap k a
235−fromListWith = coerce (Map.fromListWith :: (a -> a -> a) -> [(k, a)] -> Map k a)
236−
237−fromListWithKey :: forall k a. Ord k => (k -> a -> a -> a) -> [(k, a)] -> MonoidalMap k a
238−fromListWithKey = coerce (Map.fromListWithKey :: (k -> a -> a -> a) -> [(k, a)] -> Map k a)
239−
240−toAscList :: forall k a. MonoidalMap k a -> [(k, a)]
241−toAscList = coerce (Map.toAscList :: Map k a -> [(k, a)])
242−
243−toDescList :: forall k a. MonoidalMap k a -> [(k, a)]
244−toDescList = coerce (Map.toDescList :: Map k a -> [(k, a)])
245−
246−fromAscList :: forall k a. Eq k => [(k, a)] -> MonoidalMap k a
247−fromAscList = coerce (Map.fromAscList :: [(k, a)] -> Map k a)
248−
249−fromAscListWith :: forall k a. Eq k => (a -> a -> a) -> [(k, a)] -> MonoidalMap k a
250−fromAscListWith = coerce (Map.fromAscListWith :: (a -> a -> a) -> [(k, a)] -> Map k a)
251−
252−fromAscListWithKey :: forall k a. Eq k => (k -> a -> a -> a) -> [(k, a)] -> MonoidalMap k a
253−fromAscListWithKey = coerce (Map.fromAscListWithKey :: (k -> a -> a -> a) -> [(k, a)] -> Map k a)
254−
255−fromDistinctAscList :: forall k a. [(k, a)] -> MonoidalMap k a
256−fromDistinctAscList = coerce (Map.fromDistinctAscList :: [(k, a)] -> Map k a)
257−
258−filter :: forall k a. (a -> Bool) -> MonoidalMap k a -> MonoidalMap k a
259−filter = coerce (Map.filter :: (a -> Bool) -> Map k a -> Map k a)
260−
261−filterWithKey :: forall k a. (k -> a -> Bool) -> MonoidalMap k a -> MonoidalMap k a
262−filterWithKey = coerce (Map.filterWithKey :: (k -> a -> Bool) -> Map k a -> Map k a)
263−
264−partition :: forall k a. (a -> Bool) -> MonoidalMap k a -> (MonoidalMap k a, MonoidalMap k a)
265−partition = coerce (Map.partition :: (a -> Bool) -> Map k a -> (Map k a, Map k a))
266−
267−partitionWithKey :: forall k a. (k -> a -> Bool) -> MonoidalMap k a -> (MonoidalMap k a, MonoidalMap k a)
268−partitionWithKey = coerce (Map.partitionWithKey :: (k -> a -> Bool) -> Map k a -> (Map k a, Map k a))
269−
270−mapMaybe :: forall k a b. (a -> Maybe b) -> MonoidalMap k a -> MonoidalMap k b
271−mapMaybe = coerce (Map.mapMaybe :: (a -> Maybe b) -> Map k a -> Map k b)
272−
273−mapMaybeWithKey :: forall k a b. (k -> a -> Maybe b) -> MonoidalMap k a -> MonoidalMap k b
274−mapMaybeWithKey = coerce (Map.mapMaybeWithKey :: (k -> a -> Maybe b) -> Map k a -> Map k b)
275−
276−mapEither :: forall k a b c. (a -> Either b c) -> MonoidalMap k a -> (MonoidalMap k b, MonoidalMap k c)
277−mapEither = coerce (Map.mapEither :: (a -> Either b c) -> Map k a -> (Map k b, Map k c))
278−
279−mapEitherWithKey :: forall k a b c. (k -> a -> Either b c) -> MonoidalMap k a -> (MonoidalMap k b, MonoidalMap k c)
280−mapEitherWithKey = coerce (Map.mapEitherWithKey :: (k -> a -> Either b c) -> Map k a -> (Map k b, Map k c))
281−
282−split :: forall k a. Ord k => k -> MonoidalMap k a -> (MonoidalMap k a, MonoidalMap k a)
283−split = coerce (Map.split :: k -> Map k a -> (Map k a, Map k a))
284−
285−splitLookup :: forall k a. Ord k => k -> MonoidalMap k a -> (MonoidalMap k a, Maybe a, MonoidalMap k a)
286−splitLookup = coerce (Map.splitLookup :: k -> Map k a -> (Map k a, Maybe a, Map k a))
287−
288−splitRoot :: forall k a. MonoidalMap k a -> [MonoidalMap k a]
289−splitRoot = coerce (Map.splitRoot :: Map k a -> [Map k a])
290−
291−isSubmapOf :: forall k a. (Ord k, Eq a) => MonoidalMap k a -> MonoidalMap k a -> Bool
292−isSubmapOf = coerce (Map.isSubmapOf :: Map k a -> Map k a -> Bool)
293−
294−isSubmapOfBy :: forall k a b. Ord k => (a -> b -> Bool) -> MonoidalMap k a -> MonoidalMap k b -> Bool
295−isSubmapOfBy = coerce (Map.isSubmapOfBy :: (a -> b -> Bool) -> Map k a -> Map k b -> Bool)
296−
297−isProperSubmapOf :: forall k a. (Ord k, Eq a) => MonoidalMap k a -> MonoidalMap k a -> Bool
298−isProperSubmapOf = coerce (Map.isProperSubmapOf :: Map k a -> Map k a -> Bool)
299−
300−isProperSubmapOfBy :: forall k a b. Ord k => (a -> b -> Bool) -> MonoidalMap k a -> MonoidalMap k b -> Bool
301−isProperSubmapOfBy = coerce (Map.isProperSubmapOfBy :: (a -> b -> Bool) -> Map k a -> Map k b -> Bool)
302−
303−lookupIndex :: forall k a. Ord k => k -> MonoidalMap k a -> Maybe Int
304−lookupIndex = coerce (Map.lookupIndex :: k -> Map k a -> Maybe Int)
305−
306−findIndex :: forall k a. Ord k => k -> MonoidalMap k a -> Int
307−findIndex = coerce (Map.findIndex :: k -> Map k a -> Int)
308−
309−elemAt :: forall k a. Int -> MonoidalMap k a -> (k, a)
310−elemAt = coerce (Map.elemAt :: Int -> Map k a -> (k, a))
311−
312−updateAt :: forall k a. (k -> a -> Maybe a) -> Int -> MonoidalMap k a -> MonoidalMap k a
313−updateAt = coerce (Map.updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a)
314−
315−deleteAt :: forall k a. Int -> MonoidalMap k a -> MonoidalMap k a
316−deleteAt = coerce (Map.deleteAt :: Int -> Map k a -> Map k a)
317−
318−findMin :: forall k a. MonoidalMap k a -> (k, a)
319−findMin = coerce (Map.findMin :: Map k a -> (k, a))
320−
321−findMax :: forall k a. MonoidalMap k a -> (k, a)
322−findMax = coerce (Map.findMax :: Map k a -> (k, a))
323−
324−deleteMin :: forall k a. MonoidalMap k a -> MonoidalMap k a
325−deleteMin = coerce (Map.deleteMin :: Map k a -> Map k a)
326−
327−deleteMax :: forall k a. MonoidalMap k a -> MonoidalMap k a
328−deleteMax = coerce (Map.deleteMax :: Map k a -> Map k a)
329−
330−deleteFindMin :: forall k a. MonoidalMap k a -> ((k, a), MonoidalMap k a)
331−deleteFindMin = coerce (Map.deleteFindMin :: Map k a -> ((k, a), Map k a))
332−
333−deleteFindMax :: forall k a. MonoidalMap k a -> ((k, a), MonoidalMap k a)
334−deleteFindMax = coerce (Map.deleteFindMax :: Map k a -> ((k, a), Map k a))
335−
336−updateMin :: forall k a. (a -> Maybe a) -> MonoidalMap k a -> MonoidalMap k a
337−updateMin = coerce (Map.updateMin :: (a -> Maybe a) -> Map k a -> Map k a)
338−
339−updateMax :: forall k a. (a -> Maybe a) -> MonoidalMap k a -> MonoidalMap k a
340−updateMax = coerce (Map.updateMax :: (a -> Maybe a) -> Map k a -> Map k a)
341−
342−updateMinWithKey :: forall k a. (k -> a -> Maybe a) -> MonoidalMap k a -> MonoidalMap k a
343−updateMinWithKey = coerce (Map.updateMinWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a)
344−
345−updateMaxWithKey :: forall k a. (k -> a -> Maybe a) -> MonoidalMap k a -> MonoidalMap k a
346−updateMaxWithKey = coerce (Map.updateMaxWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a)
347−
348−minView :: forall k a. MonoidalMap k a -> Maybe (a, MonoidalMap k a)
349−minView = coerce (Map.minView :: Map k a -> Maybe (a, Map k a))
350−
351−maxView :: forall k a. MonoidalMap k a -> Maybe (a, MonoidalMap k a)
352−maxView = coerce (Map.maxView :: Map k a -> Maybe (a, Map k a))
353−
354−minViewWithKey :: forall k a. MonoidalMap k a -> Maybe ((k, a), MonoidalMap k a)
355−minViewWithKey = coerce (Map.minViewWithKey :: Map k a -> Maybe ((k, a), Map k a))
356−
357−maxViewWithKey :: forall k a. MonoidalMap k a -> Maybe ((k, a), MonoidalMap k a)
358−maxViewWithKey = coerce (Map.maxViewWithKey :: Map k a -> Maybe ((k, a), Map k a))
359−
36074showTree :: forall k a. (Show k, Show a) => MonoidalMap k a -> String
36175showTree = coerce (Map.showTree :: Map k a -> String)
36276
36377showTreeWith :: forall k a. (k -> a -> String) -> Bool -> Bool -> MonoidalMap k a -> String
36478showTreeWith = coerce (Map.showTreeWith :: (k -> a -> String) -> Bool -> Bool -> Map k a -> String)
36579
366−valid :: forall k a. Ord k => MonoidalMap k a -> Bool
367−valid = coerce (Map.valid :: Map k a -> Bool)
368−
36980instance Default (MonoidalMap k a) where
37081 def = empty
src/Reflex.hs+3
@@ -6,6 +6,9 @@ module Reflex
66 ) where
77
88import Reflex.Class as X
9+import Reflex.Adjustable.Class as X
10+import Reflex.BehaviorWriter.Base as X
11+import Reflex.BehaviorWriter.Class as X
912import Reflex.Collection as X
1013import Reflex.Dynamic as X
1114import Reflex.EventWriter.Base as X
src/Reflex/Adjustable/Class.hs+52−10
@@ -1,6 +1,8 @@
11{-# LANGUAGE CPP #-}
2+{-# LANGUAGE ConstraintKinds #-}
23{-# LANGUAGE FlexibleInstances #-}
34{-# LANGUAGE FunctionalDependencies #-}
5+{-# LANGUAGE LambdaCase #-}
46{-# LANGUAGE MultiParamTypeClasses #-}
57{-# LANGUAGE RankNTypes #-}
68{-# LANGUAGE ScopedTypeVariables #-}
@@ -16,22 +18,22 @@ module Reflex.Adjustable.Class
1618 , sequenceDMapWithAdjust
1719 , sequenceDMapWithAdjustWithMove
1820 , mapMapWithAdjustWithMove
21+ -- * Deprecated aliases
22+ , MonadAdjust
1923 ) where
2024
2125import Control.Monad.Identity
2226import Control.Monad.Reader
23−import Data.Align
2427import Data.Dependent.Map (DMap, GCompare (..))
28+import qualified Data.Dependent.Map as DMap
2529import Data.Functor.Constant
2630import Data.Functor.Misc
31+import Data.IntMap.Strict (IntMap)
32+import qualified Data.IntMap.Strict as IntMap
2733import Data.Map (Map)
28−import qualified Data.Map as Map
29−import Data.Map.Misc
30−import Data.These
3134
3235import Reflex.Class
33−import Reflex.Dynamic
34−import Reflex.PostBuild.Class
36+import Reflex.Patch.DMapWithMove
3537
3638-- | A 'Monad' that supports adjustment over time. After an action has been
3739-- run, if the given events fire, it will adjust itself so that its net effect
@@ -40,10 +42,43 @@ import Reflex.PostBuild.Class
4042-- other side-effects) cannot be undone, so it is up to the instance implementer
4143-- to determine what the best meaning for this class is in such cases.
4244class (Reflex t, Monad m) => Adjustable t m | m -> t where
43− runWithReplace :: m a -> Event t (m b) -> m (a, Event t b)
44− traverseIntMapWithKeyWithAdjust :: (IntMap.Key -> v -> m v') -> IntMap v -> Event t (PatchIntMap v) -> m (IntMap v', Event t (PatchIntMap v'))
45− traverseDMapWithKeyWithAdjust :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMap k v) -> m (DMap k v', Event t (PatchDMap k v'))
46− traverseDMapWithKeyWithAdjustWithMove :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMapWithMove k v) -> m (DMap k v', Event t (PatchDMapWithMove k v'))
45+ runWithReplace
46+ :: m a
47+ -> Event t (m b)
48+ -> m (a, Event t b)
49+
50+ traverseIntMapWithKeyWithAdjust
51+ :: (IntMap.Key -> v -> m v')
52+ -> IntMap v
53+ -> Event t (PatchIntMap v)
54+ -> m (IntMap v', Event t (PatchIntMap v'))
55+
56+ traverseDMapWithKeyWithAdjust
57+ :: GCompare k
58+ => (forall a. k a -> v a -> m (v' a))
59+ -> DMap k v
60+ -> Event t (PatchDMap k v)
61+ -> m (DMap k v', Event t (PatchDMap k v'))
62+ {-# INLINABLE traverseDMapWithKeyWithAdjust #-}
63+ traverseDMapWithKeyWithAdjust f dm0 dm' = fmap (fmap (fmap fromPatchWithMove)) $
64+ traverseDMapWithKeyWithAdjustWithMove f dm0 $ fmap toPatchWithMove dm'
65+ where
66+ toPatchWithMove (PatchDMap m) = PatchDMapWithMove $ DMap.map toNodeInfoWithMove m
67+ toNodeInfoWithMove = \case
68+ ComposeMaybe (Just v) -> NodeInfo (From_Insert v) $ ComposeMaybe Nothing
69+ ComposeMaybe Nothing -> NodeInfo From_Delete $ ComposeMaybe Nothing
70+ fromPatchWithMove (PatchDMapWithMove m) = PatchDMap $ DMap.map fromNodeInfoWithMove m
71+ fromNodeInfoWithMove (NodeInfo from _) = ComposeMaybe $ case from of
72+ From_Insert v -> Just v
73+ From_Delete -> Nothing
74+ From_Move _ -> error "traverseDMapWithKeyWithAdjust: implementation of traverseDMapWithKeyWithAdjustWithMove inserted spurious move"
75+
76+ traverseDMapWithKeyWithAdjustWithMove
77+ :: GCompare k
78+ => (forall a. k a -> v a -> m (v' a))
79+ -> DMap k v
80+ -> Event t (PatchDMapWithMove k v)
81+ -> m (DMap k v', Event t (PatchDMapWithMove k v'))
4782
4883instance Adjustable t m => Adjustable t (ReaderT r m) where
4984 runWithReplace a0 a' = do
@@ -69,3 +104,10 @@ mapMapWithAdjustWithMove :: forall t m k v v'. (Adjustable t m, Ord k) => (k ->
69104mapMapWithAdjustWithMove f m0 m' = do
70105 (out0 :: DMap (Const2 k v) (Constant v'), out') <- traverseDMapWithKeyWithAdjustWithMove (\(Const2 k) (Identity v) -> Constant <$> f k v) (mapToDMap m0) (const2PatchDMapWithMoveWith Identity <$> m')
71106 return (dmapToMapWith (\(Constant v') -> v') out0, patchDMapWithMoveToPatchMapWithMoveWith (\(Constant v') -> v') <$> out')
107+
108+--------------------------------------------------------------------------------
109+-- Deprecated functions
110+--------------------------------------------------------------------------------
111+
112+{-# DEPRECATED MonadAdjust "Use Adjustable instead" #-}
113+type MonadAdjust = Adjustable
src/Reflex/BehaviorWriter/Base.hsnew file+202
@@ -0,0 +1,202 @@
1+{-|
2+Module: Reflex.BehaviorWriter.Base
3+Description: Implementation of MonadBehaviorWriter
4+-}
5+{-# LANGUAGE CPP #-}
6+{-# LANGUAGE FlexibleInstances #-}
7+{-# LANGUAGE GADTs #-}
8+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
9+{-# LANGUAGE MultiParamTypeClasses #-}
10+{-# LANGUAGE RankNTypes #-}
11+{-# LANGUAGE ScopedTypeVariables #-}
12+{-# LANGUAGE TypeFamilies #-}
13+{-# LANGUAGE UndecidableInstances #-}
14+{-# LANGUAGE StandaloneDeriving #-}
15+#ifdef USE_REFLEX_OPTIMIZER
16+{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
17+#endif
18+module Reflex.BehaviorWriter.Base
19+ ( BehaviorWriterT (..)
20+ , runBehaviorWriterT
21+ , withBehaviorWriterT
22+ ) where
23+
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.Dependent.Map (DMap)
31+import qualified Data.Dependent.Map as DMap
32+import Data.Functor.Misc
33+import Data.IntMap (IntMap)
34+import qualified Data.IntMap as IntMap
35+import Data.Map (Map)
36+import qualified Data.Map as Map
37+import Data.Some (Some)
38+
39+import Reflex.Class
40+import Reflex.Adjustable.Class
41+import Reflex.BehaviorWriter.Class
42+import Reflex.Host.Class
43+import Reflex.PerformEvent.Class
44+import Reflex.PostBuild.Class
45+import Reflex.Query.Class
46+import Reflex.Requester.Class
47+import Reflex.TriggerEvent.Class
48+
49+-- | A basic implementation of 'MonadBehaviorWriter'.
50+newtype BehaviorWriterT t w m a = BehaviorWriterT { unBehaviorWriterT :: StateT [Behavior t w] m a }
51+ deriving (Functor, Applicative, Monad, MonadIO, MonadFix, MonadAsyncException, MonadException) -- The list is kept in reverse order
52+
53+-- | Run a 'BehaviorWriterT' action. The behavior writer output will be provided
54+-- along with the result of the action.
55+runBehaviorWriterT :: (Monad m, Reflex t, Monoid w) => BehaviorWriterT t w m a -> m (a, Behavior t w)
56+runBehaviorWriterT (BehaviorWriterT a) = do
57+ (result, ws) <- runStateT a []
58+ return (result, mconcat $ reverse ws)
59+
60+-- | Map a function over the output of a 'BehaviorWriterT'.
61+withBehaviorWriterT :: (Monoid w, Monoid w', Reflex t, MonadHold t m)
62+ => (w -> w')
63+ -> BehaviorWriterT t w m a
64+ -> BehaviorWriterT t w' m a
65+withBehaviorWriterT f dw = do
66+ (r, d) <- lift $ do
67+ (r, d) <- runBehaviorWriterT dw
68+ let d' = fmap f d
69+ return (r, d')
70+ tellBehavior d
71+ return r
72+
73+deriving instance MonadHold t m => MonadHold t (BehaviorWriterT t w m)
74+deriving instance MonadSample t m => MonadSample t (BehaviorWriterT t w m)
75+
76+instance MonadTrans (BehaviorWriterT t w) where
77+ lift = BehaviorWriterT . lift
78+
79+instance MonadRef m => MonadRef (BehaviorWriterT t w m) where
80+ type Ref (BehaviorWriterT t w m) = Ref m
81+ newRef = lift . newRef
82+ readRef = lift . readRef
83+ writeRef r = lift . writeRef r
84+
85+instance MonadAtomicRef m => MonadAtomicRef (BehaviorWriterT t w m) where
86+ atomicModifyRef r = lift . atomicModifyRef r
87+
88+instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (BehaviorWriterT t w m) where
89+ newEventWithTrigger = lift . newEventWithTrigger
90+ newFanEventWithTrigger f = lift $ newFanEventWithTrigger f
91+
92+instance (Monad m, Monoid w, Reflex t) => MonadBehaviorWriter t w (BehaviorWriterT t w m) where
93+ tellBehavior w = BehaviorWriterT $ modify (w :)
94+
95+instance MonadReader r m => MonadReader r (BehaviorWriterT t w m) where
96+ ask = lift ask
97+ local f (BehaviorWriterT a) = BehaviorWriterT $ mapStateT (local f) a
98+ reader = lift . reader
99+
100+instance PerformEvent t m => PerformEvent t (BehaviorWriterT t w m) where
101+ type Performable (BehaviorWriterT t w m) = Performable m
102+ performEvent_ = lift . performEvent_
103+ performEvent = lift . performEvent
104+
105+instance TriggerEvent t m => TriggerEvent t (BehaviorWriterT t w m) where
106+ newTriggerEvent = lift newTriggerEvent
107+ newTriggerEventWithOnComplete = lift newTriggerEventWithOnComplete
108+ newEventWithLazyTriggerWithOnComplete = lift . newEventWithLazyTriggerWithOnComplete
109+
110+instance PostBuild t m => PostBuild t (BehaviorWriterT t w m) where
111+ getPostBuild = lift getPostBuild
112+
113+instance MonadState s m => MonadState s (BehaviorWriterT t w m) where
114+ get = lift get
115+ put = lift . put
116+
117+instance Requester t m => Requester t (BehaviorWriterT t w m) where
118+ type Request (BehaviorWriterT t w m) = Request m
119+ type Response (BehaviorWriterT t w m) = Response m
120+ requesting = lift . requesting
121+ requesting_ = lift . requesting_
122+
123+instance (MonadQuery t q m, Monad m) => MonadQuery t q (BehaviorWriterT t w m) where
124+ tellQueryIncremental = lift . tellQueryIncremental
125+ askQueryResult = lift askQueryResult
126+ queryIncremental = lift . queryIncremental
127+
128+instance (Adjustable t m, Monoid w, MonadHold t m, Reflex t) => Adjustable t (BehaviorWriterT t w m) where
129+ runWithReplace a0 a' = do
130+ (result0, result') <- lift $ runWithReplace (runBehaviorWriterT a0) $ runBehaviorWriterT <$> a'
131+ tellBehavior . join =<< hold (snd result0) (snd <$> result')
132+ return (fst result0, fst <$> result')
133+ traverseIntMapWithKeyWithAdjust = traverseIntMapWithKeyWithAdjustImpl traverseIntMapWithKeyWithAdjust
134+ traverseDMapWithKeyWithAdjustWithMove = traverseDMapWithKeyWithAdjustImpl traverseDMapWithKeyWithAdjustWithMove mapPatchDMapWithMove weakenPatchDMapWithMoveWith
135+
136+traverseIntMapWithKeyWithAdjustImpl
137+ :: forall t w v' p p' v m.
138+ ( PatchTarget (p' (Behavior t w)) ~ IntMap (Behavior t w)
139+ , Patch (p' (Behavior t w))
140+ , Monoid w
141+ , Reflex t
142+ , MonadHold t m
143+ , Functor p
144+ , p ~ p'
145+ )
146+ => ( (IntMap.Key -> v -> m (v', Behavior t w))
147+ -> IntMap v
148+ -> Event t (p v)
149+ -> m (IntMap (v', Behavior t w), Event t (p (v', Behavior t w)))
150+ )
151+ -> (IntMap.Key -> v -> BehaviorWriterT t w m v')
152+ -> IntMap v
153+ -> Event t (p v)
154+ -> BehaviorWriterT t w m (IntMap v', Event t (p v'))
155+traverseIntMapWithKeyWithAdjustImpl base f (dm0 :: IntMap v) dm' = do
156+ (result0, result') <- lift $ base (\k v -> runBehaviorWriterT $ f k v) dm0 dm'
157+ let liftedResult0 = fmap fst result0
158+ liftedResult' = fmap (fmap fst) result'
159+ liftedWritten0 :: IntMap (Behavior t w)
160+ liftedWritten0 = fmap snd result0
161+ liftedWritten' = fmap (fmap snd) result'
162+ i <- holdIncremental liftedWritten0 liftedWritten'
163+ tellBehavior $ pull $ do
164+ m <- sample $ currentIncremental i
165+ mconcat . IntMap.elems <$> traverse sample m
166+ return (liftedResult0, liftedResult')
167+
168+newtype BehaviorWriterTLoweredResult t w v a = BehaviorWriterTLoweredResult (v a, Behavior t w)
169+
170+traverseDMapWithKeyWithAdjustImpl
171+ :: forall t w k v' p p' v m.
172+ ( PatchTarget (p' (Some k) (Behavior t w)) ~ Map (Some k) (Behavior t w)
173+ , Patch (p' (Some k) (Behavior t w))
174+ , Monoid w
175+ , Reflex t
176+ , MonadHold t m
177+ )
178+ => ( (forall a. k a -> v a -> m (BehaviorWriterTLoweredResult t w v' a))
179+ -> DMap k v
180+ -> Event t (p k v)
181+ -> m (DMap k (BehaviorWriterTLoweredResult t w v'), Event t (p k (BehaviorWriterTLoweredResult t w v')))
182+ )
183+ -> ((forall a. BehaviorWriterTLoweredResult t w v' a -> v' a) -> p k (BehaviorWriterTLoweredResult t w v') -> p k v')
184+ -> ((forall a. BehaviorWriterTLoweredResult t w v' a -> Behavior t w) -> p k (BehaviorWriterTLoweredResult t w v') -> p' (Some k) (Behavior t w))
185+ -> (forall a. k a -> v a -> BehaviorWriterT t w m (v' a))
186+ -> DMap k v
187+ -> Event t (p k v)
188+ -> BehaviorWriterT t w m (DMap k v', Event t (p k v'))
189+traverseDMapWithKeyWithAdjustImpl base mapPatch weakenPatchWith f (dm0 :: DMap k v) dm' = do
190+ (result0, result') <- lift $ base (\k v -> fmap BehaviorWriterTLoweredResult $ runBehaviorWriterT $ f k v) dm0 dm'
191+ let getValue (BehaviorWriterTLoweredResult (v, _)) = v
192+ getWritten (BehaviorWriterTLoweredResult (_, w)) = w
193+ liftedResult0 = DMap.map getValue result0
194+ liftedResult' = ffor result' $ mapPatch getValue
195+ liftedWritten0 :: Map (Some k) (Behavior t w)
196+ liftedWritten0 = weakenDMapWith getWritten result0
197+ liftedWritten' = ffor result' $ weakenPatchWith getWritten
198+ i <- holdIncremental liftedWritten0 liftedWritten'
199+ tellBehavior $ pull $ do
200+ m <- sample $ currentIncremental i
201+ mconcat . Map.elems <$> traverse sample m
202+ return (liftedResult0, liftedResult')
src/Reflex/BehaviorWriter/Class.hsnew file+26
@@ -0,0 +1,26 @@
1+{-|
2+Module: Reflex.BehaviorWriter.Class
3+Description: This module defines the 'MonadBehaviorWriter' class
4+-}
5+{-# LANGUAGE CPP #-}
6+{-# LANGUAGE FlexibleInstances #-}
7+{-# LANGUAGE FunctionalDependencies #-}
8+{-# LANGUAGE MultiParamTypeClasses #-}
9+{-# LANGUAGE UndecidableInstances #-}
10+#ifdef USE_REFLEX_OPTIMIZER
11+{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
12+#endif
13+module Reflex.BehaviorWriter.Class
14+ ( MonadBehaviorWriter (..)
15+ ) where
16+
17+import Control.Monad.Reader (ReaderT, lift)
18+import Reflex.Class (Behavior)
19+
20+-- | 'MonadBehaviorWriter' efficiently collects 'Behavior' values using 'tellBehavior'
21+-- and combines them monoidally to provide a 'Behavior' result.
22+class (Monad m, Monoid w) => MonadBehaviorWriter t w m | m -> t w where
23+ tellBehavior :: Behavior t w -> m ()
24+
25+instance MonadBehaviorWriter t w m => MonadBehaviorWriter t w (ReaderT r m) where
26+ tellBehavior = lift . tellBehavior
src/Reflex/Class.hs+252−77
@@ -9,6 +9,7 @@
99{-# LANGUAGE LambdaCase #-}
1010{-# LANGUAGE MultiParamTypeClasses #-}
1111{-# LANGUAGE NoMonomorphismRestriction #-}
12+{-# LANGUAGE PolyKinds #-}
1213{-# LANGUAGE RankNTypes #-}
1314{-# LANGUAGE RecursiveDo #-}
1415{-# LANGUAGE RoleAnnotations #-}
@@ -43,9 +44,13 @@ module Reflex.Class
4344 -- ** Combining 'Event's
4445 , leftmost
4546 , mergeMap
47+ , mergeIntMap
4648 , mergeMapIncremental
4749 , mergeMapIncrementalWithMove
4850 , mergeIntMapIncremental
51+ , coincidencePatchMap
52+ , coincidencePatchMapWithMove
53+ , coincidencePatchIntMap
4954 , mergeList
5055 , mergeWith
5156 , difference
@@ -59,12 +64,16 @@ module Reflex.Class
5964 , EitherTag (..)
6065 , eitherToDSum
6166 , dsumToEither
67+ , factorEvent
68+ , filterEventKey
6269 -- ** Collapsing 'Event . Event'
6370 , switchHold
6471 , switchHoldPromptly
6572 , switchHoldPromptOnly
73+ , switchHoldPromptOnlyIncremental
6674 -- ** Using 'Event's to sample 'Behavior's
6775 , tag
76+ , tagMaybe
6877 , attach
6978 , attachWith
7079 , attachWithMaybe
@@ -98,6 +107,14 @@ module Reflex.Class
98107 , mapAccumM_
99108 , mapAccumMaybe_
100109 , mapAccumMaybeM_
110+ , accumIncremental
111+ , accumMIncremental
112+ , accumMaybeIncremental
113+ , accumMaybeMIncremental
114+ , mapAccumIncremental
115+ , mapAccumMIncremental
116+ , mapAccumMaybeIncremental
117+ , mapAccumMaybeMIncremental
101118 , zipListWithEvent
102119 , numberOccurrences
103120 , numberOccurrencesFrom
@@ -107,6 +124,9 @@ module Reflex.Class
107124 , tailE
108125 , headTailE
109126 , takeWhileE
127+ , takeWhileJustE
128+ , dropWhileE
129+ , takeDropWhileJustE
110130 , switcher
111131 -- * Debugging functions
112132 , traceEvent
@@ -120,15 +140,11 @@ module Reflex.Class
120140 , ffilter
121141 , filterLeft
122142 , filterRight
123− -- * 'Adjustable'
124− , Adjustable(..)
125− , sequenceDMapWithAdjust
126− , sequenceDMapWithAdjustWithMove
127− , mapMapWithAdjustWithMove
128143 -- * Miscellaneous convenience functions
129144 , ffor
145+ , ffor2
146+ , ffor3
130147 -- * Deprecated functions
131− , MonadAdjust
132148 , appendEvents
133149 , onceE
134150 , sequenceThese
@@ -158,12 +174,14 @@ import Data.Align
158174import Data.Bifunctor
159175import Data.Coerce
160176import Data.Default
161−import Data.Dependent.Map (DMap, DSum (..), GCompare (..))
177+import Data.Dependent.Map (DMap, DSum (..))
162178import qualified Data.Dependent.Map as DMap
179+import Data.Functor.Compose
180+import Data.Functor.Product
181+import Data.GADT.Compare (GEq (..), GCompare (..), (:~:) (..))
163182import Data.FastMutableIntMap (PatchIntMap)
164183import Data.Foldable
165184import Data.Functor.Bind
166−import Data.Functor.Constant
167185import Data.Functor.Misc
168186import Data.Functor.Plus
169187import Data.IntMap.Strict (IntMap)
@@ -171,11 +189,14 @@ import qualified Data.IntMap.Strict as IntMap
171189import Data.List.NonEmpty (NonEmpty (..))
172190import Data.Map (Map)
173191import Data.Semigroup (Semigroup, sconcat, stimes, (<>))
192+import Data.Some (Some)
193+import qualified Data.Some as Some
174194import Data.String
175195import Data.These
176196import Data.Type.Coercion
177197import Reflex.FunctorMaybe
178198import Reflex.Patch
199+import qualified Reflex.Patch.MapWithMove as PatchMapWithMove
179200
180201import Debug.Trace (trace)
181202
@@ -226,7 +247,7 @@ class ( MonadHold t (PushM t)
226247 -- recomputed whenever any of the read 'Behavior's changes
227248 pull :: PullM t a -> Behavior t a
228249 -- | Merge a collection of events; the resulting 'Event' will only occur if at
229− -- least one input event is occuring, and will contain all of the input keys
250+ -- least one input event is occurring, and will contain all of the input keys
230251 -- that are occurring simultaneously
231252 merge :: GCompare k => DMap k (Event t) -> Event t (DMap k Identity) --TODO: Generalize to get rid of DMap use --TODO: Provide a type-level guarantee that the result is not empty
232253 -- | Efficiently fan-out an event to many destinations. This function should
@@ -332,15 +353,44 @@ class MonadSample t m => MonadHold t m where
332353 holdIncremental :: Patch p => PatchTarget p -> Event t p -> m (Incremental t p)
333354 default holdIncremental :: (Patch p, m ~ f m', MonadTrans f, MonadHold t m') => PatchTarget p -> Event t p -> m (Incremental t p)
334355 holdIncremental v0 = lift . holdIncremental v0
335− buildDynamic :: PullM t a -> Event t a -> m (Dynamic t a)
356+ buildDynamic :: PushM t a -> Event t a -> m (Dynamic t a)
336357 {-
337358 default buildDynamic :: (m ~ f m', MonadTrans f, MonadHold t m') => PullM t a -> Event t a -> m (Dynamic t a)
338359 buildDynamic getV0 = lift . buildDynamic getV0
339360 -}
340− -- | Create a new 'Event' that only occurs only once, on the first occurence of
361+ -- | Create a new 'Event' that only occurs only once, on the first occurrence of
341362 -- the supplied 'Event'.
342363 headE :: Event t a -> m (Event t a)
343364
365+accumIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> p) -> PatchTarget p -> Event t b -> m (Incremental t p)
366+accumIncremental f = accumMaybeIncremental $ \v o -> Just $ f v o
367+accumMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t p) -> PatchTarget p -> Event t b -> m (Incremental t p)
368+accumMIncremental f = accumMaybeMIncremental $ \v o -> Just <$> f v o
369+accumMaybeIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> Maybe p) -> PatchTarget p -> Event t b -> m (Incremental t p)
370+accumMaybeIncremental f = accumMaybeMIncremental $ \v o -> return $ f v o
371+accumMaybeMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t (Maybe p)) -> PatchTarget p -> Event t b -> m (Incremental t p)
372+accumMaybeMIncremental f z e = do
373+ rec let e' = flip push e $ \o -> do
374+ v <- sample $ currentIncremental d'
375+ f v o
376+ d' <- holdIncremental z e'
377+ return d'
378+mapAccumIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> (p, c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
379+mapAccumIncremental f = mapAccumMaybeIncremental $ \v o -> bimap Just Just $ f v o
380+mapAccumMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t (p, c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
381+mapAccumMIncremental f = mapAccumMaybeMIncremental $ \v o -> bimap Just Just <$> f v o
382+mapAccumMaybeIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> (Maybe p, Maybe c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
383+mapAccumMaybeIncremental f = mapAccumMaybeMIncremental $ \v o -> return $ f v o
384+mapAccumMaybeMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t (Maybe p, Maybe c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
385+mapAccumMaybeMIncremental f z e = do
386+ rec let e' = flip push e $ \o -> do
387+ v <- sample $ currentIncremental d'
388+ result <- f v o
389+ return $ case result of
390+ (Nothing, Nothing) -> Nothing
391+ _ -> Just result
392+ d' <- holdIncremental z $ fmapMaybe fst e'
393+ return (d', fmapMaybe snd e')
344394
345395slowHeadE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
346396slowHeadE e = do
@@ -441,6 +491,14 @@ pushAlways f = push (fmap Just . f)
441491ffor :: Functor f => f a -> (a -> b) -> f b
442492ffor = flip fmap
443493
494+-- | Rotated version of 'liftA2'.
495+ffor2 :: Applicative f => f a -> f b -> (a -> b -> c) -> f c
496+ffor2 a b f = liftA2 f a b
497+
498+-- | Rotated version of 'liftA3'.
499+ffor3 :: Applicative f => f a -> f b -> f c -> (a -> b -> c -> d) -> f d
500+ffor3 a b c f = liftA3 f a b c
501+
444502instance Reflex t => Applicative (Behavior t) where
445503 pure = constant
446504 f <*> x = pull $ sample f `ap` sample x
@@ -543,6 +601,12 @@ instance Reflex t => Plus (Event t) where
543601tag :: Reflex t => Behavior t b -> Event t a -> Event t b
544602tag b = pushAlways $ \_ -> sample b
545603
604+-- | Replace each occurrence value of the 'Event' with the value of the
605+-- 'Behavior' at that time; if it is 'Just', fire with the contained value; if
606+-- it is 'Nothing', drop the occurrence.
607+tagMaybe :: Reflex t => Behavior t (Maybe b) -> Event t a -> Event t b
608+tagMaybe b = push $ \_ -> sample b
609+
546610-- | Create a new 'Event' that combines occurrences of supplied 'Event' with the
547611-- current value of the 'Behavior'.
548612attach :: Reflex t => Behavior t a -> Event t b -> Event t (a, b)
@@ -566,33 +630,98 @@ tailE e = snd <$> headTailE e
566630
567631-- | Create a tuple of two 'Event's with the first one occurring only the first
568632-- time the supplied 'Event' occurs and the second occurring on all but the first
569−-- occurence.
633+-- occurrence.
570634headTailE :: (Reflex t, MonadHold t m) => Event t a -> m (Event t a, Event t a)
571635headTailE e = do
572636 eHead <- headE e
573637 be <- hold never $ fmap (const e) eHead
574638 return (eHead, switch be)
575639
576−-- | Starting at the current time, fire all the occurrences of the 'Event' for
577−-- which the given predicate returns 'True'. When 'False' is returned, do not
578−-- fire, and permanently stop firing, even if 'True' values are encountered
579−-- later.
580−takeWhileE :: forall t m a. (Reflex t, MonadFix m, MonadHold t m) => (a -> Bool) -> Event t a -> m (Event t a)
581−takeWhileE f e = do
582− rec let (eFalse, eTrue) = fanEither $ ffor e' $ \a -> if f a
583− then Right a
584− else Left never
585− be <- hold e eFalse
586− let e' = switch be
640+-- | Take the streak of occurrences starting at the current time for which the
641+-- event returns 'True'.
642+--
643+-- Starting at the current time, fire all the occurrences of the 'Event' for
644+-- which the given predicate returns 'True'. When 'False' first is returned,
645+-- do not fire, and permanently stop firing, even if 'True' values would have
646+-- been encountered later.
647+takeWhileE
648+ :: forall t m a
649+ . (Reflex t, MonadFix m, MonadHold t m)
650+ => (a -> Bool)
651+ -> Event t a
652+ -> m (Event t a)
653+takeWhileE f = takeWhileJustE $ \v -> guard (f v) $> v
654+
655+-- | Take the streak of occurrences starting at the current time for which the
656+-- event returns 'Just b'.
657+--
658+-- Starting at the current time, fire all the occurrences of the 'Event' for
659+-- which the given predicate returns 'Just b'. When 'Nothing' first is returned,
660+-- do not fire, and permanently stop firing, even if 'Just b' values would have
661+-- been encountered later.
662+takeWhileJustE
663+ :: forall t m a b
664+ . (Reflex t, MonadFix m, MonadHold t m)
665+ => (a -> Maybe b)
666+ -> Event t a
667+ -> m (Event t b)
668+takeWhileJustE f e = do
669+ rec let (eBad, eTrue) = fanEither $ ffor e' $ \a -> case f a of
670+ Nothing -> Left never
671+ Just b -> Right b
672+ eFirstBad <- headE eBad
673+ e' <- switchHold e eFirstBad
587674 return eTrue
588675
589−-- | Split the supplied 'Event' into two individual 'Event's occuring at the
676+-- | Drop the streak of occurrences starting at the current time for which the
677+-- event returns 'True'.
678+--
679+-- Starting at the current time, do not fire all the occurrences of the 'Event'
680+-- for which the given predicate returns 'True'. When 'False' is first
681+-- returned, do fire, and permanently continue firing, even if 'True' values
682+-- would have been encountered later.
683+dropWhileE
684+ :: forall t m a
685+ . (Reflex t, MonadFix m, MonadHold t m)
686+ => (a -> Bool)
687+ -> Event t a
688+ -> m (Event t a)
689+dropWhileE f e = snd <$> takeDropWhileJustE (\v -> guard (f v) $> v) e
690+
691+-- | Both take and drop the streak of occurrences starting at the current time
692+-- for which the event returns 'Just b'.
693+--
694+-- For the left event, starting at the current time, fire all the occurrences
695+-- of the 'Event' for which the given function returns 'Just b'. When
696+-- 'Nothing' is returned, do not fire, and permanently stop firing, even if
697+-- 'Just b' values would have been encountered later.
698+--
699+-- For the right event, do not fire until the first occurrence where the given
700+-- function returns 'Nothing', and fire that one and all subsequent
701+-- occurrences. Even if the function would have again returned 'Just b', keep
702+-- on firing.
703+takeDropWhileJustE
704+ :: forall t m a b
705+ . (Reflex t, MonadFix m, MonadHold t m)
706+ => (a -> Maybe b)
707+ -> Event t a
708+ -> m (Event t b, Event t a)
709+takeDropWhileJustE f e = do
710+ rec let (eBad, eGood) = fanEither $ ffor e' $ \a -> case f a of
711+ Nothing -> Left ()
712+ Just b -> Right b
713+ eFirstBad <- headE eBad
714+ e' <- switchHold e (never <$ eFirstBad)
715+ eRest <- switchHoldPromptOnly never (e <$ eFirstBad)
716+ return (eGood, eRest)
717+
718+-- | Split the supplied 'Event' into two individual 'Event's occurring at the
590719-- same time with the respective values from the tuple.
591720splitE :: Reflex t => Event t (a, b) -> (Event t a, Event t b)
592721splitE e = (fmap fst e, fmap snd e)
593722
594723-- | Print the supplied 'String' and the value of the 'Event' on each
595−-- occurence. This should /only/ be used for debugging.
724+-- occurrence. This should /only/ be used for debugging.
596725--
597726-- Note: As with Debug.Trace.trace, the message will only be printed if the
598727-- 'Event' is actually used.
@@ -654,10 +783,14 @@ unsafeMapIncremental f g a = unsafeBuildIncremental (fmap f $ sample $ currentIn
654783
655784-- | Create a new 'Event' combining the map of 'Event's into an 'Event' that
656785-- occurs if at least one of them occurs and has a map of values of all 'Event's
657−-- occuring at that time.
786+-- occurring at that time.
658787mergeMap :: (Reflex t, Ord k) => Map k (Event t a) -> Event t (Map k a)
659788mergeMap = fmap dmapToMap . merge . mapWithFunctorToDMap
660789
790+-- | Like 'mergeMap' but for 'IntMap'.
791+mergeIntMap :: Reflex t => IntMap (Event t a) -> Event t (IntMap a)
792+mergeIntMap = fmap dmapToIntMap . merge . intMapWithFunctorToDMap
793+
661794-- | Create a merge whose parents can change over time
662795mergeMapIncremental :: (Reflex t, Ord k) => Incremental t (PatchMap k (Event t a)) -> Event t (Map k a)
663796mergeMapIncremental = fmap dmapToMap . mergeIncremental . unsafeMapIncremental mapWithFunctorToDMap (const2PatchDMapWith id)
@@ -736,17 +869,65 @@ switchHoldPromptOnly e0 e' = do
736869 eLag <- switch <$> hold e0 e'
737870 return $ coincidence $ leftmost [e', eLag <$ eLag]
738871
872+-- | When the given outer event fires, condense the inner events into the contained patch. Non-firing inner events will be replaced with deletions.
873+coincidencePatchMap :: (Reflex t, Ord k) => Event t (PatchMap k (Event t v)) -> Event t (PatchMap k v)
874+coincidencePatchMap e = fmapCheap PatchMap $ coincidence $ ffor e $ \(PatchMap m) -> mergeMap $ ffor m $ \case
875+ Nothing -> fmapCheap (const Nothing) e
876+ Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
877+
878+-- | See 'coincicencePatchMap'
879+coincidencePatchIntMap :: Reflex t => Event t (PatchIntMap (Event t v)) -> Event t (PatchIntMap v)
880+coincidencePatchIntMap e = fmapCheap PatchIntMap $ coincidence $ ffor e $ \(PatchIntMap m) -> mergeIntMap $ ffor m $ \case
881+ Nothing -> fmapCheap (const Nothing) e
882+ Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
883+
884+-- | See 'coincicencePatchMap'
885+coincidencePatchMapWithMove :: (Reflex t, Ord k) => Event t (PatchMapWithMove k (Event t v)) -> Event t (PatchMapWithMove k v)
886+coincidencePatchMapWithMove e = fmapCheap unsafePatchMapWithMove $ coincidence $ ffor e $ \p -> mergeMap $ ffor (unPatchMapWithMove p) $ \ni -> case PatchMapWithMove._nodeInfo_from ni of
887+ PatchMapWithMove.From_Delete -> fforCheap e $ \_ ->
888+ ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Delete }
889+ PatchMapWithMove.From_Move k -> fforCheap e $ \_ ->
890+ ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Move k }
891+ PatchMapWithMove.From_Insert ev -> leftmost
892+ [ fforCheap ev $ \v ->
893+ ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Insert v }
894+ , fforCheap e $ \_ ->
895+ ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Delete }
896+ ]
897+
898+switchHoldPromptOnlyIncremental
899+ :: forall t m p pt w
900+ . ( Reflex t
901+ , MonadHold t m
902+ , Patch (p (Event t w))
903+ , PatchTarget (p (Event t w)) ~ pt (Event t w)
904+ , Patch (p w)
905+ , PatchTarget (p w) ~ pt w
906+ , Monoid (pt w)
907+ )
908+ => (Incremental t (p (Event t w)) -> Event t (pt w))
909+ -> (Event t (p (Event t w)) -> Event t (p w))
910+ -> pt (Event t w)
911+ -> Event t (p (Event t w))
912+ -> m (Event t (pt w))
913+switchHoldPromptOnlyIncremental mergePatchIncremental coincidencePatch e0 e' = do
914+ lag <- mergePatchIncremental <$> holdIncremental e0 e'
915+ pure $ ffor (align lag (coincidencePatch e')) $ \case
916+ This old -> old
917+ That new -> new `applyAlways` mempty
918+ These old new -> new `applyAlways` old
919+
739920instance Reflex t => Align (Event t) where
740921 nil = never
741922 align = alignEventWithMaybe Just
742923
743924-- | Create a new 'Event' that only occurs if the supplied 'Event' occurs and
744−-- the 'Behavior' is true at the time of occurence.
925+-- the 'Behavior' is true at the time of occurrence.
745926gate :: Reflex t => Behavior t Bool -> Event t a -> Event t a
746927gate = attachWithMaybe $ \allow a -> if allow then Just a else Nothing
747928
748−-- | Create a new behavior given a starting behavior and switch to a the behvior
749−-- carried by the event when it fires.
929+-- | Create a new behavior given a starting behavior and switch to the behavior
930+-- carried by the event when it fires.
750931switcher :: (Reflex t, MonadHold t m)
751932 => Behavior t a -> Event t (Behavior t a) -> m (Behavior t a)
752933switcher b eb = pull . (sample <=< sample) <$> hold b eb
@@ -826,6 +1007,44 @@ alignEventWithMaybe f ea eb =
8261007 $ merge
8271008 $ DMap.fromList [LeftTag :=> ea, RightTag :=> eb]
8281009
1010+filterEventKey
1011+ :: forall t m k v a.
1012+ ( Reflex t
1013+ , MonadFix m
1014+ , MonadHold t m
1015+ , GEq k
1016+ )
1017+ => k a
1018+ -> Event t (DSum k v)
1019+ -> m (Event t (v a))
1020+filterEventKey k kv' = do
1021+ let f :: DSum k v -> Maybe (v a)
1022+ f (newK :=> newV) = case newK `geq` k of
1023+ Just Refl -> Just newV
1024+ Nothing -> Nothing
1025+ takeWhileJustE f kv'
1026+
1027+
1028+factorEvent
1029+ :: forall t m k v a.
1030+ ( Reflex t
1031+ , MonadFix m
1032+ , MonadHold t m
1033+ , GEq k
1034+ )
1035+ => k a
1036+ -> Event t (DSum k v)
1037+ -> m (Event t (v a), Event t (DSum k (Product v (Compose (Event t) v))))
1038+factorEvent k0 kv' = do
1039+ key :: Behavior t (Some k) <- hold (Some.This k0) $ fmapCheap (\(k :=> _) -> Some.This k) kv'
1040+ let update = flip push kv' $ \(newKey :=> newVal) -> sample key >>= \case
1041+ Some.This oldKey -> case newKey `geq` oldKey of
1042+ Just Refl -> return Nothing
1043+ Nothing -> do
1044+ newInner <- filterEventKey newKey kv'
1045+ return $ Just $ newKey :=> Pair newVal (Compose newInner)
1046+ eInitial <- filterEventKey k0 kv'
1047+ return (eInitial, update)
8291048
8301049--------------------------------------------------------------------------------
8311050-- Accumulator
@@ -969,7 +1188,7 @@ instance Reflex t => Accumulator t (Event t) where
9691188 accumMaybeM f z e = updated <$> accumMaybeM f z e
9701189 mapAccumMaybeM f z e = first updated <$> mapAccumMaybeM f z e
9711190
972−-- | Create a new 'Event' by combining each occurence with the next value of the
1191+-- | Create a new 'Event' by combining each occurrence with the next value of the
9731192-- list using the supplied function. If the list runs out of items, all
9741193-- subsequent 'Event' occurrences will be ignored.
9751194zipListWithEvent :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> c) -> [a] -> Event t b -> m (Event t c)
@@ -979,17 +1198,17 @@ zipListWithEvent f l e = do
9791198 _ -> (Nothing, Nothing) --TODO: Unsubscribe the event?
9801199 mapAccumMaybe_ f' l e
9811200
982−-- | Assign a number to each occurence of the given 'Event', starting from 0
1201+-- | Assign a number to each occurrence of the given 'Event', starting from 0
9831202{-# INLINE numberOccurrences #-}
9841203numberOccurrences :: (Reflex t, MonadHold t m, MonadFix m, Num b) => Event t a -> m (Event t (b, a))
9851204numberOccurrences = numberOccurrencesFrom 0
9861205
987−-- | Assign a number to each occurence of the given 'Event'
1206+-- | Assign a number to each occurrence of the given 'Event'
9881207{-# INLINE numberOccurrencesFrom #-}
9891208numberOccurrencesFrom :: (Reflex t, MonadHold t m, MonadFix m, Num b) => b -> Event t a -> m (Event t (b, a))
9901209numberOccurrencesFrom = mapAccum_ (\n a -> let !next = n + 1 in (next, (n, a)))
9911210
992−-- | Assign a number to each occurence of the given 'Event'; discard the occurrences' values
1211+-- | Assign a number to each occurrence of the given 'Event'; discard the occurrences' values
9931212{-# INLINE numberOccurrencesFrom_ #-}
9941213numberOccurrencesFrom_ :: (Reflex t, MonadHold t m, MonadFix m, Num b) => b -> Event t a -> m (Event t b)
9951214numberOccurrencesFrom_ = mapAccum_ (\n _ -> let !next = n + 1 in (next, n))
@@ -1062,47 +1281,6 @@ infixl 4 <@>
10621281(<@) = tag
10631282infixl 4 <@
10641283
1065−------------------
1066−-- Adjustable
1067−------------------
1068−
1069−-- | A 'Monad' that supports adjustment over time. After an action has been
1070−-- run, if the given events fire, it will adjust itself so that its net effect
1071−-- is as though it had originally been run with the new value. Note that there
1072−-- is some issue here with persistent side-effects: obviously, IO (and some
1073−-- other side-effects) cannot be undone, so it is up to the instance implementer
1074−-- to determine what the best meaning for this class is in such cases.
1075−class (Reflex t, Monad m) => Adjustable t m | m -> t where
1076− runWithReplace :: m a -> Event t (m b) -> m (a, Event t b)
1077− traverseIntMapWithKeyWithAdjust :: (IntMap.Key -> v -> m v') -> IntMap v -> Event t (PatchIntMap v) -> m (IntMap v', Event t (PatchIntMap v'))
1078− traverseDMapWithKeyWithAdjust :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMap k v) -> m (DMap k v', Event t (PatchDMap k v'))
1079− traverseDMapWithKeyWithAdjustWithMove :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMapWithMove k v) -> m (DMap k v', Event t (PatchDMapWithMove k v'))
1080−
1081−instance Adjustable t m => Adjustable t (ReaderT r m) where
1082− runWithReplace a0 a' = do
1083− r <- ask
1084− lift $ runWithReplace (runReaderT a0 r) $ fmap (`runReaderT` r) a'
1085− traverseIntMapWithKeyWithAdjust f dm0 dm' = do
1086− r <- ask
1087− lift $ traverseIntMapWithKeyWithAdjust (\k v -> runReaderT (f k v) r) dm0 dm'
1088− traverseDMapWithKeyWithAdjust f dm0 dm' = do
1089− r <- ask
1090− lift $ traverseDMapWithKeyWithAdjust (\k v -> runReaderT (f k v) r) dm0 dm'
1091− traverseDMapWithKeyWithAdjustWithMove f dm0 dm' = do
1092− r <- ask
1093− lift $ traverseDMapWithKeyWithAdjustWithMove (\k v -> runReaderT (f k v) r) dm0 dm'
1094−
1095−sequenceDMapWithAdjust :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMap k m) -> m (DMap k Identity, Event t (PatchDMap k Identity))
1096−sequenceDMapWithAdjust = traverseDMapWithKeyWithAdjust $ \_ -> fmap Identity
1097−
1098−sequenceDMapWithAdjustWithMove :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMapWithMove k m) -> m (DMap k Identity, Event t (PatchDMapWithMove k Identity))
1099−sequenceDMapWithAdjustWithMove = traverseDMapWithKeyWithAdjustWithMove $ \_ -> fmap Identity
1100−
1101−mapMapWithAdjustWithMove :: forall t m k v v'. (Adjustable t m, Ord k) => (k -> v -> m v') -> Map k v -> Event t (PatchMapWithMove k v) -> m (Map k v', Event t (PatchMapWithMove k v'))
1102−mapMapWithAdjustWithMove f m0 m' = do
1103− (out0 :: DMap (Const2 k v) (Constant v'), out') <- traverseDMapWithKeyWithAdjustWithMove (\(Const2 k) (Identity v) -> Constant <$> f k v) (mapToDMap m0) (const2PatchDMapWithMoveWith Identity <$> m')
1104− return (dmapToMapWith (\(Constant v') -> v') out0, patchDMapWithMoveToPatchMapWithMoveWith (\(Constant v') -> v') <$> out')
1105−
11061284------------------
11071285-- Cheap Functions
11081286------------------
@@ -1151,9 +1329,6 @@ mergeWithFoldCheap' f es =
11511329-- Deprecated functions
11521330--------------------------------------------------------------------------------
11531331
1154−{-# DEPRECATED MonadAdjust "Use Adjustable instead" #-}
1155−type MonadAdjust = Adjustable
1156−
11571332-- | Create a new 'Event' that occurs if at least one of the supplied 'Event's
11581333-- occurs. If both occur at the same time they are combined using 'mappend'.
11591334{-# DEPRECATED appendEvents "If a 'Semigroup a' instance is available, use 'mappend'; otherwise, use 'alignWith (mergeThese mappend)' instead" #-}
src/Reflex/Collection.hs+1
@@ -34,6 +34,7 @@ import Data.Map.Misc
3434import Data.These
3535
3636import Reflex.Class
37+import Reflex.Adjustable.Class
3738import Reflex.Dynamic
3839import Reflex.PostBuild.Class
3940
src/Reflex/Dynamic.hs+18−24
@@ -102,10 +102,11 @@ import Data.Align
102102import Data.Dependent.Map (DMap)
103103import qualified Data.Dependent.Map as DMap
104104import Data.Dependent.Sum (DSum (..))
105+import Data.Functor.Product
105106import Data.GADT.Compare ((:~:) (..), GCompare (..), GEq (..), GOrdering (..))
106107import Data.Map (Map)
107108import Data.Maybe
108−import Data.Monoid
109+import Data.Monoid hiding (Product)
109110import Data.These
110111
111112import Debug.Trace
@@ -173,7 +174,7 @@ foldDynMaybe = accumMaybeDyn . flip
173174foldDynMaybeM :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe b)) -> b -> Event t a -> m (Dynamic t b)
174175foldDynMaybeM = accumMaybeMDyn . flip
175176
176−-- | Create a new 'Dynamic' that counts the occurences of the 'Event'.
177+-- | Create a new 'Dynamic' that counts the occurrences of the 'Event'.
177178count :: (Reflex t, MonadHold t m, MonadFix m, Num b) => Event t a -> m (Dynamic t b)
178179count e = holdDyn 0 =<< zipListWithEvent const (iterate (+1) 1) e
179180
@@ -287,7 +288,7 @@ attachPromptlyDyn = attachPromptlyDynWith (,)
287288attachPromptlyDynWith :: Reflex t => (a -> b -> c) -> Dynamic t a -> Event t b -> Event t c
288289attachPromptlyDynWith f = attachPromptlyDynWithMaybe $ \a b -> Just $ f a b
289290
290−-- | Create a new 'Event' by combining the value at each occurence with the
291+-- | Create a new 'Event' by combining the value at each occurrence with the
291292-- current value of the 'Dynamic' value and possibly filtering if the combining
292293-- function returns 'Nothing'.
293294--
@@ -324,27 +325,20 @@ eitherDyn = fmap (fmap unpack) . factorDyn . fmap eitherToDSum
324325 LeftTag :=> Compose a -> Left $ coerceDynamic a
325326 RightTag :=> Compose b -> Right $ coerceDynamic b
326327
327−factorDyn :: forall t m k v. (Reflex t, MonadFix m, MonadHold t m, GEq k) => Dynamic t (DSum k v) -> m (Dynamic t (DSum k (Compose (Dynamic t) v)))
328−factorDyn d = do
329− let inner :: forall m' a. (MonadFix m', MonadHold t m') => k a -> v a -> m' (Dynamic t (v a))
330− inner k v0 = holdDyn v0 . fmapMaybe id =<< takeWhileE isJust newVal
331− where newVal = ffor (updated d) $ \(newK :=> newV) -> case newK `geq` k of
332− Just Refl -> Just newV
333− Nothing -> Nothing
334− getInitial = do
335− k0 :=> (v0 :: v a) <- sample $ current d
336− i0 <- inner k0 v0
337− return $ k0 :=> Compose i0
338− update = flip push (updated d) $ \(newKey :=> newVal) -> do
339− (oldKey :=> _) <- sample $ current d
340− case newKey `geq` oldKey of
341− Just Refl -> return Nothing
342− Nothing -> do
343− newInner <- inner newKey newVal
344− return $ Just $ newKey :=> Compose newInner
345− o0 <- getInitial --TODO: Figure out how to get this to run inside something like the first argument to buildDynamic
346− holdDyn o0 update
347−
328+factorDyn :: forall t m k v. (Reflex t, MonadHold t m, GEq k)
329+ => Dynamic t (DSum k v) -> m (Dynamic t (DSum k (Compose (Dynamic t) v)))
330+factorDyn d = buildDynamic (sample (current d) >>= holdKey) update where
331+ update :: Event t (DSum k (Compose (Dynamic t) v))
332+ update = flip push (updated d) $ \(newKey :=> newVal) -> do
333+ (oldKey :=> _) <- sample (current d)
334+ case newKey `geq` oldKey of
335+ Just Refl -> return Nothing
336+ Nothing -> Just <$> holdKey (newKey :=> newVal)
337+
338+ holdKey (k :=> v) = do
339+ inner' <- filterEventKey k (updated d)
340+ inner <- holdDyn v inner'
341+ return $ k :=> Compose inner
348342--------------------------------------------------------------------------------
349343-- Demux
350344--------------------------------------------------------------------------------
src/Reflex/Dynamic/TH.hs+2−2
@@ -47,8 +47,8 @@ qDynPure qe = do
4747 _ -> gmapM f d
4848 (e', exprsReversed) <- runStateT (gmapM f e) []
4949 let exprs = reverse exprsReversed
50− arg = foldr (\a b -> ConE 'FHCons `AppE` a `AppE` b) (ConE 'FHNil) $ map snd exprs
51− param = foldr (\a b -> ConP 'HCons [VarP a, b]) (ConP 'HNil []) $ map fst exprs
50+ arg = foldr (\a b -> ConE 'FHCons `AppE` snd a `AppE` b) (ConE 'FHNil) exprs
51+ param = foldr (\a b -> ConP 'HCons [VarP (fst a), b]) (ConP 'HNil []) exprs
5252 [| $(return $ LamE [param] e') <$> distributeFHListOverDynPure $(return arg) |]
5353
5454-- | Antiquote a 'Dynamic' expression. This can /only/ be used inside of a
src/Reflex/DynamicWriter/Base.hs+19−1
@@ -9,6 +9,7 @@
99{-# LANGUAGE TupleSections #-}
1010{-# LANGUAGE TypeFamilies #-}
1111{-# LANGUAGE UndecidableInstances #-}
12+{-# LANGUAGE StandaloneDeriving #-}
1213#ifdef USE_REFLEX_OPTIMIZER
1314{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
1415#endif
@@ -36,12 +37,16 @@ import qualified Data.Map as Map
3637import Data.Semigroup
3738import Data.Some (Some)
3839import Data.These
40+
41+import Reflex.Adjustable.Class
3942import Reflex.Class
4043import Reflex.DynamicWriter.Class
44+import Reflex.EventWriter.Class (EventWriter, tellEvent)
4145import Reflex.Host.Class
4246import qualified Reflex.Patch.MapWithMove as MapWithMove
4347import Reflex.PerformEvent.Class
4448import Reflex.PostBuild.Class
49+import Reflex.Query.Class
4550import Reflex.Requester.Class
4651import Reflex.TriggerEvent.Class
4752
@@ -83,7 +88,12 @@ mergeDynIncrementalWithMove a = unsafeBuildIncremental (mapM (sample . current)
8388 in Map.differenceWith (\e _ -> Just $ MapWithMove.nodeInfoSetTo Nothing e) pWithNewVals noLongerMovedMap --TODO: Check if any in the second map are not covered?
8489
8590-- | A basic implementation of 'MonadDynamicWriter'.
86−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
91+newtype DynamicWriterT t w m a = DynamicWriterT { unDynamicWriterT :: StateT [Dynamic t w] m a }
92+ deriving (Functor, Applicative, Monad, MonadIO, MonadFix, MonadAsyncException, MonadException) -- The list is kept in reverse order
93+
94+deriving instance MonadHold t m => MonadHold t (DynamicWriterT t w m)
95+deriving instance MonadSample t m => MonadSample t (DynamicWriterT t w m)
96+
8797
8898instance MonadRef m => MonadRef (DynamicWriterT t w m) where
8999 type Ref (DynamicWriterT t w m) = Ref m
@@ -212,3 +222,11 @@ instance Requester t m => Requester t (DynamicWriterT t w m) where
212222 type Response (DynamicWriterT t w m) = Response m
213223 requesting = lift . requesting
214224 requesting_ = lift . requesting_
225+
226+instance (MonadQuery t q m, Monad m) => MonadQuery t q (DynamicWriterT t w m) where
227+ tellQueryIncremental = lift . tellQueryIncremental
228+ askQueryResult = lift askQueryResult
229+ queryIncremental = lift . queryIncremental
230+
231+instance EventWriter t w m => EventWriter t w (DynamicWriterT t v m) where
232+ tellEvent = lift . tellEvent
src/Reflex/EventWriter/Base.hs+75−58
@@ -22,8 +22,10 @@ module Reflex.EventWriter.Base
2222 , withEventWriterT
2323 ) where
2424
25+import Reflex.Adjustable.Class
2526import Reflex.Class
2627import Reflex.EventWriter.Class (EventWriter, tellEvent)
28+import Reflex.DynamicWriter.Class (MonadDynamicWriter, tellDyn)
2729import Reflex.Host.Class
2830import Reflex.PerformEvent.Class
2931import Reflex.PostBuild.Class
@@ -33,12 +35,12 @@ import Reflex.TriggerEvent.Class
3335
3436import Control.Monad.Exception
3537import Control.Monad.Identity
38+import Control.Monad.Primitive
3639import Control.Monad.Reader
3740import Control.Monad.Ref
3841import Control.Monad.State.Strict
3942import Data.Dependent.Map (DMap, DSum (..))
4043import qualified Data.Dependent.Map as DMap
41−import Data.Foldable
4244import Data.Functor.Compose
4345import Data.Functor.Misc
4446import Data.GADT.Compare (GCompare (..), GEq (..), GOrdering (..))
@@ -46,16 +48,17 @@ import Data.IntMap.Strict (IntMap)
4648import qualified Data.IntMap.Strict as IntMap
4749import Data.List.NonEmpty (NonEmpty (..))
4850import Data.Map (Map)
51+import qualified Data.Map as Map
4952import Data.Semigroup
5053import Data.Some (Some)
5154import Data.Tuple
52−import Data.Type.Equality
55+import Data.Type.Equality hiding (apply)
5356
5457import Unsafe.Coerce
5558
5659{-# DEPRECATED TellId "Do not construct this directly; use tellId instead" #-}
5760newtype TellId w x
58− = TellId Int -- ^ WARNING: Do not construct this directly; use 'TellId' instead
61+ = TellId Int -- ^ WARNING: Do not construct this directly; use 'tellId' instead
5962 deriving (Show, Eq, Ord, Enum)
6063
6164tellId :: Int -> TellId w w
@@ -133,9 +136,9 @@ instance MonadHold t m => MonadHold t (EventWriterT t w m) where
133136
134137instance (Reflex t, Adjustable t m, MonadHold t m, Semigroup w) => Adjustable t (EventWriterT t w m) where
135138 runWithReplace = runWithReplaceEventWriterTWith $ \dm0 dm' -> lift $ runWithReplace dm0 dm'
136− traverseIntMapWithKeyWithAdjust = sequenceIntMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseIntMapWithKeyWithAdjust f dm0 dm') patchIntMapNewElements mergeIntIncremental
137− traverseDMapWithKeyWithAdjust = sequenceDMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseDMapWithKeyWithAdjust f dm0 dm') mapPatchDMap weakenPatchDMapWith patchMapNewElements mergeMapIncremental
138− traverseDMapWithKeyWithAdjustWithMove = sequenceDMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseDMapWithKeyWithAdjustWithMove f dm0 dm') mapPatchDMapWithMove weakenPatchDMapWithMoveWith patchMapWithMoveNewElements mergeMapIncrementalWithMove
139+ traverseIntMapWithKeyWithAdjust = sequenceIntMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseIntMapWithKeyWithAdjust f dm0 dm') mergeIntIncremental coincidencePatchIntMap
140+ traverseDMapWithKeyWithAdjust = sequenceDMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseDMapWithKeyWithAdjust f dm0 dm') mapPatchDMap weakenPatchDMapWith mergeMapIncremental coincidencePatchMap
141+ traverseDMapWithKeyWithAdjustWithMove = sequenceDMapWithAdjustEventWriterTWith (\f dm0 dm' -> lift $ traverseDMapWithKeyWithAdjustWithMove f dm0 dm') mapPatchDMapWithMove weakenPatchDMapWithMoveWith mergeMapIncrementalWithMove coincidencePatchMapWithMove
139142
140143instance Requester t m => Requester t (EventWriterT t w m) where
141144 type Request (EventWriterT t w m) = Request m
@@ -154,26 +157,33 @@ runWithReplaceEventWriterTWith :: forall m t w a b. (Reflex t, MonadHold t m, Se
154157 -> EventWriterT t w m (a, Event t b)
155158runWithReplaceEventWriterTWith f a0 a' = do
156159 (result0, result') <- f (runEventWriterT a0) $ fmapCheap runEventWriterT a'
157− request <- holdDyn (snd result0) $ fmapCheap snd result'
158− -- 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.)
159− tellEvent $ coincidence $ updated request
160− tellEvent $ switch $ current request
160+ tellEvent =<< switchHoldPromptOnly (snd result0) (fmapCheap snd result')
161161 return (fst result0, fmapCheap fst result')
162162
163163-- | Like 'runWithReplaceEventWriterTWith', but for 'sequenceIntMapWithAdjust'.
164−sequenceIntMapWithAdjustEventWriterTWith :: forall t m p w v v'. (Reflex t, MonadHold t m, Semigroup w, Functor p, Patch (p (Event t w)), PatchTarget (p (Event t w)) ~ IntMap (Event t w))
165− => ( (IntMap.Key -> v -> m (Event t w, v'))
166− -> IntMap v
167− -> Event t (p v)
168− -> EventWriterT t w m (IntMap (Event t w, v'), Event t (p (Event t w, v')))
169− )
170− -> (p (Event t w) -> [Event t w])
171− -> (Incremental t (p (Event t w)) -> Event t (IntMap w))
172− -> (IntMap.Key -> v -> EventWriterT t w m v')
173− -> IntMap v
174− -> Event t (p v)
175− -> EventWriterT t w m (IntMap v', Event t (p v'))
176−sequenceIntMapWithAdjustEventWriterTWith base patchNewElements mergePatchIncremental f dm0 dm' = do
164+sequenceIntMapWithAdjustEventWriterTWith
165+ :: forall t m p w v v'
166+ . ( Reflex t
167+ , MonadHold t m
168+ , Semigroup w
169+ , Functor p
170+ , Patch (p (Event t w))
171+ , PatchTarget (p (Event t w)) ~ IntMap (Event t w)
172+ , Patch (p w)
173+ , PatchTarget (p w) ~ IntMap w
174+ )
175+ => ( (IntMap.Key -> v -> m (Event t w, v'))
176+ -> IntMap v
177+ -> Event t (p v)
178+ -> EventWriterT t w m (IntMap (Event t w, v'), Event t (p (Event t w, v')))
179+ )
180+ -> (Incremental t (p (Event t w)) -> Event t (PatchTarget (p w)))
181+ -> (Event t (p (Event t w)) -> Event t (p w))
182+ -> (IntMap.Key -> v -> EventWriterT t w m v')
183+ -> IntMap v
184+ -> Event t (p v)
185+ -> EventWriterT t w m (IntMap v', Event t (p v'))
186+sequenceIntMapWithAdjustEventWriterTWith base mergePatchIncremental coincidencePatch f dm0 dm' = do
177187 let f' :: IntMap.Key -> v -> m (Event t w, v')
178188 f' k v = swap <$> runEventWriterT (f k v)
179189 (children0, children') <- base f' dm0 dm'
@@ -183,26 +193,39 @@ sequenceIntMapWithAdjustEventWriterTWith base patchNewElements mergePatchIncreme
183193 requests0 = fmap fst children0
184194 requests' :: Event t (p (Event t w))
185195 requests' = fmapCheap (fmap fst) children'
186− childRequestMap :: Incremental t (p (Event t w)) <- holdIncremental requests0 requests'
187− tellEventsPromptly requests' patchNewElements $ mergePatchIncremental childRequestMap
196+ e <- switchHoldPromptOnlyIncremental mergePatchIncremental coincidencePatch requests0 requests'
197+ tellEvent $ fforMaybeCheap e $ \m ->
198+ case IntMap.elems m of
199+ [] -> Nothing
200+ h : t -> Just $ sconcat $ h :| t
188201 return (result0, result')
189202
190203-- | Like 'runWithReplaceEventWriterTWith', but for 'sequenceDMapWithAdjust'.
191−sequenceDMapWithAdjustEventWriterTWith :: forall t m p p' w k v v'. (Reflex t, MonadHold t m, Semigroup w, Patch (p' (Some k) (Event t w)), PatchTarget (p' (Some k) (Event t w)) ~ Map (Some k) (Event t w))
192− => ( (forall a. k a -> v a -> m (Compose ((,) (Event t w)) v' a))
193− -> DMap k v
194− -> Event t (p k v)
195− -> EventWriterT t w m (DMap k (Compose ((,) (Event t w)) v'), Event t (p k (Compose ((,) (Event t w)) v')))
196− )
197− -> ((forall a. Compose ((,) (Event t w)) v' a -> v' a) -> p k (Compose ((,) (Event t w)) v') -> p k v')
198− -> ((forall a. Compose ((,) (Event t w)) v' a -> Event t w) -> p k (Compose ((,) (Event t w)) v') -> p' (Some k) (Event t w))
199− -> (p' (Some k) (Event t w) -> [Event t w])
200− -> (Incremental t (p' (Some k) (Event t w)) -> Event t (Map (Some k) w))
201− -> (forall a. k a -> v a -> EventWriterT t w m (v' a))
202− -> DMap k v
203− -> Event t (p k v)
204− -> EventWriterT t w m (DMap k v', Event t (p k v'))
205−sequenceDMapWithAdjustEventWriterTWith base mapPatch weakenPatchWith patchNewElements mergePatchIncremental f dm0 dm' = do
204+sequenceDMapWithAdjustEventWriterTWith
205+ :: forall t m p p' w k v v'
206+ . ( Reflex t
207+ , MonadHold t m
208+ , Semigroup w
209+ , Patch (p' (Some k) (Event t w))
210+ , PatchTarget (p' (Some k) (Event t w)) ~ Map (Some k) (Event t w)
211+ , GCompare k
212+ , Patch (p' (Some k) w)
213+ , PatchTarget (p' (Some k) w) ~ Map (Some k) w
214+ )
215+ => ( (forall a. k a -> v a -> m (Compose ((,) (Event t w)) v' a))
216+ -> DMap k v
217+ -> Event t (p k v)
218+ -> EventWriterT t w m (DMap k (Compose ((,) (Event t w)) v'), Event t (p k (Compose ((,) (Event t w)) v')))
219+ )
220+ -> ((forall a. Compose ((,) (Event t w)) v' a -> v' a) -> p k (Compose ((,) (Event t w)) v') -> p k v')
221+ -> ((forall a. Compose ((,) (Event t w)) v' a -> Event t w) -> p k (Compose ((,) (Event t w)) v') -> p' (Some k) (Event t w))
222+ -> (Incremental t (p' (Some k) (Event t w)) -> Event t (PatchTarget (p' (Some k) w)))
223+ -> (Event t (p' (Some k) (Event t w)) -> Event t (p' (Some k) w))
224+ -> (forall a. k a -> v a -> EventWriterT t w m (v' a))
225+ -> DMap k v
226+ -> Event t (p k v)
227+ -> EventWriterT t w m (DMap k v', Event t (p k v'))
228+sequenceDMapWithAdjustEventWriterTWith base mapPatch weakenPatchWith mergePatchIncremental coincidencePatch f dm0 dm' = do
206229 let f' :: forall a. k a -> v a -> m (Compose ((,) (Event t w)) v' a)
207230 f' k v = Compose . swap <$> runEventWriterT (f k v)
208231 (children0, children') <- base f' dm0 dm'
@@ -212,26 +235,13 @@ sequenceDMapWithAdjustEventWriterTWith base mapPatch weakenPatchWith patchNewEle
212235 requests0 = weakenDMapWith (fst . getCompose) children0
213236 requests' :: Event t (p' (Some k) (Event t w))
214237 requests' = fforCheap children' $ weakenPatchWith $ fst . getCompose
215− childRequestMap :: Incremental t (p' (Some k) (Event t w)) <- holdIncremental requests0 requests'
216− tellEventsPromptly requests' patchNewElements $ mergePatchIncremental childRequestMap
238+ e <- switchHoldPromptOnlyIncremental mergePatchIncremental coincidencePatch requests0 requests'
239+ tellEvent $ fforMaybeCheap e $ \m ->
240+ case Map.elems m of
241+ [] -> Nothing
242+ h : t -> Just $ sconcat $ h :| t
217243 return (result0, result')
218244
219−tellEventsPromptly
220− :: ( Foldable f
221− , Reflex t
222− , EventWriter t w m
223− )
224− => Event t a
225− -> (a -> [Event t w])
226− -> Event t (f w)
227− -> m ()
228−tellEventsPromptly requests' patchNewElements mergedChildRequestMap = do
229− -- 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.)
230− tellEvent $ coincidence $ fmapCheap (mconcat . patchNewElements) requests' --TODO: Create a mergeIncrementalPromptly, and use that to eliminate this 'coincidence'
231− tellEvent $ fforMaybeCheap mergedChildRequestMap $ \m -> case toList m of
232− [] -> Nothing
233− h : t -> Just $ sconcat $ h :| t
234−
235245instance PerformEvent t m => PerformEvent t (EventWriterT t w m) where
236246 type Performable (EventWriterT t w m) = Performable m
237247 performEvent_ = lift . performEvent_
@@ -268,6 +278,13 @@ instance (MonadQuery t q m, Monad m) => MonadQuery t q (EventWriterT t w m) wher
268278 askQueryResult = lift askQueryResult
269279 queryIncremental = lift . queryIncremental
270280
281+instance MonadDynamicWriter t w m => MonadDynamicWriter t w (EventWriterT t v m) where
282+ tellDyn = lift . tellDyn
283+
284+instance PrimMonad m => PrimMonad (EventWriterT t w m) where
285+ type PrimState (EventWriterT t w m) = PrimState m
286+ primitive = lift . primitive
287+
271288-- | Map a function over the output of a 'EventWriterT'.
272289withEventWriterT :: (Semigroup w, Semigroup w', Reflex t, MonadHold t m)
273290 => (w -> w')
src/Reflex/FunctorMaybe.hs+12−2
@@ -4,6 +4,10 @@ module Reflex.FunctorMaybe
44 ( FunctorMaybe (..)
55 ) where
66
7+import Data.IntMap (IntMap)
8+import qualified Data.IntMap as IntMap
9+import Data.Map (Map)
10+import qualified Data.Map as Map
711import Data.Maybe
812
913--TODO: See if there's a better class in the standard libraries already
@@ -28,6 +32,12 @@ class FunctorMaybe f where
2832instance FunctorMaybe Maybe where
2933 fmapMaybe = (=<<)
3034
31−-- | @fmapMaybe f = catMaybes . fmap f@
35+-- | @fmapMaybe = mapMaybe@
3236instance FunctorMaybe [] where
33− fmapMaybe f = catMaybes . fmap f
37+ fmapMaybe = mapMaybe
38+
39+instance FunctorMaybe (Map k) where
40+ fmapMaybe = Map.mapMaybe
41+
42+instance FunctorMaybe IntMap where
43+ fmapMaybe = IntMap.mapMaybe
src/Reflex/Network.hs+1
@@ -10,6 +10,7 @@ module Reflex.Network
1010 ) where
1111
1212import Reflex.Class
13+import Reflex.Adjustable.Class
1314import Reflex.NotReady.Class
1415import Reflex.PostBuild.Class
1516
src/Reflex/Optimizer.hs+5
@@ -16,6 +16,11 @@ import Control.Arrow
1616import CoreMonad
1717import Data.String
1818import GhcPlugins
19+
20+#if MIN_VERSION_base(4,9,0)
21+import Prelude hiding ((<>))
22+#endif
23+
1924#endif
2025
2126#ifdef ghcjs_HOST_OS
src/Reflex/Patch/Class.hs+12
@@ -4,8 +4,12 @@ module Reflex.Patch.Class where
44
55import Control.Monad.Identity
66import Data.Maybe
7+import Data.Semigroup
78
89-- | A 'Patch' type represents a kind of change made to a datastructure.
10+--
11+-- If an instance of 'Patch' is also an instance of 'Semigroup', it should obey
12+-- the law that @applyAlways (f <> g) == applyAlways f . applyAlways g@.
913class Patch p where
1014 type PatchTarget p :: *
1115 -- | Apply the patch @p a@ to the value @a@. If no change is needed, return
@@ -20,3 +24,11 @@ applyAlways p t = fromMaybe t $ apply p t
2024instance Patch (Identity a) where
2125 type PatchTarget (Identity a) = a
2226 apply (Identity a) _ = Just a
27+
28+-- | Like '(.)', but composes functions that return patches rather than
29+-- functions that return new values. The Semigroup instance for patches must
30+-- apply patches right-to-left, like '(.)'.
31+composePatchFunctions :: (Patch p, Semigroup p) => (PatchTarget p -> p) -> (PatchTarget p -> p) -> PatchTarget p -> p
32+composePatchFunctions g f a =
33+ let fp = f a
34+ in g (applyAlways fp a) <> fp
src/Reflex/Patch/DMapWithMove.hs+16−20
@@ -110,19 +110,14 @@ instance EqTag k (NodeInfo k v) => Eq (PatchDMapWithMove k v) where
110110-- |Higher kinded 2-tuple, identical to @Data.Functor.Product@ from base ≥ 4.9
111111data Pair1 f g a = Pair1 (f a) (g a)
112112
113−-- |Compose patches having the same effect as applying the patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
114−instance GCompare k => Semigroup (PatchDMapWithMove k v) where
115− (<>) = mappend
116−
117113-- |Helper data structure used for composing patches using the monoid instance.
118114data Fixup k v a
119115 = Fixup_Delete
120116 | Fixup_Update (These (From k v a) (To k a))
121117
122118-- |Compose patches having the same effect as applying the patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
123−instance GCompare k => Monoid (PatchDMapWithMove k v) where
124− mempty = PatchDMapWithMove mempty
125− PatchDMapWithMove ma `mappend` PatchDMapWithMove mb = PatchDMapWithMove m
119+instance GCompare k => Semigroup (PatchDMapWithMove k v) where
120+ PatchDMapWithMove ma <> PatchDMapWithMove mb = PatchDMapWithMove m
126121 where
127122 connections = DMap.toList $ DMap.intersectionWithKey (\_ a b -> Pair1 (_nodeInfo_to a) (_nodeInfo_from b)) ma mb
128123 h :: DSum k (Pair1 (ComposeMaybe k) (From k v)) -> [DSum k (Fixup k v)]
@@ -156,20 +151,21 @@ instance GCompare k => Monoid (PatchDMapWithMove k v) where
156151 , _nodeInfo_to = fromMaybe (_nodeInfo_to ni) $ getThere u
157152 }
158153 m = DMap.differenceWithKey applyFixup (DMap.unionWithKey combineNodeInfos ma mb) fixups
154+ getHere :: These a b -> Maybe a
155+ getHere = \case
156+ This a -> Just a
157+ These a _ -> Just a
158+ That _ -> Nothing
159+ getThere :: These a b -> Maybe b
160+ getThere = \case
161+ This _ -> Nothing
162+ These _ b -> Just b
163+ That b -> Just b
159164
160−-- |Project the @a@ from a @'These' a b@, identical to @preview '_Here'@ but without using preview
161−getHere :: These a b -> Maybe a
162−getHere = \case
163− This a -> Just a
164− These a _ -> Just a
165− That _ -> Nothing
166−
167−-- |Project the @b@ from a @'These' a b@, identical to @preview '_There'@ but without using preview
168−getThere :: These a b -> Maybe b
169−getThere = \case
170− This _ -> Nothing
171− These _ b -> Just b
172− That b -> Just b
165+-- |Compose patches having the same effect as applying the patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
166+instance GCompare k => Monoid (PatchDMapWithMove k v) where
167+ mempty = PatchDMapWithMove mempty
168+ mappend = (<>)
173169
174170{-
175171mappendPatchDMapWithMoveSlow :: forall k v. (ShowTag k v, GCompare k) => PatchDMapWithMove k v -> PatchDMapWithMove k v -> PatchDMapWithMove k v
src/Reflex/Patch/MapWithMove.hs+77−5
@@ -3,6 +3,7 @@
33{-# LANGUAGE DeriveTraversable #-}
44{-# LANGUAGE FlexibleContexts #-}
55{-# LANGUAGE LambdaCase #-}
6+{-# LANGUAGE PatternGuards #-}
67{-# LANGUAGE ScopedTypeVariables #-}
78{-# LANGUAGE TypeFamilies #-}
89-- | 'Patch'es on 'Map' that can insert, delete, and move values from one key to
@@ -19,7 +20,9 @@ import Data.List
1920import Data.Map (Map)
2021import qualified Data.Map as Map
2122import Data.Maybe
23+import Data.Semigroup
2224import qualified Data.Set as Set
25+import Data.These
2326import Data.Tuple
2427
2528-- | Patch a DMap with additions, deletions, and moves. Invariant: If key @k1@
@@ -48,6 +51,13 @@ patchMapWithMove m = if valid then Just $ PatchMapWithMove m else Nothing
4851 From_Move from -> Just (from, to)
4952 _ -> Nothing
5053
54+-- | Create a 'PatchMapWithMove' that inserts everything in the given 'Map'
55+patchMapWithMoveInsertAll :: Map k v -> PatchMapWithMove k v
56+patchMapWithMoveInsertAll m = PatchMapWithMove $ flip fmap m $ \v -> NodeInfo
57+ { _nodeInfo_from = From_Insert v
58+ , _nodeInfo_to = Nothing
59+ }
60+
5161-- | Extract the internal representation of the 'PatchMapWithMove'
5262unPatchMapWithMove :: PatchMapWithMove k v -> Map k (NodeInfo k v)
5363unPatchMapWithMove (PatchMapWithMove p) = p
@@ -110,11 +120,15 @@ patchThatSortsMapWith cmp m = PatchMapWithMove $ Map.fromList $ catMaybes $ zipW
110120-- will produce a 'Map' with the same values as the second 'Map' but with the
111121-- values sorted with the given ordering function.
112122patchThatChangesAndSortsMapWith :: forall k v. (Ord k, Ord v) => (v -> v -> Ordering) -> Map k v -> Map k v -> PatchMapWithMove k v
113−patchThatChangesAndSortsMapWith cmp oldByIndex newByIndexUnsorted = patch
114− where oldByValue = Map.fromListWith Set.union $ swap . first Set.singleton <$> Map.toList oldByIndex
115− newList = Map.toList newByIndexUnsorted
123+patchThatChangesAndSortsMapWith cmp oldByIndex newByIndexUnsorted = patchThatChangesMap oldByIndex newByIndex
124+ where newList = Map.toList newByIndexUnsorted
116125 newByIndex = Map.fromList $ zip (fst <$> newList) $ sortBy cmp $ snd <$> newList
117− insertsAndMoves :: Map k (NodeInfo k v)
126+
127+-- | Create a 'PatchMapWithMove' that, if applied to the first 'Map' provided,
128+-- will produce the second 'Map'.
129+patchThatChangesMap :: (Ord k, Ord v) => Map k v -> Map k v -> PatchMapWithMove k v
130+patchThatChangesMap oldByIndex newByIndex = patch
131+ where oldByValue = Map.fromListWith Set.union $ swap . first Set.singleton <$> Map.toList oldByIndex
118132 (insertsAndMoves, unusedValuesByValue) = flip runState oldByValue $ do
119133 let f k v = do
120134 remainingValues <- get
@@ -129,7 +143,7 @@ patchThatChangesAndSortsMapWith cmp oldByIndex newByIndexUnsorted = patch
129143 putRemainingKeys $ Set.delete k fromKs
130144 return $ NodeInfo (From_Move k) $ Just undefined -- There's an existing value, and it's here, so no patch necessary
131145 else do
132− Just (fromK, remainingKeys) <- return $ Set.minView fromKs -- There's an existing value, but it's not here; move it here
146+ (fromK, remainingKeys) <- return . fromJust $ Set.minView fromKs -- There's an existing value, but it's not here; move it here
133147 putRemainingKeys remainingKeys
134148 return $ NodeInfo (From_Move fromK) $ Just undefined
135149 Map.traverseWithKey f newByIndex
@@ -154,3 +168,61 @@ nodeInfoMapMFrom f ni = fmap (\result -> ni { _nodeInfo_from = result }) $ f $ _
154168-- | Set the 'To' field of a 'NodeInfo'
155169nodeInfoSetTo :: To k -> NodeInfo k v -> NodeInfo k v
156170nodeInfoSetTo to ni = ni { _nodeInfo_to = to }
171+
172+-- |Helper data structure used for composing patches using the monoid instance.
173+data Fixup k v
174+ = Fixup_Delete
175+ | Fixup_Update (These (From k v) (To k))
176+
177+-- |Compose patches having the same effect as applying the patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
178+instance Ord k => Semigroup (PatchMapWithMove k v) where
179+ PatchMapWithMove ma <> PatchMapWithMove mb = PatchMapWithMove m
180+ where
181+ connections = Map.toList $ Map.intersectionWithKey (\_ a b -> (_nodeInfo_to a, _nodeInfo_from b)) ma mb
182+ h :: (k, (Maybe k, From k v)) -> [(k, Fixup k v)]
183+ h (_, (mToAfter, editBefore)) = case (mToAfter, editBefore) of
184+ (Just toAfter, From_Move fromBefore)
185+ | fromBefore == toAfter
186+ -> [(toAfter, Fixup_Delete)]
187+ | otherwise
188+ -> [ (toAfter, Fixup_Update (This editBefore))
189+ , (fromBefore, Fixup_Update (That mToAfter))
190+ ]
191+ (Nothing, From_Move fromBefore) -> [(fromBefore, Fixup_Update (That mToAfter))] -- The item is destroyed in the second patch, so indicate that it is destroyed in the source map
192+ (Just toAfter, _) -> [(toAfter, Fixup_Update (This editBefore))]
193+ (Nothing, _) -> []
194+ mergeFixups _ Fixup_Delete Fixup_Delete = Fixup_Delete
195+ mergeFixups _ (Fixup_Update a) (Fixup_Update b)
196+ | This x <- a, That y <- b
197+ = Fixup_Update $ These x y
198+ | That y <- a, This x <- b
199+ = Fixup_Update $ These x y
200+ mergeFixups _ _ _ = error "PatchMapWithMove: incompatible fixups"
201+ fixups = Map.fromListWithKey mergeFixups $ concatMap h connections
202+ combineNodeInfos _ nia nib = NodeInfo
203+ { _nodeInfo_from = _nodeInfo_from nia
204+ , _nodeInfo_to = _nodeInfo_to nib
205+ }
206+ applyFixup _ ni = \case
207+ Fixup_Delete -> Nothing
208+ Fixup_Update u -> Just $ NodeInfo
209+ { _nodeInfo_from = fromMaybe (_nodeInfo_from ni) $ getHere u
210+ , _nodeInfo_to = fromMaybe (_nodeInfo_to ni) $ getThere u
211+ }
212+ m = Map.differenceWithKey applyFixup (Map.unionWithKey combineNodeInfos ma mb) fixups
213+ getHere :: These a b -> Maybe a
214+ getHere = \case
215+ This a -> Just a
216+ These a _ -> Just a
217+ That _ -> Nothing
218+ getThere :: These a b -> Maybe b
219+ getThere = \case
220+ This _ -> Nothing
221+ These _ b -> Just b
222+ That b -> Just b
223+
224+--TODO: Figure out how to implement this in terms of PatchDMapWithMove rather than duplicating it here
225+-- |Compose patches having the same effect as applying the patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
226+instance Ord k => Monoid (PatchMapWithMove k v) where
227+ mempty = PatchMapWithMove mempty
228+ mappend = (<>)
src/Reflex/PerformEvent/Base.hs+1
@@ -25,6 +25,7 @@ module Reflex.PerformEvent.Base
2525 ) where
2626
2727import Reflex.Class
28+import Reflex.Adjustable.Class
2829import Reflex.Host.Class
2930import Reflex.PerformEvent.Class
3031import Reflex.Requester.Base
src/Reflex/PostBuild/Base.hs+1
@@ -23,6 +23,7 @@ module Reflex.PostBuild.Base
2323 ) where
2424
2525import Reflex.Class
26+import Reflex.Adjustable.Class
2627import Reflex.Host.Class
2728import Reflex.PerformEvent.Class
2829import Reflex.PostBuild.Class
src/Reflex/Profiled.hs+3−1
@@ -12,6 +12,7 @@ module Reflex.Profiled where
1212
1313import Control.Lens hiding (children)
1414import Control.Monad
15+import Control.Monad.Exception
1516import Control.Monad.Fix
1617import Control.Monad.Primitive
1718import Control.Monad.Reader
@@ -101,7 +102,8 @@ writeProfilingData :: FilePath -> IO ()
101102writeProfilingData p = do
102103 writeFile p =<< formatCostCentreTree =<< getCostCentreTree
103104
104−newtype ProfiledM m a = ProfiledM { runProfiledM :: m a } deriving (Functor, Applicative, Monad, MonadFix)
105+newtype ProfiledM m a = ProfiledM { runProfiledM :: m a }
106+ deriving (Functor, Applicative, Monad, MonadFix, MonadException, MonadAsyncException)
105107
106108profileEvent :: Reflex t => Event t a -> Event t a
107109profileEvent e = unsafePerformIO $ do
src/Reflex/Query/Base.hs+65−8
@@ -8,6 +8,8 @@
88{-# LANGUAGE ScopedTypeVariables #-}
99{-# LANGUAGE TypeFamilies #-}
1010{-# LANGUAGE UndecidableInstances #-}
11+{-# LANGUAGE StandaloneDeriving #-}
12+
1113module Reflex.Query.Base
1214 ( QueryT (..)
1315 , runQueryT
@@ -20,6 +22,7 @@ module Reflex.Query.Base
2022import Control.Applicative (liftA2)
2123import Control.Monad.Exception
2224import Control.Monad.Fix
25+import Control.Monad.Primitive
2326import Control.Monad.Reader
2427import Control.Monad.Ref
2528import Control.Monad.State.Strict
@@ -29,6 +32,8 @@ import qualified Data.Dependent.Map as DMap
2932import Data.Foldable
3033import Data.Functor.Compose
3134import Data.Functor.Misc
35+import Data.IntMap (IntMap)
36+import qualified Data.IntMap as IntMap
3237import Data.Map (Map)
3338import qualified Data.Map as Map
3439import Data.Monoid ((<>))
@@ -38,6 +43,8 @@ import qualified Data.Some as Some
3843import Data.These
3944
4045import Reflex.Class
46+import Reflex.Adjustable.Class
47+import Reflex.DynamicWriter.Class
4148import Reflex.EventWriter.Base
4249import Reflex.EventWriter.Class
4350import Reflex.Host.Class
@@ -49,7 +56,10 @@ import Reflex.Requester.Class
4956import Reflex.TriggerEvent.Class
5057
5158newtype QueryT t q m a = QueryT { unQueryT :: StateT [Behavior t q] (EventWriterT t q (ReaderT (Dynamic t (QueryResult q)) m)) a }
52− deriving (Functor, Applicative, Monad, MonadException, MonadFix, MonadIO, MonadHold t, MonadSample t, MonadAtomicRef)
59+ deriving (Functor, Applicative, Monad, MonadException, MonadFix, MonadIO, MonadAtomicRef)
60+
61+deriving instance MonadHold t m => MonadHold t (QueryT t q m)
62+deriving instance MonadSample t m => MonadSample t (QueryT t q m)
5363
5464runQueryT :: (MonadFix m, Additive q, Group q, Reflex t) => QueryT t q m a -> Dynamic t (QueryResult q) -> m (a, Incremental t (AdditivePatch q))
5565runQueryT (QueryT a) qr = do
@@ -80,6 +90,52 @@ instance (Reflex t, MonadFix m, Group q, Additive q, Query q, Eq q, MonadHold t
8090 QueryT $ modify $ (:) $ pull $ sampleBs =<< sample bbs
8191 QueryT $ lift $ tellEvent patches
8292 return (r0, fmapCheap fst r')
93+
94+ traverseIntMapWithKeyWithAdjust :: forall v v'. (IntMap.Key -> v -> QueryT t q m v') -> IntMap v -> Event t (PatchIntMap v) -> QueryT t q m (IntMap v', Event t (PatchIntMap v'))
95+ traverseIntMapWithKeyWithAdjust f im0 im' = do
96+ let f' :: IntMap.Key -> v -> EventWriterT t q (ReaderT (Dynamic t (QueryResult q)) m) (QueryTLoweredResult t q v')
97+ f' k v = fmap QueryTLoweredResult $ flip runStateT [] $ unQueryT $ f k v
98+ (result0, result') <- QueryT $ lift $ traverseIntMapWithKeyWithAdjust f' im0 im'
99+ let liftedResult0 = IntMap.map getQueryTLoweredResultValue result0
100+ liftedResult' = fforCheap result' $ \(PatchIntMap p) -> PatchIntMap $
101+ IntMap.map (fmap getQueryTLoweredResultValue) p
102+ liftedBs0 :: IntMap [Behavior t q]
103+ liftedBs0 = IntMap.map getQueryTLoweredResultWritten result0
104+ liftedBs' :: Event t (PatchIntMap [Behavior t q])
105+ liftedBs' = fforCheap result' $ \(PatchIntMap p) -> PatchIntMap $
106+ IntMap.map (fmap getQueryTLoweredResultWritten) p
107+ sampleBs :: forall m'. MonadSample t m' => [Behavior t q] -> m' q
108+ sampleBs = foldlM (\b a -> (b <>) <$> sample a) mempty
109+ accumBehaviors :: forall m'. MonadHold t m'
110+ => IntMap [Behavior t q]
111+ -> PatchIntMap [Behavior t q]
112+ -> m' ( Maybe (IntMap [Behavior t q])
113+ , Maybe (AdditivePatch q))
114+ -- f accumulates the child behavior state we receive from running traverseIntMapWithKeyWithAdjust for the underlying monad.
115+ -- When an update occurs, it also computes a patch to communicate to the parent QueryT state.
116+ -- bs0 is a Map denoting the behaviors of the current children.
117+ -- pbs is a PatchMap denoting an update to the behaviors of the current children
118+ accumBehaviors bs0 pbs@(PatchIntMap bs') = do
119+ let p k bs = case IntMap.lookup k bs0 of
120+ Nothing -> case bs of
121+ -- If the update is to delete the state for a child that doesn't exist, the patch is mempty.
122+ Nothing -> return mempty
123+ -- If the update is to update the state for a child that doesn't exist, the patch is the sample of the new state.
124+ Just newBs -> sampleBs newBs
125+ Just oldBs -> case bs of
126+ -- If the update is to delete the state for a child that already exists, the patch is the negation of the child's current state
127+ Nothing -> negateG <$> sampleBs oldBs
128+ -- If the update is to update the state for a child that already exists, the patch is the negation of sampling the child's current state
129+ -- composed with the sampling the child's new state.
130+ Just newBs -> (~~) <$> sampleBs newBs <*> sampleBs oldBs
131+ -- we compute the patch by iterating over the update PatchMap and proceeding by cases. Then we fold over the
132+ -- child patches and wrap them in AdditivePatch.
133+ patch <- AdditivePatch . fold <$> IntMap.traverseWithKey p bs'
134+ return (apply pbs bs0, Just patch)
135+ (qpatch :: Event t (AdditivePatch q)) <- mapAccumMaybeM_ accumBehaviors liftedBs0 liftedBs'
136+ tellQueryIncremental $ unsafeBuildIncremental (fold <$> mapM sampleBs liftedBs0) qpatch
137+ return (liftedResult0, liftedResult')
138+
83139 traverseDMapWithKeyWithAdjust :: forall (k :: * -> *) v v'. (DMap.GCompare k) => (forall a. k a -> v a -> QueryT t q m (v' a)) -> DMap k v -> Event t (PatchDMap k v) -> QueryT t q m (DMap k v', Event t (PatchDMap k v'))
84140 traverseDMapWithKeyWithAdjust f dm0 dm' = do
85141 let f' :: forall a. k a -> v a -> EventWriterT t q (ReaderT (Dynamic t (QueryResult q)) m) (Compose (QueryTLoweredResult t q) v' a)
@@ -124,6 +180,7 @@ instance (Reflex t, MonadFix m, Group q, Additive q, Query q, Eq q, MonadHold t
124180 (qpatch :: Event t (AdditivePatch q)) <- mapAccumMaybeM_ accumBehaviors liftedBs0 liftedBs'
125181 tellQueryIncremental $ unsafeBuildIncremental (fold <$> mapM sampleBs liftedBs0) qpatch
126182 return (liftedResult0, liftedResult')
183+
127184 traverseDMapWithKeyWithAdjustWithMove :: forall (k :: * -> *) v v'. (DMap.GCompare k) => (forall a. k a -> v a -> QueryT t q m (v' a)) -> DMap k v -> Event t (PatchDMapWithMove k v) -> QueryT t q m (DMap k v', Event t (PatchDMapWithMove k v'))
128185 traverseDMapWithKeyWithAdjustWithMove f dm0 dm' = do
129186 let f' :: forall a. k a -> v a -> EventWriterT t q (ReaderT (Dynamic t (QueryResult q)) m) (Compose (QueryTLoweredResult t q) v' a)
@@ -181,6 +238,10 @@ instance (Reflex t, MonadFix m, Group q, Additive q, Query q, Eq q, MonadHold t
181238instance MonadTrans (QueryT t q) where
182239 lift = QueryT . lift . lift . lift
183240
241+instance PrimMonad m => PrimMonad (QueryT t q m) where
242+ type PrimState (QueryT t q m) = PrimState m
243+ primitive = lift . primitive
244+
184245instance PostBuild t m => PostBuild t (QueryT t q m) where
185246 getPostBuild = lift getPostBuild
186247
@@ -215,13 +276,6 @@ instance (Monoid a, Monad m) => Monoid (QueryT t q m a) where
215276instance (S.Semigroup a, Monad m) => S.Semigroup (QueryT t q m a) where
216277 (<>) = liftA2 (S.<>)
217278
218−
219−mapQuery :: QueryMorphism q q' -> q -> q'
220−mapQuery = _queryMorphism_mapQuery
221−
222−mapQueryResult :: QueryMorphism q q' -> QueryResult q' -> QueryResult q
223−mapQueryResult = _queryMorphism_mapQueryResult
224−
225279-- | withQueryT's QueryMorphism argument needs to be a group homomorphism in order to behave correctly
226280withQueryT :: (MonadFix m, PostBuild t m, Group q, Group q', Additive q, Additive q', Query q')
227281 => QueryMorphism q q'
@@ -278,3 +332,6 @@ instance Requester t m => Requester t (QueryT t q m) where
278332
279333instance EventWriter t w m => EventWriter t w (QueryT t q m) where
280334 tellEvent = lift . tellEvent
335+
336+instance MonadDynamicWriter t w m => MonadDynamicWriter t w (QueryT t q m) where
337+ tellDyn = lift . tellDyn
src/Reflex/Query/Class.hs+23
@@ -15,12 +15,18 @@ module Reflex.Query.Class
1515 , MonadQuery (..)
1616 , tellQueryDyn
1717 , queryDyn
18+ , mapQuery
19+ , mapQueryResult
1820 ) where
1921
22+import Control.Category (Category)
23+import qualified Control.Category as Cat
2024import Control.Monad.Reader
2125import Data.Bits
2226import Data.Data
2327import Data.Ix
28+import Data.Map.Monoidal (MonoidalMap)
29+import qualified Data.Map.Monoidal as MonoidalMap
2430import Data.Semigroup
2531import Foreign.Storable
2632
@@ -30,6 +36,10 @@ class (Monoid (QueryResult a), Semigroup (QueryResult a)) => Query a where
3036 type QueryResult a :: *
3137 crop :: a -> QueryResult a -> QueryResult a
3238
39+instance (Ord k, Query v) => Query (MonoidalMap k v) where
40+ type QueryResult (MonoidalMap k v) = MonoidalMap k (QueryResult v)
41+ crop q r = MonoidalMap.intersectionWith (flip crop) r q
42+
3343-- | NB: QueryMorphism's must be group homomorphisms when acting on the query type
3444-- and compatible with the query relationship when acting on the query result
3545data QueryMorphism q q' = QueryMorphism
@@ -37,6 +47,19 @@ data QueryMorphism q q' = QueryMorphism
3747 , _queryMorphism_mapQueryResult :: QueryResult q' -> QueryResult q
3848 }
3949
50+instance Category QueryMorphism where
51+ id = QueryMorphism id id
52+ qm . qm' = QueryMorphism
53+ { _queryMorphism_mapQuery = mapQuery qm . mapQuery qm'
54+ , _queryMorphism_mapQueryResult = mapQueryResult qm' . mapQueryResult qm
55+ }
56+
57+mapQuery :: QueryMorphism q q' -> q -> q'
58+mapQuery = _queryMorphism_mapQuery
59+
60+mapQueryResult :: QueryMorphism q q' -> QueryResult q' -> QueryResult q
61+mapQueryResult = _queryMorphism_mapQueryResult
62+
4063-- | This type keeps track of the multiplicity of elements of the view selector that are being used by the app
4164newtype SelectedCount = SelectedCount { unSelectedCount :: Int }
4265 deriving (Eq, Ord, Show, Read, Integral, Num, Bounded, Enum, Real, Ix, Bits, FiniteBits, Storable, Data)
src/Reflex/Requester/Base.hs+1
@@ -32,6 +32,7 @@ module Reflex.Requester.Base
3232 ) where
3333
3434import Reflex.Class
35+import Reflex.Adjustable.Class
3536import Reflex.Dynamic
3637import Reflex.Host.Class
3738import Reflex.PerformEvent.Class
src/Reflex/Spider/Internal.hs+35−19
@@ -1135,7 +1135,11 @@ instance HasSpiderTimeline x => Align (Event x) where
11351135 nil = eventNever
11361136 align ea eb = fmapMaybe dmapToThese $ merge $ dynamicConst $ DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
11371137
1138−newtype Dyn x p = Dyn { unDyn :: IORef (Either (BehaviorM x (PatchTarget p), Event x p) (Hold x p)) }
1138+data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p)
1139+ | BuildDyn !(EventM x (PatchTarget p), Event x p)
1140+ | HoldDyn !(Hold x p)
1141+
1142+newtype Dyn x p = Dyn { unDyn :: IORef (DynType x p) }
11391143
11401144newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)
11411145newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
@@ -1156,15 +1160,15 @@ zipDynWith f da db =
11561160 return $ Just $ Identity $ f a b
11571161 in dynamicDynIdentity $ unsafeBuildDynamic (f <$> readBehaviorUntracked (dynamicCurrent da) <*> readBehaviorUntracked (dynamicCurrent db)) ec
11581162
1159−buildDynamic :: (Defer (SomeDynInit x) m, Patch p) => BehaviorM x (PatchTarget p) -> Event x p -> m (Dyn x p)
1163+buildDynamic :: (Defer (SomeDynInit x) m, Patch p) => EventM x (PatchTarget p) -> Event x p -> m (Dyn x p)
11601164buildDynamic readV0 v' = do
1161− result <- liftIO $ newIORef $ Left (readV0, v')
1165+ result <- liftIO $ newIORef $ BuildDyn (readV0, v')
11621166 let !d = Dyn result
11631167 defer $ SomeDynInit d
11641168 return d
11651169
11661170unsafeBuildDynamic :: BehaviorM x (PatchTarget p) -> Event x p -> Dyn x p
1167−unsafeBuildDynamic readV0 v' = Dyn $ unsafeNewIORef x $ Left x
1171+unsafeBuildDynamic readV0 v' = Dyn $ unsafeNewIORef x $ UnsafeDyn x
11681172 where x = (readV0, v')
11691173
11701174-- ResultM can read behaviors and events
@@ -1213,8 +1217,8 @@ coincidence a = eventCoincidence $ Coincidence
12131217run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> ResultM x b -> SpiderHost x b
12141218run roots after = do
12151219 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
1216− t <- SpiderHost ask
1217− result <- SpiderHost $ lift $ withMVar (_spiderTimeline_lock t) $ \_ -> flip runReaderT t $ unSpiderHost $ runFrame $ do
1220+ let t = spiderTimeline :: SpiderTimelineEnv x
1221+ result <- SpiderHost $ withMVar (_spiderTimeline_lock t) $ \_ -> unSpiderHost $ runFrame $ do
12181222 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
12191223 occBefore <- liftIO $ do
12201224 occBefore <- readIORef occRef
@@ -1374,14 +1378,21 @@ getDynHold :: (Defer (SomeHoldInit x) m, Patch p) => Dyn x p -> m (Hold x p)
13741378getDynHold d = do
13751379 mh <- liftIO $ readIORef $ unDyn d
13761380 case mh of
1377− Right h -> return h
1378− Left (readV0, v') -> do
1381+ HoldDyn h -> return h
1382+ UnsafeDyn (readV0, v') -> do
13791383 holdInits <- getDeferralQueue
13801384 v0 <- liftIO $ runBehaviorM readV0 Nothing holdInits
1385+ hold' v0 v'
1386+ BuildDyn (readV0, v') -> do
1387+ v0 <- liftIO $ runEventM readV0
1388+ hold' v0 v'
1389+ where
1390+ hold' v0 v' = do
13811391 h <- hold v0 v'
1382− liftIO $ writeIORef (unDyn d) $ Right h
1392+ liftIO $ writeIORef (unDyn d) $ HoldDyn h
13831393 return h
13841394
1395+
13851396-- Always refers to 0
13861397{-# NOINLINE zeroRef #-}
13871398zeroRef :: IORef Height
@@ -2074,7 +2085,7 @@ clearEventEnv (EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeI
20742085
20752086-- | Run an event action outside of a frame
20762087runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
2077−runFrame a = SpiderHost $ ask >>= \_ -> lift $ do
2088+runFrame a = SpiderHost $ do
20782089 let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
20792090 let go = do
20802091 result <- a
@@ -2115,7 +2126,7 @@ runFrame a = SpiderHost $ ask >>= \_ -> lift $ do
21152126 runEventM $ runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) --TODO: Is this actually OK? It seems like it should be, since we know that no events are firing at this point, but it still seems inelegant
21162127 --TODO: Make sure we touch the pieces of the SwitchSubscribed at the appropriate times
21172128 sub <- newSubscriberSwitch subscribed
2118− subscription <- runReaderT (unSpiderHost (runFrame ({-# SCC "subscribeSwitch" #-} subscribe e sub))) spiderTimeline --TODO: Assert that the event isn't firing --TODO: This should not loop because none of the events should be firing, but still, it is inefficient
2129+ subscription <- unSpiderHost $ runFrame $ {-# SCC "subscribeSwitch" #-} subscribe e sub --TODO: Assert that the event isn't firing --TODO: This should not loop because none of the events should be firing, but still, it is inefficient
21192130 {-
21202131 stackTrace <- liftIO $ fmap renderStack $ ccsToStrings =<< (getCCSOf $! switchSubscribedParent subscribed)
21212132 liftIO $ putStrLn $ (++stackTrace) $ "subd' subscribed to " ++ case e of
@@ -2296,9 +2307,13 @@ newJoinDyn d =
22962307 in Reflex.Spider.Internal.unsafeBuildDynamic readV0 v'
22972308
22982309instance HasSpiderTimeline x => Functor (Reflex.Class.Dynamic (SpiderTimeline x)) where
2299− fmap f = SpiderDynamic . newMapDyn f . unSpiderDynamic
2310+ fmap = mapDynamicSpider
23002311 x <$ d = R.unsafeBuildDynamic (return x) $ x <$ R.updated d
23012312
2313+mapDynamicSpider :: HasSpiderTimeline x => (a -> b) -> Reflex.Class.Dynamic (SpiderTimeline x) a -> Reflex.Class.Dynamic (SpiderTimeline x) b
2314+mapDynamicSpider f = SpiderDynamic . newMapDyn f . unSpiderDynamic
2315+{-# INLINE [1] mapDynamicSpider #-}
2316+
23022317instance HasSpiderTimeline x => Applicative (Reflex.Class.Dynamic (SpiderTimeline x)) where
23032318 pure = SpiderDynamic . dynamicConst
23042319#if MIN_VERSION_base(4,10,0)
@@ -2317,7 +2332,7 @@ holdDynSpiderEventM v0 e = fmap (SpiderDynamic . dynamicHoldIdentity) $ Reflex.S
23172332holdIncrementalSpiderEventM :: (HasSpiderTimeline x, Patch p) => PatchTarget p -> Reflex.Class.Event (SpiderTimeline x) p -> EventM x (Reflex.Class.Incremental (SpiderTimeline x) p)
23182333holdIncrementalSpiderEventM v0 e = fmap (SpiderIncremental . dynamicHold) $ Reflex.Spider.Internal.hold v0 $ unSpiderEvent e
23192334
2320−buildDynamicSpiderEventM :: HasSpiderTimeline x => SpiderPullM x a -> Reflex.Class.Event (SpiderTimeline x) a -> EventM x (Reflex.Class.Dynamic (SpiderTimeline x) a)
2335+buildDynamicSpiderEventM :: HasSpiderTimeline x => SpiderPushM x a -> Reflex.Class.Event (SpiderTimeline x) a -> EventM x (Reflex.Class.Dynamic (SpiderTimeline x) a)
23212336buildDynamicSpiderEventM getV0 e = fmap (SpiderDynamic . dynamicDynIdentity) $ Reflex.Spider.Internal.buildDynamic (coerce getV0) $ coerce $ unSpiderEvent e
23222337
23232338instance HasSpiderTimeline x => Reflex.Class.MonadHold (SpiderTimeline x) (SpiderHost x) where
@@ -2405,8 +2420,8 @@ instance HasSpiderTimeline x => Reflex.Host.Class.MonadReadEvent (SpiderTimeline
24052420 return result
24062421
24072422instance Reflex.Host.Class.MonadReflexCreateTrigger (SpiderTimeline x) (SpiderHost x) where
2408− newEventWithTrigger = SpiderHost . lift . fmap SpiderEvent . newEventWithTriggerIO
2409− newFanEventWithTrigger f = SpiderHost $ lift $ do
2423+ newEventWithTrigger = SpiderHost . fmap SpiderEvent . newEventWithTriggerIO
2424+ newFanEventWithTrigger f = SpiderHost $ do
24102425 es <- newFanEventWithTriggerIO f
24112426 return $ Reflex.Class.EventSelector $ SpiderEvent . Reflex.Spider.Internal.select es
24122427
@@ -2543,7 +2558,7 @@ instance MonadAtomicRef (EventM x) where
25432558 atomicModifyRef r f = liftIO $ atomicModifyRef r f
25442559
25452560-- | The monad for actions that manipulate a Spider timeline identified by @x@
2546−newtype SpiderHost x a = SpiderHost { unSpiderHost :: ReaderT (SpiderTimelineEnv x) IO a } deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
2561+newtype SpiderHost x a = SpiderHost { unSpiderHost :: IO a } deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
25472562
25482563instance Monad (SpiderHost x) where
25492564 {-# INLINABLE (>>=) #-}
@@ -2558,14 +2573,15 @@ instance Monad (SpiderHost x) where
25582573-- | Run an action affecting the global Spider timeline; this will be guarded by
25592574-- a mutex for that timeline
25602575runSpiderHost :: SpiderHost Global a -> IO a
2561−runSpiderHost (SpiderHost a) = runReaderT a globalSpiderTimelineEnv
2576+runSpiderHost (SpiderHost a) = a
25622577
25632578-- | Run an action affecting a given Spider timeline; this will be guarded by a
25642579-- mutex for that timeline
25652580runSpiderHostForTimeline :: SpiderHost x a -> SpiderTimelineEnv x -> IO a
2566−runSpiderHostForTimeline (SpiderHost a) = runReaderT a
2581+runSpiderHostForTimeline (SpiderHost a) _ = a
25672582
2568−newtype SpiderHostFrame x a = SpiderHostFrame { runSpiderHostFrame :: EventM x a } deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
2583+newtype SpiderHostFrame x a = SpiderHostFrame { runSpiderHostFrame :: EventM x a }
2584+ deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
25692585
25702586instance Monad (SpiderHostFrame x) where
25712587 {-# INLINABLE (>>=) #-}
src/Reflex/Time.hs+2−2
@@ -107,7 +107,7 @@ delay dt e = performEventAsync $ ffor e $ \a cb -> liftIO $ void $ forkIO $ do
107107 cb a
108108
109109-- | Send events with Poisson timing with the given basis and rate
110−-- Each occurence of the resulting event will contain the index of
110+-- Each occurrence of the resulting event will contain the index of
111111-- the current interval, with 0 representing the basis time
112112poissonLossyFrom
113113 :: (RandomGen g, MonadIO (Performable m), PerformEvent t m, TriggerEvent t m)
@@ -126,7 +126,7 @@ poissonLossyFrom rnd rate = inhomogeneousPoissonFrom rnd (constant rate) rate
126126
127127
128128-- | Send events with Poisson timing with the given basis and rate
129−-- Each occurence of the resulting event will contain the index of
129+-- Each occurrence of the resulting event will contain the index of
130130-- the current interval, with 0 representing the basis time.
131131-- Automatically begin sending events when the DOM is built
132132poissonLossy
src/Reflex/TriggerEvent/Base.hs+1
@@ -25,6 +25,7 @@ import Data.IORef
2525import Data.Monoid ((<>))
2626import qualified Data.Semigroup as S
2727import Reflex.Class
28+import Reflex.Adjustable.Class
2829import Reflex.Host.Class
2930import Reflex.PerformEvent.Class
3031import Reflex.PostBuild.Class
src/Reflex/Widget/Basic.hs+2
@@ -10,7 +10,9 @@ module Reflex.Widget.Basic where
1010
1111import Control.Monad.Fix (MonadFix)
1212import Data.Map (Map)
13+
1314import Reflex.Class
15+import Reflex.Adjustable.Class
1416import Reflex.Patch.MapWithMove
1517
1618
src/Reflex/Workflow.hs+1
@@ -13,6 +13,7 @@ import Control.Arrow ((***))
1313import Control.Monad.Fix (MonadFix)
1414
1515import Reflex.Class
16+import Reflex.Adjustable.Class
1617import Reflex.Network
1718import Reflex.NotReady.Class
1819import Reflex.PostBuild.Class
test/EventWriterT.hs+69
@@ -1,9 +1,15 @@
11{-# LANGUAGE FlexibleContexts #-}
22{-# LANGUAGE GADTs #-}
3+{-# LANGUAGE RecursiveDo #-}
4+{-# LANGUAGE ScopedTypeVariables #-}
35module Main where
46
57import Control.Lens
68import Control.Monad
9+import Control.Monad.Fix
10+import qualified Data.Dependent.Map as DMap
11+import Data.Functor.Misc
12+import qualified Data.Map as M
713import Data.These
814
915import Reflex
@@ -24,6 +30,12 @@ main = do
2430 , These () ()
2531 ]
2632 print os2
33+ os3@[[Nothing, Just [2]]] <- runApp' (unwrapApp testMoribundTellEvent) [Just ()]
34+ print os3
35+ os4@[[Nothing, Just [2]]] <- runApp' (unwrapApp testMoribundTellEventDMap) [Just ()]
36+ print os4
37+ os5@[[Nothing, Just [1, 2]]] <- runApp' (unwrapApp testLiveTellEventDMap) [Just ()]
38+ print os5
2739 return ()
2840
2941unwrapApp :: (Reflex t, Monad m) => (a -> EventWriterT t [Int] m ()) -> a -> m (Event t [Int])
@@ -43,3 +55,60 @@ testSimultaneous pulse = do
4355 forM_ [1,3..9] $ \i -> runWithReplace (tellEvent ([i] <$ e0)) $ ffor e1 $ \_ -> tellEvent ([i+1] <$ e0)
4456 return ()
4557
58+-- | Test that a widget telling and event which fires at the same time it has been replaced
59+-- doesn't count along with the new widget.
60+testMoribundTellEvent
61+ :: forall t m
62+ . ( Reflex t
63+ , Adjustable t m
64+ , MonadHold t m
65+ , MonadFix m
66+ )
67+ => Event t ()
68+ -> EventWriterT t [Int] m ()
69+testMoribundTellEvent pulse = do
70+ rec let tellIntOnReplace :: Int -> EventWriterT t [Int] m ()
71+ tellIntOnReplace x = tellEvent $ [x] <$ rwrFinished
72+ (_, rwrFinished) <- runWithReplace (tellIntOnReplace 1) $ tellIntOnReplace 2 <$ pulse
73+ return ()
74+
75+-- | The equivalent of 'testMoribundTellEvent' for 'traverseDMapWithKeyWithAdjust'.
76+testMoribundTellEventDMap
77+ :: forall t m
78+ . ( Reflex t
79+ , Adjustable t m
80+ , MonadHold t m
81+ , MonadFix m
82+ )
83+ => Event t ()
84+ -> EventWriterT t [Int] m ()
85+testMoribundTellEventDMap pulse = do
86+ rec let tellIntOnReplace :: Int -> EventWriterT t [Int] m ()
87+ tellIntOnReplace x = tellEvent $ [x] <$ rwrFinished
88+ (_, rwrFinished :: Event t (PatchDMap (Const2 () Int) Identity)) <-
89+ traverseDMapWithKeyWithAdjust
90+ (\(Const2 ()) (Identity v) -> Identity . const v <$> tellIntOnReplace v)
91+ (mapToDMap $ M.singleton () 1)
92+ ((PatchDMap $ DMap.map (ComposeMaybe . Just) $ mapToDMap $ M.singleton () 2) <$ pulse)
93+ return ()
94+
95+-- | Ensures that elements which are _not_ removed can still fire 'tellEvent's
96+-- during the same frame as other elements are updated.
97+testLiveTellEventDMap
98+ :: forall t m
99+ . ( Reflex t
100+ , Adjustable t m
101+ , MonadHold t m
102+ , MonadFix m
103+ )
104+ => Event t ()
105+ -> EventWriterT t [Int] m ()
106+testLiveTellEventDMap pulse = do
107+ rec let tellIntOnReplace :: Int -> EventWriterT t [Int] m ()
108+ tellIntOnReplace x = tellEvent $ [x] <$ rwrFinished
109+ (_, rwrFinished :: Event t (PatchDMap (Const2 Int ()) Identity)) <-
110+ traverseDMapWithKeyWithAdjust
111+ (\(Const2 k) (Identity ()) -> Identity <$> tellIntOnReplace k)
112+ (mapToDMap $ M.singleton 1 ())
113+ ((PatchDMap $ DMap.map (ComposeMaybe . Just) $ mapToDMap $ M.singleton 2 ()) <$ pulse)
114+ return ()
test/QueryT.hs+12−6
@@ -1,14 +1,16 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DeriveFunctor #-}
23{-# LANGUAGE FlexibleContexts #-}
34{-# LANGUAGE GeneralizedNewtypeDeriving #-}
45{-# LANGUAGE LambdaCase #-}
56{-# LANGUAGE RankNTypes #-}
7+{-# LANGUAGE StandaloneDeriving #-}
68{-# LANGUAGE TypeFamilies #-}
9+{-# LANGUAGE UndecidableInstances #-}
710
811import Control.Lens
912import Control.Monad.Fix
1013import Data.Align
11−import Data.AppendMap () -- for the Align instance
1214import qualified Data.AppendMap as AMap
1315import Data.Functor.Misc
1416import Data.Map (Map)
@@ -28,14 +30,18 @@ instance Query MyQuery where
2830 type QueryResult MyQuery = ()
2931 crop _ _ = ()
3032
31−instance (Ord k, Query a, Eq (QueryResult a)) => Query (Selector k a) where
33+instance (Ord k, Query a, Eq (QueryResult a), Align (MonoidalMap k)) => Query (Selector k a) where
3234 type QueryResult (Selector k a) = Selector k (QueryResult a)
3335 crop q r = undefined
3436
3537newtype Selector k a = Selector { unSelector :: MonoidalMap k a }
3638 deriving (Show, Read, Eq, Ord, Functor)
3739
38−instance (Ord k, Eq a, Monoid a) => Semigroup (Selector k a) where
40+#if !(MIN_VERSION_monoidal_containers(0,4,1))
41+deriving instance Ord k => Align (MonoidalMap k)
42+#endif
43+
44+instance (Ord k, Eq a, Monoid a, Align (MonoidalMap k)) => Semigroup (Selector k a) where
3945 (Selector a) <> (Selector b) = Selector $ fmapMaybe id $ f a b
4046 where
4147 f = alignWith $ \case
@@ -45,14 +51,14 @@ instance (Ord k, Eq a, Monoid a) => Semigroup (Selector k a) where
4551 let z = x `mappend` y
4652 in if z == mempty then Nothing else Just z
4753
48−instance (Ord k, Eq a, Monoid a) => Monoid (Selector k a) where
54+instance (Ord k, Eq a, Monoid a, Align (MonoidalMap k)) => Monoid (Selector k a) where
4955 mempty = Selector AMap.empty
5056 mappend = (<>)
5157
52−instance (Eq a, Ord k, Group a) => Group (Selector k a) where
58+instance (Eq a, Ord k, Group a, Align (MonoidalMap k)) => Group (Selector k a) where
5359 negateG = fmap negateG
5460
55−instance (Eq a, Ord k, Group a) => Additive (Selector k a)
61+instance (Eq a, Ord k, Group a, Align (MonoidalMap k)) => Additive (Selector k a)
5662
5763main :: IO ()
5864main = do
test/Reflex/Bench/Focused.hs+1−1
@@ -184,7 +184,7 @@ switchMergeBehaviors mapChanges = pull . joinMap <$> holdMap mapChanges
184184
185185-- | Turn an UpdatedMap into a Dynamic by applying the differences to the initial value
186186holdMapDyn :: (Reflex t, MonadHold t m, MonadFix m, Ord k) => UpdatedMap t k a -> m (Dynamic t (Map k a))
187−holdMapDyn (UpdatedMap initial changes) = foldDyn (flip (Map.foldWithKey modify)) initial changes
187+holdMapDyn (UpdatedMap initial changes) = foldDyn (flip (Map.foldrWithKey modify)) initial changes
188188
189189 where
190190 modify k Nothing items = Map.delete k items
test/Reflex/Plan/Pure.hs+4−4
@@ -55,15 +55,15 @@ instance TestPlan (Pure Int) PurePlan where
5555runPure :: PurePlan a -> (a, IntSet)
5656runPure (PurePlan p) = runStateT p mempty $ 0
5757
58−relavantTimes :: IntSet -> IntSet
59−relavantTimes occs = IntSet.fromList [0..l + 1]
58+relevantTimes :: IntSet -> IntSet
59+relevantTimes occs = IntSet.fromList [0..l + 1]
6060 where l = fromMaybe 0 (fst <$> IntSet.maxView occs)
6161
6262testBehavior :: (Behavior (Pure Int) a, IntSet) -> IntMap a
63−testBehavior (b, occs) = IntMap.fromSet (sample b) (relavantTimes occs)
63+testBehavior (b, occs) = IntMap.fromSet (sample b) (relevantTimes occs)
6464
6565testEvent :: (Event (Pure Int) a, IntSet) -> IntMap (Maybe a)
66−testEvent (Event readEvent, occs) = IntMap.fromSet readEvent (relavantTimes occs)
66+testEvent (Event readEvent, occs) = IntMap.fromSet readEvent (relevantTimes occs)
6767
6868
6969
test/Reflex/Plan/Reflex.hs+2−2
@@ -74,13 +74,13 @@ deriving instance ReflexHost t => MonadFix (Plan t)
7474
7575
7676instance (ReflexHost t, MonadRef (HostFrame t), Ref (HostFrame t) ~ Ref IO) => TestPlan t (Plan t) where
77− plan occurances = Plan $ do
77+ plan occurrences = Plan $ do
7878 (e, ref) <- newEventWithTriggerRef
7979 modify (IntMap.unionWith mappend (firings ref))
8080 return e
8181
8282 where
83− firings ref = IntMap.fromList (makeFiring ref <$> occurances)
83+ firings ref = IntMap.fromList (makeFiring ref <$> occurrences)
8484 makeFiring ref (t, a) = (fromIntegral t, [Firing ref a])
8585
8686
test/Reflex/Test/CrossImpl.hs+6−4
@@ -12,7 +12,6 @@
1212{-# LANGUAGE TypeFamilies #-}
1313{-# LANGUAGE TypeOperators #-}
1414{-# LANGUAGE UndecidableInstances #-}
15−module Reflex.Test.CrossImpl (test) where
1615
1716import Prelude hiding (and, foldl, mapM, mapM_, sequence, sequence_)
1817
@@ -26,12 +25,12 @@ import qualified Reflex.Spider.Internal as S
2625import Control.Arrow (second, (&&&))
2726import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
2827import Control.Monad.State.Strict hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
29−import Control.Monad.Writer hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
3028import Data.Dependent.Map (DSum (..))
3129import Data.Foldable
3230import Data.Map.Strict (Map)
3331import qualified Data.Map.Strict as Map
3432import qualified Data.Set as Set
33+import Data.Monoid
3534import Data.Traversable
3635import System.Exit
3736import System.Mem
@@ -230,6 +229,9 @@ testCases =
230229 rec result <- holdUniqDyn d
231230 d <- holdDyn (0 :: Int) e
232231 return (current result, updated result)
232+
233+
234+
233235 {-
234236 , (,) "mergeIncrementalWithMove" $ TestCase (Map.singleton 0 (0 :: Int), Map.fromList [(1, PatchDMapWithMove.moveDMapKey LeftTag RightTag), (2, mempty)]) $ \(b, e :: Event t (PatchDMapWithMove (EitherTag () ()) (Const2 () ()))) -> do
235237 x <- holdIncremental (DMap.singleton LeftTag $ void e) $ PatchDMapWithMove.mapPatchDMapWithMove (\(Const2 _) -> void e) <$> e
@@ -245,8 +247,8 @@ splitRecombineEvent e =
245247 in leftmost [ea, eb]
246248
247249
248−test :: IO ()
249−test = do
250+main :: IO ()
251+main = do
250252 results <- forM testCases $ \(name, TestCase inputs builder) -> do
251253 putStrLn $ "Test: " <> name
252254 testAgreement builder inputs
test/Reflex/Test/Micro.hs+64−3
@@ -3,6 +3,7 @@
33{-# LANGUAGE FlexibleContexts #-}
44{-# LANGUAGE FlexibleInstances #-}
55{-# LANGUAGE GADTs #-}
6+{-# LANGUAGE ScopedTypeVariables #-}
67{-# LANGUAGE MultiParamTypeClasses #-}
78{-# LANGUAGE RankNTypes #-}
89{-# LANGUAGE RecursiveDo #-}
@@ -23,6 +24,24 @@ import Data.Monoid
2324
2425import Prelude
2526
27+pushDyn :: (Reflex t, MonadHold t m) => (a -> PushM t b) -> Dynamic t a -> m (Dynamic t b)
28+pushDyn f d = buildDynamic (sample (current d) >>= f) (pushAlways f (updated d))
29+
30+foldedDyn :: (Reflex t, MonadHold t m) => (a -> a -> a) -> Dynamic t a -> m (Dynamic t a)
31+foldedDyn f d = fmap join $ flip buildDynamic never $ do
32+ a <- sample (current d)
33+ foldDyn f a (updated d)
34+
35+scannedDyn :: (Reflex t, MonadHold t m) => Dynamic t a -> m (Dynamic t [a])
36+scannedDyn = fmap (fmap reverse) . foldedDyn (<>) . fmap pure
37+
38+scanInnerDyns :: (Reflex t, MonadHold t m) => Dynamic t (Dynamic t a) -> m (Dynamic t [a])
39+scanInnerDyns d = do
40+ scans <- scannedDyn d
41+ return (join (fmap distributeListOverDynPure scans))
42+
43+
44+
2645{-# ANN testCases "HLint: ignore Functor law" #-}
2746testCases :: [(String, TestCase)]
2847testCases =
@@ -201,6 +220,14 @@ testCases =
201220 bb <- hold (constant "x") $ pushAlways (const $ hold "a" eo) eo
202221 return $ pull $ sample =<< sample bb
203222
223+
224+ , testB "foldDynWhileFiring" $ do
225+ e <- events1
226+ d <- foldDyn (:) [] $
227+ pushAlways (\a -> foldDyn (:) [a] e) e
228+
229+ return $ current (join (fmap distributeListOverDynPure d))
230+
204231 , testE "joinDyn" $ do
205232 e <- events1
206233 bb <- hold "b" e
@@ -223,6 +250,38 @@ testCases =
223250 d2 <- fmap (fmap (map toUpper)) $ foldDyn (++) "0" =<< events2
224251
225252 return $ current $ zipDynWith (<>) d1 d2
253+
254+ , testB "buildDynamicStrictness" $ do
255+ rec
256+ d'' <- pushDyn return d'
257+ d' <- pushDyn return d
258+ d <- holdDyn "0" =<< events1
259+
260+ _ <- sample (current d'')
261+ return (current d'')
262+
263+ , testB "factorDyn" $ do
264+ d <- holdDyn (Left "a") =<< eithers
265+
266+ eithers' <- eitherDyn d
267+ let unFactor = either id id
268+ return $ current (join (fmap unFactor eithers'))
269+
270+ , testB "pushDynDeep" $ do
271+ _ <- events1
272+ _ <- events2
273+
274+ d1 <- holdDyn "d1" =<< events1
275+ d2 <- holdDyn "d2" =<< events2
276+
277+ d <- flip pushDyn d1 $ \a ->
278+ flip pushDyn d2 $ \b ->
279+ flip pushDyn d1 $ \c ->
280+ return (a <> b <> c)
281+
282+ d' <- pushDyn scanInnerDyns d >>= scanInnerDyns
283+ return $ current d'
284+
226285 , testE "fan-1" $ do
227286 e <- fmap toMap <$> events1
228287 let es = select (fanMap e) . Const2 <$> values
@@ -264,14 +323,18 @@ testCases =
264323 return $ void e
265324 lazyHold
266325
326+
267327 ] where
268328
269329 events1, events2, events3 :: TestPlan t m => m (Event t String)
270330 events1 = plan [(1, "a"), (2, "b"), (5, "c"), (7, "d"), (8, "e")]
271331 events2 = plan [(1, "e"), (3, "d"), (4, "c"), (6, "b"), (7, "a")]
272−
273332 events3 = liftA2 mappend events1 events2
274333
334+ eithers :: TestPlan t m => m (Event t (Either String String))
335+ eithers = plan [(1, Left "e"), (3, Left "d"), (4, Right "c"), (6, Right "b"), (7, Left "a")]
336+
337+
275338 values = "abcde"
276339 toMap str = Map.fromList $ map (\c -> (c, c)) str
277340
@@ -281,5 +344,3 @@ testCases =
281344
282345 deep e = leftmost [e, e]
283346 leftmost2 e1 e2 = leftmost [e1, e2]
284−
285−
test/Reflex/TestPlan.hs+2−2
@@ -26,8 +26,8 @@ import Reflex.Class
2626import Prelude
2727
2828class (Reflex t, MonadHold t m, MonadFix m) => TestPlan t m where
29− -- | Speicify a plan of an input Event firing
30− -- Occurances must be in the future (i.e. Time > 0)
29+ -- | Specify a plan of an input Event firing
30+ -- Occurrences must be in the future (i.e. Time > 0)
3131 -- Initial specification is
3232
3333 plan :: [(Word, a)] -> m (Event t a)
test/Test/Run.hs+8
@@ -64,3 +64,11 @@ runApp' :: (t ~ SpiderTimeline Global, m ~ SpiderHost Global)
6464runApp' app input = do
6565 let app' = fmap (AppOut (pure ())) . app
6666 map (map snd) <$> runApp (app' . _appIn_event) () (map (fmap That) input)
67+
68+runAppB :: (t ~ SpiderTimeline Global, m ~ SpiderHost Global)
69+ => (Event t eIn -> PerformEventT t m (Behavior t bOut))
70+ -> [Maybe eIn]
71+ -> IO [[bOut]]
72+runAppB app input = do
73+ let app' = fmap (flip AppOut never) . app
74+ map (map fst) <$> runApp (app' . _appIn_event) () (map (fmap That) input)
test/hlint.hs+1
@@ -20,6 +20,7 @@ main = do
2020 , "--ignore=Use >=>"
2121 , "--ignore=Use ."
2222 , "--ignore=Use unless"
23+ , "--ignore=Reduce duplication"
2324 , "--cpp-define=USE_TEMPLATE_HASKELL"
2425 ]
2526 recurseInto = and <$> sequence
test/semantics.hs−2
@@ -45,5 +45,3 @@ main = do
4545 ]
4646
4747 makeGroup name tests = first (\test -> intercalate "/" [name, test]) <$> tests
48−
49−