on develop help sign in
Merge branch 'release/0.6.2.3' of github.com:reflex-frp/reflex

* 'release/0.6.2.3' of github.com:reflex-frp/reflex: (34 commits) v0.6.2.3 - Add an upper-bound to witherable Use align (a merge) instead of coincidence for <.> (#346) Allow witherable ==0.3.* Use haskell-ci regenerate Update .travis.yml Add freeze file to avoid text 1.2.4.0 duplicate instances (#347) default.nix: Add missing profunctors dep Use xenial and manually install node 8 for ghcjs Fix merges (#340) contributing: add note on dependency ver bounds travis-ci: Add ghcjs to allowed failures list bc of travis time limit Less unsafeCoerce (#322) travis: disable benchmarks changelog: document v0.6.2.2 ci: Fix travis config cabal: Avoid hlint 2.1.* cabal: Limit witherable version ci: Remove cabal.project.local before building hlint: More linting cabal: remove some version bounds ...

commiteb70babe85f39fe84de34e3601947e17ff00f769 authorAli Abrar <aliabrar@gmail.com> dateFri 23 Aug 2019, 05:49 (7 years ago) parentf54933a9b684de
40 files changed+513−160
.travis.yml+171 CONTRIBUTING.md+4 ChangeLog.md+19−2 cabal.haskell-ci+16 cabal.project+1 cabal.project.freeze+1 default.nix+10−6 reflex.cabal+62−32 release.nix+4−4 src/Control/Monad/ReaderIO.hs+60 src/Data/AppendMap.hs+2 src/Data/Functor/Misc.hs−1 src/Reflex/Adjustable/Class.hs−1 src/Reflex/BehaviorWriter/Class.hs−1 src/Reflex/Class.hs+28−15 src/Reflex/Collection.hs+4 src/Reflex/Dynamic/TH.hs+1−1 src/Reflex/DynamicWriter/Class.hs−1 src/Reflex/EventWriter/Base.hs+1−1 src/Reflex/EventWriter/Class.hs−1 src/Reflex/Host/Class.hs−1 src/Reflex/NotReady/Class.hs−1 src/Reflex/Patch/IntMap.hs−8 src/Reflex/Patch/Map.hs−8 src/Reflex/PerformEvent/Base.hs+1−1 src/Reflex/PerformEvent/Class.hs−1 src/Reflex/PostBuild/Class.hs−1 src/Reflex/Profiled.hs+14−10 src/Reflex/Pure.hs+3−6 src/Reflex/Query/Base.hs−1 src/Reflex/Query/Class.hs−1 src/Reflex/Requester/Class.hs−1 src/Reflex/Spider/Internal.hs+78−49 src/Reflex/TriggerEvent/Class.hs−1 test/EventWriterT.hs+6−4 test/QueryT.hs+4 test/Reflex/Bench/Focused.hs+12 test/Reflex/Test/CrossImpl.hs+5 test/RequesterT.hs+5 test/hlint.hs+1
.travis.ymlnew file+171
@@ -0,0 +1,171 @@
1+# This Travis job script has been generated by a script via
2+#
3+# haskell-ci '--config=cabal.haskell-ci' 'cabal.project'
4+#
5+# For more information, see https://github.com/haskell-CI/haskell-ci
6+#
7+# version: 0.3.20190814
8+#
9+language: c
10+dist: xenial
11+sudo: required
12+git:
13+ # whether to recursively clone submodules
14+ submodules: false
15+cache:
16+ directories:
17+ - $HOME/.cabal/packages
18+ - $HOME/.cabal/store
19+before_cache:
20+ - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log
21+ # remove files that are regenerated by 'cabal update'
22+ - rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*
23+ - rm -fv $CABALHOME/packages/hackage.haskell.org/*.json
24+ - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache
25+ - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar
26+ - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx
27+ - rm -rfv $CABALHOME/packages/head.hackage
28+matrix:
29+ include:
30+ - compiler: ghcjs-8.4
31+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["cabal-install-3.0"]}}
32+ - compiler: ghc-8.6.5
33+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-2.4"]}}
34+ - compiler: ghc-8.4.4
35+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-2.4"]}}
36+ - compiler: ghc-8.2.2
37+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-2.4"]}}
38+ - compiler: ghc-8.0.2
39+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-2.4"]}}
40+before_install:
41+ - |
42+ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
43+ sudo add-apt-repository -y ppa:hvr/ghcjs;
44+ curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | sudo apt-key add -
45+ sudo apt-add-repository 'https://deb.nodesource.com/node_8.x xenial main'
46+ sudo apt-get update;
47+ sudo apt-get install $CC cabal-install-3.0 nodejs;
48+ fi
49+ - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')
50+ - WITHCOMPILER="-w $HC"
51+ - |
52+ if echo $CC | grep -q ghcjs; then
53+ GHCJS=true
54+ HC=${HC}js
55+ WITHCOMPILER="--ghcjs ${WITHCOMPILER}js"
56+ else
57+ GHCJS=false;
58+ fi
59+ - if $GHCJS ; then sudo apt-get install -y ghc-8.4.4 ; fi
60+ - if $GHCJS ; then PATH="/opt/ghc/8.4.4/bin:$PATH" ; fi
61+ - HCPKG="$HC-pkg"
62+ - unset CC
63+ - CABAL=/opt/ghc/bin/cabal
64+ - CABALHOME=$HOME/.cabal
65+ - export PATH="$CABALHOME/bin:$PATH"
66+ - TOP=$(pwd)
67+ - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"
68+ - echo $HCNUMVER
69+ - CABAL="$CABAL -vnormal+nowrap+markoutput"
70+ - set -o pipefail
71+ - |
72+ echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }' >> .colorful.awk
73+ echo 'BEGIN { state = "output"; }' >> .colorful.awk
74+ echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }' >> .colorful.awk
75+ echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }' >> .colorful.awk
76+ echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk
77+ echo ' if (state == "cabal") {' >> .colorful.awk
78+ echo ' print blue($0)' >> .colorful.awk
79+ echo ' } else {' >> .colorful.awk
80+ echo ' print $0' >> .colorful.awk
81+ echo ' }' >> .colorful.awk
82+ echo '}' >> .colorful.awk
83+ - cat .colorful.awk
84+ - |
85+ color_cabal_output () {
86+ awk -f $TOP/.colorful.awk
87+ }
88+ - echo text | color_cabal_output
89+install:
90+ - ${CABAL} --version
91+ - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
92+ - node --version
93+ - echo $GHCJS
94+ - TEST=--enable-tests
95+ - BENCH=--enable-benchmarks
96+ - BENCH=--disable-benchmarks
97+ - HEADHACKAGE=false
98+ - rm -f $CABALHOME/config
99+ - |
100+ echo "verbose: normal +nowrap +markoutput" >> $CABALHOME/config
101+ echo "remote-build-reporting: anonymous" >> $CABALHOME/config
102+ echo "write-ghc-environment-files: always" >> $CABALHOME/config
103+ echo "remote-repo-cache: $CABALHOME/packages" >> $CABALHOME/config
104+ echo "logs-dir: $CABALHOME/logs" >> $CABALHOME/config
105+ echo "world-file: $CABALHOME/world" >> $CABALHOME/config
106+ echo "extra-prog-path: $CABALHOME/bin" >> $CABALHOME/config
107+ echo "symlink-bindir: $CABALHOME/bin" >> $CABALHOME/config
108+ echo "installdir: $CABALHOME/bin" >> $CABALHOME/config
109+ echo "build-summary: $CABALHOME/logs/build.log" >> $CABALHOME/config
110+ echo "store-dir: $CABALHOME/store" >> $CABALHOME/config
111+ echo "install-dirs user" >> $CABALHOME/config
112+ echo " prefix: $CABALHOME" >> $CABALHOME/config
113+ echo "repository hackage.haskell.org" >> $CABALHOME/config
114+ echo " url: http://hackage.haskell.org/" >> $CABALHOME/config
115+ - cat $CABALHOME/config
116+ - rm -fv cabal.project cabal.project.local cabal.project.freeze
117+ - travis_retry ${CABAL} v2-update -v
118+ - if $GHCJS ; then (cd /tmp && ${CABAL} v2-install -w ghc-8.4.4 happy) ; fi
119+ # Generate cabal.project
120+ - rm -rf cabal.project cabal.project.local cabal.project.freeze
121+ - touch cabal.project
122+ - |
123+ echo "packages: ." >> cabal.project
124+ - |
125+ - cat cabal.project || true
126+ - cat cabal.project.local || true
127+ - if [ -f "./configure.ac" ]; then (cd "." && autoreconf -i); fi
128+ - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output
129+ - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"
130+ - rm cabal.project.freeze
131+script:
132+ - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)
133+ # Packaging...
134+ - ${CABAL} v2-sdist all | color_cabal_output
135+ # Unpacking...
136+ - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/
137+ - cd ${DISTDIR} || false
138+ - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;
139+ - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm '{}' \;
140+ - PKGDIR_reflex="$(find . -maxdepth 1 -type d -regex '.*/reflex-[0-9.]*')"
141+ # Generate cabal.project
142+ - rm -rf cabal.project cabal.project.local cabal.project.freeze
143+ - touch cabal.project
144+ - |
145+ echo "packages: ${PKGDIR_reflex}" >> cabal.project
146+ - |
147+ - cat cabal.project || true
148+ - cat cabal.project.local || true
149+ # Building...
150+ # this builds all libraries and executables (without tests/benchmarks)
151+ - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output
152+ # Building with tests and benchmarks...
153+ # build & run tests, build benchmarks
154+ - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output
155+ # Testing...
156+ - if ! $GHCJS ; then ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output ; fi
157+ # cabal check...
158+ - (cd ${PKGDIR_reflex} && ${CABAL} -vnormal check)
159+ # haddock...
160+ - if ! $GHCJS ; then ${CABAL} v2-haddock $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output ; fi
161+ # Constraint sets
162+ - rm -rf cabal.project.local
163+ # Constraint set no-th
164+ - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --constraint='reflex -use-template-haskell' all | color_cabal_output
165+ # Constraint set old-these
166+ - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --constraint='these <1' all | color_cabal_output
167+ # Constraint set old-witherable
168+ - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --constraint='witherable <0.3.2' all | color_cabal_output
169+
170+# REGENDATA ["--config=cabal.haskell-ci","cabal.project"]
171+# EOF
CONTRIBUTING.md+4
@@ -45,6 +45,10 @@ Your pull request should add no new warnings to the project. It should also gene
4545
4646Make sure the project builds and that the tests pass! This will generally also be checked by CI before merge, but trying it yourself first means you'll catch problems earlier and your contribution can be merged that much sooner!
4747
48+#### Dependencies
49+
50+Include version bounds whenever adding a dependency to the library stanza of the cabal file. Note that libraries added to reflex.cabal also need to be added to default.nix.
51+
4852### Documentation
4953
5054#### In the code
ChangeLog.md+19−2
@@ -1,16 +1,33 @@
11# Revision history for reflex
22
3+## 0.6.2.3
4+
5+* Add an upper-bound to witherable
6+
7+## 0.6.2.2
8+
9+* Support these >= 1. Add `split-these` flag to control whether to use new these/semialign combination or not.
10+* Update version bounds to fix some CI failures
11+* Add travis CI configuration
12+
313## 0.6.2.1
414
515* Generalize `fan` to `fanG` to take a `DMap` with non-`Identity`
6− values.
16+ functor:
17+ * `fan` to `fanG`
18+ * `EventSelectorG` for `fanG` result selector.
19+
20+* Reduce the amount of unsafeCoerce in coercing newtypes under Event/Dynamic/Behavior.
21+ * Add fused ReaderIO for the purpose of coercion (ReaderT's third argument has nominal role preventing automated coerce)
22+ * Add incrementalCoercion/coerceIncremental to go with dynamicCoercion/coerceDynamic
723
824* Generalize merging functions:
925 `merge` to `mergeG`,
1026 `mergeIncremental` to `mergeIncrementalG`,
11− `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`,
1227 `mergeIncrementalWithMove` to `mergeIncrementalWithMoveG`.
1328
29+* Generalize distribute function:
30+ `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`,
1431
1532## 0.6.2.0
1633
cabal.haskell-cinew file+16
@@ -0,0 +1,16 @@
1+distribution: xenial
2+benchmarks: False
3+unconstrained: False
4+installed: -all
5+
6+-- https://github.com/haskell/cabal/issues/6106
7+install-dependencies: False
8+
9+constraint-set no-th
10+ constraints: reflex -use-template-haskell
11+
12+constraint-set old-these
13+ constraints: these <1
14+
15+constraint-set old-witherable
16+ constraints: witherable <0.3.2
cabal.projectnew file+1
@@ -0,0 +1 @@
1+packages: .
cabal.project.freezenew file+1
@@ -0,0 +1 @@
1+constraints: any.text < 1.2.4.0
default.nix+10−6
@@ -6,12 +6,13 @@
66, template-haskell , these, time, transformers
77, transformers-compat, unbounded-delays, prim-uniq
88, data-default, filepath, directory, filemanip, ghcjs-base
9−, monoidal-containers, witherable
9+, monoidal-containers, witherable, profunctors
10+, semialign ? null, splitThese ? (semialign != null)
1011, useTemplateHaskell ? true
1112}:
1213mkDerivation {
1314 pname = "reflex";
14− version = "0.6.2.1";
15+ version = "0.6.2.3";
1516 src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".git" "dist" ])) ./.;
1617 libraryHaskellDepends = [
1718 base bifunctors containers dependent-map dependent-sum
@@ -22,17 +23,20 @@ mkDerivation {
2223 base bifunctors containers deepseq dependent-map dependent-sum
2324 mtl ref-tf split transformers data-default
2425 random time unbounded-delays monoidal-containers witherable
26+ profunctors
2527 ] ++ (if ghc.isGhcjs or false then [
2628 ghcjs-base
2729 ] else []) ++ (if !useTemplateHaskell then [] else [
2830 haskell-src-exts haskell-src-meta
29− ]);
31+ ]) ++ (if splitThese then [
32+ semialign
33+ ] else []);
3034 testHaskellDepends = if ghc.isGhcjs or false then [] else [
3135 hlint filepath directory filemanip
3236 ];
33− configureFlags = if useTemplateHaskell then [] else [
34− "-f-use-template-haskell"
35− ];
37+ configureFlags =
38+ stdenv.lib.optional (!useTemplateHaskell) [ "-f-use-template-haskell" ] ++
39+ stdenv.lib.optional (!splitThese) [ "-f-split-these" ];
3640 homepage = "https://github.com/reflex-frp/reflex";
3741 description = "Higher-order Functional Reactive Programming";
3842 license = stdenv.lib.licenses.bsd3;
reflex.cabal+62−32
@@ -1,5 +1,5 @@
11Name: reflex
2−Version: 0.6.2.1
2+Version: 0.6.2.3
33Synopsis: Higher-order Functional Reactive Programming
44Description: Reflex is a high-performance, deterministic, higher-order Functional Reactive Programming system
55License: BSD3
@@ -17,6 +17,10 @@ extra-source-files:
1717 Quickref.md
1818 ChangeLog.md
1919
20+tested-with:
21+ GHC ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.5,
22+ GHCJS ==8.4
23+
2024flag use-reflex-optimizer
2125 description: Use the GHC plugin Reflex.Optimizer on some of the modules in the package. This is still experimental.
2226 default: False
@@ -37,40 +41,51 @@ flag fast-weak
3741 default: False
3842 manual: True
3943
44+flag split-these
45+ description: Use split these/semialign packages
46+ manual: False
47+ default: True
48+
4049library
4150 hs-source-dirs: src
4251 build-depends:
4352 MemoTrie == 0.6.*,
4453 base >= 4.9 && < 4.13,
4554 bifunctors >= 5.2 && < 5.6,
46− comonad,
47− constraints-extras >= 0.2,
48− containers >= 0.5 && < 0.7,
55+ comonad >= 5.0.4 && < 5.1,
56+ constraints-extras >= 0.3 && < 0.4,
57+ containers >= 0.6 && < 0.7,
4958 data-default >= 0.5 && < 0.8,
5059 dependent-map >= 0.3 && < 0.4,
5160 exception-transformers == 0.4.*,
52− profunctors,
61+ profunctors >= 5.3 && < 5.5,
5362 lens >= 4.7 && < 5,
5463 monad-control >= 1.0.1 && < 1.1,
55− monoidal-containers >= 0.4 && < 0.6,
5664 mtl >= 2.1 && < 2.3,
5765 prim-uniq >= 0.1.0.1 && < 0.2,
58− primitive >= 0.5 && < 0.7,
66+ primitive >= 0.5 && < 0.8,
67+ profunctors,
5968 random == 1.1.*,
6069 ref-tf == 0.4.*,
6170 reflection == 2.1.*,
6271 semigroupoids >= 4.0 && < 6,
63− semigroups >= 0.16 && < 0.19,
6472 stm >= 2.4 && < 2.6,
6573 syb >= 0.5 && < 0.8,
66− these >= 0.4 && < 0.9,
6774 time >= 1.4 && < 1.9,
68− transformers >= 0.2,
69− transformers-compat >= 0.3,
75+ transformers >= 0.5.6.0 && < 0.6,
7076 unbounded-delays >= 0.1.0.0 && < 0.2,
71− witherable >= 0.2 && < 0.4
77+ witherable >= 0.3 && < 0.3.2
78+
79+ if flag(split-these)
80+ build-depends: these >= 1 && <1.1,
81+ semialign >=1 && <1.1,
82+ monoidal-containers >= 0.5.0.1 && < 0.6
83+ else
84+ build-depends: these >= 0.4 && <0.9,
85+ monoidal-containers == 0.5.0.0
7286
7387 exposed-modules:
88+ Control.Monad.ReaderIO
7489 Data.AppendMap,
7590 Data.FastMutableIntMap,
7691 Data.FastWeakBag,
@@ -144,7 +159,7 @@ library
144159 other-extensions: TemplateHaskell
145160 else
146161 build-depends:
147− dependent-sum == 0.6.*
162+ dependent-sum >= 0.6 && < 0.7
148163
149164 if flag(fast-weak) && impl(ghcjs)
150165 cpp-options: -DGHCJS_FAST_WEAK
@@ -161,14 +176,14 @@ test-suite semantics
161176 base,
162177 bifunctors,
163178 containers,
164− deepseq >= 1.3 && < 1.5,
179+ deepseq,
165180 dependent-map,
166181 dependent-sum,
167182 mtl,
168183 ref-tf,
169184 reflex,
170185 split,
171− transformers >= 0.3
186+ transformers
172187 other-modules:
173188 Reflex.Bench.Focused
174189 Reflex.Plan.Pure
@@ -187,7 +202,7 @@ test-suite CrossImpl
187202 containers,
188203 dependent-map,
189204 dependent-sum,
190− deepseq >= 1.3 && < 1.5,
205+ deepseq,
191206 mtl,
192207 transformers,
193208 ref-tf,
@@ -206,7 +221,7 @@ test-suite hlint
206221 , directory
207222 , filepath
208223 , filemanip
209− , hlint
224+ , hlint < 2.1 || >= 2.2.2
210225 if impl(ghcjs)
211226 buildable: False
212227
@@ -216,7 +231,7 @@ test-suite EventWriterT
216231 hs-source-dirs: test
217232 build-depends: base
218233 , containers
219− , deepseq >= 1.3 && < 1.5
234+ , deepseq
220235 , dependent-map
221236 , dependent-sum
222237 , lens
@@ -225,6 +240,10 @@ test-suite EventWriterT
225240 , transformers
226241 , reflex
227242 , ref-tf
243+
244+ if flag(split-these)
245+ build-depends: these-lens
246+
228247 other-modules:
229248 Reflex.Test
230249 Reflex.TestPlan
@@ -232,13 +251,14 @@ test-suite EventWriterT
232251 Reflex.Plan.Pure
233252 Test.Run
234253
254+
235255test-suite RequesterT
236256 type: exitcode-stdio-1.0
237257 main-is: RequesterT.hs
238258 hs-source-dirs: test
239259 build-depends: base
240260 , containers
241− , deepseq >= 1.3 && < 1.5
261+ , deepseq
242262 , dependent-sum
243263 , dependent-map
244264 , lens
@@ -247,9 +267,14 @@ test-suite RequesterT
247267 , transformers
248268 , reflex
249269 , ref-tf
270+
271+ if flag(split-these)
272+ build-depends: these-lens
273+
250274 other-modules:
251275 Reflex.TestPlan
252276 Reflex.Plan.Pure
277+ Test.Run
253278
254279test-suite QueryT
255280 type: exitcode-stdio-1.0
@@ -259,15 +284,18 @@ test-suite QueryT
259284 , containers
260285 , dependent-map
261286 , dependent-sum
262− , deepseq >= 1.3 && < 1.5
287+ , deepseq
263288 , lens
264289 , monoidal-containers
265290 , mtl
266291 , ref-tf
267292 , reflex
268− , semigroups
269293 , these
270294 , transformers
295+
296+ if flag(split-these)
297+ build-depends: semialign, these-lens
298+
271299 other-modules:
272300 Test.Run
273301 Reflex.TestPlan
@@ -282,14 +310,16 @@ test-suite GC-Semantics
282310 , containers
283311 , dependent-sum
284312 , dependent-map
285− , deepseq >= 1.3 && < 1.5
313+ , deepseq
286314 , mtl
287315 , these
288316 , transformers
289317 , reflex
290318 , ref-tf
291− if impl(ghc < 8)
292− build-depends: semigroups
319+
320+ if flag(split-these)
321+ build-depends: semialign
322+
293323 other-modules:
294324 Reflex.Plan.Pure
295325 Reflex.Plan.Reflex
@@ -302,7 +332,7 @@ test-suite rootCleanup
302332 hs-source-dirs: test
303333 build-depends: base
304334 , containers
305− , deepseq >= 1.3 && < 1.5
335+ , deepseq
306336 , dependent-sum
307337 , mtl
308338 , reflex
@@ -321,8 +351,8 @@ benchmark spider-bench
321351 build-depends:
322352 base,
323353 containers,
324− criterion >= 1.1 && < 1.6,
325− deepseq >= 1.3 && < 1.5,
354+ criterion,
355+ deepseq,
326356 dependent-map,
327357 dependent-sum,
328358 ref-tf,
@@ -331,7 +361,7 @@ benchmark spider-bench
331361 reflex,
332362 split,
333363 stm,
334− transformers >= 0.3
364+ transformers
335365 other-modules:
336366 Reflex.TestPlan
337367 Reflex.Plan.Reflex
@@ -345,9 +375,9 @@ benchmark saulzar-bench
345375 ghc-options: -Wall -O2 -rtsopts -threaded
346376 build-depends:
347377 base,
348− containers >= 0.5 && < 0.7,
349− criterion >= 1.1 && < 1.6,
350− deepseq >= 1.3 && < 1.5,
378+ containers,
379+ criterion,
380+ deepseq,
351381 dependent-map,
352382 dependent-sum,
353383 loch-th,
@@ -359,7 +389,7 @@ benchmark saulzar-bench
359389 split,
360390 stm,
361391 time,
362− transformers >= 0.3
392+ transformers
363393 other-modules:
364394 Reflex.TestPlan
365395 Reflex.Plan.Reflex
release.nix+4−4
@@ -3,7 +3,7 @@
33let
44 inherit (rp.nixpkgs) lib;
55 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−})
6+in lib.attrValues (lib.genAttrs compilers (ghc: {
7+ reflex-useTemplateHaskell = rp.${ghc}.callPackage ./. { useTemplateHaskell = true; splitThese = false; };
8+ reflex = rp.${ghc}.callPackage ./. { useTemplateHaskell = false; splitThese = false; };
9+}))
src/Control/Monad/ReaderIO.hsnew file+60
@@ -0,0 +1,60 @@
1+{-# language RoleAnnotations #-}
2+{-# language MultiParamTypeClasses #-}
3+{-# language FlexibleInstances #-}
4+{-# language CPP #-}
5+module Control.Monad.ReaderIO
6+ (
7+ ReaderIO (..)
8+ )
9+ where
10+
11+import Control.Monad.Fix
12+#if MIN_VERSION_base(4,10,0)
13+import Control.Applicative
14+#endif
15+import Control.Monad
16+import Control.Monad.Reader.Class
17+import Control.Monad.IO.Class
18+
19+-- | An approximate clone of @RIO@ from the @rio@ package, but not based on
20+-- @ReaderT@. The trouble with @ReaderT@ is that its third type argument has a
21+-- @nominal@ role, so we can't coerce through it when it's wrapped in some
22+-- other @data@ type. Ugh.
23+newtype ReaderIO e a = ReaderIO { runReaderIO :: e -> IO a }
24+type role ReaderIO representational representational
25+
26+instance Functor (ReaderIO e) where
27+ fmap = liftM
28+ {-# INLINE fmap #-}
29+ a <$ m = m >> pure a
30+ {-# INLINE (<$) #-}
31+
32+instance Applicative (ReaderIO e) where
33+ pure a = ReaderIO $ \_ -> pure a
34+ {-# INLINE pure #-}
35+ (<*>) = ap
36+ {-# INLINE (<*>) #-}
37+#if MIN_VERSION_base(4,10,0)
38+ liftA2 = liftM2
39+ {-# INLINE liftA2 #-}
40+#endif
41+ (*>) = (>>)
42+ {-# INLINE (*>) #-}
43+
44+instance Monad (ReaderIO e) where
45+ ReaderIO q >>= f = ReaderIO $ \e -> q e >>= \a -> runReaderIO (f a) e
46+ {-# INLINE (>>=) #-}
47+
48+instance MonadFix (ReaderIO e) where
49+ mfix f = ReaderIO $ \e -> mfix $ \r -> runReaderIO (f r) e
50+ {-# INLINE mfix #-}
51+
52+instance MonadIO (ReaderIO e) where
53+ liftIO m = ReaderIO $ \_ -> m
54+ {-# INLINE liftIO #-}
55+
56+instance MonadReader e (ReaderIO e) where
57+ ask = ReaderIO pure
58+ {-# INLINE ask #-}
59+ local f (ReaderIO m) = ReaderIO (m . f)
60+ {-# INLINE local #-}
src/Data/AppendMap.hs+2
@@ -46,8 +46,10 @@ _unAppendMap = getMonoidalMap
4646pattern AppendMap :: Map k v -> MonoidalMap k v
4747pattern AppendMap m = MonoidalMap m
4848
49+#if !MIN_VERSION_witherable(0,3,2)
4950instance W.Filterable (MonoidalMap k) where
5051 mapMaybe = mapMaybe
52+#endif
5153
5254-- | Deletes a key, returning 'Nothing' if the result is empty.
5355nonEmptyDelete :: Ord k => k -> MonoidalMap k a -> Maybe (MonoidalMap k a)
src/Data/Functor/Misc.hs−1
@@ -4,7 +4,6 @@
44{-# LANGUAGE FlexibleContexts #-}
55{-# LANGUAGE FlexibleInstances #-}
66{-# LANGUAGE GADTs #-}
7−{-# LANGUAGE KindSignatures #-}
87{-# LANGUAGE LambdaCase #-}
98{-# LANGUAGE MultiParamTypeClasses #-}
109{-# LANGUAGE PatternSynonyms #-}
src/Reflex/Adjustable/Class.hs−1
@@ -3,7 +3,6 @@
33{-# LANGUAGE FlexibleInstances #-}
44{-# LANGUAGE FunctionalDependencies #-}
55{-# LANGUAGE LambdaCase #-}
6−{-# LANGUAGE MultiParamTypeClasses #-}
76{-# LANGUAGE RankNTypes #-}
87{-# LANGUAGE ScopedTypeVariables #-}
98{-# LANGUAGE TypeFamilies #-}
src/Reflex/BehaviorWriter/Class.hs−1
@@ -5,7 +5,6 @@ Description: This module defines the 'MonadBehaviorWriter' class
55{-# LANGUAGE CPP #-}
66{-# LANGUAGE FlexibleInstances #-}
77{-# LANGUAGE FunctionalDependencies #-}
8−{-# LANGUAGE MultiParamTypeClasses #-}
98{-# LANGUAGE UndecidableInstances #-}
109#ifdef USE_REFLEX_OPTIMIZER
1110{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
src/Reflex/Class.hs+28−15
@@ -7,7 +7,6 @@
77{-# LANGUAGE FunctionalDependencies #-}
88{-# LANGUAGE GADTs #-}
99{-# LANGUAGE LambdaCase #-}
10−{-# LANGUAGE MultiParamTypeClasses #-}
1110{-# LANGUAGE NoMonomorphismRestriction #-}
1211{-# LANGUAGE PolyKinds #-}
1312{-# LANGUAGE RankNTypes #-}
@@ -37,6 +36,7 @@ module Reflex.Class
3736 , coerceBehavior
3837 , coerceEvent
3938 , coerceDynamic
39+ , coerceIncremental
4040 , MonadSample (..)
4141 , MonadHold (..)
4242 -- ** 'fan' related types
@@ -173,6 +173,14 @@ module Reflex.Class
173173 , slowHeadE
174174 ) where
175175
176+#if defined(MIN_VERSION_semialign)
177+import Prelude hiding (zip, zipWith)
178+
179+#if MIN_VERSION_these(0,8,0)
180+import Data.These.Combinators (justThese)
181+#endif
182+#endif
183+
176184import Control.Applicative
177185import Control.Monad.Identity
178186import Control.Monad.Reader
@@ -312,6 +320,10 @@ class ( MonadHold t (PushM t)
312320 -- | Construct a 'Coercion' for a 'Dynamic' given an 'Coercion' for its
313321 -- occurrence type
314322 dynamicCoercion :: Coercion a b -> Coercion (Dynamic t a) (Dynamic t b)
323+ -- | Construct a 'Coercion' for an 'Incremental' given 'Coercion's for its
324+ -- patch target and patch types.
325+ incrementalCoercion
326+ :: Coercion (PatchTarget a) (PatchTarget b) -> Coercion a b -> Coercion (Incremental t a) (Incremental t b)
315327 mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a)
316328 fanInt :: Event t (IntMap a) -> EventSelectorInt t a
317329
@@ -345,6 +357,12 @@ coerceEvent = coerceWith $ eventCoercion Coercion
345357coerceDynamic :: (Reflex t, Coercible a b) => Dynamic t a -> Dynamic t b
346358coerceDynamic = coerceWith $ dynamicCoercion Coercion
347359
360+-- | Coerce an 'Incremental' between representationally-equivalent value types
361+coerceIncremental
362+ :: (Reflex t, Coercible a b, Coercible (PatchTarget a) (PatchTarget b))
363+ => Incremental t a -> Incremental t b
364+coerceIncremental = coerceWith $ incrementalCoercion Coercion Coercion
365+
348366-- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'. The 'Behavior'
349367-- __must__ change when and only when the 'Event' fires, such that the
350368-- 'Behavior''s value is always equal to the most recent firing of the 'Event';
@@ -669,11 +687,7 @@ instance (Num a, Reflex t) => Num (Dynamic t a) where
669687instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
670688 a <> b = pull $ liftM2 (<>) (sample a) (sample b)
671689 sconcat = pull . fmap sconcat . mapM sample
672−#if MIN_VERSION_semigroups(0,17,0)
673690 stimes n = fmap $ stimes n
674−#else
675− times1p n = fmap $ times1p n
676−#endif
677691
678692-- | Alias for 'mapMaybe'
679693fmapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b
@@ -700,9 +714,12 @@ filterRight = mapMaybe (either (const Nothing) Just)
700714instance Reflex t => Alt (Event t) where
701715 ev1 <!> ev2 = leftmost [ev1, ev2]
702716
703−-- | 'Event' intersection (convenient interface to 'coincidence').
717+-- | 'Event' intersection. Only occurs when both events are co-incident.
704718instance Reflex t => Apply (Event t) where
705− evf <.> evx = coincidence (fmap (<$> evx) evf)
719+ evf <.> evx = mapMaybe f (align evf evx) where
720+ f (These g a) = Just (g a)
721+ f _ = Nothing
722+
706723
707724-- | 'Event' intersection (convenient interface to 'coincidence').
708725instance Reflex t => Bind (Event t) where
@@ -871,11 +888,7 @@ traceEventWith f = push $ \x -> trace (f x) $ return $ Just x
871888instance (Semigroup a, Reflex t) => Semigroup (Event t a) where
872889 (<>) = alignWith (mergeThese (<>))
873890 sconcat = fmap sconcat . mergeList . toList
874−#if MIN_VERSION_semigroups(0,17,0)
875891 stimes n = fmap $ stimes n
876−#else
877− times1p n = fmap $ times1p n
878−#endif
879892
880893instance (Semigroup a, Reflex t) => Monoid (Event t a) where
881894 mempty = never
@@ -1064,6 +1077,10 @@ instance Reflex t => Semialign (Event t) where
10641077#endif
10651078 align = alignEventWithMaybe Just
10661079
1080+#if defined(MIN_VERSION_semialign)
1081+ zip x y = mapMaybe justThese $ align x y
1082+#endif
1083+
10671084
10681085-- | Create a new 'Event' that only occurs if the supplied 'Event' occurs and
10691086-- the 'Behavior' is true at the time of occurrence.
@@ -1104,11 +1121,7 @@ zipDynWith f da db =
11041121
11051122instance (Reflex t, Semigroup a) => Semigroup (Dynamic t a) where
11061123 (<>) = zipDynWith (<>)
1107−#if MIN_VERSION_semigroups(0,17,0)
11081124 stimes n = fmap $ stimes n
1109−#else
1110− times1p n = fmap $ times1p n
1111−#endif
11121125
11131126instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where
11141127 mconcat = distributeListOverDynWith mconcat
src/Reflex/Collection.hs+4
@@ -27,6 +27,10 @@ module Reflex.Collection
2727 , simpleList
2828 ) where
2929
30+#if defined(MIN_VERSION_semialign)
31+import Prelude hiding (zip, zipWith)
32+#endif
33+
3034import Control.Monad.Identity
3135import Data.Align
3236import Data.Functor.Misc
src/Reflex/Dynamic/TH.hs+1−1
@@ -81,7 +81,7 @@ mkDynPure = QuasiQuoter
8181 }
8282
8383mkDynExp :: String -> Q Exp
84−mkDynExp s = case Hs.parseExpWithMode (Hs.defaultParseMode { Hs.extensions = [ Hs.EnableExtension Hs.TemplateHaskell ] }) s of
84+mkDynExp s = case Hs.parseExpWithMode Hs.defaultParseMode { Hs.extensions = [ Hs.EnableExtension Hs.TemplateHaskell ] } s of
8585 Hs.ParseFailed (Hs.SrcLoc _ l c) err -> fail $ "mkDyn:" <> show l <> ":" <> show c <> ": " <> err
8686 Hs.ParseOk e -> qDynPure $ return $ everywhere (id `extT` reinstateUnqDyn) $ Hs.toExp $ everywhere (id `extT` antiE) e
8787 where TH.Name (TH.OccName occName) (TH.NameG _ _ (TH.ModName modName)) = 'unqMarker
src/Reflex/DynamicWriter/Class.hs−1
@@ -3,7 +3,6 @@
33{-# LANGUAGE CPP #-}
44{-# LANGUAGE FlexibleInstances #-}
55{-# LANGUAGE FunctionalDependencies #-}
6−{-# LANGUAGE MultiParamTypeClasses #-}
76{-# LANGUAGE UndecidableInstances #-}
87#ifdef USE_REFLEX_OPTIMIZER
98{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
src/Reflex/EventWriter/Base.hs+1−1
@@ -52,7 +52,7 @@ import qualified Data.Map as Map
5252import Data.Semigroup
5353import Data.Some (Some)
5454import Data.Tuple
55−import Data.Type.Equality hiding (apply)
55+import Data.Type.Equality
5656
5757import Unsafe.Coerce
5858
src/Reflex/EventWriter/Class.hs−1
@@ -2,7 +2,6 @@
22{-# LANGUAGE CPP #-}
33{-# LANGUAGE FlexibleInstances #-}
44{-# LANGUAGE FunctionalDependencies #-}
5−{-# LANGUAGE MultiParamTypeClasses #-}
65{-# LANGUAGE UndecidableInstances #-}
76#ifdef USE_REFLEX_OPTIMIZER
87{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
src/Reflex/Host/Class.hs−1
@@ -4,7 +4,6 @@
44{-# LANGUAGE FlexibleInstances #-}
55{-# LANGUAGE FunctionalDependencies #-}
66{-# LANGUAGE GADTs #-}
7−{-# LANGUAGE MultiParamTypeClasses #-}
87{-# LANGUAGE RankNTypes #-}
98{-# LANGUAGE RoleAnnotations #-}
109{-# LANGUAGE ScopedTypeVariables #-}
src/Reflex/NotReady/Class.hs−1
@@ -3,7 +3,6 @@
33{-# LANGUAGE FlexibleContexts #-}
44{-# LANGUAGE FlexibleInstances #-}
55{-# LANGUAGE FunctionalDependencies #-}
6−{-# LANGUAGE MultiParamTypeClasses #-}
76{-# LANGUAGE TypeFamilies #-}
87{-# LANGUAGE UndecidableInstances #-}
98#ifdef USE_REFLEX_OPTIMIZER
src/Reflex/Patch/IntMap.hs−8
@@ -1,4 +1,3 @@
1−{-# LANGUAGE CPP #-}
21{-# LANGUAGE DeriveFoldable #-}
32{-# LANGUAGE DeriveFunctor #-}
43{-# LANGUAGE DeriveTraversable #-}
@@ -33,14 +32,7 @@ instance Patch (PatchIntMap a) where
3332instance Semigroup (PatchIntMap v) where
3433 PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b --TODO: Add a semigroup instance for Map
3534 -- PatchMap is idempotent, so stimes n is id for every n
36−#if MIN_VERSION_semigroups(0,17,0)
3735 stimes = stimesIdempotentMonoid
38−#else
39− times1p n x = case compare n 0 of
40− LT -> error "stimesIdempotentMonoid: negative multiplier"
41− EQ -> mempty
42− GT -> x
43−#endif
4436
4537-- | Map a function @Int -> a -> b@ over all @a@s in the given @'PatchIntMap' a@
4638-- (that is, all inserts/updates), producing a @PatchIntMap b@.
src/Reflex/Patch/Map.hs−8
@@ -1,4 +1,3 @@
1−{-# LANGUAGE CPP #-}
21{-# LANGUAGE LambdaCase #-}
32{-# LANGUAGE TypeFamilies #-}
43-- | 'Patch'es on 'Map' that consist only of insertions (including overwrites)
@@ -35,14 +34,7 @@ instance Ord k => Patch (PatchMap k v) where
3534instance Ord k => Semigroup (PatchMap k v) where
3635 PatchMap a <> PatchMap b = PatchMap $ a `mappend` b --TODO: Add a semigroup instance for Map
3736 -- PatchMap is idempotent, so stimes n is id for every n
38−#if MIN_VERSION_semigroups(0,17,0)
3937 stimes = stimesIdempotentMonoid
40−#else
41− times1p n x = case compare n 0 of
42− LT -> error "stimesIdempotentMonoid: negative multiplier"
43− EQ -> mempty
44− GT -> x
45−#endif
4638
4739-- | The empty 'PatchMap' contains no insertions or deletions
4840instance Ord k => Monoid (PatchMap k v) where
src/Reflex/PerformEvent/Base.hs+1−1
@@ -141,7 +141,7 @@ hostPerformEventT a = do
141141 case mToPerform of
142142 Nothing -> return [result']
143143 Just toPerform -> do
144− responses <- runHostFrame $ traverseRequesterData (\v -> Identity <$> v) toPerform
144+ responses <- runHostFrame $ traverseRequesterData (Identity <$>) toPerform
145145 mrt <- readRef responseTrigger
146146 let followupEventTriggers = case mrt of
147147 Just rt -> [rt :=> Identity responses]
src/Reflex/PerformEvent/Class.hs−1
@@ -5,7 +5,6 @@
55{-# LANGUAGE FlexibleContexts #-}
66{-# LANGUAGE FlexibleInstances #-}
77{-# LANGUAGE FunctionalDependencies #-}
8−{-# LANGUAGE MultiParamTypeClasses #-}
98{-# LANGUAGE RankNTypes #-}
109{-# LANGUAGE ScopedTypeVariables #-}
1110{-# LANGUAGE TypeFamilies #-}
src/Reflex/PostBuild/Class.hs−1
@@ -4,7 +4,6 @@
44{-# LANGUAGE DataKinds #-}
55{-# LANGUAGE FlexibleInstances #-}
66{-# LANGUAGE FunctionalDependencies #-}
7−{-# LANGUAGE MultiParamTypeClasses #-}
87{-# LANGUAGE ScopedTypeVariables #-}
98{-# LANGUAGE TypeFamilies #-}
109{-# LANGUAGE TypeOperators #-}
src/Reflex/Profiled.hs+14−10
@@ -9,6 +9,7 @@
99{-# LANGUAGE TypeFamilies #-}
1010{-# LANGUAGE UndecidableInstances #-}
1111{-# LANGUAGE PolyKinds #-}
12+{-# LANGUAGE TypeApplications #-}
1213{-# LANGUAGE RankNTypes #-}
1314-- |
1415-- Module:
@@ -79,9 +80,9 @@ getCostCentreStack = go []
7980 go (cc : l) parent
8081
8182toCostCentreTree :: Ptr CostCentreStack -> Int -> IO CostCentreTree
82−toCostCentreTree ccs n = do
83− ccList <- getCostCentreStack ccs
84− return $ foldr (\cc child -> CostCentreTree 0 n $ Map.singleton cc child) (CostCentreTree n n mempty) ccList
83+toCostCentreTree ccs n =
84+ foldr (\cc child -> CostCentreTree 0 n $ Map.singleton cc child) (CostCentreTree n n mempty)
85+ <$> getCostCentreStack ccs
8586
8687getCostCentreTree :: IO CostCentreTree
8788getCostCentreTree = do
@@ -151,13 +152,16 @@ instance Reflex t => Reflex (ProfiledTimeline t) where
151152 currentIncremental (Incremental_Profiled i) = coerce $ currentIncremental i
152153 updatedIncremental (Incremental_Profiled i) = coerce $ profileEvent $ updatedIncremental i
153154 incrementalToDynamic (Incremental_Profiled i) = coerce $ incrementalToDynamic i
154− behaviorCoercion (c :: Coercion a b) = case behaviorCoercion c :: Coercion (Behavior t a) (Behavior t b) of
155− Coercion -> unsafeCoerce (Coercion :: Coercion (Behavior (ProfiledTimeline t) a) (Behavior (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce
156− eventCoercion (c :: Coercion a b) = case eventCoercion c :: Coercion (Event t a) (Event t b) of
157− Coercion -> unsafeCoerce (Coercion :: Coercion (Event (ProfiledTimeline t) a) (Event (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce
158− dynamicCoercion (c :: Coercion a b) = case dynamicCoercion c :: Coercion (Dynamic t a) (Dynamic t b) of
159− Coercion -> unsafeCoerce (Coercion :: Coercion (Dynamic (ProfiledTimeline t) a) (Dynamic (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce
160− mergeIntIncremental = Event_Profiled . mergeIntIncremental . (unsafeCoerce :: Incremental (ProfiledTimeline t) (PatchIntMap (Event (ProfiledTimeline t) a)) -> Incremental t (PatchIntMap (Event t a)))
155+ behaviorCoercion c =
156+ Coercion `trans` behaviorCoercion @t c `trans` Coercion
157+ eventCoercion c =
158+ Coercion `trans` eventCoercion @t c `trans` Coercion
159+ dynamicCoercion c =
160+ Coercion `trans` dynamicCoercion @t c `trans` Coercion
161+ incrementalCoercion c d =
162+ Coercion `trans` incrementalCoercion @t c d `trans` Coercion
163+ mergeIntIncremental = Event_Profiled . mergeIntIncremental .
164+ coerceWith (Coercion `trans` incrementalCoercion Coercion Coercion `trans` Coercion)
161165 fanInt (Event_Profiled e) = coerce $ fanInt $ profileEvent e
162166
163167deriving instance Functor (Dynamic t) => Functor (Dynamic (ProfiledTimeline t))
src/Reflex/Pure.hs+3−6
@@ -31,14 +31,9 @@ module Reflex.Pure
3131 , Incremental (..)
3232 ) where
3333
34−#if !MIN_VERSION_base(4,8,0)
35−import Control.Applicative
36−#endif
37−
3834import Control.Monad
3935import Data.Dependent.Map (DMap, GCompare)
4036import qualified Data.Dependent.Map as DMap
41−import Data.Functor.Identity
4237import Data.IntMap (IntMap)
4338import qualified Data.IntMap as IntMap
4439import Data.Maybe
@@ -93,7 +88,8 @@ instance (Enum t, HasTrie t, Ord t) => Reflex (Pure t) where
9388 then Nothing
9489 else Just currentOccurrences
9590
96− -- fanG :: GCompare k => Event (Pure t) (DMap k v) -> EventSelectorG (Pure t) k v
91+-- The instance signature doeesn't compile, leave commented for documentation
92+-- fanG :: GCompare k => Event (Pure t) (DMap k v) -> EventSelectorG (Pure t) k v
9793 fanG e = EventSelectorG $ \k -> Event $ \t -> unEvent e t >>= DMap.lookup k
9894
9995 switch :: Behavior (Pure t) (Event (Pure t) a) -> Event (Pure t) a
@@ -133,6 +129,7 @@ instance (Enum t, HasTrie t, Ord t) => Reflex (Pure t) where
133129 behaviorCoercion Coercion = Coercion
134130 eventCoercion Coercion = Coercion
135131 dynamicCoercion Coercion = Coercion
132+ incrementalCoercion Coercion Coercion = Coercion
136133
137134 fanInt e = EventSelectorInt $ \k -> Event $ \t -> unEvent e t >>= IntMap.lookup k
138135
src/Reflex/Query/Base.hs−1
@@ -1,7 +1,6 @@
11{-# LANGUAGE FlexibleInstances #-}
22{-# LANGUAGE GeneralizedNewtypeDeriving #-}
33{-# LANGUAGE InstanceSigs #-}
4−{-# LANGUAGE KindSignatures #-}
54{-# LANGUAGE LambdaCase #-}
65{-# LANGUAGE MultiParamTypeClasses #-}
76{-# LANGUAGE RankNTypes #-}
src/Reflex/Query/Class.hs−1
@@ -3,7 +3,6 @@
33{-# LANGUAGE FlexibleInstances #-}
44{-# LANGUAGE FunctionalDependencies #-}
55{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6−{-# LANGUAGE MultiParamTypeClasses #-}
76{-# LANGUAGE TypeFamilies #-}
87{-# LANGUAGE UndecidableInstances #-}
98-- |
src/Reflex/Requester/Class.hs−1
@@ -6,7 +6,6 @@
66{-# LANGUAGE CPP #-}
77{-# LANGUAGE FlexibleInstances #-}
88{-# LANGUAGE FunctionalDependencies #-}
9−{-# LANGUAGE MultiParamTypeClasses #-}
109{-# LANGUAGE RecursiveDo #-}
1110{-# LANGUAGE TypeFamilies #-}
1211{-# LANGUAGE UndecidableInstances #-}
src/Reflex/Spider/Internal.hs+78−49
@@ -9,7 +9,6 @@
99{-# LANGUAGE GADTs #-}
1010{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1111{-# LANGUAGE LambdaCase #-}
12−{-# LANGUAGE MultiParamTypeClasses #-}
1312{-# LANGUAGE MultiWayIf #-}
1413{-# LANGUAGE RankNTypes #-}
1514{-# LANGUAGE RoleAnnotations #-}
@@ -18,6 +17,8 @@
1817{-# LANGUAGE TypeOperators #-}
1918{-# LANGUAGE UndecidableInstances #-}
2019{-# LANGUAGE PolyKinds #-}
20+{-# LANGUAGE DeriveFunctor #-}
21+{-# LANGUAGE StandaloneDeriving #-}
2122{-# LANGUAGE InstanceSigs #-}
2223
2324#ifdef USE_REFLEX_OPTIMIZER
@@ -37,7 +38,10 @@ import Control.Monad hiding (forM, forM_, mapM, mapM_)
3738import Control.Monad.Exception
3839import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_)
3940import Control.Monad.Primitive
40−import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)
41+--import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)
42+import Control.Monad.Reader.Class
43+import Control.Monad.IO.Class
44+import Control.Monad.ReaderIO
4145import Control.Monad.Ref
4246import Data.Align
4347import Data.Coerce
@@ -68,6 +72,12 @@ import System.IO.Unsafe
6872import System.Mem.Weak
6973import Unsafe.Coerce
7074
75+#if defined(MIN_VERSION_semialign)
76+#if MIN_VERSION_these(0,8,0)
77+import Data.These.Combinators (justThese)
78+#endif
79+#endif
80+
7181#ifdef DEBUG_CYCLES
7282import Control.Monad.State hiding (forM, forM_, mapM, mapM_, sequence)
7383import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
@@ -545,6 +555,11 @@ propagateFast a subscribers = withIncreasedDepth $ do
545555toAny :: a -> Any
546556toAny = unsafeCoerce
547557
558+-- Why do we use Any here, instead of just giving eventSubscribedRetained an
559+-- existential type? Sadly, GHC does not currently know how to unbox types
560+-- with existentially quantified fields. So instead we just coerce values
561+-- to type Any on the way in. Since we never coerce them back, this is
562+-- perfectly safe.
548563data EventSubscribed x = EventSubscribed
549564 { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height)
550565 , eventSubscribedRetained :: {-# NOUNPACK #-} !Any
@@ -668,7 +683,7 @@ behaviorPull !p = Behavior $ do
668683 wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull"
669684 parentsRef <- liftIO $ newIORef []
670685 holdInits <- askBehaviorHoldInits
671− a <- liftIO $ runReaderT (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
686+ a <- liftIO $ runReaderIO (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
672687 invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator
673688 parents <- liftIO $ readIORef parentsRef
674689 let subscribed = PullSubscribed
@@ -703,42 +718,46 @@ readBehaviorUntracked b = do
703718-- Dynamic
704719--------------------------------------------------------------------------------
705720
706−data Dynamic x p = Dynamic
707− { dynamicCurrent :: !(Behavior x (PatchTarget p))
721+type DynamicS x p = Dynamic x (PatchTarget p) p
722+
723+data Dynamic x target p = Dynamic
724+ { dynamicCurrent :: !(Behavior x target)
708725 , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`?
709726 }
710727
711−dynamicHold :: Hold x p -> Dynamic x p
728+deriving instance (HasSpiderTimeline x) => Functor (Dynamic x target)
729+
730+
731+
732+
733+dynamicHold :: Hold x p -> DynamicS x p
712734dynamicHold !h = Dynamic
713735 { dynamicCurrent = behaviorHold h
714736 , dynamicUpdated = eventHold h
715737 }
716738
717−dynamicHoldIdentity :: Hold x (Identity a) -> Dynamic x (Identity a)
739+dynamicHoldIdentity :: Hold x (Identity a) -> DynamicS x (Identity a)
718740dynamicHoldIdentity = dynamicHold
719741
720−dynamicConst :: PatchTarget p -> Dynamic x p
742+dynamicConst :: PatchTarget p -> DynamicS x p
721743dynamicConst !a = Dynamic
722744 { dynamicCurrent = behaviorConst a
723745 , dynamicUpdated = eventNever
724746 }
725747
726−dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> Dynamic x p
748+dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> DynamicS x p
727749dynamicDyn !d = Dynamic
728750 { dynamicCurrent = behaviorDyn d
729751 , dynamicUpdated = eventDyn d
730752 }
731753
732−dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> Dynamic x (Identity a)
754+dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> DynamicS x (Identity a)
733755dynamicDynIdentity = dynamicDyn
734756
735757--------------------------------------------------------------------------------
736758-- Combinators
737759--------------------------------------------------------------------------------
738760
739−--TODO: Figure out why certain things are not 'representational', then make them
740−--representational so we can use coerce
741−
742761--type role Hold representational
743762data Hold x p
744763 = Hold { holdValue :: !(IORef (PatchTarget p))
@@ -759,20 +778,25 @@ globalSpiderTimelineEnv = unsafePerformIO unsafeNewSpiderTimelineEnv
759778
760779-- | Stores all global data relevant to a particular Spider timeline; only one
761780-- value should exist for each type @x@
762−data SpiderTimelineEnv x = SpiderTimelineEnv
781+newtype SpiderTimelineEnv x = STE {unSTE :: SpiderTimelineEnv' x}
782+-- We implement SpiderTimelineEnv with a newtype wrapper so
783+-- we can get the coercions we want safely.
784+type role SpiderTimelineEnv nominal
785+
786+data SpiderTimelineEnv' x = SpiderTimelineEnv
763787 { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ())
764788 , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x)
765789#ifdef DEBUG
766790 , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int)
767791#endif
768792 }
769−type role SpiderTimelineEnv nominal
793+type role SpiderTimelineEnv' phantom
770794
771795instance Eq (SpiderTimelineEnv x) where
772796 _ == _ = True -- Since only one exists of each type
773797
774798instance GEq SpiderTimelineEnv where
775− a `geq` b = if _spiderTimeline_lock a == _spiderTimeline_lock b
799+ a `geq` b = if _spiderTimeline_lock (unSTE a) == _spiderTimeline_lock (unSTE b)
776800 then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments
777801 else Nothing
778802
@@ -795,7 +819,7 @@ runEventM :: EventM x a -> IO a
795819runEventM = unEventM
796820
797821asksEventEnv :: forall x a. HasSpiderTimeline x => (EventEnv x -> a) -> EventM x a
798−asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
822+asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (unSTE (spiderTimeline :: SpiderTimelineEnv x))
799823
800824class MonadIO m => Defer a m where
801825 getDeferralQueue :: m (IORef [a])
@@ -933,9 +957,9 @@ getHoldEventSubscription h = do
933957
934958type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x])
935959
936−--type role BehaviorM representational
937960-- BehaviorM can sample behaviors
938−newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderT (BehaviorEnv x) IO a } deriving (Functor, Applicative, MonadIO, MonadFix)
961+newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderIO (BehaviorEnv x) a }
962+ deriving (Functor, Applicative, MonadIO, MonadFix, MonadReader (BehaviorEnv x))
939963
940964instance Monad (BehaviorM x) where
941965 {-# INLINE (>>=) #-}
@@ -1139,17 +1163,21 @@ instance HasSpiderTimeline x => Semialign (Event x) where
11391163 align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
11401164 DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
11411165
1166+#if defined(MIN_VERSION_semialign)
1167+ zip x y = mapMaybe justThese $ align x y
1168+#endif
1169+
11421170data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p)
11431171 | BuildDyn !(EventM x (PatchTarget p), Event x p)
11441172 | HoldDyn !(Hold x p)
11451173
11461174newtype Dyn (x :: Type) p = Dyn { unDyn :: IORef (DynType x p) }
11471175
1148−newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)
1176+newMapDyn :: HasSpiderTimeline x => (a -> b) -> DynamicS x (Identity a) -> DynamicS x (Identity b)
11491177newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
11501178
11511179--TODO: Avoid the duplication between this and R.zipDynWith
1152−zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c)
1180+zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> DynamicS x (Identity a) -> DynamicS x (Identity b) -> DynamicS x (Identity c)
11531181zipDynWith f da db =
11541182 let eab = align (dynamicUpdated da) (dynamicUpdated db)
11551183 ec = flip push eab $ \o -> do
@@ -1225,7 +1253,7 @@ run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> Res
12251253run roots after = do
12261254 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
12271255 let t = spiderTimeline :: SpiderTimelineEnv x
1228− result <- SpiderHost $ withMVar (_spiderTimeline_lock t) $ \_ -> unSpiderHost $ runFrame $ do
1256+ result <- SpiderHost $ withMVar (_spiderTimeline_lock (unSTE t)) $ \_ -> unSpiderHost $ runFrame $ do
12291257 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
12301258 occBefore <- liftIO $ do
12311259 occBefore <- readIORef occRef
@@ -1289,9 +1317,9 @@ type WeakList a = [Weak a]
12891317withIncreasedDepth :: CanTrace x m => m a -> m a
12901318withIncreasedDepth a = do
12911319 spiderTimeline <- askSpiderTimelineEnv
1292− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) succ
1320+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) succ
12931321 result <- a
1294− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) pred
1322+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) pred
12951323 return result
12961324#else
12971325withIncreasedDepth :: m a -> m a
@@ -1318,7 +1346,7 @@ traceMWhen _ b getMessage = when b $ do
13181346 message <- getMessage
13191347#ifdef DEBUG
13201348 spiderTimeline <- askSpiderTimelineEnv
1321− d <- liftIO $ readIORef $ _spiderTimeline_depth spiderTimeline
1349+ d <- liftIO $ readIORef $ _spiderTimeline_depth $ unSTE spiderTimeline
13221350#else
13231351 let d = 0
13241352#endif
@@ -1359,25 +1387,25 @@ propagateSubscriberHold h a = do
13591387data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset
13601388
13611389runBehaviorM :: BehaviorM x a -> Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]) -> IORef [SomeHoldInit x] -> IO a
1362−runBehaviorM a mwi holdInits = runReaderT (unBehaviorM a) (mwi, holdInits)
1390+runBehaviorM a mwi holdInits = runReaderIO (unBehaviorM a) (mwi, holdInits)
13631391
13641392askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x)))
13651393askInvalidator = do
1366− (!m, _) <- BehaviorM ask
1394+ (!m, _) <- ask
13671395 case m of
13681396 Nothing -> return Nothing
13691397 Just (!wi, _) -> return $ Just wi
13701398
13711399askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x]))
13721400askParentsRef = do
1373− (!m, _) <- BehaviorM ask
1401+ (!m, _) <- ask
13741402 case m of
13751403 Nothing -> return Nothing
13761404 Just (_, !p) -> return $ Just p
13771405
13781406askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x])
13791407askBehaviorHoldInits = do
1380− (_, !his) <- BehaviorM ask
1408+ (_, !his) <- ask
13811409 return his
13821410
13831411{-# INLINE getDynHold #-}
@@ -1701,20 +1729,20 @@ subscribeCoincidenceSubscribed subscribed sub = WeakBag.insert sub (coincidenceS
17011729{-# INLINE mergeG #-}
17021730mergeG :: forall k q x v. (HasSpiderTimeline x, GCompare k)
17031731 => (forall a. q a -> Event x (v a))
1704− -> Dynamic x (PatchDMap k q) -> Event x (DMap k v)
1732+ -> DynamicS x (PatchDMap k q) -> Event x (DMap k v)
17051733mergeG nt d = cacheEvent (mergeCheap nt d)
17061734
17071735{-# INLINE mergeWithMove #-}
17081736mergeWithMove :: forall k v q x. (HasSpiderTimeline x, GCompare k)
17091737 => (forall a. q a -> Event x (v a))
1710− -> Dynamic x (PatchDMapWithMove k q) -> Event x (DMap k v)
1738+ -> DynamicS x (PatchDMapWithMove k q) -> Event x (DMap k v)
17111739mergeWithMove nt d = cacheEvent (mergeCheapWithMove nt d)
17121740
17131741{-# INLINE [1] mergeCheap #-}
17141742mergeCheap
17151743 :: forall k x q v. (HasSpiderTimeline x, GCompare k)
17161744 => (forall a. q a -> Event x (v a))
1717− -> Dynamic x (PatchDMap k q)
1745+ -> DynamicS x (PatchDMap k q)
17181746 -> Event x (DMap k v)
17191747mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
17201748 where
@@ -1742,7 +1770,7 @@ mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
17421770 let s = subscriber $ return k
17431771 (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
17441772 height <- liftIO $ getEventSubscribedHeight parentSubd
1745− return (fmap (\x -> k :=> x) parentOcc, height, k :=> MergeSubscribedParent subscription)
1773+ return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParent subscription)
17461774 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
17471775 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
17481776 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
@@ -1754,7 +1782,7 @@ mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
17541782{-# INLINE [1] mergeCheapWithMove #-}
17551783mergeCheapWithMove :: forall k x v q. (HasSpiderTimeline x, GCompare k)
17561784 => (forall a. q a -> Event x (v a))
1757− -> Dynamic x (PatchDMapWithMove k q)
1785+ -> DynamicS x (PatchDMapWithMove k q)
17581786 -> Event x (DMap k v)
17591787mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy
17601788 where
@@ -1790,7 +1818,7 @@ mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy
17901818 let s = subscriber $ liftIO $ readIORef keyRef
17911819 (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
17921820 height <- liftIO $ getEventSubscribedHeight parentSubd
1793− return (fmap (\x -> k :=> x) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef)
1821+ return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef)
17941822 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
17951823 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
17961824 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
@@ -1902,7 +1930,7 @@ updateMerge m updateFunc p = SomeMergeUpdate updateMe (invalidateMergeHeight m)
19021930
19031931{-# INLINE mergeGCheap' #-}
19041932mergeGCheap' :: forall k v x p s q. (HasSpiderTimeline x, GCompare k, PatchTarget p ~ DMap k q)
1905− => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> Dynamic x p -> Event x (DMap k v)
1933+ => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> DynamicS x p -> Event x (DMap k v)
19061934mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
19071935 initialParents <- readBehaviorUntracked $ dynamicCurrent d
19081936 accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
@@ -1951,11 +1979,11 @@ mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
19511979 , occ
19521980 )
19531981
1954−mergeInt :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1982+mergeInt :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
19551983mergeInt = cacheEvent . mergeIntCheap
19561984
19571985{-# INLINABLE mergeIntCheap #-}
1958−mergeIntCheap :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1986+mergeIntCheap :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
19591987mergeIntCheap d = Event $ \sub -> do
19601988 initialParents <- readBehaviorUntracked $ dynamicCurrent d
19611989 accum <- liftIO $ FastMutableIntMap.newEmpty
@@ -2115,7 +2143,7 @@ clearEventEnv (EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeI
21152143-- | Run an event action outside of a frame
21162144runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
21172145runFrame a = SpiderHost $ do
2118− let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
2146+ let env = _spiderTimeline_eventEnv $ unSTE (spiderTimeline :: SpiderTimelineEnv x)
21192147 let go = do
21202148 result <- a
21212149 runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events
@@ -2326,7 +2354,7 @@ instance HasSpiderTimeline x => Monad (Reflex.Class.Dynamic (SpiderTimeline x))
23262354 fail _ = error "Dynamic does not support 'fail'"
23272355
23282356{-# INLINABLE newJoinDyn #-}
2329−newJoinDyn :: HasSpiderTimeline x => Reflex.Spider.Internal.Dynamic x (Identity (Reflex.Spider.Internal.Dynamic x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
2357+newJoinDyn :: HasSpiderTimeline x => DynamicS x (Identity (DynamicS x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
23302358newJoinDyn d =
23312359 let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d)
23322360 eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d
@@ -2476,7 +2504,7 @@ unsafeNewSpiderTimelineEnv = do
24762504#ifdef DEBUG
24772505 depthRef <- newIORef 0
24782506#endif
2479− return $ SpiderTimelineEnv
2507+ return $ STE $ SpiderTimelineEnv
24802508 { _spiderTimeline_lock = lock
24812509 , _spiderTimeline_eventEnv = env
24822510#ifdef DEBUG
@@ -2492,13 +2520,13 @@ data LocalSpiderTimeline (x :: Type) s
24922520
24932521instance Reifies s (SpiderTimelineEnv x) =>
24942522 HasSpiderTimeline (LocalSpiderTimeline x s) where
2495− spiderTimeline = localSpiderTimeline (Proxy :: Proxy s) $ reflect (Proxy :: Proxy s)
2523+ spiderTimeline = localSpiderTimeline Proxy $ reflect (Proxy :: Proxy s)
24962524
24972525localSpiderTimeline
2498− :: Proxy s
2526+ :: proxy s
24992527 -> SpiderTimelineEnv x
25002528 -> SpiderTimelineEnv (LocalSpiderTimeline x s)
2501−localSpiderTimeline _ = unsafeCoerce
2529+localSpiderTimeline _ = coerce
25022530
25032531-- | Pass a new timeline to the given function.
25042532withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r
@@ -2516,8 +2544,8 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
25162544 {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-}
25172545 newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
25182546 newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }
2519− newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: Dynamic x (Identity a) } -- deriving (Functor, Applicative, Monad)
2520− newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: Dynamic x p }
2547+ newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: DynamicS x (Identity a) } -- deriving (Functor, Applicative, Monad)
2548+ newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: DynamicS x p }
25212549 type PullM (SpiderTimeline x) = SpiderPullM x
25222550 type PushM (SpiderTimeline x) = SpiderPushM x
25232551 {-# INLINABLE never #-}
@@ -2546,7 +2574,7 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
25462574 {-# INLINABLE current #-}
25472575 current = SpiderBehavior . dynamicCurrent . unSpiderDynamic
25482576 {-# INLINABLE updated #-}
2549− updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic
2577+ updated = SpiderEvent #. dynamicUpdated .# fmap coerce . unSpiderDynamic
25502578 {-# INLINABLE unsafeBuildDynamic #-}
25512579 unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
25522580 {-# INLINABLE unsafeBuildIncremental #-}
@@ -2565,9 +2593,10 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
25652593 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
25662594 eventCoercion Coercion = Coercion
25672595 behaviorCoercion Coercion = Coercion
2568− dynamicCoercion = unsafeCoerce --TODO: How can we avoid this unsafeCoerce? This is safe only because we know how Identity works as a Patch instance
2596+ dynamicCoercion Coercion = Coercion
2597+ incrementalCoercion Coercion Coercion = Coercion
25692598 {-# INLINABLE mergeIntIncremental #-}
2570− mergeIntIncremental = SpiderEvent . mergeInt . (unsafeCoerce :: Dynamic x (PatchIntMap (R.Event (SpiderTimeline x) a)) -> Dynamic x (PatchIntMap (Event x a))) . unSpiderIncremental
2599+ mergeIntIncremental = SpiderEvent . mergeInt . coerce
25712600 {-# INLINABLE fanInt #-}
25722601 fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e))
25732602
src/Reflex/TriggerEvent/Class.hs−1
@@ -2,7 +2,6 @@
22-- new 'Event's that can be triggered from 'IO'.
33{-# LANGUAGE FlexibleInstances #-}
44{-# LANGUAGE FunctionalDependencies #-}
5−{-# LANGUAGE MultiParamTypeClasses #-}
65{-# LANGUAGE UndecidableInstances #-}
76module Reflex.TriggerEvent.Class
87 ( TriggerEvent (..)
test/EventWriterT.hs+6−4
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE BangPatterns #-}
23{-# LANGUAGE FlexibleContexts #-}
34{-# LANGUAGE GADTs #-}
@@ -13,6 +14,10 @@ import Data.Functor.Misc
1314import qualified Data.Map as M
1415import Data.These
1516
17+#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))
18+import Data.These.Lens
19+#endif
20+
1621import Reflex
1722import Reflex.EventWriter.Base
1823import Test.Run
@@ -48,16 +53,13 @@ unwrapApp x appIn = do
4853 return e
4954
5055testOrdering :: (Reflex t, Monad m) => Event t () -> EventWriterT t [Int] m ()
51−testOrdering pulse = do
52− forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse)
53− return ()
56+testOrdering pulse = forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse)
5457
5558testSimultaneous :: (Reflex t, Adjustable t m, MonadHold t m) => Event t (These () ()) -> EventWriterT t [Int] m ()
5659testSimultaneous pulse = do
5760 let e0 = fmapMaybe (^? here) pulse
5861 e1 = fmapMaybe (^? there) pulse
5962 forM_ [1,3..9] $ \i -> runWithReplace (tellEvent ([i] <$ e0)) $ ffor e1 $ \_ -> tellEvent ([i+1] <$ e0)
60− return ()
6163
6264-- | Test that a widget telling and event which fires at the same time it has been replaced
6365-- doesn't count along with the new widget.
test/QueryT.hs+4
@@ -19,6 +19,10 @@ import Data.Map.Monoidal (MonoidalMap)
1919import Data.Semigroup
2020import Data.These
2121
22+#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))
23+import Data.These.Lens
24+#endif
25+
2226import Reflex
2327import Reflex.Patch.MapWithMove
2428import Test.Run
test/Reflex/Bench/Focused.hs+12
@@ -130,6 +130,16 @@ mapDynChain = iterM (return . fmap (+1))
130130joinDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
131131joinDynChain = iterM (\d -> return $ join $ fmap (const d) d)
132132
133+holdDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
134+holdDynChain = iterM (\d -> sample (current d) >>= flip holdDyn (updated d))
135+
136+buildDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
137+buildDynChain = iterM (\d -> do
138+ let b = fmap (+1) (current d)
139+ e = fmap (*2) (updated d)
140+ buildDynamic (sample b) e)
141+
142+
133143combineDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
134144combineDynChain = iterM (\d -> return $ zipDynWith (+) d d)
135145
@@ -308,6 +318,8 @@ dynamics :: Word -> [(String, TestCase)]
308318dynamics n =
309319 [ testE "mapDynChain" $ fmap updated $ mapDynChain n =<< d
310320 , testE "joinDynChain" $ fmap updated $ joinDynChain n =<< d
321+ , testE "holdDynChain" $ fmap updated $ holdDynChain n =<< d
322+ , testE "buildDynChain" $ fmap updated $ buildDynChain n =<< d
311323 , testE "combineDynChain" $ fmap updated $ combineDynChain n =<< d
312324 , testE "dense mergeTree" $ fmap (updated . mergeTreeDyn 8) dense
313325 , testE "sparse mergeTree" $ fmap (updated . mergeTreeDyn 8) sparse
test/Reflex/Test/CrossImpl.hs+5
@@ -218,6 +218,11 @@ testCases =
218218 bb <- hold b $ pushAlways (const $ hold "asdf" eo) eo
219219 let b' = pull $ sample =<< sample bb
220220 return (b', e)
221+ , (,) "foldDynWhileFiring" $ TestCase (Map.singleton 0 "zxc", Map.fromList [(1, "qwer"), (2, "lkj")]) $ \(_, e) -> do
222+ d <- foldDyn (:) [] $
223+ pushAlways (\a -> foldDyn (:) [a] e) e
224+ let b = current (join (fmap distributeListOverDynPure d))
225+ return (b, e)
221226 , (,) "joinDyn" $ TestCase (Map.singleton 0 (0 :: Int), Map.fromList [(1, "qwer"), (2, "lkj")]) $ \(b, e) -> do
222227 bb <- hold "b" e
223228 bd <- hold never . fmap (const e) =<< headE e
test/RequesterT.hs+5
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE BangPatterns #-}
23{-# LANGUAGE FlexibleContexts #-}
34{-# LANGUAGE GADTs #-}
@@ -15,6 +16,10 @@ import Data.Functor.Misc
1516import qualified Data.Map as M
1617import Data.These
1718
19+#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))
20+import Data.These.Lens
21+#endif
22+
1823import Reflex
1924import Reflex.Requester.Base
2025import Reflex.Requester.Class
test/hlint.hs+1
@@ -22,6 +22,7 @@ main = do
2222 , "--ignore=Use unless"
2323 , "--ignore=Reduce duplication"
2424 , "--cpp-define=USE_TEMPLATE_HASKELL"
25+ , "--ignore=Use tuple-section"
2526 ]
2627 recurseInto = and <$> sequence
2728 [ fileType ==? Directory