on develop help sign in
Merge branch 'develop' into ls-cleanup-debug
194ba06leon.smith@obsidian.systems
ChangeLog.md+32
@@ -1,9 +1,31 @@
1# Revision history for reflex
1# Revision history for reflex
2
2
3+## Unreleased
4+
5+* Data.WeakBag.traverse and Data.FastWeakBag.traverse have been
6+ renamed to Data.WeakBag.traverse_ and Data.FastWeakBag.traverse_
7+ respectively.
8+
9+* Fixes a bug in `Reflex.Patch.MapWithMove.patchThatSortsMapWith` that was producing invalid `PatchMapWithMove`.
10+
11+* Add missing `NotReady` instances:
12+ - `instance NotReady (SpiderTimeline x) (SpiderHost x)`
13+ - `instance HasSpiderTimeline x => NotReady (SpiderTimeline x) (PerformEventT (SpiderTimeline x) (SpiderHost x))`
14+
15+## 0.6.2.4
16+
17+* Update to monoidal-containers 0.6
18+
19+## 0.6.2.3
20+
21+* Add an upper-bound to witherable
22+
3## 0.6.2.2
23## 0.6.2.2
4
24
5* Support these >= 1. Add `split-these` flag to control whether to use new these/semialign combination or not.
25* Support these >= 1. Add `split-these` flag to control whether to use new these/semialign combination or not.
26+
6* Update version bounds to fix some CI failures
27* Update version bounds to fix some CI failures
28+
7* Add travis CI configuration
29* Add travis CI configuration
8
30
9## 0.6.2.1
31## 0.6.2.1
@@ -29,21 +51,31 @@
29
51
30* Fix `holdDyn` so that it is lazy in its event argument
52* Fix `holdDyn` so that it is lazy in its event argument
31 These produce `DMap`s whose values needn't be `Identity`.
53 These produce `DMap`s whose values needn't be `Identity`.
54+
32* Stop using the now-deprecated `*Tag` classes (e.g., `ShowTag`).
55* Stop using the now-deprecated `*Tag` classes (e.g., `ShowTag`).
56+
33* Fix `holdDyn` so that it is lazy in its event argument.
57* Fix `holdDyn` so that it is lazy in its event argument.
34
58
35## 0.6.1.0
59## 0.6.1.0
36
60
37* Re-export all of `Data.Map.Monoidal`
61* Re-export all of `Data.Map.Monoidal`
62+
38* Fix `QueryT` and `RequesterT` tests
63* Fix `QueryT` and `RequesterT` tests
39
64
40## 0.6.0.0 -- 2019-03-20
65## 0.6.0.0 -- 2019-03-20
41
66
42* Deprecate `FunctorMaybe` in favor of `Data.Witherable.Filterable`. We still export `fmapMaybe`, `ffilter`, etc., but they all rely on `Filterable` now.
67* Deprecate `FunctorMaybe` in favor of `Data.Witherable.Filterable`. We still export `fmapMaybe`, `ffilter`, etc., but they all rely on `Filterable` now.
68+
43* Rename `MonadDynamicWriter` to `DynamicWriter` and add a deprecation for the old name.
69* Rename `MonadDynamicWriter` to `DynamicWriter` and add a deprecation for the old name.
70+
44* Remove many deprecated functions.
71* Remove many deprecated functions.
72+
45* Add a `Num` instance for `Dynamic`.
73* Add a `Num` instance for `Dynamic`.
74+
46* Add `matchRequestsWithResponses` to make it easier to use `Requester` with protocols that don't do this matching for you.
75* Add `matchRequestsWithResponses` to make it easier to use `Requester` with protocols that don't do this matching for you.
76+
47* Add `withRequesterT` to map functions over the request and response of a `RequesterT`.
77* Add `withRequesterT` to map functions over the request and response of a `RequesterT`.
78+
48* Suppress nil patches in `QueryT` as an optimization. The `Query` type must now have an `Eq` instance.
79* Suppress nil patches in `QueryT` as an optimization. The `Query` type must now have an `Eq` instance.
80+
49* Add `throttleBatchWithLag` to `Reflex.Time`. See that module for details.
81* Add `throttleBatchWithLag` to `Reflex.Time`. See that module for details.
Quickref.md+14−11
@@ -198,7 +198,7 @@ For Events, the returned Event fires whenever the latest Event supplied by the w
198The functions mentioned above are used to create a static FRP network.
198The functions mentioned above are used to create a static FRP network.
199There are additional typeclasses that can be used to modify the FRP network, to have it interact with IO action, or to introspect the building of the network.
199There are additional typeclasses that can be used to modify the FRP network, to have it interact with IO action, or to introspect the building of the network.
200
200
201−Th typeclasses and their associated annotations include:
201+The typeclasses and their associated annotations include:
202
202
203- `PostBuild`
203- `PostBuild`
204 Fire an Event when an FRP network has been set up.
204 Fire an Event when an FRP network has been set up.
@@ -206,7 +206,7 @@ Th typeclasses and their associated annotations include:
206 [B] -- Function runs in any monad supporting PostBuild
206 [B] -- Function runs in any monad supporting PostBuild
207 ```
207 ```
208
208
209−- `Adjustable`
209+- `Adjustable`
210 Use Events to add or remove pieces of an FRP network.
210 Use Events to add or remove pieces of an FRP network.
211 ```haskell
211 ```haskell
212 [A] -- Function runs in any monad supporting Adjustable
212 [A] -- Function runs in any monad supporting Adjustable
@@ -271,7 +271,7 @@ Th typeclasses and their associated annotations include:
271```haskell
271```haskell
272-- Run side-effecting actions in Event when it occurs; returned Event contains
272-- Run side-effecting actions in Event when it occurs; returned Event contains
273-- results. Side effects run in the (Performable m) monad which is associated with
273-- results. Side effects run in the (Performable m) monad which is associated with
274−-- the (PerformEvent t m) typeclass constraint.
274+-- the (PerformEvent t m) typeclass constraint.
275-- This allows for working with IO when a ((MonadIO (Performable m)) constraint is available.
275-- This allows for working with IO when a ((MonadIO (Performable m)) constraint is available.
276[P] performEvent :: Event (Performable m a ) -> m (Event a)
276[P] performEvent :: Event (Performable m a ) -> m (Event a)
277
277
@@ -295,17 +295,20 @@ Th typeclasses and their associated annotations include:
295## Networks
295## Networks
296
296
297```haskell
297```haskell
298−-- Functions from Reflex.Network used to deal with Dynamics/Events carrying (m a)
298+-- Functions from Reflex.Adjustable / Reflex.Network used to deal with Dynamics/Events carrying (m a)
299
299
300+[A] runWithReplace :: m a -> Event t (m b) -> m (a, Event t b)
301+
300−-- Given a Dynamic of network-creating actions, create a network that is recreated whenever the Dynamic updates.
302+-- 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,
303+-- 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).
304-- 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)
305+[P,A] networkView :: Dynamic (m a) -> m (Event a)
304
306
305−-- Given an initial network and an Event of network-creating actions, create a network that is recreated whenever the
307+-- 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
308+-- 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.
309-- 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)
310+[H,A] networkHold :: m a -> Event (m a) -> m (Dynamic a)
309
311
310-- Render a placeholder network to be shown while another network is not yet done building
312-- 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)
313+[P,A] untilReady :: m a -> m b -> m (a, Event b)
314+```
default.nixdeleted−43
@@ -1,43 +0,0 @@
1−{ mkDerivation, ghc, base, bifunctors, containers, deepseq
2−, dependent-map, dependent-sum, exception-transformers
3−, haskell-src-exts, haskell-src-meta, hlint, lens, MemoTrie
4−, monad-control, mtl, primitive, random, ref-tf
5−, semigroupoids , semigroups, split, stdenv, stm, syb
6−, template-haskell , these, time, transformers
7−, transformers-compat, unbounded-delays, prim-uniq
8−, data-default, filepath, directory, filemanip, ghcjs-base
9−, monoidal-containers, witherable, profunctors
10−, semialign ? null, splitThese ? (semialign != null)
11−, useTemplateHaskell ? true
12−}:
13−mkDerivation {
14− pname = "reflex";
15− version = "0.6.2.2";
16− src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".git" "dist" ])) ./.;
17− libraryHaskellDepends = [
18− base bifunctors containers dependent-map dependent-sum
19− exception-transformers lens
20− MemoTrie monad-control mtl primitive ref-tf semigroupoids
21− semigroups stm syb template-haskell these transformers
22− transformers-compat prim-uniq
23− base bifunctors containers deepseq dependent-map dependent-sum
24− mtl ref-tf split transformers data-default
25− random time unbounded-delays monoidal-containers witherable
26− profunctors
27− ] ++ (if ghc.isGhcjs or false then [
28− ghcjs-base
29− ] else []) ++ (if !useTemplateHaskell then [] else [
30− haskell-src-exts haskell-src-meta
31− ]) ++ (if splitThese then [
32− semialign
33− ] else []);
34− testHaskellDepends = if ghc.isGhcjs or false then [] else [
35− hlint filepath directory filemanip
36− ];
37− configureFlags =
38− stdenv.lib.optional (!useTemplateHaskell) [ "-f-use-template-haskell" ] ++
39− stdenv.lib.optional (!splitThese) [ "-f-split-these" ];
40− homepage = "https://github.com/reflex-frp/reflex";
41− description = "Higher-order Functional Reactive Programming";
42− license = stdenv.lib.licenses.bsd3;
43−}
dep/reflex-platform/default.nixnew file+7
@@ -0,0 +1,7 @@
1+# DO NOT HAND-EDIT THIS FILE
2+import ((import <nixpkgs> {}).fetchFromGitHub (
3+ let json = builtins.fromJSON (builtins.readFile ./github.json);
4+ in { inherit (json) owner repo rev sha256;
5+ private = json.private or false;
6+ }
7+))
dep/reflex-platform/github.jsonnew file+7
@@ -0,0 +1,7 @@
1+{
2+ "owner": "reflex-frp",
3+ "repo": "reflex-platform",
4+ "branch": "develop",
5+ "rev": "e7b76dd552a10916c7d8702c11292dac4f4299ea",
6+ "sha256": "0s1183arrwldcs50qhzgnv94v24n9bgq6dfq64wp0a3q2nzyvgwh"
7+}
hydra.jsondeleted−29
@@ -1,29 +0,0 @@
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.nixdeleted−70
@@ -1,70 +0,0 @@
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.nixdeleted−8
@@ -1,8 +0,0 @@
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+5−5
@@ -1,5 +1,5 @@
1Name: reflex
1Name: reflex
2−Version: 0.6.2.2
2+Version: 0.6.2.4
3Synopsis: Higher-order Functional Reactive Programming
3Synopsis: Higher-order Functional Reactive Programming
4Description: Reflex is a high-performance, deterministic, higher-order Functional Reactive Programming system
4Description: Reflex is a high-performance, deterministic, higher-order Functional Reactive Programming system
5License: BSD3
5License: BSD3
@@ -85,15 +85,15 @@ library
85 time >= 1.4 && < 1.9,
85 time >= 1.4 && < 1.9,
86 transformers >= 0.5.6.0 && < 0.6,
86 transformers >= 0.5.6.0 && < 0.6,
87 unbounded-delays >= 0.1.0.0 && < 0.2,
87 unbounded-delays >= 0.1.0.0 && < 0.2,
88− witherable >= 0.2 && < 0.4
88+ witherable >= 0.3 && < 0.3.2
89
89
90 if flag(split-these)
90 if flag(split-these)
91 build-depends: these >= 1 && <1.1,
91 build-depends: these >= 1 && <1.1,
92− semialign >=1 && <1.1,
92+ semialign >=1 && <1.2,
93− monoidal-containers >= 0.5.0.1 && < 0.6
93+ monoidal-containers >= 0.6 && < 0.7
94 else
94 else
95 build-depends: these >= 0.4 && <0.9,
95 build-depends: these >= 0.4 && <0.9,
96− monoidal-containers == 0.5.0.0
96+ monoidal-containers == 0.4.0.0
97
97
98 exposed-modules:
98 exposed-modules:
99 Control.Monad.ReaderIO
99 Control.Monad.ReaderIO
release.nix+53−7
@@ -1,9 +1,55 @@
1−{ rp ? import ./reflex-platform.nix {}
1+{ reflex-platform-fun ? import ./dep/reflex-platform
2}:
2}:
3+
3let
4let
5+ native-reflex-platform = reflex-platform-fun {};
4− inherit (rp.nixpkgs) lib;
6+ inherit (native-reflex-platform.nixpkgs) lib;
5− compilers = ["ghc8_4" "ghc8_0" "ghcjs8_4" "ghcjs8_0"];
7+ systems = ["x86_64-linux" "x86_64-darwin"];
6−in lib.attrValues (lib.genAttrs compilers (ghc: {
8+
7− reflex-useTemplateHaskell = rp.${ghc}.callPackage ./. { useTemplateHaskell = true; splitThese = false; };
9+ perPlatform = lib.genAttrs systems (system: let
8− reflex = rp.${ghc}.callPackage ./. { useTemplateHaskell = false; splitThese = false; };
10+ reflex-platform = reflex-platform-fun { inherit system; };
9−}))
11+ compilers = [
12+ "ghc"
13+ "ghcjs"
14+ ] ++ lib.optionals (reflex-platform.androidSupport) [
15+ "ghcAndroidAarch64"
16+ "ghcAndroidAarch32"
17+ ] ++ lib.optionals (reflex-platform.iosSupport) [
18+ "ghcIosAarch64"
19+ ];
20+ variations = map (v: "reflex" + v) [
21+ "-dontUseTemplateHaskell"
22+ ""
23+ ];
24+ compilerPkgs = lib.genAttrs compilers (ghc: let
25+ variationPkgs = lib.genAttrs variations (variation: let
26+ reflex-platform = reflex-platform-fun {
27+ inherit system;
28+ __useTemplateHaskell = variation == "reflex"; # TODO hack
29+ haskellOverlays = [
30+ # Use this package's source for reflex
31+ (self: super: {
32+ _dep = super._dep // {
33+ reflex = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [
34+ "release.nix"
35+ ".git"
36+ "dist"
37+ ])) ./.;
38+ };
39+ })
40+ ];
41+ };
42+ in reflex-platform.${ghc}.reflex);
43+ in variationPkgs // {
44+ cache = reflex-platform.pinBuildInputs "reflex-${system}-${ghc}"
45+ (builtins.attrValues variationPkgs);
46+ });
47+ in compilerPkgs // {
48+ cache = reflex-platform.pinBuildInputs "reflex-${system}"
49+ (map (a: a.cache) (builtins.attrValues compilerPkgs));
50+ });
51+
52+ metaCache = native-reflex-platform.pinBuildInputs "reflex-everywhere"
53+ (map (a: a.cache) (builtins.attrValues perPlatform));
54+
55+in perPlatform // { inherit metaCache; }
src/Data/AppendMap.hs+3−1
@@ -32,6 +32,8 @@ import qualified Data.Map as Map (showTree, showTreeWith)
32#endif
32#endif
33import qualified Data.Witherable as W
33import qualified Data.Witherable as W
34import Data.Map.Monoidal
34import Data.Map.Monoidal
35+import qualified Data.Map.Monoidal as MonoidalMap
36+
35
37
36{-# DEPRECATED AppendMap "Use 'MonoidalMap' instead" #-}
38{-# DEPRECATED AppendMap "Use 'MonoidalMap' instead" #-}
37-- | AppendMap is a synonym for 'Data.Map.Monoidal.MonoidalMap'
39-- | AppendMap is a synonym for 'Data.Map.Monoidal.MonoidalMap'
@@ -48,7 +50,7 @@ pattern AppendMap m = MonoidalMap m
48
50
49#if !MIN_VERSION_witherable(0,3,2)
51#if !MIN_VERSION_witherable(0,3,2)
50instance W.Filterable (MonoidalMap k) where
52instance W.Filterable (MonoidalMap k) where
51− mapMaybe = mapMaybe
53+ mapMaybe = MonoidalMap.mapMaybe
52#endif
54#endif
53
55
54-- | Deletes a key, returning 'Nothing' if the result is empty.
56-- | Deletes a key, returning 'Nothing' if the result is empty.
src/Data/FastWeakBag.hs+9−4
@@ -18,6 +18,7 @@ module Data.FastWeakBag
18 , isEmpty
18 , isEmpty
19 , insert
19 , insert
20 , traverse
20 , traverse
21+ , traverse_
21 , remove
22 , remove
22 -- * Internal functions
23 -- * Internal functions
23 -- These will not always be available.
24 -- These will not always be available.
@@ -116,14 +117,14 @@ foreign import javascript unsafe "(function(){ for(var i = 0; i < $1.tickets.len
116isEmpty bag = {-# SCC "isEmpty" #-} IntMap.null <$> readIORef (_weakBag_children bag)
117isEmpty bag = {-# SCC "isEmpty" #-} IntMap.null <$> readIORef (_weakBag_children bag)
117#endif
118#endif
118
119
119−{-# INLINE traverse #-}
120+{-# INLINE traverse_ #-}
120-- | Visit every node in the given list. If new nodes are appended during the
121-- | Visit every node in the given list. If new nodes are appended during the
121-- traversal, they will not be visited. Every live node that was in the list
122-- traversal, they will not be visited. Every live node that was in the list
122-- when the traversal began will be visited exactly once; however, no guarantee
123-- when the traversal began will be visited exactly once; however, no guarantee
123-- is made about the order of the traversal.
124-- is made about the order of the traversal.
124−traverse :: forall a m. MonadIO m => FastWeakBag a -> (a -> m ()) -> m ()
125+traverse_ :: forall a m. MonadIO m => FastWeakBag a -> (a -> m ()) -> m ()
125#ifdef GHCJS_FAST_WEAK
126#ifdef GHCJS_FAST_WEAK
126−traverse wb f = do
127+traverse_ wb f = do
127 let go cursor = when (not $ js_isNull cursor) $ do
128 let go cursor = when (not $ js_isNull cursor) $ do
128 val <- liftIO $ js_getTicketValue cursor
129 val <- liftIO $ js_getTicketValue cursor
129 f $ unsafeFromRawJSVal val
130 f $ unsafeFromRawJSVal val
@@ -134,13 +135,17 @@ foreign import javascript unsafe "$r = $1.val;" js_getTicketValue :: JSVal -> IO
134--TODO: Fix the race condition where if a cursor is deleted (presumably using 'remove', below) while we're holding it, it can't find its way back to the correct bag
135--TODO: Fix the race condition where if a cursor is deleted (presumably using 'remove', below) while we're holding it, it can't find its way back to the correct bag
135foreign import javascript unsafe "(function(){ for(var i = $1.pos - 1; i >= 0; i--) { if($1.bag.tickets[i] !== null) { return $1.bag.tickets[i]; } }; return null; })()" js_getNext :: FastWeakBagTicket a -> IO JSVal --TODO: Clean up as we go along so this isn't O(n) every time -- Result can be null or a FastWeakBagTicket a
136foreign import javascript unsafe "(function(){ for(var i = $1.pos - 1; i >= 0; i--) { if($1.bag.tickets[i] !== null) { return $1.bag.tickets[i]; } }; return null; })()" js_getNext :: FastWeakBagTicket a -> IO JSVal --TODO: Clean up as we go along so this isn't O(n) every time -- Result can be null or a FastWeakBagTicket a
136#else
137#else
137−traverse (FastWeakBag _ children) f = {-# SCC "traverse" #-} do
138+traverse_ (FastWeakBag _ children) f = {-# SCC "traverse_" #-} do
138 cs <- liftIO $ readIORef children
139 cs <- liftIO $ readIORef children
139 forM_ cs $ \c -> do
140 forM_ cs $ \c -> do
140 ma <- liftIO $ deRefWeak c
141 ma <- liftIO $ deRefWeak c
141 mapM_ f ma
142 mapM_ f ma
142#endif
143#endif
143
144
145+{-# DEPRECATED traverse "Use 'traverse_' instead" #-}
146+traverse :: forall a m. MonadIO m => FastWeakBag a -> (a -> m ()) -> m ()
147+traverse = traverse_
148+
144-- | Remove an item from the 'FastWeakBag'; does nothing if invoked multiple times
149-- | Remove an item from the 'FastWeakBag'; does nothing if invoked multiple times
145-- on the same 'FastWeakBagTicket'.
150-- on the same 'FastWeakBagTicket'.
146{-# INLINE remove #-}
151{-# INLINE remove #-}
src/Data/WeakBag.hs+8−3
@@ -15,6 +15,7 @@ module Data.WeakBag
15 , singleton
15 , singleton
16 , insert
16 , insert
17 , traverse
17 , traverse
18+ , traverse_
18 , remove
19 , remove
19 -- * Internal functions
20 -- * Internal functions
20 -- These will not always be available.
21 -- These will not always be available.
@@ -99,18 +100,22 @@ singleton a wbRef finalizer = {-# SCC "singleton" #-} do
99 ticket <- insert a bag wbRef finalizer
100 ticket <- insert a bag wbRef finalizer
100 return (bag, ticket)
101 return (bag, ticket)
101
102
102−{-# INLINE traverse #-}
103+{-# INLINE traverse_ #-}
103-- | Visit every node in the given list. If new nodes are appended during the
104-- | Visit every node in the given list. If new nodes are appended during the
104-- traversal, they will not be visited. Every live node that was in the list
105-- traversal, they will not be visited. Every live node that was in the list
105-- when the traversal began will be visited exactly once; however, no guarantee
106-- when the traversal began will be visited exactly once; however, no guarantee
106-- is made about the order of the traversal.
107-- is made about the order of the traversal.
107−traverse :: MonadIO m => WeakBag a -> (a -> m ()) -> m ()
108+traverse_ :: MonadIO m => WeakBag a -> (a -> m ()) -> m ()
108−traverse (WeakBag _ children) f = {-# SCC "traverse" #-} do
109+traverse_ (WeakBag _ children) f = {-# SCC "traverse" #-} do
109 cs <- liftIO $ readIORef children
110 cs <- liftIO $ readIORef children
110 forM_ cs $ \c -> do
111 forM_ cs $ \c -> do
111 ma <- liftIO $ deRefWeak c
112 ma <- liftIO $ deRefWeak c
112 mapM_ f ma
113 mapM_ f ma
113
114
115+{-# DEPRECATED traverse "Use 'traverse_' instead" #-}
116+traverse :: MonadIO m => WeakBag a -> (a -> m ()) -> m ()
117+traverse = traverse_
118+
114-- | Remove an item from the 'WeakBag'; does nothing if invoked multiple times
119-- | Remove an item from the 'WeakBag'; does nothing if invoked multiple times
115-- on the same 'WeakBagTicket'.
120-- on the same 'WeakBagTicket'.
116{-# INLINE remove #-}
121{-# INLINE remove #-}
src/Reflex/Class.hs+8−2
@@ -173,12 +173,15 @@ module Reflex.Class
173 , slowHeadE
173 , slowHeadE
174 ) where
174 ) where
175
175
176−#if defined(MIN_VERSION_semialign)
176+#ifdef MIN_VERSION_semialign
177import Prelude hiding (zip, zipWith)
177import Prelude hiding (zip, zipWith)
178
178
179#if MIN_VERSION_these(0,8,0)
179#if MIN_VERSION_these(0,8,0)
180import Data.These.Combinators (justThese)
180import Data.These.Combinators (justThese)
181#endif
181#endif
182+#if MIN_VERSION_semialign(1,1,0)
183+import Data.Zip (Zip (..))
184+#endif
182#endif
185#endif
183
186
184import Control.Applicative
187import Control.Applicative
@@ -1077,7 +1080,10 @@ instance Reflex t => Semialign (Event t) where
1077#endif
1080#endif
1078 align = alignEventWithMaybe Just
1081 align = alignEventWithMaybe Just
1079
1082
1080−#if defined(MIN_VERSION_semialign)
1083+#ifdef MIN_VERSION_semialign
1084+#if MIN_VERSION_semialign(1,1,0)
1085+instance Reflex t => Zip (Event t) where
1086+#endif
1081 zip x y = mapMaybe justThese $ align x y
1087 zip x y = mapMaybe justThese $ align x y
1082#endif
1088#endif
1083
1089
src/Reflex/Collection.hs+4−1
@@ -27,8 +27,11 @@ module Reflex.Collection
27 , simpleList
27 , simpleList
28 ) where
28 ) where
29
29
30−#if defined(MIN_VERSION_semialign)
30+#ifdef MIN_VERSION_semialign
31import Prelude hiding (zip, zipWith)
31import Prelude hiding (zip, zipWith)
32+#if MIN_VERSION_semialign(1,1,0)
33+import Data.Zip (Zip (..))
34+#endif
32#endif
35#endif
33
36
34import Control.Monad.Identity
37import Control.Monad.Identity
src/Reflex/Network.hs+1−1
@@ -20,7 +20,7 @@ import Reflex.NotReady.Class
20import Reflex.PostBuild.Class
20import Reflex.PostBuild.Class
21
21
22-- | A 'Dynamic' "network": Takes a 'Dynamic' of network-creating actions and replaces the network whenever the 'Dynamic' updates.
22-- | A 'Dynamic' "network": Takes a 'Dynamic' of network-creating actions and replaces the network whenever the 'Dynamic' updates.
23−-- The returned Event of network results fires when the 'Dynamic' updates.
23+-- The returned Event of network results fires at post-build time and when the 'Dynamic' updates.
24-- Note: Often, the type 'a' is an Event, in which case the return value is an Event-of-Events, where the outer 'Event' fires
24-- Note: Often, the type 'a' is an Event, in which case the return value is an Event-of-Events, where the outer 'Event' fires
25-- when switching networks. Such an 'Event' would typically be flattened (via 'switchPromptly').
25-- when switching networks. Such an 'Event' would typically be flattened (via 'switchPromptly').
26networkView :: (NotReady t m, Adjustable t m, PostBuild t m) => Dynamic t (m a) -> m (Event t a)
26networkView :: (NotReady t m, Adjustable t m, PostBuild t m) => Dynamic t (m a) -> m (Event t a)
src/Reflex/Patch/MapWithMove.hs+1−1
@@ -155,7 +155,7 @@ patchThatSortsMapWith cmp m = PatchMapWithMove $ Map.fromList $ catMaybes $ zipW
155 Just (from, to)
155 Just (from, to)
156 reverseMapping = Map.fromList $ catMaybes $ zipWith f unsorted sorted
156 reverseMapping = Map.fromList $ catMaybes $ zipWith f unsorted sorted
157 g (to, _) (from, _) = if to == from then Nothing else
157 g (to, _) (from, _) = if to == from then Nothing else
158− let Just movingTo = Map.lookup from reverseMapping
158+ let Just movingTo = Map.lookup to reverseMapping
159 in Just (to, NodeInfo (From_Move from) $ Just movingTo)
159 in Just (to, NodeInfo (From_Move from) $ Just movingTo)
160
160
161-- | Create a 'PatchMapWithMove' that, if applied to the first 'Map' provided,
161-- | Create a 'PatchMapWithMove' that, if applied to the first 'Map' provided,
src/Reflex/Spider/Internal.hs+55−18
@@ -73,10 +73,13 @@ import System.IO.Unsafe
73import System.Mem.Weak
73import System.Mem.Weak
74import Unsafe.Coerce
74import Unsafe.Coerce
75
75
76−#if defined(MIN_VERSION_semialign)
76+#ifdef MIN_VERSION_semialign
77#if MIN_VERSION_these(0,8,0)
77#if MIN_VERSION_these(0,8,0)
78import Data.These.Combinators (justThese)
78import Data.These.Combinators (justThese)
79#endif
79#endif
80+#if MIN_VERSION_semialign(1,1,0)
81+import Data.Zip (Zip (..))
82+#endif
80#endif
83#endif
81
84
82#ifdef DEBUG_CYCLES
85#ifdef DEBUG_CYCLES
@@ -103,6 +106,7 @@ import qualified Reflex.Host.Class
103import Reflex.NotReady.Class
106import Reflex.NotReady.Class
104import Reflex.Patch
107import Reflex.Patch
105import qualified Reflex.Patch.DMapWithMove as PatchDMapWithMove
108import qualified Reflex.Patch.DMapWithMove as PatchDMapWithMove
109+import Reflex.PerformEvent.Base (PerformEventT)
106
110
107#ifdef DEBUG_TRACE_EVENTS
111#ifdef DEBUG_TRACE_EVENTS
108import qualified Data.ByteString.Char8 as BS8
112import qualified Data.ByteString.Char8 as BS8
@@ -294,6 +298,7 @@ cacheEvent e =
294#endif
298#endif
295 subscribers <- liftIO FastWeakBag.empty
299 subscribers <- liftIO FastWeakBag.empty
296 occRef <- liftIO $ newIORef Nothing -- This should never be read prior to being set below
300 occRef <- liftIO $ newIORef Nothing -- This should never be read prior to being set below
301+<<<<<<< HEAD
297 (parentSub, occ) <- subscribeAndRead e $ debugSubscriber' ("cacheEvent" <> showNodeId' nodeId) $ Subscriber
302 (parentSub, occ) <- subscribeAndRead e $ debugSubscriber' ("cacheEvent" <> showNodeId' nodeId) $ Subscriber
298 { subscriberPropagate = \a -> do
303 { subscriberPropagate = \a -> do
299 -- checkCycle (_eventSubscription_subscribed parentSub)
304 -- checkCycle (_eventSubscription_subscribed parentSub)
@@ -303,6 +308,29 @@ cacheEvent e =
303 , subscriberInvalidateHeight = FastWeakBag.traverse subscribers . invalidateSubscriberHeight
308 , subscriberInvalidateHeight = FastWeakBag.traverse subscribers . invalidateSubscriberHeight
304 , subscriberRecalculateHeight = FastWeakBag.traverse subscribers . recalculateSubscriberHeight
309 , subscriberRecalculateHeight = FastWeakBag.traverse subscribers . recalculateSubscriberHeight
305 }
310 }
311+||||||| merged common ancestors
312+ (parentSub, occ) <- subscribeAndRead e $ Subscriber
313+ { subscriberPropagate = \a -> do
314+ liftIO $ writeIORef occRef $ Just a
315+ scheduleClear occRef
316+ propagateFast a subscribers
317+ , subscriberInvalidateHeight = \old -> do
318+ FastWeakBag.traverse subscribers $ invalidateSubscriberHeight old
319+ , subscriberRecalculateHeight = \new -> do
320+ FastWeakBag.traverse subscribers $ recalculateSubscriberHeight new
321+ }
322+=======
323+ (parentSub, occ) <- subscribeAndRead e $ Subscriber
324+ { subscriberPropagate = \a -> do
325+ liftIO $ writeIORef occRef $ Just a
326+ scheduleClear occRef
327+ propagateFast a subscribers
328+ , subscriberInvalidateHeight = \old -> do
329+ FastWeakBag.traverse_ subscribers $ invalidateSubscriberHeight old
330+ , subscriberRecalculateHeight = \new -> do
331+ FastWeakBag.traverse_ subscribers $ recalculateSubscriberHeight new
332+ }
333+>>>>>>> develop
306 when (isJust occ) $ do
334 when (isJust occ) $ do
307 liftIO $ writeIORef occRef occ -- Set the initial value of occRef; we don't need to do this if occ is Nothing
335 liftIO $ writeIORef occRef occ -- Set the initial value of occRef; we don't need to do this if occ is Nothing
308 scheduleClear occRef
336 scheduleClear occRef
@@ -435,14 +463,12 @@ newSubscriberFan subscribed = debugSubscriber ("SubscriberFan " <> showNodeId su
435 return ()
463 return ()
436 , subscriberInvalidateHeight = \old -> do
464 , subscriberInvalidateHeight = \old -> do
437 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
465 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
438− forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse (_fanSubscribedChildren_list v) $ invalidateSubscriberHeight old
466+ forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse_ (_fanSubscribedChildren_list v) $ invalidateSubscriberHeight old
439−
440 , subscriberRecalculateHeight = \new -> do
467 , subscriberRecalculateHeight = \new -> do
441 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
468 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
442− forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse (_fanSubscribedChildren_list v) $ recalculateSubscriberHeight new
469+ forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse_ (_fanSubscribedChildren_list v) $ recalculateSubscriberHeight new
443 }
470 }
444
471
445−
446newSubscriberSwitch :: forall x a. HasSpiderTimeline x => SwitchSubscribed x a -> IO (Subscriber x a)
472newSubscriberSwitch :: forall x a. HasSpiderTimeline x => SwitchSubscribed x a -> IO (Subscriber x a)
447newSubscriberSwitch subscribed = debugSubscriber ("SubscriberCoincidenceOuter" <> showNodeId subscribed) $ Subscriber
473newSubscriberSwitch subscribed = debugSubscriber ("SubscriberCoincidenceOuter" <> showNodeId subscribed) $ Subscriber
448 { subscriberPropagate = \a -> {-# SCC "traverseSwitch" #-} do
474 { subscriberPropagate = \a -> {-# SCC "traverseSwitch" #-} do
@@ -453,7 +479,7 @@ newSubscriberSwitch subscribed = debugSubscriber ("SubscriberCoincidenceOuter" <
453 oldHeight <- readIORef $ switchSubscribedHeight subscribed
479 oldHeight <- readIORef $ switchSubscribedHeight subscribed
454 when (oldHeight /= invalidHeight) $ do
480 when (oldHeight /= invalidHeight) $ do
455 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
481 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
456− WeakBag.traverse (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
482+ WeakBag.traverse_ (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
457 , subscriberRecalculateHeight = (`updateSwitchHeight` subscribed)
483 , subscriberRecalculateHeight = (`updateSwitchHeight` subscribed)
458 }
484 }
459
485
@@ -472,8 +498,8 @@ newSubscriberCoincidenceOuter subscribed = debugSubscriber ("SubscriberCoinciden
472 Nothing ->
498 Nothing ->
473 when (innerHeight > outerHeight) $ liftIO $ do -- If the event fires, it will fire at a later height
499 when (innerHeight > outerHeight) $ liftIO $ do -- If the event fires, it will fire at a later height
474 writeIORef (coincidenceSubscribedHeight subscribed) $! innerHeight
500 writeIORef (coincidenceSubscribedHeight subscribed) $! innerHeight
475− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight outerHeight
501+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight outerHeight
476− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight innerHeight
502+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight innerHeight
477 Just o -> do -- Since it's already firing, no need to adjust height
503 Just o -> do -- Since it's already firing, no need to adjust height
478 liftIO $ writeIORef (coincidenceSubscribedOccurrence subscribed) occ
504 liftIO $ writeIORef (coincidenceSubscribedOccurrence subscribed) occ
479 scheduleClear $ coincidenceSubscribedOccurrence subscribed
505 scheduleClear $ coincidenceSubscribedOccurrence subscribed
@@ -507,14 +533,14 @@ propagate :: forall x a. HasSpiderTimeline x => a -> WeakBag (Subscriber x a) ->
507propagate a subscribers = withIncreasedDepth (Proxy::Proxy x) $
533propagate a subscribers = withIncreasedDepth (Proxy::Proxy x) $
508 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
534 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
509 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
535 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
510− WeakBag.traverse subscribers $ \s -> subscriberPropagate s a
536+ WeakBag.traverse_ subscribers $ \s -> subscriberPropagate s a
511
537
512-- | Propagate everything at the current height
538-- | Propagate everything at the current height
513propagateFast :: forall x a. HasSpiderTimeline x => a -> FastWeakBag (Subscriber x a) -> EventM x ()
539propagateFast :: forall x a. HasSpiderTimeline x => a -> FastWeakBag (Subscriber x a) -> EventM x ()
514propagateFast a subscribers = withIncreasedDepth (Proxy::Proxy x) $
540propagateFast a subscribers = withIncreasedDepth (Proxy::Proxy x) $
515 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
541 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
516 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
542 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
517− FastWeakBag.traverse subscribers $ \s -> subscriberPropagate s a
543+ FastWeakBag.traverse_ subscribers $ \s -> subscriberPropagate s a
518
544
519--------------------------------------------------------------------------------
545--------------------------------------------------------------------------------
520-- EventSubscribed
546-- EventSubscribed
@@ -1139,7 +1165,10 @@ instance HasSpiderTimeline x => Semialign (Event x) where
1139 align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
1165 align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
1140 DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1166 DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1141
1167
1142−#if defined(MIN_VERSION_semialign)
1168+#ifdef MIN_VERSION_semialign
1169+#if MIN_VERSION_semialign(1,1,0)
1170+instance HasSpiderTimeline x => Zip (Event x) where
1171+#endif
1143 zip x y = mapMaybe justThese $ align x y
1172 zip x y = mapMaybe justThese $ align x y
1144#endif
1173#endif
1145
1174
@@ -1587,15 +1616,15 @@ fanInt p = unsafePerformIO $ do
1587 liftIO $ writeIORef (_fanInt_occRef self) m
1616 liftIO $ writeIORef (_fanInt_occRef self) m
1588 scheduleIntClear $ _fanInt_occRef self
1617 scheduleIntClear $ _fanInt_occRef self
1589 FastMutableIntMap.forIntersectionWithImmutable_ (_fanInt_subscribers self) m $ \b v -> --TODO: Do we need to know that no subscribers are being added as we traverse?
1618 FastMutableIntMap.forIntersectionWithImmutable_ (_fanInt_subscribers self) m $ \b v -> --TODO: Do we need to know that no subscribers are being added as we traverse?
1590− FastWeakBag.traverse b $ \s ->
1619+ FastWeakBag.traverse_ b $ \s ->
1591 subscriberPropagate s v
1620 subscriberPropagate s v
1592 , subscriberInvalidateHeight = \old ->
1621 , subscriberInvalidateHeight = \old ->
1593 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b ->
1622 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b ->
1594− FastWeakBag.traverse b $ \s ->
1623+ FastWeakBag.traverse_ b $ \s ->
1595 subscriberInvalidateHeight s old
1624 subscriberInvalidateHeight s old
1596 , subscriberRecalculateHeight = \new ->
1625 , subscriberRecalculateHeight = \new ->
1597 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b ->
1626 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b ->
1598− FastWeakBag.traverse b $ \s ->
1627+ FastWeakBag.traverse_ b $ \s ->
1599 subscriberRecalculateHeight s new
1628 subscriberRecalculateHeight s new
1600 }
1629 }
1601 liftIO $ do
1630 liftIO $ do
@@ -2326,7 +2355,7 @@ runFrame a = SpiderHost $ do
2326 myHeight <- readIORef $ switchSubscribedHeight subscribed
2355 myHeight <- readIORef $ switchSubscribedHeight subscribed
2327 when (parentHeight /= myHeight) $ do
2356 when (parentHeight /= myHeight) $ do
2328 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
2357 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
2329− WeakBag.traverse (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight myHeight
2358+ WeakBag.traverse_ (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight myHeight
2330 mapM_ _someMergeUpdate_invalidateHeight mergeUpdates --TODO: In addition to when the patch is completely empty, we should also not run this if it has some Nothing values, but none of them have actually had any effect; potentially, we could even check for Just values with no effect (e.g. by comparing their IORefs and ignoring them if they are unchanged); actually, we could just check if the new height is different
2359 mapM_ _someMergeUpdate_invalidateHeight mergeUpdates --TODO: In addition to when the patch is completely empty, we should also not run this if it has some Nothing values, but none of them have actually had any effect; potentially, we could even check for Just values with no effect (e.g. by comparing their IORefs and ignoring them if they are unchanged); actually, we could just check if the new height is different
2331 forM_ coincidenceInfos $ \(SomeResetCoincidence subscription mcs) -> do
2360 forM_ coincidenceInfos $ \(SomeResetCoincidence subscription mcs) -> do
2332 unsubscribe subscription
2361 unsubscribe subscription
@@ -2367,7 +2396,7 @@ invalidateCoincidenceHeight subscribed = do
2367 oldHeight <- readIORef $ coincidenceSubscribedHeight subscribed
2396 oldHeight <- readIORef $ coincidenceSubscribedHeight subscribed
2368 when (oldHeight /= invalidHeight) $ do
2397 when (oldHeight /= invalidHeight) $ do
2369 writeIORef (coincidenceSubscribedHeight subscribed) $! invalidHeight
2398 writeIORef (coincidenceSubscribedHeight subscribed) $! invalidHeight
2370− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
2399+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
2371
2400
2372updateSwitchHeight :: Height -> SwitchSubscribed x a -> IO ()
2401updateSwitchHeight :: Height -> SwitchSubscribed x a -> IO ()
2373updateSwitchHeight new subscribed = do
2402updateSwitchHeight new subscribed = do
@@ -2375,7 +2404,7 @@ updateSwitchHeight new subscribed = do
2375 when (oldHeight == invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2404 when (oldHeight == invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2376 when (new /= invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2405 when (new /= invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2377 writeIORef (switchSubscribedHeight subscribed) $! new
2406 writeIORef (switchSubscribedHeight subscribed) $! new
2378− WeakBag.traverse (switchSubscribedSubscribers subscribed) $ recalculateSubscriberHeight new
2407+ WeakBag.traverse_ (switchSubscribedSubscribers subscribed) $ recalculateSubscriberHeight new
2379
2408
2380recalculateCoincidenceHeight :: CoincidenceSubscribed x a -> IO ()
2409recalculateCoincidenceHeight :: CoincidenceSubscribed x a -> IO ()
2381recalculateCoincidenceHeight subscribed = do
2410recalculateCoincidenceHeight subscribed = do
@@ -2384,7 +2413,7 @@ recalculateCoincidenceHeight subscribed = do
2384 height <- calculateCoincidenceHeight subscribed
2413 height <- calculateCoincidenceHeight subscribed
2385 when (height /= invalidHeight) $ do
2414 when (height /= invalidHeight) $ do
2386 writeIORef (coincidenceSubscribedHeight subscribed) $! height
2415 writeIORef (coincidenceSubscribedHeight subscribed) $! height
2387− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight height
2416+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight height
2388
2417
2389calculateSwitchHeight :: SwitchSubscribed x a -> IO Height
2418calculateSwitchHeight :: SwitchSubscribed x a -> IO Height
2390calculateSwitchHeight subscribed = getEventSubscribedHeight . _eventSubscription_subscribed =<< readIORef (switchSubscribedCurrentParent subscribed)
2419calculateSwitchHeight subscribed = getEventSubscribedHeight . _eventSubscription_subscribed =<< readIORef (switchSubscribedCurrentParent subscribed)
@@ -2824,3 +2853,11 @@ instance MonadAtomicRef (SpiderHostFrame x) where
2824instance PrimMonad (SpiderHostFrame x) where
2853instance PrimMonad (SpiderHostFrame x) where
2825 type PrimState (SpiderHostFrame x) = PrimState IO
2854 type PrimState (SpiderHostFrame x) = PrimState IO
2826 primitive = SpiderHostFrame . EventM . primitive
2855 primitive = SpiderHostFrame . EventM . primitive
2856+
2857+instance NotReady (SpiderTimeline x) (SpiderHost x) where
2858+ notReadyUntil _ = return ()
2859+ notReady = return ()
2860+
2861+instance HasSpiderTimeline x => NotReady (SpiderTimeline x) (PerformEventT (SpiderTimeline x) (SpiderHost x)) where
2862+ notReadyUntil _ = return ()
2863+ notReady = return ()
src/Reflex/Workflow.hs+1−1
@@ -34,7 +34,7 @@ workflow w0 = do
34 rec eResult <- networkHold (unWorkflow w0) $ fmap unWorkflow $ switch $ snd <$> current eResult
34 rec eResult <- networkHold (unWorkflow w0) $ fmap unWorkflow $ switch $ snd <$> current eResult
35 return $ fmap fst eResult
35 return $ fmap fst eResult
36
36
37−-- | Similar to 'workflow', but outputs an 'Event' that fires whenever the current 'Workflow' is replaced by the next 'Workflow'.
37+-- | Similar to 'workflow', but outputs an 'Event' that fires at post-build time and whenever the current 'Workflow' is replaced by the next 'Workflow'.
38workflowView :: forall t m a. (Reflex t, NotReady t m, Adjustable t m, MonadFix m, MonadHold t m, PostBuild t m) => Workflow t m a -> m (Event t a)
38workflowView :: forall t m a. (Reflex t, NotReady t m, Adjustable t m, MonadFix m, MonadHold t m, PostBuild t m) => Workflow t m a -> m (Event t a)
39workflowView w0 = do
39workflowView w0 = do
40 rec eResult <- networkView . fmap unWorkflow =<< holdDyn w0 eReplace
40 rec eResult <- networkView . fmap unWorkflow =<< holdDyn w0 eReplace