on develop help sign in
Merge branch 'release/0.6.2.3' of github.com:reflex-frp/reflex
eb70babAli Abrar
.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
45
45
46Make 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!
46Make 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!
47
47
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+
48### Documentation
52### Documentation
49
53
50#### In the code
54#### In the code
ChangeLog.md+19−2
@@ -1,16 +1,33 @@
1# Revision history for reflex
1# Revision history for reflex
2
2
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+
3## 0.6.2.1
13## 0.6.2.1
4
14
5* Generalize `fan` to `fanG` to take a `DMap` with non-`Identity`
15* 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
7
23
8* Generalize merging functions:
24* Generalize merging functions:
9 `merge` to `mergeG`,
25 `merge` to `mergeG`,
10 `mergeIncremental` to `mergeIncrementalG`,
26 `mergeIncremental` to `mergeIncrementalG`,
11− `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`,
12 `mergeIncrementalWithMove` to `mergeIncrementalWithMoveG`.
27 `mergeIncrementalWithMove` to `mergeIncrementalWithMoveG`.
13
28
29+* Generalize distribute function:
30+ `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`,
14
31
15## 0.6.2.0
32## 0.6.2.0
16
33
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 @@
6, template-haskell , these, time, transformers
6, template-haskell , these, time, transformers
7, transformers-compat, unbounded-delays, prim-uniq
7, transformers-compat, unbounded-delays, prim-uniq
8, data-default, filepath, directory, filemanip, ghcjs-base
8, data-default, filepath, directory, filemanip, ghcjs-base
9−, monoidal-containers, witherable
9+, monoidal-containers, witherable, profunctors
10+, semialign ? null, splitThese ? (semialign != null)
10, useTemplateHaskell ? true
11, useTemplateHaskell ? true
11}:
12}:
12mkDerivation {
13mkDerivation {
13 pname = "reflex";
14 pname = "reflex";
14− version = "0.6.2.1";
15+ version = "0.6.2.3";
15 src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".git" "dist" ])) ./.;
16 src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".git" "dist" ])) ./.;
16 libraryHaskellDepends = [
17 libraryHaskellDepends = [
17 base bifunctors containers dependent-map dependent-sum
18 base bifunctors containers dependent-map dependent-sum
@@ -22,17 +23,20 @@ mkDerivation {
22 base bifunctors containers deepseq dependent-map dependent-sum
23 base bifunctors containers deepseq dependent-map dependent-sum
23 mtl ref-tf split transformers data-default
24 mtl ref-tf split transformers data-default
24 random time unbounded-delays monoidal-containers witherable
25 random time unbounded-delays monoidal-containers witherable
26+ profunctors
25 ] ++ (if ghc.isGhcjs or false then [
27 ] ++ (if ghc.isGhcjs or false then [
26 ghcjs-base
28 ghcjs-base
27 ] else []) ++ (if !useTemplateHaskell then [] else [
29 ] else []) ++ (if !useTemplateHaskell then [] else [
28 haskell-src-exts haskell-src-meta
30 haskell-src-exts haskell-src-meta
29− ]);
31+ ]) ++ (if splitThese then [
32+ semialign
33+ ] else []);
30 testHaskellDepends = if ghc.isGhcjs or false then [] else [
34 testHaskellDepends = if ghc.isGhcjs or false then [] else [
31 hlint filepath directory filemanip
35 hlint filepath directory filemanip
32 ];
36 ];
33− configureFlags = if useTemplateHaskell then [] else [
37+ configureFlags =
34− "-f-use-template-haskell"
38+ stdenv.lib.optional (!useTemplateHaskell) [ "-f-use-template-haskell" ] ++
35− ];
39+ stdenv.lib.optional (!splitThese) [ "-f-split-these" ];
36 homepage = "https://github.com/reflex-frp/reflex";
40 homepage = "https://github.com/reflex-frp/reflex";
37 description = "Higher-order Functional Reactive Programming";
41 description = "Higher-order Functional Reactive Programming";
38 license = stdenv.lib.licenses.bsd3;
42 license = stdenv.lib.licenses.bsd3;
reflex.cabal+62−32
@@ -1,5 +1,5 @@
1Name: reflex
1Name: reflex
2−Version: 0.6.2.1
2+Version: 0.6.2.3
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
@@ -17,6 +17,10 @@ extra-source-files:
17 Quickref.md
17 Quickref.md
18 ChangeLog.md
18 ChangeLog.md
19
19
20+tested-with:
21+ GHC ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.5,
22+ GHCJS ==8.4
23+
20flag use-reflex-optimizer
24flag use-reflex-optimizer
21 description: Use the GHC plugin Reflex.Optimizer on some of the modules in the package. This is still experimental.
25 description: Use the GHC plugin Reflex.Optimizer on some of the modules in the package. This is still experimental.
22 default: False
26 default: False
@@ -37,40 +41,51 @@ flag fast-weak
37 default: False
41 default: False
38 manual: True
42 manual: True
39
43
44+flag split-these
45+ description: Use split these/semialign packages
46+ manual: False
47+ default: True
48+
40library
49library
41 hs-source-dirs: src
50 hs-source-dirs: src
42 build-depends:
51 build-depends:
43 MemoTrie == 0.6.*,
52 MemoTrie == 0.6.*,
44 base >= 4.9 && < 4.13,
53 base >= 4.9 && < 4.13,
45 bifunctors >= 5.2 && < 5.6,
54 bifunctors >= 5.2 && < 5.6,
46− comonad,
55+ comonad >= 5.0.4 && < 5.1,
47− constraints-extras >= 0.2,
56+ constraints-extras >= 0.3 && < 0.4,
48− containers >= 0.5 && < 0.7,
57+ containers >= 0.6 && < 0.7,
49 data-default >= 0.5 && < 0.8,
58 data-default >= 0.5 && < 0.8,
50 dependent-map >= 0.3 && < 0.4,
59 dependent-map >= 0.3 && < 0.4,
51 exception-transformers == 0.4.*,
60 exception-transformers == 0.4.*,
52− profunctors,
61+ profunctors >= 5.3 && < 5.5,
53 lens >= 4.7 && < 5,
62 lens >= 4.7 && < 5,
54 monad-control >= 1.0.1 && < 1.1,
63 monad-control >= 1.0.1 && < 1.1,
55− monoidal-containers >= 0.4 && < 0.6,
56 mtl >= 2.1 && < 2.3,
64 mtl >= 2.1 && < 2.3,
57 prim-uniq >= 0.1.0.1 && < 0.2,
65 prim-uniq >= 0.1.0.1 && < 0.2,
58− primitive >= 0.5 && < 0.7,
66+ primitive >= 0.5 && < 0.8,
67+ profunctors,
59 random == 1.1.*,
68 random == 1.1.*,
60 ref-tf == 0.4.*,
69 ref-tf == 0.4.*,
61 reflection == 2.1.*,
70 reflection == 2.1.*,
62 semigroupoids >= 4.0 && < 6,
71 semigroupoids >= 4.0 && < 6,
63− semigroups >= 0.16 && < 0.19,
64 stm >= 2.4 && < 2.6,
72 stm >= 2.4 && < 2.6,
65 syb >= 0.5 && < 0.8,
73 syb >= 0.5 && < 0.8,
66− these >= 0.4 && < 0.9,
67 time >= 1.4 && < 1.9,
74 time >= 1.4 && < 1.9,
68− transformers >= 0.2,
75+ transformers >= 0.5.6.0 && < 0.6,
69− transformers-compat >= 0.3,
70 unbounded-delays >= 0.1.0.0 && < 0.2,
76 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
72
86
73 exposed-modules:
87 exposed-modules:
88+ Control.Monad.ReaderIO
74 Data.AppendMap,
89 Data.AppendMap,
75 Data.FastMutableIntMap,
90 Data.FastMutableIntMap,
76 Data.FastWeakBag,
91 Data.FastWeakBag,
@@ -144,7 +159,7 @@ library
144 other-extensions: TemplateHaskell
159 other-extensions: TemplateHaskell
145 else
160 else
146 build-depends:
161 build-depends:
147− dependent-sum == 0.6.*
162+ dependent-sum >= 0.6 && < 0.7
148
163
149 if flag(fast-weak) && impl(ghcjs)
164 if flag(fast-weak) && impl(ghcjs)
150 cpp-options: -DGHCJS_FAST_WEAK
165 cpp-options: -DGHCJS_FAST_WEAK
@@ -161,14 +176,14 @@ test-suite semantics
161 base,
176 base,
162 bifunctors,
177 bifunctors,
163 containers,
178 containers,
164− deepseq >= 1.3 && < 1.5,
179+ deepseq,
165 dependent-map,
180 dependent-map,
166 dependent-sum,
181 dependent-sum,
167 mtl,
182 mtl,
168 ref-tf,
183 ref-tf,
169 reflex,
184 reflex,
170 split,
185 split,
171− transformers >= 0.3
186+ transformers
172 other-modules:
187 other-modules:
173 Reflex.Bench.Focused
188 Reflex.Bench.Focused
174 Reflex.Plan.Pure
189 Reflex.Plan.Pure
@@ -187,7 +202,7 @@ test-suite CrossImpl
187 containers,
202 containers,
188 dependent-map,
203 dependent-map,
189 dependent-sum,
204 dependent-sum,
190− deepseq >= 1.3 && < 1.5,
205+ deepseq,
191 mtl,
206 mtl,
192 transformers,
207 transformers,
193 ref-tf,
208 ref-tf,
@@ -206,7 +221,7 @@ test-suite hlint
206 , directory
221 , directory
207 , filepath
222 , filepath
208 , filemanip
223 , filemanip
209− , hlint
224+ , hlint < 2.1 || >= 2.2.2
210 if impl(ghcjs)
225 if impl(ghcjs)
211 buildable: False
226 buildable: False
212
227
@@ -216,7 +231,7 @@ test-suite EventWriterT
216 hs-source-dirs: test
231 hs-source-dirs: test
217 build-depends: base
232 build-depends: base
218 , containers
233 , containers
219− , deepseq >= 1.3 && < 1.5
234+ , deepseq
220 , dependent-map
235 , dependent-map
221 , dependent-sum
236 , dependent-sum
222 , lens
237 , lens
@@ -225,6 +240,10 @@ test-suite EventWriterT
225 , transformers
240 , transformers
226 , reflex
241 , reflex
227 , ref-tf
242 , ref-tf
243+
244+ if flag(split-these)
245+ build-depends: these-lens
246+
228 other-modules:
247 other-modules:
229 Reflex.Test
248 Reflex.Test
230 Reflex.TestPlan
249 Reflex.TestPlan
@@ -232,13 +251,14 @@ test-suite EventWriterT
232 Reflex.Plan.Pure
251 Reflex.Plan.Pure
233 Test.Run
252 Test.Run
234
253
254+
235test-suite RequesterT
255test-suite RequesterT
236 type: exitcode-stdio-1.0
256 type: exitcode-stdio-1.0
237 main-is: RequesterT.hs
257 main-is: RequesterT.hs
238 hs-source-dirs: test
258 hs-source-dirs: test
239 build-depends: base
259 build-depends: base
240 , containers
260 , containers
241− , deepseq >= 1.3 && < 1.5
261+ , deepseq
242 , dependent-sum
262 , dependent-sum
243 , dependent-map
263 , dependent-map
244 , lens
264 , lens
@@ -247,9 +267,14 @@ test-suite RequesterT
247 , transformers
267 , transformers
248 , reflex
268 , reflex
249 , ref-tf
269 , ref-tf
270+
271+ if flag(split-these)
272+ build-depends: these-lens
273+
250 other-modules:
274 other-modules:
251 Reflex.TestPlan
275 Reflex.TestPlan
252 Reflex.Plan.Pure
276 Reflex.Plan.Pure
277+ Test.Run
253
278
254test-suite QueryT
279test-suite QueryT
255 type: exitcode-stdio-1.0
280 type: exitcode-stdio-1.0
@@ -259,15 +284,18 @@ test-suite QueryT
259 , containers
284 , containers
260 , dependent-map
285 , dependent-map
261 , dependent-sum
286 , dependent-sum
262− , deepseq >= 1.3 && < 1.5
287+ , deepseq
263 , lens
288 , lens
264 , monoidal-containers
289 , monoidal-containers
265 , mtl
290 , mtl
266 , ref-tf
291 , ref-tf
267 , reflex
292 , reflex
268− , semigroups
269 , these
293 , these
270 , transformers
294 , transformers
295+
296+ if flag(split-these)
297+ build-depends: semialign, these-lens
298+
271 other-modules:
299 other-modules:
272 Test.Run
300 Test.Run
273 Reflex.TestPlan
301 Reflex.TestPlan
@@ -282,14 +310,16 @@ test-suite GC-Semantics
282 , containers
310 , containers
283 , dependent-sum
311 , dependent-sum
284 , dependent-map
312 , dependent-map
285− , deepseq >= 1.3 && < 1.5
313+ , deepseq
286 , mtl
314 , mtl
287 , these
315 , these
288 , transformers
316 , transformers
289 , reflex
317 , reflex
290 , ref-tf
318 , ref-tf
291− if impl(ghc < 8)
319+
320+ if flag(split-these)
292− build-depends: semigroups
321+ build-depends: semialign
322+
293 other-modules:
323 other-modules:
294 Reflex.Plan.Pure
324 Reflex.Plan.Pure
295 Reflex.Plan.Reflex
325 Reflex.Plan.Reflex
@@ -302,7 +332,7 @@ test-suite rootCleanup
302 hs-source-dirs: test
332 hs-source-dirs: test
303 build-depends: base
333 build-depends: base
304 , containers
334 , containers
305− , deepseq >= 1.3 && < 1.5
335+ , deepseq
306 , dependent-sum
336 , dependent-sum
307 , mtl
337 , mtl
308 , reflex
338 , reflex
@@ -321,8 +351,8 @@ benchmark spider-bench
321 build-depends:
351 build-depends:
322 base,
352 base,
323 containers,
353 containers,
324− criterion >= 1.1 && < 1.6,
354+ criterion,
325− deepseq >= 1.3 && < 1.5,
355+ deepseq,
326 dependent-map,
356 dependent-map,
327 dependent-sum,
357 dependent-sum,
328 ref-tf,
358 ref-tf,
@@ -331,7 +361,7 @@ benchmark spider-bench
331 reflex,
361 reflex,
332 split,
362 split,
333 stm,
363 stm,
334− transformers >= 0.3
364+ transformers
335 other-modules:
365 other-modules:
336 Reflex.TestPlan
366 Reflex.TestPlan
337 Reflex.Plan.Reflex
367 Reflex.Plan.Reflex
@@ -345,9 +375,9 @@ benchmark saulzar-bench
345 ghc-options: -Wall -O2 -rtsopts -threaded
375 ghc-options: -Wall -O2 -rtsopts -threaded
346 build-depends:
376 build-depends:
347 base,
377 base,
348− containers >= 0.5 && < 0.7,
378+ containers,
349− criterion >= 1.1 && < 1.6,
379+ criterion,
350− deepseq >= 1.3 && < 1.5,
380+ deepseq,
351 dependent-map,
381 dependent-map,
352 dependent-sum,
382 dependent-sum,
353 loch-th,
383 loch-th,
@@ -359,7 +389,7 @@ benchmark saulzar-bench
359 split,
389 split,
360 stm,
390 stm,
361 time,
391 time,
362− transformers >= 0.3
392+ transformers
363 other-modules:
393 other-modules:
364 Reflex.TestPlan
394 Reflex.TestPlan
365 Reflex.Plan.Reflex
395 Reflex.Plan.Reflex
release.nix+4−4
@@ -3,7 +3,7 @@
3let
3let
4 inherit (rp.nixpkgs) lib;
4 inherit (rp.nixpkgs) lib;
5 compilers = ["ghc8_4" "ghc8_0" "ghcjs8_4" "ghcjs8_0"];
5 compilers = ["ghc8_4" "ghc8_0" "ghcjs8_4" "ghcjs8_0"];
6−in lib.genAttrs compilers (ghc: {
6+in lib.attrValues (lib.genAttrs compilers (ghc: {
7− reflex-useTemplateHaskell = rp.${ghc}.callPackage ./. { useTemplateHaskell = true; };
7+ reflex-useTemplateHaskell = rp.${ghc}.callPackage ./. { useTemplateHaskell = true; splitThese = false; };
8− reflex = rp.${ghc}.callPackage ./. { useTemplateHaskell = false; };
8+ reflex = rp.${ghc}.callPackage ./. { useTemplateHaskell = false; splitThese = false; };
9−})
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
46pattern AppendMap :: Map k v -> MonoidalMap k v
46pattern AppendMap :: Map k v -> MonoidalMap k v
47pattern AppendMap m = MonoidalMap m
47pattern AppendMap m = MonoidalMap m
48
48
49+#if !MIN_VERSION_witherable(0,3,2)
49instance W.Filterable (MonoidalMap k) where
50instance W.Filterable (MonoidalMap k) where
50 mapMaybe = mapMaybe
51 mapMaybe = mapMaybe
52+#endif
51
53
52-- | Deletes a key, returning 'Nothing' if the result is empty.
54-- | Deletes a key, returning 'Nothing' if the result is empty.
53nonEmptyDelete :: Ord k => k -> MonoidalMap k a -> Maybe (MonoidalMap k a)
55nonEmptyDelete :: Ord k => k -> MonoidalMap k a -> Maybe (MonoidalMap k a)
src/Data/Functor/Misc.hs−1
@@ -4,7 +4,6 @@
4{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE GADTs #-}
6{-# LANGUAGE GADTs #-}
7−{-# LANGUAGE KindSignatures #-}
8{-# LANGUAGE LambdaCase #-}
7{-# LANGUAGE LambdaCase #-}
9{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE MultiParamTypeClasses #-}
10{-# LANGUAGE PatternSynonyms #-}
9{-# LANGUAGE PatternSynonyms #-}
src/Reflex/Adjustable/Class.hs−1
@@ -3,7 +3,6 @@
3{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FunctionalDependencies #-}
4{-# LANGUAGE FunctionalDependencies #-}
5{-# LANGUAGE LambdaCase #-}
5{-# LANGUAGE LambdaCase #-}
6−{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE RankNTypes #-}
6{-# LANGUAGE RankNTypes #-}
8{-# LANGUAGE ScopedTypeVariables #-}
7{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE TypeFamilies #-}
src/Reflex/BehaviorWriter/Class.hs−1
@@ -5,7 +5,6 @@ Description: This module defines the 'MonadBehaviorWriter' class
5{-# LANGUAGE CPP #-}
5{-# LANGUAGE CPP #-}
6{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE FunctionalDependencies #-}
7{-# LANGUAGE FunctionalDependencies #-}
8−{-# LANGUAGE MultiParamTypeClasses #-}
9{-# LANGUAGE UndecidableInstances #-}
8{-# LANGUAGE UndecidableInstances #-}
10#ifdef USE_REFLEX_OPTIMIZER
9#ifdef USE_REFLEX_OPTIMIZER
11{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
10{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
src/Reflex/Class.hs+28−15
@@ -7,7 +7,6 @@
7{-# LANGUAGE FunctionalDependencies #-}
7{-# LANGUAGE FunctionalDependencies #-}
8{-# LANGUAGE GADTs #-}
8{-# LANGUAGE GADTs #-}
9{-# LANGUAGE LambdaCase #-}
9{-# LANGUAGE LambdaCase #-}
10−{-# LANGUAGE MultiParamTypeClasses #-}
11{-# LANGUAGE NoMonomorphismRestriction #-}
10{-# LANGUAGE NoMonomorphismRestriction #-}
12{-# LANGUAGE PolyKinds #-}
11{-# LANGUAGE PolyKinds #-}
13{-# LANGUAGE RankNTypes #-}
12{-# LANGUAGE RankNTypes #-}
@@ -37,6 +36,7 @@ module Reflex.Class
37 , coerceBehavior
36 , coerceBehavior
38 , coerceEvent
37 , coerceEvent
39 , coerceDynamic
38 , coerceDynamic
39+ , coerceIncremental
40 , MonadSample (..)
40 , MonadSample (..)
41 , MonadHold (..)
41 , MonadHold (..)
42 -- ** 'fan' related types
42 -- ** 'fan' related types
@@ -173,6 +173,14 @@ module Reflex.Class
173 , slowHeadE
173 , slowHeadE
174 ) where
174 ) where
175
175
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+
176import Control.Applicative
184import Control.Applicative
177import Control.Monad.Identity
185import Control.Monad.Identity
178import Control.Monad.Reader
186import Control.Monad.Reader
@@ -312,6 +320,10 @@ class ( MonadHold t (PushM t)
312 -- | Construct a 'Coercion' for a 'Dynamic' given an 'Coercion' for its
320 -- | Construct a 'Coercion' for a 'Dynamic' given an 'Coercion' for its
313 -- occurrence type
321 -- occurrence type
314 dynamicCoercion :: Coercion a b -> Coercion (Dynamic t a) (Dynamic t b)
322 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)
315 mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a)
327 mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a)
316 fanInt :: Event t (IntMap a) -> EventSelectorInt t a
328 fanInt :: Event t (IntMap a) -> EventSelectorInt t a
317
329
@@ -345,6 +357,12 @@ coerceEvent = coerceWith $ eventCoercion Coercion
345coerceDynamic :: (Reflex t, Coercible a b) => Dynamic t a -> Dynamic t b
357coerceDynamic :: (Reflex t, Coercible a b) => Dynamic t a -> Dynamic t b
346coerceDynamic = coerceWith $ dynamicCoercion Coercion
358coerceDynamic = coerceWith $ dynamicCoercion Coercion
347
359
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+
348-- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'. The 'Behavior'
366-- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'. The 'Behavior'
349-- __must__ change when and only when the 'Event' fires, such that the
367-- __must__ change when and only when the 'Event' fires, such that the
350-- 'Behavior''s value is always equal to the most recent firing of the 'Event';
368-- '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
669instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
687instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
670 a <> b = pull $ liftM2 (<>) (sample a) (sample b)
688 a <> b = pull $ liftM2 (<>) (sample a) (sample b)
671 sconcat = pull . fmap sconcat . mapM sample
689 sconcat = pull . fmap sconcat . mapM sample
672−#if MIN_VERSION_semigroups(0,17,0)
673 stimes n = fmap $ stimes n
690 stimes n = fmap $ stimes n
674−#else
675− times1p n = fmap $ times1p n
676−#endif
677
691
678-- | Alias for 'mapMaybe'
692-- | Alias for 'mapMaybe'
679fmapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b
693fmapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b
@@ -700,9 +714,12 @@ filterRight = mapMaybe (either (const Nothing) Just)
700instance Reflex t => Alt (Event t) where
714instance Reflex t => Alt (Event t) where
701 ev1 <!> ev2 = leftmost [ev1, ev2]
715 ev1 <!> ev2 = leftmost [ev1, ev2]
702
716
703−-- | 'Event' intersection (convenient interface to 'coincidence').
717+-- | 'Event' intersection. Only occurs when both events are co-incident.
704instance Reflex t => Apply (Event t) where
718instance 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+
706
723
707-- | 'Event' intersection (convenient interface to 'coincidence').
724-- | 'Event' intersection (convenient interface to 'coincidence').
708instance Reflex t => Bind (Event t) where
725instance Reflex t => Bind (Event t) where
@@ -871,11 +888,7 @@ traceEventWith f = push $ \x -> trace (f x) $ return $ Just x
871instance (Semigroup a, Reflex t) => Semigroup (Event t a) where
888instance (Semigroup a, Reflex t) => Semigroup (Event t a) where
872 (<>) = alignWith (mergeThese (<>))
889 (<>) = alignWith (mergeThese (<>))
873 sconcat = fmap sconcat . mergeList . toList
890 sconcat = fmap sconcat . mergeList . toList
874−#if MIN_VERSION_semigroups(0,17,0)
875 stimes n = fmap $ stimes n
891 stimes n = fmap $ stimes n
876−#else
877− times1p n = fmap $ times1p n
878−#endif
879
892
880instance (Semigroup a, Reflex t) => Monoid (Event t a) where
893instance (Semigroup a, Reflex t) => Monoid (Event t a) where
881 mempty = never
894 mempty = never
@@ -1064,6 +1077,10 @@ instance Reflex t => Semialign (Event t) where
1064#endif
1077#endif
1065 align = alignEventWithMaybe Just
1078 align = alignEventWithMaybe Just
1066
1079
1080+#if defined(MIN_VERSION_semialign)
1081+ zip x y = mapMaybe justThese $ align x y
1082+#endif
1083+
1067
1084
1068-- | Create a new 'Event' that only occurs if the supplied 'Event' occurs and
1085-- | Create a new 'Event' that only occurs if the supplied 'Event' occurs and
1069-- the 'Behavior' is true at the time of occurrence.
1086-- the 'Behavior' is true at the time of occurrence.
@@ -1104,11 +1121,7 @@ zipDynWith f da db =
1104
1121
1105instance (Reflex t, Semigroup a) => Semigroup (Dynamic t a) where
1122instance (Reflex t, Semigroup a) => Semigroup (Dynamic t a) where
1106 (<>) = zipDynWith (<>)
1123 (<>) = zipDynWith (<>)
1107−#if MIN_VERSION_semigroups(0,17,0)
1108 stimes n = fmap $ stimes n
1124 stimes n = fmap $ stimes n
1109−#else
1110− times1p n = fmap $ times1p n
1111−#endif
1112
1125
1113instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where
1126instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where
1114 mconcat = distributeListOverDynWith mconcat
1127 mconcat = distributeListOverDynWith mconcat
src/Reflex/Collection.hs+4
@@ -27,6 +27,10 @@ module Reflex.Collection
27 , simpleList
27 , simpleList
28 ) where
28 ) where
29
29
30+#if defined(MIN_VERSION_semialign)
31+import Prelude hiding (zip, zipWith)
32+#endif
33+
30import Control.Monad.Identity
34import Control.Monad.Identity
31import Data.Align
35import Data.Align
32import Data.Functor.Misc
36import Data.Functor.Misc
src/Reflex/Dynamic/TH.hs+1−1
@@ -81,7 +81,7 @@ mkDynPure = QuasiQuoter
81 }
81 }
82
82
83mkDynExp :: String -> Q Exp
83mkDynExp :: 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
85 Hs.ParseFailed (Hs.SrcLoc _ l c) err -> fail $ "mkDyn:" <> show l <> ":" <> show c <> ": " <> err
85 Hs.ParseFailed (Hs.SrcLoc _ l c) err -> fail $ "mkDyn:" <> show l <> ":" <> show c <> ": " <> err
86 Hs.ParseOk e -> qDynPure $ return $ everywhere (id `extT` reinstateUnqDyn) $ Hs.toExp $ everywhere (id `extT` antiE) e
86 Hs.ParseOk e -> qDynPure $ return $ everywhere (id `extT` reinstateUnqDyn) $ Hs.toExp $ everywhere (id `extT` antiE) e
87 where TH.Name (TH.OccName occName) (TH.NameG _ _ (TH.ModName modName)) = 'unqMarker
87 where TH.Name (TH.OccName occName) (TH.NameG _ _ (TH.ModName modName)) = 'unqMarker
src/Reflex/DynamicWriter/Class.hs−1
@@ -3,7 +3,6 @@
3{-# LANGUAGE CPP #-}
3{-# LANGUAGE CPP #-}
4{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FunctionalDependencies #-}
5{-# LANGUAGE FunctionalDependencies #-}
6−{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE UndecidableInstances #-}
6{-# LANGUAGE UndecidableInstances #-}
8#ifdef USE_REFLEX_OPTIMIZER
7#ifdef USE_REFLEX_OPTIMIZER
9{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
8{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
src/Reflex/EventWriter/Base.hs+1−1
@@ -52,7 +52,7 @@ import qualified Data.Map as Map
52import Data.Semigroup
52import Data.Semigroup
53import Data.Some (Some)
53import Data.Some (Some)
54import Data.Tuple
54import Data.Tuple
55−import Data.Type.Equality hiding (apply)
55+import Data.Type.Equality
56
56
57import Unsafe.Coerce
57import Unsafe.Coerce
58
58
src/Reflex/EventWriter/Class.hs−1
@@ -2,7 +2,6 @@
2{-# LANGUAGE CPP #-}
2{-# LANGUAGE CPP #-}
3{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FunctionalDependencies #-}
4{-# LANGUAGE FunctionalDependencies #-}
5−{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE UndecidableInstances #-}
5{-# LANGUAGE UndecidableInstances #-}
7#ifdef USE_REFLEX_OPTIMIZER
6#ifdef USE_REFLEX_OPTIMIZER
8{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
7{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
src/Reflex/Host/Class.hs−1
@@ -4,7 +4,6 @@
4{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FunctionalDependencies #-}
5{-# LANGUAGE FunctionalDependencies #-}
6{-# LANGUAGE GADTs #-}
6{-# LANGUAGE GADTs #-}
7−{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE RankNTypes #-}
7{-# LANGUAGE RankNTypes #-}
9{-# LANGUAGE RoleAnnotations #-}
8{-# LANGUAGE RoleAnnotations #-}
10{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE ScopedTypeVariables #-}
src/Reflex/NotReady/Class.hs−1
@@ -3,7 +3,6 @@
3{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FunctionalDependencies #-}
5{-# LANGUAGE FunctionalDependencies #-}
6−{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE TypeFamilies #-}
6{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE UndecidableInstances #-}
7{-# LANGUAGE UndecidableInstances #-}
9#ifdef USE_REFLEX_OPTIMIZER
8#ifdef USE_REFLEX_OPTIMIZER
src/Reflex/Patch/IntMap.hs−8
@@ -1,4 +1,3 @@
1−{-# LANGUAGE CPP #-}
2{-# LANGUAGE DeriveFoldable #-}
1{-# LANGUAGE DeriveFoldable #-}
3{-# LANGUAGE DeriveFunctor #-}
2{-# LANGUAGE DeriveFunctor #-}
4{-# LANGUAGE DeriveTraversable #-}
3{-# LANGUAGE DeriveTraversable #-}
@@ -33,14 +32,7 @@ instance Patch (PatchIntMap a) where
33instance Semigroup (PatchIntMap v) where
32instance Semigroup (PatchIntMap v) where
34 PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b --TODO: Add a semigroup instance for Map
33 PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b --TODO: Add a semigroup instance for Map
35 -- PatchMap is idempotent, so stimes n is id for every n
34 -- PatchMap is idempotent, so stimes n is id for every n
36−#if MIN_VERSION_semigroups(0,17,0)
37 stimes = stimesIdempotentMonoid
35 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
44
36
45-- | Map a function @Int -> a -> b@ over all @a@s in the given @'PatchIntMap' a@
37-- | Map a function @Int -> a -> b@ over all @a@s in the given @'PatchIntMap' a@
46-- (that is, all inserts/updates), producing a @PatchIntMap b@.
38-- (that is, all inserts/updates), producing a @PatchIntMap b@.
src/Reflex/Patch/Map.hs−8
@@ -1,4 +1,3 @@
1−{-# LANGUAGE CPP #-}
2{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
3{-# LANGUAGE TypeFamilies #-}
2{-# LANGUAGE TypeFamilies #-}
4-- | 'Patch'es on 'Map' that consist only of insertions (including overwrites)
3-- | 'Patch'es on 'Map' that consist only of insertions (including overwrites)
@@ -35,14 +34,7 @@ instance Ord k => Patch (PatchMap k v) where
35instance Ord k => Semigroup (PatchMap k v) where
34instance Ord k => Semigroup (PatchMap k v) where
36 PatchMap a <> PatchMap b = PatchMap $ a `mappend` b --TODO: Add a semigroup instance for Map
35 PatchMap a <> PatchMap b = PatchMap $ a `mappend` b --TODO: Add a semigroup instance for Map
37 -- PatchMap is idempotent, so stimes n is id for every n
36 -- PatchMap is idempotent, so stimes n is id for every n
38−#if MIN_VERSION_semigroups(0,17,0)
39 stimes = stimesIdempotentMonoid
37 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
46
38
47-- | The empty 'PatchMap' contains no insertions or deletions
39-- | The empty 'PatchMap' contains no insertions or deletions
48instance Ord k => Monoid (PatchMap k v) where
40instance Ord k => Monoid (PatchMap k v) where
src/Reflex/PerformEvent/Base.hs+1−1
@@ -141,7 +141,7 @@ hostPerformEventT a = do
141 case mToPerform of
141 case mToPerform of
142 Nothing -> return [result']
142 Nothing -> return [result']
143 Just toPerform -> do
143 Just toPerform -> do
144− responses <- runHostFrame $ traverseRequesterData (\v -> Identity <$> v) toPerform
144+ responses <- runHostFrame $ traverseRequesterData (Identity <$>) toPerform
145 mrt <- readRef responseTrigger
145 mrt <- readRef responseTrigger
146 let followupEventTriggers = case mrt of
146 let followupEventTriggers = case mrt of
147 Just rt -> [rt :=> Identity responses]
147 Just rt -> [rt :=> Identity responses]
src/Reflex/PerformEvent/Class.hs−1
@@ -5,7 +5,6 @@
5{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE FunctionalDependencies #-}
7{-# LANGUAGE FunctionalDependencies #-}
8−{-# LANGUAGE MultiParamTypeClasses #-}
9{-# LANGUAGE RankNTypes #-}
8{-# LANGUAGE RankNTypes #-}
10{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE TypeFamilies #-}
src/Reflex/PostBuild/Class.hs−1
@@ -4,7 +4,6 @@
4{-# LANGUAGE DataKinds #-}
4{-# LANGUAGE DataKinds #-}
5{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FunctionalDependencies #-}
6{-# LANGUAGE FunctionalDependencies #-}
7−{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE ScopedTypeVariables #-}
7{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE TypeOperators #-}
9{-# LANGUAGE TypeOperators #-}
src/Reflex/Profiled.hs+14−10
@@ -9,6 +9,7 @@
9{-# LANGUAGE TypeFamilies #-}
9{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE UndecidableInstances #-}
10{-# LANGUAGE UndecidableInstances #-}
11{-# LANGUAGE PolyKinds #-}
11{-# LANGUAGE PolyKinds #-}
12+{-# LANGUAGE TypeApplications #-}
12{-# LANGUAGE RankNTypes #-}
13{-# LANGUAGE RankNTypes #-}
13-- |
14-- |
14-- Module:
15-- Module:
@@ -79,9 +80,9 @@ getCostCentreStack = go []
79 go (cc : l) parent
80 go (cc : l) parent
80
81
81toCostCentreTree :: Ptr CostCentreStack -> Int -> IO CostCentreTree
82toCostCentreTree :: Ptr CostCentreStack -> Int -> IO CostCentreTree
82−toCostCentreTree ccs n = do
83+toCostCentreTree ccs n =
83− ccList <- getCostCentreStack ccs
84− return $ foldr (\cc child -> CostCentreTree 0 n $ Map.singleton cc child) (CostCentreTree n n mempty) ccList
84+ foldr (\cc child -> CostCentreTree 0 n $ Map.singleton cc child) (CostCentreTree n n mempty)
85+ <$> getCostCentreStack ccs
85
86
86getCostCentreTree :: IO CostCentreTree
87getCostCentreTree :: IO CostCentreTree
87getCostCentreTree = do
88getCostCentreTree = do
@@ -151,13 +152,16 @@ instance Reflex t => Reflex (ProfiledTimeline t) where
151 currentIncremental (Incremental_Profiled i) = coerce $ currentIncremental i
152 currentIncremental (Incremental_Profiled i) = coerce $ currentIncremental i
152 updatedIncremental (Incremental_Profiled i) = coerce $ profileEvent $ updatedIncremental i
153 updatedIncremental (Incremental_Profiled i) = coerce $ profileEvent $ updatedIncremental i
153 incrementalToDynamic (Incremental_Profiled i) = coerce $ incrementalToDynamic i
154 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+ behaviorCoercion c =
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+ Coercion `trans` behaviorCoercion @t c `trans` Coercion
156− eventCoercion (c :: Coercion a b) = case eventCoercion c :: Coercion (Event t a) (Event t b) of
157+ eventCoercion c =
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+ Coercion `trans` eventCoercion @t c `trans` Coercion
159+ dynamicCoercion c =
158− dynamicCoercion (c :: Coercion a b) = case dynamicCoercion c :: Coercion (Dynamic t a) (Dynamic t b) of
160+ Coercion `trans` dynamicCoercion @t c `trans` Coercion
159− Coercion -> unsafeCoerce (Coercion :: Coercion (Dynamic (ProfiledTimeline t) a) (Dynamic (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce
161+ incrementalCoercion c d =
162+ Coercion `trans` incrementalCoercion @t c d `trans` Coercion
160− mergeIntIncremental = Event_Profiled . mergeIntIncremental . (unsafeCoerce :: Incremental (ProfiledTimeline t) (PatchIntMap (Event (ProfiledTimeline t) a)) -> Incremental t (PatchIntMap (Event t a)))
163+ mergeIntIncremental = Event_Profiled . mergeIntIncremental .
164+ coerceWith (Coercion `trans` incrementalCoercion Coercion Coercion `trans` Coercion)
161 fanInt (Event_Profiled e) = coerce $ fanInt $ profileEvent e
165 fanInt (Event_Profiled e) = coerce $ fanInt $ profileEvent e
162
166
163deriving instance Functor (Dynamic t) => Functor (Dynamic (ProfiledTimeline t))
167deriving instance Functor (Dynamic t) => Functor (Dynamic (ProfiledTimeline t))
src/Reflex/Pure.hs+3−6
@@ -31,14 +31,9 @@ module Reflex.Pure
31 , Incremental (..)
31 , Incremental (..)
32 ) where
32 ) where
33
33
34−#if !MIN_VERSION_base(4,8,0)
35−import Control.Applicative
36−#endif
37−
38import Control.Monad
34import Control.Monad
39import Data.Dependent.Map (DMap, GCompare)
35import Data.Dependent.Map (DMap, GCompare)
40import qualified Data.Dependent.Map as DMap
36import qualified Data.Dependent.Map as DMap
41−import Data.Functor.Identity
42import Data.IntMap (IntMap)
37import Data.IntMap (IntMap)
43import qualified Data.IntMap as IntMap
38import qualified Data.IntMap as IntMap
44import Data.Maybe
39import Data.Maybe
@@ -93,7 +88,8 @@ instance (Enum t, HasTrie t, Ord t) => Reflex (Pure t) where
93 then Nothing
88 then Nothing
94 else Just currentOccurrences
89 else Just currentOccurrences
95
90
91+-- The instance signature doeesn't compile, leave commented for documentation
96− -- fanG :: GCompare k => Event (Pure t) (DMap k v) -> EventSelectorG (Pure t) k v
92+-- fanG :: GCompare k => Event (Pure t) (DMap k v) -> EventSelectorG (Pure t) k v
97 fanG e = EventSelectorG $ \k -> Event $ \t -> unEvent e t >>= DMap.lookup k
93 fanG e = EventSelectorG $ \k -> Event $ \t -> unEvent e t >>= DMap.lookup k
98
94
99 switch :: Behavior (Pure t) (Event (Pure t) a) -> Event (Pure t) a
95 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
133 behaviorCoercion Coercion = Coercion
129 behaviorCoercion Coercion = Coercion
134 eventCoercion Coercion = Coercion
130 eventCoercion Coercion = Coercion
135 dynamicCoercion Coercion = Coercion
131 dynamicCoercion Coercion = Coercion
132+ incrementalCoercion Coercion Coercion = Coercion
136
133
137 fanInt e = EventSelectorInt $ \k -> Event $ \t -> unEvent e t >>= IntMap.lookup k
134 fanInt e = EventSelectorInt $ \k -> Event $ \t -> unEvent e t >>= IntMap.lookup k
138
135
src/Reflex/Query/Base.hs−1
@@ -1,7 +1,6 @@
1{-# LANGUAGE FlexibleInstances #-}
1{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE InstanceSigs #-}
3{-# LANGUAGE InstanceSigs #-}
4−{-# LANGUAGE KindSignatures #-}
5{-# LANGUAGE LambdaCase #-}
4{-# LANGUAGE LambdaCase #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
5{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE RankNTypes #-}
6{-# LANGUAGE RankNTypes #-}
src/Reflex/Query/Class.hs−1
@@ -3,7 +3,6 @@
3{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FunctionalDependencies #-}
4{-# LANGUAGE FunctionalDependencies #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6−{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE TypeFamilies #-}
6{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE UndecidableInstances #-}
7{-# LANGUAGE UndecidableInstances #-}
9-- |
8-- |
src/Reflex/Requester/Class.hs−1
@@ -6,7 +6,6 @@
6{-# LANGUAGE CPP #-}
6{-# LANGUAGE CPP #-}
7{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE FlexibleInstances #-}
8{-# LANGUAGE FunctionalDependencies #-}
8{-# LANGUAGE FunctionalDependencies #-}
9−{-# LANGUAGE MultiParamTypeClasses #-}
10{-# LANGUAGE RecursiveDo #-}
9{-# LANGUAGE RecursiveDo #-}
11{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE TypeFamilies #-}
12{-# LANGUAGE UndecidableInstances #-}
11{-# LANGUAGE UndecidableInstances #-}
src/Reflex/Spider/Internal.hs+78−49
@@ -9,7 +9,6 @@
9{-# LANGUAGE GADTs #-}
9{-# LANGUAGE GADTs #-}
10{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10{-# LANGUAGE GeneralizedNewtypeDeriving #-}
11{-# LANGUAGE LambdaCase #-}
11{-# LANGUAGE LambdaCase #-}
12−{-# LANGUAGE MultiParamTypeClasses #-}
13{-# LANGUAGE MultiWayIf #-}
12{-# LANGUAGE MultiWayIf #-}
14{-# LANGUAGE RankNTypes #-}
13{-# LANGUAGE RankNTypes #-}
15{-# LANGUAGE RoleAnnotations #-}
14{-# LANGUAGE RoleAnnotations #-}
@@ -18,6 +17,8 @@
18{-# LANGUAGE TypeOperators #-}
17{-# LANGUAGE TypeOperators #-}
19{-# LANGUAGE UndecidableInstances #-}
18{-# LANGUAGE UndecidableInstances #-}
20{-# LANGUAGE PolyKinds #-}
19{-# LANGUAGE PolyKinds #-}
20+{-# LANGUAGE DeriveFunctor #-}
21+{-# LANGUAGE StandaloneDeriving #-}
21{-# LANGUAGE InstanceSigs #-}
22{-# LANGUAGE InstanceSigs #-}
22
23
23#ifdef USE_REFLEX_OPTIMIZER
24#ifdef USE_REFLEX_OPTIMIZER
@@ -37,7 +38,10 @@ import Control.Monad hiding (forM, forM_, mapM, mapM_)
37import Control.Monad.Exception
38import Control.Monad.Exception
38import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_)
39import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_)
39import Control.Monad.Primitive
40import 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
41import Control.Monad.Ref
45import Control.Monad.Ref
42import Data.Align
46import Data.Align
43import Data.Coerce
47import Data.Coerce
@@ -68,6 +72,12 @@ import System.IO.Unsafe
68import System.Mem.Weak
72import System.Mem.Weak
69import Unsafe.Coerce
73import Unsafe.Coerce
70
74
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+
71#ifdef DEBUG_CYCLES
81#ifdef DEBUG_CYCLES
72import Control.Monad.State hiding (forM, forM_, mapM, mapM_, sequence)
82import Control.Monad.State hiding (forM, forM_, mapM, mapM_, sequence)
73import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
83import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
@@ -545,6 +555,11 @@ propagateFast a subscribers = withIncreasedDepth $ do
545toAny :: a -> Any
555toAny :: a -> Any
546toAny = unsafeCoerce
556toAny = unsafeCoerce
547
557
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.
548data EventSubscribed x = EventSubscribed
563data EventSubscribed x = EventSubscribed
549 { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height)
564 { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height)
550 , eventSubscribedRetained :: {-# NOUNPACK #-} !Any
565 , eventSubscribedRetained :: {-# NOUNPACK #-} !Any
@@ -668,7 +683,7 @@ behaviorPull !p = Behavior $ do
668 wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull"
683 wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull"
669 parentsRef <- liftIO $ newIORef []
684 parentsRef <- liftIO $ newIORef []
670 holdInits <- askBehaviorHoldInits
685 holdInits <- askBehaviorHoldInits
671− a <- liftIO $ runReaderT (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
686+ a <- liftIO $ runReaderIO (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
672 invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator
687 invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator
673 parents <- liftIO $ readIORef parentsRef
688 parents <- liftIO $ readIORef parentsRef
674 let subscribed = PullSubscribed
689 let subscribed = PullSubscribed
@@ -703,42 +718,46 @@ readBehaviorUntracked b = do
703-- Dynamic
718-- Dynamic
704--------------------------------------------------------------------------------
719--------------------------------------------------------------------------------
705
720
721+type DynamicS x p = Dynamic x (PatchTarget p) p
722+
706−data Dynamic x p = Dynamic
723+data Dynamic x target p = Dynamic
707− { dynamicCurrent :: !(Behavior x (PatchTarget p))
724+ { dynamicCurrent :: !(Behavior x target)
708 , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`?
725 , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`?
709 }
726 }
710
727
728+deriving instance (HasSpiderTimeline x) => Functor (Dynamic x target)
729+
730+
731+
732+
711−dynamicHold :: Hold x p -> Dynamic x p
733+dynamicHold :: Hold x p -> DynamicS x p
712dynamicHold !h = Dynamic
734dynamicHold !h = Dynamic
713 { dynamicCurrent = behaviorHold h
735 { dynamicCurrent = behaviorHold h
714 , dynamicUpdated = eventHold h
736 , dynamicUpdated = eventHold h
715 }
737 }
716
738
717−dynamicHoldIdentity :: Hold x (Identity a) -> Dynamic x (Identity a)
739+dynamicHoldIdentity :: Hold x (Identity a) -> DynamicS x (Identity a)
718dynamicHoldIdentity = dynamicHold
740dynamicHoldIdentity = dynamicHold
719
741
720−dynamicConst :: PatchTarget p -> Dynamic x p
742+dynamicConst :: PatchTarget p -> DynamicS x p
721dynamicConst !a = Dynamic
743dynamicConst !a = Dynamic
722 { dynamicCurrent = behaviorConst a
744 { dynamicCurrent = behaviorConst a
723 , dynamicUpdated = eventNever
745 , dynamicUpdated = eventNever
724 }
746 }
725
747
726−dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> Dynamic x p
748+dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> DynamicS x p
727dynamicDyn !d = Dynamic
749dynamicDyn !d = Dynamic
728 { dynamicCurrent = behaviorDyn d
750 { dynamicCurrent = behaviorDyn d
729 , dynamicUpdated = eventDyn d
751 , dynamicUpdated = eventDyn d
730 }
752 }
731
753
732−dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> Dynamic x (Identity a)
754+dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> DynamicS x (Identity a)
733dynamicDynIdentity = dynamicDyn
755dynamicDynIdentity = dynamicDyn
734
756
735--------------------------------------------------------------------------------
757--------------------------------------------------------------------------------
736-- Combinators
758-- Combinators
737--------------------------------------------------------------------------------
759--------------------------------------------------------------------------------
738
760
739−--TODO: Figure out why certain things are not 'representational', then make them
740−--representational so we can use coerce
741−
742--type role Hold representational
761--type role Hold representational
743data Hold x p
762data Hold x p
744 = Hold { holdValue :: !(IORef (PatchTarget p))
763 = Hold { holdValue :: !(IORef (PatchTarget p))
@@ -759,20 +778,25 @@ globalSpiderTimelineEnv = unsafePerformIO unsafeNewSpiderTimelineEnv
759
778
760-- | Stores all global data relevant to a particular Spider timeline; only one
779-- | Stores all global data relevant to a particular Spider timeline; only one
761-- value should exist for each type @x@
780-- value should exist for each type @x@
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+
762−data SpiderTimelineEnv x = SpiderTimelineEnv
786+data SpiderTimelineEnv' x = SpiderTimelineEnv
763 { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ())
787 { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ())
764 , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x)
788 , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x)
765#ifdef DEBUG
789#ifdef DEBUG
766 , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int)
790 , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int)
767#endif
791#endif
768 }
792 }
769−type role SpiderTimelineEnv nominal
793+type role SpiderTimelineEnv' phantom
770
794
771instance Eq (SpiderTimelineEnv x) where
795instance Eq (SpiderTimelineEnv x) where
772 _ == _ = True -- Since only one exists of each type
796 _ == _ = True -- Since only one exists of each type
773
797
774instance GEq SpiderTimelineEnv where
798instance 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)
776 then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments
800 then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments
777 else Nothing
801 else Nothing
778
802
@@ -795,7 +819,7 @@ runEventM :: EventM x a -> IO a
795runEventM = unEventM
819runEventM = unEventM
796
820
797asksEventEnv :: forall x a. HasSpiderTimeline x => (EventEnv x -> a) -> EventM x a
821asksEventEnv :: 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))
799
823
800class MonadIO m => Defer a m where
824class MonadIO m => Defer a m where
801 getDeferralQueue :: m (IORef [a])
825 getDeferralQueue :: m (IORef [a])
@@ -933,9 +957,9 @@ getHoldEventSubscription h = do
933
957
934type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x])
958type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x])
935
959
936−--type role BehaviorM representational
937-- BehaviorM can sample behaviors
960-- 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))
939
963
940instance Monad (BehaviorM x) where
964instance Monad (BehaviorM x) where
941 {-# INLINE (>>=) #-}
965 {-# INLINE (>>=) #-}
@@ -1139,17 +1163,21 @@ instance HasSpiderTimeline x => Semialign (Event x) where
1139 align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
1163 align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
1140 DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1164 DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1141
1165
1166+#if defined(MIN_VERSION_semialign)
1167+ zip x y = mapMaybe justThese $ align x y
1168+#endif
1169+
1142data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p)
1170data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p)
1143 | BuildDyn !(EventM x (PatchTarget p), Event x p)
1171 | BuildDyn !(EventM x (PatchTarget p), Event x p)
1144 | HoldDyn !(Hold x p)
1172 | HoldDyn !(Hold x p)
1145
1173
1146newtype Dyn (x :: Type) p = Dyn { unDyn :: IORef (DynType x p) }
1174newtype Dyn (x :: Type) p = Dyn { unDyn :: IORef (DynType x p) }
1147
1175
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)
1149newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
1177newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
1150
1178
1151--TODO: Avoid the duplication between this and R.zipDynWith
1179--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)
1153zipDynWith f da db =
1181zipDynWith f da db =
1154 let eab = align (dynamicUpdated da) (dynamicUpdated db)
1182 let eab = align (dynamicUpdated da) (dynamicUpdated db)
1155 ec = flip push eab $ \o -> do
1183 ec = flip push eab $ \o -> do
@@ -1225,7 +1253,7 @@ run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> Res
1225run roots after = do
1253run roots after = do
1226 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
1254 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
1227 let t = spiderTimeline :: SpiderTimelineEnv x
1255 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
1229 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
1257 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
1230 occBefore <- liftIO $ do
1258 occBefore <- liftIO $ do
1231 occBefore <- readIORef occRef
1259 occBefore <- readIORef occRef
@@ -1289,9 +1317,9 @@ type WeakList a = [Weak a]
1289withIncreasedDepth :: CanTrace x m => m a -> m a
1317withIncreasedDepth :: CanTrace x m => m a -> m a
1290withIncreasedDepth a = do
1318withIncreasedDepth a = do
1291 spiderTimeline <- askSpiderTimelineEnv
1319 spiderTimeline <- askSpiderTimelineEnv
1292− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) succ
1320+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) succ
1293 result <- a
1321 result <- a
1294− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) pred
1322+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) pred
1295 return result
1323 return result
1296#else
1324#else
1297withIncreasedDepth :: m a -> m a
1325withIncreasedDepth :: m a -> m a
@@ -1318,7 +1346,7 @@ traceMWhen _ b getMessage = when b $ do
1318 message <- getMessage
1346 message <- getMessage
1319#ifdef DEBUG
1347#ifdef DEBUG
1320 spiderTimeline <- askSpiderTimelineEnv
1348 spiderTimeline <- askSpiderTimelineEnv
1321− d <- liftIO $ readIORef $ _spiderTimeline_depth spiderTimeline
1349+ d <- liftIO $ readIORef $ _spiderTimeline_depth $ unSTE spiderTimeline
1322#else
1350#else
1323 let d = 0
1351 let d = 0
1324#endif
1352#endif
@@ -1359,25 +1387,25 @@ propagateSubscriberHold h a = do
1359data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset
1387data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset
1360
1388
1361runBehaviorM :: BehaviorM x a -> Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]) -> IORef [SomeHoldInit x] -> IO a
1389runBehaviorM :: 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)
1363
1391
1364askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x)))
1392askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x)))
1365askInvalidator = do
1393askInvalidator = do
1366− (!m, _) <- BehaviorM ask
1394+ (!m, _) <- ask
1367 case m of
1395 case m of
1368 Nothing -> return Nothing
1396 Nothing -> return Nothing
1369 Just (!wi, _) -> return $ Just wi
1397 Just (!wi, _) -> return $ Just wi
1370
1398
1371askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x]))
1399askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x]))
1372askParentsRef = do
1400askParentsRef = do
1373− (!m, _) <- BehaviorM ask
1401+ (!m, _) <- ask
1374 case m of
1402 case m of
1375 Nothing -> return Nothing
1403 Nothing -> return Nothing
1376 Just (_, !p) -> return $ Just p
1404 Just (_, !p) -> return $ Just p
1377
1405
1378askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x])
1406askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x])
1379askBehaviorHoldInits = do
1407askBehaviorHoldInits = do
1380− (_, !his) <- BehaviorM ask
1408+ (_, !his) <- ask
1381 return his
1409 return his
1382
1410
1383{-# INLINE getDynHold #-}
1411{-# INLINE getDynHold #-}
@@ -1701,20 +1729,20 @@ subscribeCoincidenceSubscribed subscribed sub = WeakBag.insert sub (coincidenceS
1701{-# INLINE mergeG #-}
1729{-# INLINE mergeG #-}
1702mergeG :: forall k q x v. (HasSpiderTimeline x, GCompare k)
1730mergeG :: forall k q x v. (HasSpiderTimeline x, GCompare k)
1703 => (forall a. q a -> Event x (v a))
1731 => (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)
1705mergeG nt d = cacheEvent (mergeCheap nt d)
1733mergeG nt d = cacheEvent (mergeCheap nt d)
1706
1734
1707{-# INLINE mergeWithMove #-}
1735{-# INLINE mergeWithMove #-}
1708mergeWithMove :: forall k v q x. (HasSpiderTimeline x, GCompare k)
1736mergeWithMove :: forall k v q x. (HasSpiderTimeline x, GCompare k)
1709 => (forall a. q a -> Event x (v a))
1737 => (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)
1711mergeWithMove nt d = cacheEvent (mergeCheapWithMove nt d)
1739mergeWithMove nt d = cacheEvent (mergeCheapWithMove nt d)
1712
1740
1713{-# INLINE [1] mergeCheap #-}
1741{-# INLINE [1] mergeCheap #-}
1714mergeCheap
1742mergeCheap
1715 :: forall k x q v. (HasSpiderTimeline x, GCompare k)
1743 :: forall k x q v. (HasSpiderTimeline x, GCompare k)
1716 => (forall a. q a -> Event x (v a))
1744 => (forall a. q a -> Event x (v a))
1717− -> Dynamic x (PatchDMap k q)
1745+ -> DynamicS x (PatchDMap k q)
1718 -> Event x (DMap k v)
1746 -> Event x (DMap k v)
1719mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
1747mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
1720 where
1748 where
@@ -1742,7 +1770,7 @@ mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
1742 let s = subscriber $ return k
1770 let s = subscriber $ return k
1743 (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
1771 (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
1744 height <- liftIO $ getEventSubscribedHeight parentSubd
1772 height <- liftIO $ getEventSubscribedHeight parentSubd
1745− return (fmap (\x -> k :=> x) parentOcc, height, k :=> MergeSubscribedParent subscription)
1773+ return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParent subscription)
1746 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
1774 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
1747 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
1775 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
1748 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
1776 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
@@ -1754,7 +1782,7 @@ mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
1754{-# INLINE [1] mergeCheapWithMove #-}
1782{-# INLINE [1] mergeCheapWithMove #-}
1755mergeCheapWithMove :: forall k x v q. (HasSpiderTimeline x, GCompare k)
1783mergeCheapWithMove :: forall k x v q. (HasSpiderTimeline x, GCompare k)
1756 => (forall a. q a -> Event x (v a))
1784 => (forall a. q a -> Event x (v a))
1757− -> Dynamic x (PatchDMapWithMove k q)
1785+ -> DynamicS x (PatchDMapWithMove k q)
1758 -> Event x (DMap k v)
1786 -> Event x (DMap k v)
1759mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy
1787mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy
1760 where
1788 where
@@ -1790,7 +1818,7 @@ mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy
1790 let s = subscriber $ liftIO $ readIORef keyRef
1818 let s = subscriber $ liftIO $ readIORef keyRef
1791 (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
1819 (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
1792 height <- liftIO $ getEventSubscribedHeight parentSubd
1820 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)
1794 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
1822 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
1795 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
1823 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
1796 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
1824 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
@@ -1902,7 +1930,7 @@ updateMerge m updateFunc p = SomeMergeUpdate updateMe (invalidateMergeHeight m)
1902
1930
1903{-# INLINE mergeGCheap' #-}
1931{-# INLINE mergeGCheap' #-}
1904mergeGCheap' :: forall k v x p s q. (HasSpiderTimeline x, GCompare k, PatchTarget p ~ DMap k q)
1932mergeGCheap' :: 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)
1906mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
1934mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
1907 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1935 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1908 accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
1936 accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
@@ -1951,11 +1979,11 @@ mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
1951 , occ
1979 , occ
1952 )
1980 )
1953
1981
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)
1955mergeInt = cacheEvent . mergeIntCheap
1983mergeInt = cacheEvent . mergeIntCheap
1956
1984
1957{-# INLINABLE mergeIntCheap #-}
1985{-# 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)
1959mergeIntCheap d = Event $ \sub -> do
1987mergeIntCheap d = Event $ \sub -> do
1960 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1988 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1961 accum <- liftIO $ FastMutableIntMap.newEmpty
1989 accum <- liftIO $ FastMutableIntMap.newEmpty
@@ -2115,7 +2143,7 @@ clearEventEnv (EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeI
2115-- | Run an event action outside of a frame
2143-- | Run an event action outside of a frame
2116runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
2144runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
2117runFrame a = SpiderHost $ do
2145runFrame a = SpiderHost $ do
2118− let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
2146+ let env = _spiderTimeline_eventEnv $ unSTE (spiderTimeline :: SpiderTimelineEnv x)
2119 let go = do
2147 let go = do
2120 result <- a
2148 result <- a
2121 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
2149 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))
2326 fail _ = error "Dynamic does not support 'fail'"
2354 fail _ = error "Dynamic does not support 'fail'"
2327
2355
2328{-# INLINABLE newJoinDyn #-}
2356{-# 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)
2330newJoinDyn d =
2358newJoinDyn d =
2331 let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d)
2359 let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d)
2332 eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d
2360 eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d
@@ -2476,7 +2504,7 @@ unsafeNewSpiderTimelineEnv = do
2476#ifdef DEBUG
2504#ifdef DEBUG
2477 depthRef <- newIORef 0
2505 depthRef <- newIORef 0
2478#endif
2506#endif
2479− return $ SpiderTimelineEnv
2507+ return $ STE $ SpiderTimelineEnv
2480 { _spiderTimeline_lock = lock
2508 { _spiderTimeline_lock = lock
2481 , _spiderTimeline_eventEnv = env
2509 , _spiderTimeline_eventEnv = env
2482#ifdef DEBUG
2510#ifdef DEBUG
@@ -2492,13 +2520,13 @@ data LocalSpiderTimeline (x :: Type) s
2492
2520
2493instance Reifies s (SpiderTimelineEnv x) =>
2521instance Reifies s (SpiderTimelineEnv x) =>
2494 HasSpiderTimeline (LocalSpiderTimeline x s) where
2522 HasSpiderTimeline (LocalSpiderTimeline x s) where
2495− spiderTimeline = localSpiderTimeline (Proxy :: Proxy s) $ reflect (Proxy :: Proxy s)
2523+ spiderTimeline = localSpiderTimeline Proxy $ reflect (Proxy :: Proxy s)
2496
2524
2497localSpiderTimeline
2525localSpiderTimeline
2498− :: Proxy s
2526+ :: proxy s
2499 -> SpiderTimelineEnv x
2527 -> SpiderTimelineEnv x
2500 -> SpiderTimelineEnv (LocalSpiderTimeline x s)
2528 -> SpiderTimelineEnv (LocalSpiderTimeline x s)
2501−localSpiderTimeline _ = unsafeCoerce
2529+localSpiderTimeline _ = coerce
2502
2530
2503-- | Pass a new timeline to the given function.
2531-- | Pass a new timeline to the given function.
2504withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r
2532withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r
@@ -2516,8 +2544,8 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2516 {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-}
2544 {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-}
2517 newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
2545 newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
2518 newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }
2546 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)
2547+ newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: DynamicS x (Identity a) } -- deriving (Functor, Applicative, Monad)
2520− newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: Dynamic x p }
2548+ newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: DynamicS x p }
2521 type PullM (SpiderTimeline x) = SpiderPullM x
2549 type PullM (SpiderTimeline x) = SpiderPullM x
2522 type PushM (SpiderTimeline x) = SpiderPushM x
2550 type PushM (SpiderTimeline x) = SpiderPushM x
2523 {-# INLINABLE never #-}
2551 {-# INLINABLE never #-}
@@ -2546,7 +2574,7 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2546 {-# INLINABLE current #-}
2574 {-# INLINABLE current #-}
2547 current = SpiderBehavior . dynamicCurrent . unSpiderDynamic
2575 current = SpiderBehavior . dynamicCurrent . unSpiderDynamic
2548 {-# INLINABLE updated #-}
2576 {-# INLINABLE updated #-}
2549− updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic
2577+ updated = SpiderEvent #. dynamicUpdated .# fmap coerce . unSpiderDynamic
2550 {-# INLINABLE unsafeBuildDynamic #-}
2578 {-# INLINABLE unsafeBuildDynamic #-}
2551 unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
2579 unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
2552 {-# INLINABLE unsafeBuildIncremental #-}
2580 {-# INLINABLE unsafeBuildIncremental #-}
@@ -2565,9 +2593,10 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2565 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
2593 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
2566 eventCoercion Coercion = Coercion
2594 eventCoercion Coercion = Coercion
2567 behaviorCoercion Coercion = Coercion
2595 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
2569 {-# INLINABLE mergeIntIncremental #-}
2598 {-# 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
2571 {-# INLINABLE fanInt #-}
2600 {-# INLINABLE fanInt #-}
2572 fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e))
2601 fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e))
2573
2602
src/Reflex/TriggerEvent/Class.hs−1
@@ -2,7 +2,6 @@
2-- new 'Event's that can be triggered from 'IO'.
2-- new 'Event's that can be triggered from 'IO'.
3{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FunctionalDependencies #-}
4{-# LANGUAGE FunctionalDependencies #-}
5−{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE UndecidableInstances #-}
5{-# LANGUAGE UndecidableInstances #-}
7module Reflex.TriggerEvent.Class
6module Reflex.TriggerEvent.Class
8 ( TriggerEvent (..)
7 ( TriggerEvent (..)
test/EventWriterT.hs+6−4
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE GADTs #-}
4{-# LANGUAGE GADTs #-}
@@ -13,6 +14,10 @@ import Data.Functor.Misc
13import qualified Data.Map as M
14import qualified Data.Map as M
14import Data.These
15import Data.These
15
16
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+
16import Reflex
21import Reflex
17import Reflex.EventWriter.Base
22import Reflex.EventWriter.Base
18import Test.Run
23import Test.Run
@@ -48,16 +53,13 @@ unwrapApp x appIn = do
48 return e
53 return e
49
54
50testOrdering :: (Reflex t, Monad m) => Event t () -> EventWriterT t [Int] m ()
55testOrdering :: (Reflex t, Monad m) => Event t () -> EventWriterT t [Int] m ()
51−testOrdering pulse = do
52− forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse)
56+testOrdering pulse = forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse)
53− return ()
54
57
55testSimultaneous :: (Reflex t, Adjustable t m, MonadHold t m) => Event t (These () ()) -> EventWriterT t [Int] m ()
58testSimultaneous :: (Reflex t, Adjustable t m, MonadHold t m) => Event t (These () ()) -> EventWriterT t [Int] m ()
56testSimultaneous pulse = do
59testSimultaneous pulse = do
57 let e0 = fmapMaybe (^? here) pulse
60 let e0 = fmapMaybe (^? here) pulse
58 e1 = fmapMaybe (^? there) pulse
61 e1 = fmapMaybe (^? there) pulse
59 forM_ [1,3..9] $ \i -> runWithReplace (tellEvent ([i] <$ e0)) $ ffor e1 $ \_ -> tellEvent ([i+1] <$ e0)
62 forM_ [1,3..9] $ \i -> runWithReplace (tellEvent ([i] <$ e0)) $ ffor e1 $ \_ -> tellEvent ([i+1] <$ e0)
60− return ()
61
63
62-- | Test that a widget telling and event which fires at the same time it has been replaced
64-- | Test that a widget telling and event which fires at the same time it has been replaced
63-- doesn't count along with the new widget.
65-- doesn't count along with the new widget.
test/QueryT.hs+4
@@ -19,6 +19,10 @@ import Data.Map.Monoidal (MonoidalMap)
19import Data.Semigroup
19import Data.Semigroup
20import Data.These
20import Data.These
21
21
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+
22import Reflex
26import Reflex
23import Reflex.Patch.MapWithMove
27import Reflex.Patch.MapWithMove
24import Test.Run
28import Test.Run
test/Reflex/Bench/Focused.hs+12
@@ -130,6 +130,16 @@ mapDynChain = iterM (return . fmap (+1))
130joinDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
130joinDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
131joinDynChain = iterM (\d -> return $ join $ fmap (const d) d)
131joinDynChain = iterM (\d -> return $ join $ fmap (const d) d)
132
132
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+
133combineDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
143combineDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
134combineDynChain = iterM (\d -> return $ zipDynWith (+) d d)
144combineDynChain = iterM (\d -> return $ zipDynWith (+) d d)
135
145
@@ -308,6 +318,8 @@ dynamics :: Word -> [(String, TestCase)]
308dynamics n =
318dynamics n =
309 [ testE "mapDynChain" $ fmap updated $ mapDynChain n =<< d
319 [ testE "mapDynChain" $ fmap updated $ mapDynChain n =<< d
310 , testE "joinDynChain" $ fmap updated $ joinDynChain n =<< d
320 , testE "joinDynChain" $ fmap updated $ joinDynChain n =<< d
321+ , testE "holdDynChain" $ fmap updated $ holdDynChain n =<< d
322+ , testE "buildDynChain" $ fmap updated $ buildDynChain n =<< d
311 , testE "combineDynChain" $ fmap updated $ combineDynChain n =<< d
323 , testE "combineDynChain" $ fmap updated $ combineDynChain n =<< d
312 , testE "dense mergeTree" $ fmap (updated . mergeTreeDyn 8) dense
324 , testE "dense mergeTree" $ fmap (updated . mergeTreeDyn 8) dense
313 , testE "sparse mergeTree" $ fmap (updated . mergeTreeDyn 8) sparse
325 , testE "sparse mergeTree" $ fmap (updated . mergeTreeDyn 8) sparse
test/Reflex/Test/CrossImpl.hs+5
@@ -218,6 +218,11 @@ testCases =
218 bb <- hold b $ pushAlways (const $ hold "asdf" eo) eo
218 bb <- hold b $ pushAlways (const $ hold "asdf" eo) eo
219 let b' = pull $ sample =<< sample bb
219 let b' = pull $ sample =<< sample bb
220 return (b', e)
220 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)
221 , (,) "joinDyn" $ TestCase (Map.singleton 0 (0 :: Int), Map.fromList [(1, "qwer"), (2, "lkj")]) $ \(b, e) -> do
226 , (,) "joinDyn" $ TestCase (Map.singleton 0 (0 :: Int), Map.fromList [(1, "qwer"), (2, "lkj")]) $ \(b, e) -> do
222 bb <- hold "b" e
227 bb <- hold "b" e
223 bd <- hold never . fmap (const e) =<< headE e
228 bd <- hold never . fmap (const e) =<< headE e
test/RequesterT.hs+5
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE GADTs #-}
4{-# LANGUAGE GADTs #-}
@@ -15,6 +16,10 @@ import Data.Functor.Misc
15import qualified Data.Map as M
16import qualified Data.Map as M
16import Data.These
17import Data.These
17
18
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+
18import Reflex
23import Reflex
19import Reflex.Requester.Base
24import Reflex.Requester.Base
20import Reflex.Requester.Class
25import Reflex.Requester.Class
test/hlint.hs+1
@@ -22,6 +22,7 @@ main = do
22 , "--ignore=Use unless"
22 , "--ignore=Use unless"
23 , "--ignore=Reduce duplication"
23 , "--ignore=Reduce duplication"
24 , "--cpp-define=USE_TEMPLATE_HASKELL"
24 , "--cpp-define=USE_TEMPLATE_HASKELL"
25+ , "--ignore=Use tuple-section"
25 ]
26 ]
26 recurseInto = and <$> sequence
27 recurseInto = and <$> sequence
27 [ fileType ==? Directory
28 [ fileType ==? Directory