on 92c716b help sign in
151 files changed+3333−7852
since splitsnapshots
unifiedsplit
.circleci/config.yml+277−73 .github/workflows/haskell.yml+60−61 .hlint.ignore−5 benchmark/Streamly/Benchmark/Data/Fold.hs+2−2 benchmark/Streamly/Benchmark/Data/Serialize.hs+15−10 benchmark/Streamly/Benchmark/Data/Serialize/RecCompatible.hs+1−1 benchmark/Streamly/Benchmark/Data/Serialize/TH.hs+3−3 benchmark/Streamly/Benchmark/Data/Stream/ConcurrentCommon.hs+2−2 benchmark/Streamly/Benchmark/Data/Stream/ConcurrentEager.hs+1−1 benchmark/Streamly/Benchmark/Data/Stream/ConcurrentInterleaved.hs+1−1 benchmark/Streamly/Benchmark/Data/Stream/ConcurrentOrdered.hs+1−1 benchmark/Streamly/Benchmark/Data/Stream/Eliminate.hs−2 benchmark/Streamly/Benchmark/Data/Stream/Exceptions.hs+2−2 benchmark/Streamly/Benchmark/Data/Stream/Reduce.hs+1−1 benchmark/Streamly/Benchmark/Data/Stream/StreamKAlt.hs+1−1 benchmark/Streamly/Benchmark/Data/Stream/ToStreamK.hs+1−1 benchmark/Streamly/Benchmark/Data/Stream/Transform.hs+1−1 benchmark/Streamly/Benchmark/Data/Unfold.hs+1−1 benchmark/Streamly/Benchmark/FileSystem/Handle/Read.hs+8−7 benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs+9−8 benchmark/Streamly/Benchmark/Unicode/Stream.hs+3−4 benchmark/streamly-benchmarks.cabal+1−1 configure+9−9 configure.ac+1−1 core/configure+9−9 core/configure.ac+1−1 core/docs/ApiChangelogs/0.1.0-0.2.0.txt−1471 core/docs/ApiChangelogs/0.2.0-0.2.2.txt−306 core/docs/Changelog.md+27−44 core/src/DocTestDataArray.hs−3 core/src/DocTestDataStream.hs−2 core/src/DocTestFileSystemHandle.hs+1−1 core/src/Streamly/Data/Array.hs+28−35 core/src/Streamly/Data/Array/Generic.hs+13−16 core/src/Streamly/Data/MutArray.hs+6−12 core/src/Streamly/Data/MutArray/Generic.hs+3−8 core/src/Streamly/Data/MutByteArray.hs+13−29 core/src/Streamly/Data/Stream.hs+20−129 core/src/Streamly/Internal/Data/Array.hs+128−559 core/src/Streamly/Internal/Data/Array/Generic.hs+6−22 core/src/Streamly/Internal/Data/Array/Stream.hs+564−57 core/src/Streamly/Internal/Data/Array/Type.hs+98−503 core/src/Streamly/Internal/Data/Fold/Combinators.hs+92 core/src/Streamly/Internal/Data/Fold/Type.hs−91 core/src/Streamly/Internal/Data/IsMap.hs−4 core/src/Streamly/Internal/Data/MutArray.hs+35−151 core/src/Streamly/Internal/Data/MutArray/Generic.hs+30−65 core/src/Streamly/Internal/Data/MutArray/Stream.hs+195−11 core/src/Streamly/Internal/Data/MutArray/Type.hs+342−1199 core/src/Streamly/Internal/Data/MutByteArray/Type.hs+15−55 core/src/Streamly/Internal/Data/Serialize/TH.hs+15−28 core/src/Streamly/Internal/Data/Serialize/TH/Bottom.hs+29−35 core/src/Streamly/Internal/Data/Serialize/Type.hs+9−10 core/src/Streamly/Internal/Data/Stream/Container.hs+48−56 core/src/Streamly/Internal/Data/Stream/Eliminate.hs+25−33 core/src/Streamly/Internal/Data/Stream/Exception.hs+6−9 core/src/Streamly/Internal/Data/Stream/Generate.hs+12−2 core/src/Streamly/Internal/Data/Stream/Nesting.hs+146−19 core/src/Streamly/Internal/Data/Stream/Top.hs+115−243 core/src/Streamly/Internal/Data/Stream/Transform.hs+27−53 core/src/Streamly/Internal/Data/Stream/Transformer.hs+1−2 core/src/Streamly/Internal/Data/Stream/Type.hs+3−132 core/src/Streamly/Internal/Data/StreamK.hs+28−19 core/src/Streamly/Internal/Data/StreamK/Type.hs+11−80 core/src/Streamly/Internal/Data/Time/Units.hs+4 core/src/Streamly/Internal/Data/Unbox.hs+39−75 core/src/Streamly/Internal/Data/Unbox/TH.hs+1−4 core/src/Streamly/Internal/Data/Unfold.hs+4−6 core/src/Streamly/Internal/FileSystem/File.hs+9−4 core/src/Streamly/Internal/FileSystem/Handle.hs+28−21 core/src/Streamly/Internal/FileSystem/Path.hs−515 core/src/Streamly/Internal/Unicode/Parser.hs−3 core/src/Streamly/Internal/Unicode/Stream.hs+3−30 core/src/Streamly/Internal/Unicode/String.hs+7−7 core/streamly-core.cabal+16−62 docs/Developer/optimization-guidelines.md−12 docs/Developer/paths.rst+2−25 docs/User/Project/ApiChangelogs/0.9.0-0.10.0.txt−424 docs/User/Project/Changelog.md+10−23 docs/User/Project/README.md+2−9 docs/User/Project/Upgrading-0.8-to-0.9.md → docs/User/Project/Upgrading.md+9−87 docs/User/Tutorials/quick-overview.md+14−10 src/Streamly/Data/Fold/Prelude.hs+13−31 src/Streamly/Data/Stream/Concurrent.hs+194 src/Streamly/Data/Stream/Exception.hs+25 src/Streamly/Data/Stream/MkType.hs+10−41 src/Streamly/Data/Stream/Prelude.hs+15−217 src/Streamly/Data/Stream/Time.hs+37 src/Streamly/Internal/Data/Channel.hs−19 src/Streamly/Internal/Data/Fold/Concurrent.hs+44−1 src/Streamly/Internal/Data/Fold/Concurrent/Channel.hs+6−4 src/Streamly/Internal/Data/Fold/Concurrent/Channel/Type.hs+3−3 src/Streamly/Internal/Data/Fold/Prelude.hs−19 src/Streamly/Internal/Data/Fold/SVar.hs−1 src/Streamly/Internal/Data/IsMap/HashMap.hs−5 src/Streamly/Internal/Data/SVar.hs−1 src/Streamly/Internal/Data/SmallArray.hs+1−1 src/Streamly/Internal/Data/Channel/Dispatcher.hs → src/Streamly/Internal/Data/Stream/Channel/Dispatcher.hs+3−3 src/Streamly/Internal/Data/Channel/Types.hs → src/Streamly/Internal/Data/Stream/Channel/Types.hs+37−12 src/Streamly/Internal/Data/Channel/Worker.hs → src/Streamly/Internal/Data/Stream/Channel/Worker.hs+3−3 src/Streamly/Internal/Data/Stream/Concurrent.hs+35−47 src/Streamly/Internal/Data/Stream/Concurrent/Channel.hs+14−17 src/Streamly/Internal/Data/Stream/Concurrent/Channel/Append.hs+10−10 src/Streamly/Internal/Data/Stream/Concurrent/Channel/Consumer.hs+2−2 src/Streamly/Internal/Data/Stream/Concurrent/Channel/Dispatcher.hs+3−3 src/Streamly/Internal/Data/Stream/Concurrent/Channel/Interleave.hs+8−8 src/Streamly/Internal/Data/Stream/Concurrent/Channel/Operations.hs+1−1 src/Streamly/Internal/Data/Stream/Concurrent/Channel/Type.hs+3−3 src/Streamly/Internal/Data/Stream/Lifted.hs → src/Streamly/Internal/Data/Stream/Exception/Lifted.hs+2−2 src/Streamly/Internal/Data/Stream/IsStream.hs−6 src/Streamly/Internal/Data/Stream/IsStream/Common.hs+1−1 src/Streamly/Internal/Data/Stream/IsStream/Exception.hs+1−1 src/Streamly/Internal/Data/Stream/IsStream/Expand.hs−5 src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs+1−1 src/Streamly/Internal/Data/Stream/IsStream/Top.hs+1−1 src/Streamly/Internal/Data/Stream/MkType.hs+34−33 src/Streamly/Internal/Data/Stream/Prelude.hs−19 src/Streamly/Internal/Data/Stream/SVar.hs−18 src/Streamly/Internal/Data/Stream/Serial.hs−5 src/Streamly/Internal/Data/Stream/Zip.hs−37 src/Streamly/Internal/Data/Stream/Zip/Concurrent.hs+50 src/Streamly/Internal/Data/Stream/ZipAsync.hs+1−2 src/Streamly/Internal/Data/Unfold/Prelude.hs−17 src/Streamly/Internal/Data/Unfold/SVar.hs−1 src/Streamly/Internal/FileSystem/Event.hs−3 src/Streamly/Internal/FileSystem/Event/Darwin.hs+1−1 src/Streamly/Internal/FileSystem/Event/Linux.hs+2−2 src/Streamly/Internal/FileSystem/Event/Windows.hs+2−2 src/Streamly/Internal/FileSystem/FD.hs+8−7 src/Streamly/Internal/Network/Inet/TCP.hs+4−4 src/Streamly/Internal/Network/Socket.hs+13−16 src/Streamly/Internal/Unicode/Char.hs+3−3 src/Streamly/Network/Inet/TCP.hs−28 src/Streamly/Network/Socket.hs+4−3 streamly.cabal+51−68 targets/Targets.hs+1−4 test/Streamly/Test/Data/Array.hs+2−2 test/Streamly/Test/Data/Fold.hs+6−7 test/Streamly/Test/Data/Parser.hs+4−6 test/Streamly/Test/Data/Serialize.hs+3−34 test/Streamly/Test/Data/Serialize/CompatV0.hs+2−2 test/Streamly/Test/Data/Serialize/CompatV1.hs+2−2 test/Streamly/Test/Data/Serialize/TH.hs+2−2 test/Streamly/Test/Data/Stream/Concurrent.hs+1−1 test/Streamly/Test/Data/Unbox.hs−19 test/Streamly/Test/FileSystem/Event/Common.hs+1−1 test/Streamly/Test/FileSystem/Handle.hs+2−2 test/Streamly/Test/Prelude/Serial.hs+2−2 test/Streamly/Test/Unicode/Char.hs+1−1 test/lib/Streamly/Test/Prelude/Common.hs+1−1 test/streamly-tests.cabal+7−8
.circleci/config.yml+277−73
@@ -1,7 +1,7 @@
11version: 2.1
22
33#-----------------------------------------------------------------------------
4−# packcheck-0.7.0
4+# packcheck-0.4.2
55# Packcheck global environment variables
66#-----------------------------------------------------------------------------
77
@@ -11,8 +11,6 @@ env: &env
1111 # Common options
1212 # ------------------------------------------------------------------------
1313 # GHC_OPTIONS: "-Werror"
14− # For updating see: https://downloads.haskell.org/~ghcup/
15− GHCUP_VERSION: 0.1.20.0
1614 CABAL_REINIT_CONFIG: "y"
1715 LC_ALL: "C.UTF-8"
1816
@@ -24,6 +22,7 @@ env: &env
2422 # DISABLE_DOCS: "y"
2523 # DISABLE_SDIST_BUILD: "y"
2624 # DISABLE_DIST_CHECKS: "y"
25+ ENABLE_INSTALL: "y"
2726
2827 # ------------------------------------------------------------------------
2928 # stack options
@@ -39,12 +38,15 @@ env: &env
3938 # cabal options
4039 # ------------------------------------------------------------------------
4140 CABAL_CHECK_RELAX: "y"
41+ CABAL_NO_SANDBOX: "y"
42+ CABAL_HACKAGE_MIRROR: "hackage.haskell.org:http://hackage.fpcomplete.com"
4243 CABAL_BUILD_OPTIONS: "-j1 --flag limit-build-mem"
4344
4445 # ------------------------------------------------------------------------
4546 # Where to find the required tools
4647 # ------------------------------------------------------------------------
47− PATH: /sbin:/usr/sbin:/bin:/usr/bin
48+ PATH: /opt/ghc/bin:/opt/ghcjs/bin:/sbin:/usr/sbin:/bin:/usr/bin
49+ TOOLS_DIR: /opt
4850
4951 # ------------------------------------------------------------------------
5052 # Location of packcheck.sh (the shell script invoked to perform CI tests ).
@@ -57,15 +59,15 @@ env: &env
5759 # If you have not committed packcheck.sh in your repo at PACKCHECK
5860 # then it is automatically pulled from this URL.
5961 PACKCHECK_GITHUB_URL: "https://raw.githubusercontent.com/composewell/packcheck"
60− PACKCHECK_GITHUB_COMMIT: "f6cfd7b7a33b4bf6fd63cce6a3fb3d26f5031403"
62+ PACKCHECK_GITHUB_COMMIT: "a302772c8f3791c477edd1764b82f8d1f5b22fdf"
6163
6264executors:
6365 amd64-executor:
6466 docker:
65− - image: ubuntu:latest
67+ - image: ubuntu:xenial
6668 x86-executor:
6769 docker:
68− - image: i386/ubuntu:focal
70+ - image: i386/ubuntu:eoan
6971
7072#-----------------------------------------------------------------------------
7173# Common utility stuff, not to be modified usually
@@ -77,50 +79,38 @@ preinstall: &preinstall
7779 # required for https/cache save and restore
7880 apt-get install -y ca-certificates
7981
80− # Alternative way of installing ghc and cabal, directly from
81− # haskell.org instead of using ghcup. NOTE: this is for Debian
82− # only and is debian release specific.
83− # gnupg is required for apt-key to work
84− #apt-get install -y gnupg
85− #apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA3CBA3FFE22B574
86− #echo "deb http://downloads.haskell.org/debian buster main" >> /etc/apt/sources.list
87− #apt-get update
88−
89− # required for outbound https for stack and for stack setup
90− apt-get install -y netbase xz-utils make
91− apt-get install -y zlib1g-dev
82+ # required to (re)generate the configure script
83+ apt-get install -y autoconf
9284
93− # For ghcup to install ghc
94− if test -n "$GHCUP_VERSION"
95− then
96− apt-get install -y gcc
97− apt-get install -y g++
98− fi
85+ # For ghc and cabal-install packages from hvr's ppa
86+ # gnupg is required for apt-key to work
87+ apt-get install -y gnupg
88+ apt-get install -y apt-transport-https
89+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA3CBA3FFE22B574
90+ apt-get install -y software-properties-common
91+ add-apt-repository -y ppa:hvr/ghc
92+ # echo "deb http://downloads.haskell.org/debian stretch main" >> /etc/apt/sources.list
93+ echo "deb-src http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main" >> /etc/apt/sources.list
94+ apt-get update
9995
100− # libgmp required by ghc for linking
101− apt-get install -y libgmp-dev
102− apt-get install -y libtinfo-dev
96+ # required for packcheck
97+ apt-get install -y curl
10398
104− # Required by cabal when git URL is specified in project file
99+ # required for circleci.
100+ apt-get install -y libcurl4-gnutls-dev
105101 apt-get install -y git
102+ apt-get install -y libtinfo-dev
106103
107− # Required for and by packcheck
108− apt-get install -y curl
104+ # required for outbound https for stack and for stack setup
105+ apt-get install -y netbase xz-utils make
109106
107+project-preinstall: &project-preinstall
108+ run: |
110109 # Get packcheck if needed
111− if test ! -e "$PACKCHECK"
112− then
113− if test -z "$PACKCHECK_GITHUB_COMMIT"
114− then
115− die "PACKCHECK_GITHUB_COMMIT is not specified."
116− fi
117− PACKCHECK_URL=${PACKCHECK_GITHUB_URL}/${PACKCHECK_GITHUB_COMMIT}/packcheck.sh
118− curl --fail -sL -o "$PACKCHECK" $PACKCHECK_URL || exit 1
119− chmod +x $PACKCHECK
120− elif test ! -x "$PACKCHECK"
121− then
122− chmod +x $PACKCHECK
123− fi
110+ CURL=$(which curl)
111+ PACKCHECK_URL=${PACKCHECK_GITHUB_URL}/${PACKCHECK_GITHUB_COMMIT}/packcheck.sh
112+ if test ! -e "$PACKCHECK"; then $CURL -sL -o "$PACKCHECK" $PACKCHECK_URL; fi;
113+ chmod +x $PACKCHECK
124114
125115restore: &restore
126116 # Needs to happen after installing ca-certificates
@@ -136,71 +126,271 @@ save: &save
136126 save_cache:
137127 key: v1-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}
138128 paths:
139− - ~/.local
140129 - ~/.cabal
130+ - ~/.ghc
131+ - ~/.local
141132 - ~/.stack
142− - ~/.ghcup
143133
144134#-----------------------------------------------------------------------------
145135# Build matrix
146136#-----------------------------------------------------------------------------
147137
148138jobs:
149− cabal-ghc-8_6_5:
139+ cabal-ghc-8_10_4:
150140 <<: *env
151141 executor: amd64-executor
152142 steps:
143+ - *preinstall
153144 - checkout
145+ - *project-preinstall
154146 - *restore
155− - *preinstall
156147 - run:
157148 environment:
158− GHCVER: "8.6.5"
159− CABAL_VERSION: "3.6.2.0"
160149 CABAL_PROJECT: "cabal.project"
150+ DISABLE_TEST: "yes"
151+ DISABLE_BENCH: "yes"
161152 DISABLE_SDIST_BUILD: "yes"
162− CABAL_BUILD_OPTIONS: "--flag debug --flag -opt"
163153 command: |
154+ apt-get install -y ghc-8.10.4
155+ apt-get install -y cabal-install-3.4
164156 bash -c "$PACKCHECK cabal"
165157 - *save
166− cabal-ghc-9_8_1-docspec:
158+ stack-ghc-8_8:
167159 <<: *env
168160 executor: amd64-executor
169161 steps:
162+ - *preinstall
170163 - checkout
164+ - *project-preinstall
171165 - *restore
166+ - run:
167+ name: GHC 8.8 + stack lts-16.12
168+ environment:
169+ BUILD: "stack"
170+ RESOLVER: "lts-16.12"
171+ SDIST_OPTIONS: "--ignore-check"
172+ STACK_BUILD_OPTIONS: "--flag streamly-benchmarks:-opt"
173+ command: |
174+ apt-get build-dep -y ghc-8.8.4
175+ apt-get install -y cabal-install-3.2
176+ bash -c "$PACKCHECK $BUILD"
177+ - *save
178+ cabal-ghc-8_6_5:
179+ <<: *env
180+ executor: amd64-executor
181+ steps:
172182 - *preinstall
183+ - checkout
184+ - *project-preinstall
185+ - *restore
186+ - run: |
187+ apt-get install -y ghc-8.6.3
188+ apt-get install -y cabal-install-2.4
189+ bash -c "$PACKCHECK cabal-v2"
190+ - *save
191+ cabal-ghc-8_4_4:
192+ <<: *env
193+ executor: x86-executor
194+ steps:
195+ - *preinstall
196+ - checkout
197+ - *project-preinstall
198+ - *restore
199+ - run:
200+ name: GHC 8.4.4 + x86 + debug
201+ environment:
202+ BUILD: "cabal-v2"
203+ GHCVER: "8.4.4"
204+ CABAL_BUILD_OPTIONS: "--flag debug --flag limit-build-mem"
205+ command: |
206+ apt-get install -y ghc-8.4.4
207+ apt-get install -y cabal-install-3.2
208+ bash -c "$PACKCHECK $BUILD"
209+ - *save
210+ cabal-ghc-8_2_2:
211+ <<: *env
212+ executor: amd64-executor
213+ steps:
214+ - *preinstall
215+ - checkout
216+ - *project-preinstall
217+ - *restore
173218 - run:
174219 environment:
175− GHCVER: "9.8.1"
176− CABAL_VERSION: "3.10.1.0"
177− CABAL_PROJECT: "cabal.project.doctest"
178− DISABLE_SDIST_BUILD: "y"
179− DISABLE_TEST: "y"
180− DISABLE_BENCH: "y"
181− DISABLE_DOCS: "y"
182− ENABLE_DOCSPEC: "y"
183− DOCSPEC_URL: https://github.com/phadej/cabal-extras/releases/download/cabal-docspec-0.0.0.20210111/cabal-docspec-0.0.0.20210111.xz
184− DOCSPEC_OPTIONS: "--timeout 60 --check-properties --property-variables xs"
220+ BUILD: "cabal-v2"
221+ DISABLE_TEST: "yes"
222+ DISABLE_BENCH: "yes"
223+ DISABLE_DOCS: "yes"
224+ DISABLE_SDIST_BUILD: "yes"
225+ DISABLE_DIST_CHECKS: "yes"
185226 command: |
186− bash -c "$PACKCHECK cabal"
227+ apt-get install -y ghc-8.2.2
228+ apt-get install -y cabal-install-3.2
229+ bash -c "$PACKCHECK $BUILD"
187230 - *save
188− hlint-trailing-spaces:
231+ cabal-ghc-8_0_2:
189232 <<: *env
190233 executor: amd64-executor
191234 steps:
235+ - *preinstall
192236 - checkout
237+ - *project-preinstall
193238 - *restore
239+ - run:
240+ environment:
241+ BUILD: "cabal-v2"
242+ DISABLE_TEST: "yes"
243+ DISABLE_BENCH: "yes"
244+ DISABLE_DOCS: "yes"
245+ DISABLE_SDIST_BUILD: "yes"
246+ DISABLE_DIST_CHECKS: "yes"
247+ command: |
248+ apt-get install -y ghc-8.0.2
249+ apt-get install -y cabal-install-3.2
250+ bash -c "$PACKCHECK $BUILD"
251+ - *save
252+ cabal-ghc-7_10_3:
253+ <<: *env
254+ executor: amd64-executor
255+ steps:
194256 - *preinstall
257+ - checkout
258+ - *project-preinstall
259+ - *restore
260+ - run: |
261+ apt-get install -y ghc-7.10.3
262+ apt-get install -y cabal-install-2.4
263+ bash -c "$PACKCHECK cabal-v2"
264+ - *save
265+ stack-ghc-8_4:
266+ <<: *env
267+ executor: amd64-executor
268+ steps:
269+ - *preinstall
270+ - checkout
271+ - *project-preinstall
272+ - *restore
273+ - run: |
274+ bash -c "$PACKCHECK stack RESOLVER=lts-12"
275+ - *save
276+ stack-ghc-8_2:
277+ <<: *env
278+ executor: amd64-executor
279+ steps:
280+ - *preinstall
281+ - checkout
282+ - *project-preinstall
283+ - *restore
284+ - run: |
285+ bash -c "$PACKCHECK stack RESOLVER=lts-11"
286+ - *save
287+ cabal-ghcjs-8_4:
288+ <<: *env
289+ executor: amd64-executor
290+ steps:
291+ - *preinstall
292+ - checkout
293+ - *project-preinstall
294+ - *restore
195295 - run:
196− name: hlint and trailing spaces
296+ name: GHCJS 8.4+no-test+no-docs
197297 environment:
298+ BUILD: cabal-v2
299+ ENABLE_GHCJS: "yes"
300+ DISABLE_TEST: "yes"
301+ ENABLE_INSTALL: ""
302+ DISABLE_DOCS: "yes"
198303 DISABLE_SDIST_BUILD: "yes"
199− HLINT_VERSION: 3.6.1
304+ command: |
305+ add-apt-repository -y ppa:hvr/ghcjs
306+ add-apt-repository -y 'deb https://deb.nodesource.com/node_11.x xenial main'
307+ curl -sSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
308+ apt-get update
309+ apt-get install -y cabal-install-3.2
310+ apt-get install -y nodejs
311+ apt-get install -y ghcjs-8.4
312+ cabal user-config update -a "jobs: 1"
313+ bash -c "$PACKCHECK $BUILD"
314+ - *save
315+ coveralls-ghc-8_2_2:
316+ <<: *env
317+ executor: amd64-executor
318+ steps:
319+ - *preinstall
320+ - checkout
321+ - *project-preinstall
322+ - *restore
323+ - run:
324+ environment:
325+ BUILD: cabal
326+ COVERALLS_OPTIONS: "--repo-token=\"$REPO_TOKEN\" --coverage-mode=StrictlyFullLines --exclude-dir=test test"
327+ GHC_OPTIONS: "-DCOVERAGE_BUILD"
328+ command: |
329+ apt-get install -y ghc-8.2.2
330+ apt-get install -y cabal-install-2.4
331+ bash -c "$PACKCHECK cabal-v1"
332+ - *save
333+ coveralls-ghc-8_8_3:
334+ <<: *env
335+ executor: amd64-executor
336+ steps:
337+ - *preinstall
338+ - checkout
339+ - *project-preinstall
340+ - *restore
341+ - run:
342+ environment:
343+ BUILD: cabal-v2
344+ COVERALLS_OPTIONS: "--repo-token=\"$REPO_TOKEN\" --coverage-mode=StrictlyFullLines --exclude-dir=test"
345+ CABAL_PROJECT: "cabal.project.coverage"
346+ CABAL_BUILD_TARGETS: ""
347+ command: |
348+ apt-get install -y ghc-8.8.3
349+ apt-get install -y cabal-install-3.0
350+ bash -c "$PACKCHECK cabal-v2"
351+ no_output_timeout: 25m
352+ - *save
353+ coveralls-ghc-8_10_2:
354+ <<: *env
355+ executor: amd64-executor
356+ steps:
357+ - *preinstall
358+ - checkout
359+ - *project-preinstall
360+ - *restore
361+ - run:
362+ name: Build and test with inspection, coverage, Werror
363+ command: |
364+ apt-get install -y ghc-8.10.2
365+ apt-get install -y cabal-install-3.2
366+ # Run tests with coverage
367+ cabal update
368+ cabal user-config update -a "jobs: 1"
369+ bin/test.sh --coverage --raw
370+ # Upload results to coveralls.io
371+ PATH=$HOME/.cabal/bin:$PATH
372+ export PATH
373+ which hpc-coveralls 2>/dev/null || cabal install --project-file cabal.project.hpc-coveralls hpc-coveralls
374+ hpc-coveralls --repo-token="$REPO_TOKEN" --coverage-mode=StrictlyFullLines
375+ no_output_timeout: 25m
376+ - *save
377+ hlint-src:
378+ <<: *env
379+ executor: amd64-executor
380+ steps:
381+ - *preinstall
382+ - checkout
383+ - *project-preinstall
384+ - *restore
385+ - run:
386+ name: Hlint src
387+ environment:
388+ BUILD: hlint
200389 HLINT_OPTIONS: lint
390+ DISABLE_SDIST_BUILD: "yes"
201391 HLINT_TARGETS: core/src src test benchmark
202392 command: |
203− bash -c "$PACKCHECK hlint" || exit 1
393+ bash -c "$PACKCHECK $BUILD" || exit 1
204394 echo "Checking trailing spaces..."
205395 count=$(find . -name "*.hs" -exec grep -H '\ $' {} \; | tee /dev/tty | wc -l)
206396 exit $count
@@ -210,9 +400,23 @@ workflows:
210400 version: 2
211401 build:
212402 jobs:
213− #- cabal-ghc-8_6_5:
214− # name: 8.6.5-debug-unoptimized
215− - cabal-ghc-9_8_1-docspec:
216− name: ghc-9.8.1-docspec
217− - hlint-trailing-spaces:
218− name: hlint and trailing spaces
403+ - cabal-ghc-8_10_4:
404+ name: GHC 8.10.4 + sdist + no-test + no-bench
405+ #- cabal-ghc-8.6.5
406+ #- cabal-ghc-8_4_4:
407+ # name: GHC 8.4.4 + x86 + debug
408+ #- cabal-ghc-8_2_2:
409+ # name: GHC 8.2.2 + no-test + no-bench + no-docs
410+ #- cabal-ghc-8_0_2:
411+ # name: GHC 8.0.2 + no-test + no-bench + no-docs
412+ #- cabal-ghc-7.10.3
413+ # - cabal-ghcjs-8_4:
414+ # name: GHCJS 8.4 + no-test + no-docs
415+ #- stack-ghc-8.4
416+ #- stack-ghc-8.2
417+ #- coveralls-ghc-8.2.2
418+ #- coveralls-ghc-8.8.3
419+ #- coveralls-ghc-8_10_2:
420+ # name: GHC 8.10.2 + inspection + coverage + Werror
421+ - hlint-src:
422+ name: Hlint src + Trailing Spaces
.github/workflows/haskell.yml+60−61
@@ -13,15 +13,9 @@ jobs:
1313 # packcheck environment variables
1414 LC_ALL: C.UTF-8
1515 BUILD: ${{ matrix.build }}
16− # For updating see: https://downloads.haskell.org/~ghcup/
17− GHCUP_VERSION: 0.1.20.0
18− DOCSPEC_URL: https://github.com/phadej/cabal-extras/releases/download/cabal-docspec-0.0.0.20210111/cabal-docspec-0.0.0.20210111.xz
19− DOCSPEC_OPTIONS: "--timeout 60 --check-properties --property-variables xs"
20− GHCUP_GHC_OPTIONS: ${{ matrix.ghcup_ghc_options }}
2116 GHCVER: ${{ matrix.ghc_version }}
2217 CABALVER: ${{ matrix.cabal_version }}
2318 DISABLE_DOCS: ${{ matrix.disable_docs }}
24− ENABLE_DOCSPEC: ${{ matrix.enable_docspec }}
2519 DISABLE_TEST: ${{ matrix.disable_test }}
2620 DISABLE_BENCH: ${{ matrix.disable_bench }}
2721 DISABLE_DIST_CHECKS: ${{ matrix.disable_dist_checks }}
@@ -45,18 +39,14 @@ jobs:
4539 STACK_BUILD_OPTIONS: ${{ matrix.stack_build_options }}
4640
4741 # packcheck location and revision
48− PACKCHECK: "./packcheck.sh"
42+ PACKCHECK_LOCAL_PATH: "./packcheck.sh"
4943 PACKCHECK_GITHUB_URL: "https://raw.githubusercontent.com/composewell/packcheck"
50− PACKCHECK_GITHUB_COMMIT: "v0.7.0"
44+ PACKCHECK_GITHUB_COMMIT: "a302772c8f3791c477edd1764b82f8d1f5b22fdf"
5145
5246 # Pull token from "secrets" setting of the github repo
5347 COVERALLS_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
5448 COVERAGE: ${{ matrix.coverage }}
55−
56− # hlint
57− HLINT_VERSION: 3.6.1
58− HLINT_OPTIONS: "lint"
59− HLINT_TARGETS: "core/src src test benchmark"
49+ DOCTEST: ${{ matrix.doctest }}
6050
6151 # Subdir
6252 SUBDIR: ${{ matrix.subdir }}
@@ -69,7 +59,7 @@ jobs:
6959 # The order is important to optimize fail-fast.
7060 name:
7161 - 9.8.1-Werror
72− # - 9.8.1-docspec
62+ - 9.2.8-docspec
7363 # - 8.10.7-coverage
7464
7565 # Note: if cabal.project is not specified benchmarks and tests won't
@@ -78,19 +68,9 @@ jobs:
7868 include:
7969 - name: head
8070 ghc_version: head
81− # The URL may change, to find a working URL go to https://gitlab.haskell.org/ghc/ghc/-/jobs/
82− # Find a debian10/11/12 job, click on a passed/failed status, at the
83− # end of the output you will find the tar.xz name, put that tar
84− # name after "raw/", and put the job name after "job=".
85− # Also see https://github.com/mpickering/ghc-artefact-nix/blob/master/gitlab-artifact.nix
86− #
87− # May also use ghcup for installing ghc head version, use the
88− # version "LatestNightly", and the following config:
89− # ghcup config add-release-channel https://ghc.gitlab.haskell.org/ghcup-metadata/ghcup-nightlies-0.0.7.yaml
90− ghcup_ghc_options: "-u https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-deb10-int_native-validate.tar.xz?job=x86_64-linux-deb10-int_native-validate"
9171 runner: ubuntu-latest
9272 build: cabal
93− cabal_version: 3.10.2.0
73+ cabal_version: 3.10.1.0
9474 cabal_project: cabal.project.ghc-head
9575 disable_sdist_build: "y"
9676 ignore_error: true
@@ -103,18 +83,6 @@ jobs:
10383 disable_sdist_build: "y"
10484 cabal_project: cabal.project.Werror
10585 ignore_error: false
106− #- name: 9.8.1-docspec
107− # ghc_version: 9.8.1
108− # runner: ubuntu-latest
109− # build: cabal
110− # cabal_version: 3.10.1.0
111− # cabal_project: cabal.project.doctest
112− # disable_test: "y"
113− # disable_bench: "y"
114− # disable_docs: "y"
115− # enable_docspec: "y"
116− # disable_sdist_build: "y"
117− # ignore_error: false
11886 - name: 9.8.1-fusion-inspection
11987 ghc_version: 9.8.1
12088 runner: ubuntu-latest
@@ -148,6 +116,14 @@ jobs:
148116 cabal_version: 3.6.2.0
149117 disable_sdist_build: "y"
150118 ignore_error: false
119+ - name: 9.2.8-docspec
120+ ghc_version: 9.2.8
121+ runner: ubuntu-latest
122+ doctest: "y"
123+ cabal_version: 3.6.2.0
124+ cabal_project: cabal.project
125+ disable_sdist_build: "y"
126+ ignore_error: false
151127 - name: 9.0.2-streamly-sdist
152128 ghc_version: 9.0.2
153129 runner: ubuntu-latest
@@ -194,44 +170,66 @@ jobs:
194170 cabal_build_options: "--flag debug --flag -opt"
195171 disable_sdist_build: "y"
196172 ignore_error: false
197− - name: hlint
198− build: hlint
199− runner: ubuntu-latest
200− ignore_error: true
201173
202174 steps:
203175 - uses: actions/checkout@v2
204176
205177 - uses: actions/cache@v1
206− name: Cache common directories
178+ name: Cache ~/.cabal
207179 with:
208− path: |
209− ~/.local
210− ~/.cabal
211− ~/.stack
212− ~/.ghcup
180+ path: ~/.cabal
213181 # Bump the key version to clear the cache
214182 key: ${{ runner.os }}-${{ matrix.ghc_version }}-cabal-v2
215183
216184 - name: Download packcheck
217185 run: |
218− if test ! -e "$PACKCHECK"
219− then
220− if test -z "$PACKCHECK_GITHUB_COMMIT"
221− then
222− die "PACKCHECK_GITHUB_COMMIT is not specified."
223− fi
224− PACKCHECK_URL=${PACKCHECK_GITHUB_URL}/${PACKCHECK_GITHUB_COMMIT}/packcheck.sh
225− curl --fail -sL -o "$PACKCHECK" $PACKCHECK_URL || exit 1
226− chmod +x $PACKCHECK
227− elif test ! -x "$PACKCHECK"
186+ # Get packcheck if needed
187+ CURL=$(which curl)
188+ PACKCHECK_URL=${PACKCHECK_GITHUB_URL}/${PACKCHECK_GITHUB_COMMIT}/packcheck.sh
189+ if test ! -e "$PACKCHECK_LOCAL_PATH"; then $CURL -sL -o "$PACKCHECK_LOCAL_PATH" $PACKCHECK_URL; fi;
190+ chmod +x $PACKCHECK_LOCAL_PATH
191+
192+ os=$(uname -s -m)
193+ case "$os" in
194+ "Linux x86_64") GHCUP_ARCH="x86_64-linux" ;;
195+ "Darwin x86_64") GHCUP_ARCH="x86_64-apple-darwin" ;;
196+ *) echo "Unknown OS/Arch: $os"; exit 1;;
197+ esac
198+
199+ # Check available versions here: https://downloads.haskell.org/~ghcup/
200+ GHCUP_VER=0.1.18.0
201+ $CURL -sL -o ./ghcup https://downloads.haskell.org/~ghcup/$GHCUP_VER/${GHCUP_ARCH}-ghcup-$GHCUP_VER
202+ chmod +x ./ghcup
203+ if test "$GHCVER" = "head"
228204 then
229− chmod +x $PACKCHECK
205+ # The URL may change, to find a working URL go to https://gitlab.haskell.org/ghc/ghc/-/jobs/
206+ # Find a debian10 job, click on a passed/failed job, at the
207+ # end of the output you will find the tar.xz name, put that after
208+ # "raw/", and put the job name after "job=".
209+ # Also see https://github.com/mpickering/ghc-artefact-nix/blob/master/gitlab-artifact.nix
210+ ./ghcup install ghc -u https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-deb10-int_native-validate.tar.xz?job=x86_64-linux-deb10-int_native-validate head
211+ else
212+ ./ghcup install ghc $GHCVER
230213 fi
214+ ./ghcup install cabal $CABALVER
215+ ./ghcup set ghc $GHCVER
216+ ./ghcup set cabal $CABALVER
231217
232218 - name: Run tests
233219 run: |
234− if test -n "$COVERAGE"
220+ if test -n "$DOCTEST"
221+ then
222+ mkdir -p $HOME/.cabal/bin
223+ curl -sL https://github.com/phadej/cabal-extras/releases/download/cabal-docspec-0.0.0.20210111/cabal-docspec-0.0.0.20210111.xz > cabal-docspec.xz
224+ echo '0829bd034fba901cbcfe491d98ed8b28fd54f9cb5c91fa8e1ac62dc4413c9562 cabal-docspec.xz' | sha256sum -c -
225+ xz -d < cabal-docspec.xz > $HOME/.cabal/bin/cabal-docspec
226+ rm -f cabal-docspec.xz
227+ chmod a+x $HOME/.cabal/bin/cabal-docspec
228+ cabal update
229+ cabal build --project-file cabal.project.doctest all
230+ $HOME/.cabal/bin/cabal-docspec --version
231+ $HOME/.cabal/bin/cabal-docspec --timeout 60 --check-properties --property-variables xs
232+ elif test -n "$COVERAGE"
235233 then
236234 # Run tests with coverage
237235 cabal update
@@ -244,15 +242,16 @@ jobs:
244242 # XXX Uncomment this and fix it properly later
245243 # hpc-coveralls --repo-token="$COVERALLS_TOKEN" --coverage-mode=StrictlyFullLines
246244 else
245+ export TOOLS_DIR=/opt
247246 # /usr/local/opt/curl/bin for macOS
248247 export PATH=$HOME/.local/bin:$HOME/.ghcup/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/opt/curl/bin
249248 if test -n "$SUBDIR"
250249 then
251− mv "$PACKCHECK" "$SUBDIR/packcheck.sh"
250+ mv "$PACKCHECK_LOCAL_PATH" "$SUBDIR/packcheck.sh"
252251 # This is required as dist-newstyle will be created on the top level
253252 # directory as it is considered the working dir.
254253 rm cabal.project
255254 cd "$SUBDIR"
256255 fi
257− bash -c "$PACKCHECK $BUILD"
256+ bash -c "$PACKCHECK_LOCAL_PATH $BUILD"
258257 fi
.hlint.ignore−5
@@ -2,9 +2,6 @@ core/src/Streamly/Internal/Data/Stream/StreamK/Type.hs
22core/src/Streamly/Internal/Data/Pipe/Type.hs
33core/src/Streamly/Internal/Unicode/Stream.hs
44src/Streamly/Internal/Data/SmallArray/Type.hs
5−src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs
6−src/Streamly/Internal/Data/Stream/Serial.hs
7−src/Streamly/Internal/Data/Stream/Zip.hs
85test/Streamly/Test/Data/Array.hs
96test/Streamly/Test/Data/Parser.hs
107test/Streamly/Test/Data/ParserK.hs
@@ -13,7 +10,6 @@ test/Streamly/Test/Data/Unfold.hs
1310test/Streamly/Test/FileSystem/Event.hs
1411test/Streamly/Test/Prelude/Concurrent.hs
1512test/Streamly/Test/Data/Stream/Concurrent.hs
16−test/lib/Streamly/Test/Prelude/Common.hs
1713test/Streamly/Test/Prelude/Fold.hs
1814test/Streamly/Test/Prelude/Rate.hs
1915test/Streamly/Test/Prelude/Serial.hs
@@ -31,7 +27,6 @@ benchmark/Streamly/Benchmark/Data/Stream/StreamK.hs
3127benchmark/Streamly/Benchmark/Data/Unfold.hs
3228benchmark/Streamly/Benchmark/FileSystem/Handle.hs
3329benchmark/Streamly/Benchmark/Prelude/Async.hs
34−benchmark/Streamly/Benchmark/Prelude/Concurrent.hs
3530benchmark/Streamly/Benchmark/Prelude/Merge.hs
3631benchmark/Streamly/Benchmark/Prelude/Parallel.hs
3732benchmark/Streamly/Benchmark/Prelude/Rate.hs
benchmark/Streamly/Benchmark/Data/Fold.hs+2−2
@@ -269,13 +269,13 @@ unzip = Stream.fold $ FL.lmap (\a -> (a, a)) (FL.unzip FL.sum FL.length)
269269{-# INLINE unzipWithFstM #-}
270270unzipWithFstM :: Monad m => Stream m Int -> m (Int, Int)
271271unzipWithFstM = do
272− let f a = return (a + 1, a)
272+ let f = \a -> return (a + 1, a)
273273 Stream.fold (FL.unzipWithFstM f FL.sum FL.length)
274274
275275{-# INLINE unzipWithMinM #-}
276276unzipWithMinM :: Monad m => Stream m Int -> m (Int, Int)
277277unzipWithMinM = do
278− let f a = return (a + 1, a)
278+ let f = \a -> return (a + 1, a)
279279 Stream.fold (FL.unzipWithMinM f FL.sum FL.length)
280280
281281-------------------------------------------------------------------------------
benchmark/Streamly/Benchmark/Data/Serialize.hs+15−10
@@ -1,5 +1,4 @@
11{-# LANGUAGE TemplateHaskell #-}
2−{- HLINT ignore -}
32
43#undef FUSION_CHECK
54#ifdef FUSION_CHECK
@@ -19,7 +18,6 @@ module Main (main) where
1918-------------------------------------------------------------------------------
2019
2120import Control.DeepSeq (NFData(..), deepseq)
22−import Control.Monad (when, void)
2321import GHC.Generics (Generic)
2422import System.Random (randomRIO)
2523#ifndef USE_UNBOX
@@ -266,14 +264,13 @@ $(deriveSerialize [d|instance Serialize a => Serialize (BinTree a)|])
266264instance NFData a => NFData (BinTree a) where
267265 {-# INLINE rnf #-}
268266 rnf (Leaf a) = rnf a `seq` ()
269− rnf (Tree l r) = rnf l `seq` rnf r
267+ rnf (Tree l r) = rnf l `seq` rnf r `seq` ()
270268
271−-- XXX This may not terminate, or could become really large.
272269instance Arbitrary a => Arbitrary (BinTree a) where
273270 arbitrary = oneof [Leaf <$> arbitrary, Tree <$> arbitrary <*> arbitrary]
274271
275272mkBinTree :: (Arbitrary a) => Int -> IO (BinTree a)
276−mkBinTree = go (generate arbitrary)
273+mkBinTree = go (generate $ arbitrary)
277274
278275 where
279276
@@ -298,14 +295,16 @@ getSize = addSizeTo 0
298295-- Common helpers
299296-------------------------------------------------------------------------------
300297
301−{- HLINT ignore "Eta reduce" -}
302298-- Parts of "f" that are dependent on val will not be optimized out.
303299{-# INLINE loop #-}
304300loop :: Int -> (a -> IO b) -> a -> IO ()
305301loop count f val = go count val
306302 where
307303
308− go n x = when (n > 0) $ f x >> go (n-1) x
304+ go n x = do
305+ if n > 0
306+ then f x >> go (n-1) x
307+ else return ()
309308
310309-- The first arg of "f" is the environment which is not threaded around in the
311310-- loop.
@@ -314,7 +313,10 @@ loopWith :: Int -> (e -> a -> IO b) -> e -> a -> IO ()
314313loopWith count f e val = go count val
315314 where
316315
317− go n x = when (n > 0) $ f e x >> go (n-1) x
316+ go n x = do
317+ if n > 0
318+ then f e x >> go (n-1) x
319+ else return ()
318320
319321benchSink :: NFData b => String -> Int -> (Int -> IO b) -> Benchmark
320322benchSink name times f = bench name (nfIO (randomRIO (times, times) >>= f))
@@ -340,7 +342,7 @@ pokeTimesWithSize val times = do
340342
341343{-# INLINE poke #-}
342344poke :: SERIALIZE_CLASS a => MutByteArray -> a -> IO ()
343−poke arr val = void (SERIALIZE_OP 0 arr val)
345+poke arr val = SERIALIZE_OP 0 arr val >> return ()
344346
345347{-# INLINE pokeTimes #-}
346348pokeTimes :: SERIALIZE_CLASS a => a -> Int -> IO ()
@@ -354,7 +356,7 @@ encode :: SERIALIZE_CLASS a => a -> IO ()
354356encode val = do
355357 let n = getSize val
356358 arr <- MBA.new n
357− void (SERIALIZE_OP 0 arr val)
359+ SERIALIZE_OP 0 arr val >> return ()
358360
359361{-# INLINE encodeTimes #-}
360362encodeTimes :: SERIALIZE_CLASS a => a -> Int -> IO ()
@@ -560,6 +562,8 @@ main = do
560562 let !len = length lInt -- evaluate the list
561563#endif
562564#ifndef FUSION_CHECK
565+ -- This can take too much memory/CPU, need to restrict the test
566+ -- runQC
563567#ifdef USE_UNBOX
564568 runWithCLIOpts defaultStreamSize allBenchmarks
565569#else
@@ -567,6 +571,7 @@ main = do
567571 `seq` runWithCLIOpts
568572 defaultStreamSize
569573 (allBenchmarks tInt lInt recL recR)
574+
570575#endif
571576#else
572577 -- Enable FUSION_CHECK macro at the beginning of the file
benchmark/Streamly/Benchmark/Data/Serialize/RecCompatible.hs+1−1
@@ -20,5 +20,5 @@ import qualified Streamly.Internal.Data.MutByteArray as Serialize
2020
2121$(genLargeRecord "RecCompatible" 50)
2222$(Serialize.deriveSerializeWith
23− (Serialize.encodeRecordFields True)
23+ (Serialize.encodeRecordFields True Serialize.serializeConfig)
2424 [d|instance Serialize RecCompatible|])
benchmark/Streamly/Benchmark/Data/Serialize/TH.hs+3−3
@@ -18,7 +18,7 @@ import Control.DeepSeq (NFData(..))
1818genLargeRecord :: String -> Int -> Q [Dec]
1919genLargeRecord tyName numFields =
2020 sequence
21− [ dataD
21+ ([ dataD
2222 (pure [])
2323 (mkName tyName)
2424 []
@@ -28,7 +28,7 @@ genLargeRecord tyName numFields =
2828 , mkValueSigDec
2929 , mkValueDec
3030 , nfDataInstance tyName
31− ]
31+ ])
3232
3333 where
3434
@@ -64,7 +64,7 @@ genLargeRecord tyName numFields =
6464 (foldl
6565 (\b a -> [|$(b) $(a)|])
6666 (conE (mkName tyName))
67− (conE '() <$ [0 .. (numFields - 1)])))
67+ (const (conE '()) <$> [0 .. (numFields - 1)])))
6868 []
6969 ]
7070 mkCon nm = recC (mkName nm) (mkField <$> [0 .. (numFields - 1)])
benchmark/Streamly/Benchmark/Data/Stream/ConcurrentCommon.hs+2−2
@@ -14,12 +14,12 @@ where
1414import Stream.Common
1515 (composeN, benchIO, benchIOSink, benchIOSrc, sourceUnfoldrM)
1616import Streamly.Data.Stream (Stream)
17−import Streamly.Internal.Data.Stream.Prelude (MonadAsync, Config)
17+import Streamly.Internal.Data.Stream.Concurrent (MonadAsync, Config)
1818
1919import qualified Data.List as List
2020import qualified Streamly.Data.Fold as Fold
2121import qualified Streamly.Data.Stream as Stream
22−import qualified Streamly.Internal.Data.Stream.Prelude as Async
22+import qualified Streamly.Internal.Data.Stream.Concurrent as Async
2323
2424import Test.Tasty.Bench
2525import Prelude hiding (mapM)
benchmark/Streamly/Benchmark/Data/Stream/ConcurrentEager.hs+1−1
@@ -9,7 +9,7 @@
99import Stream.ConcurrentCommon (allBenchmarks)
1010import Streamly.Benchmark.Common (runWithCLIOpts, defaultStreamSize)
1111
12−import qualified Streamly.Internal.Data.Stream.Prelude as Async
12+import qualified Streamly.Internal.Data.Stream.Concurrent as Async
1313
1414moduleName :: String
1515moduleName = "Data.Stream.ConcurrentEager"
benchmark/Streamly/Benchmark/Data/Stream/ConcurrentInterleaved.hs+1−1
@@ -9,7 +9,7 @@
99import Stream.ConcurrentCommon (allBenchmarks)
1010import Streamly.Benchmark.Common (runWithCLIOpts, defaultStreamSize)
1111
12−import qualified Streamly.Internal.Data.Stream.Prelude as Async
12+import qualified Streamly.Internal.Data.Stream.Concurrent as Async
1313
1414moduleName :: String
1515moduleName = "Data.Stream.ConcurrentInterleaved"
benchmark/Streamly/Benchmark/Data/Stream/ConcurrentOrdered.hs+1−1
@@ -9,7 +9,7 @@
99import Stream.ConcurrentCommon (allBenchmarks)
1010import Streamly.Benchmark.Common (runWithCLIOpts, defaultStreamSize)
1111
12−import qualified Streamly.Internal.Data.Stream.Prelude as Async
12+import qualified Streamly.Internal.Data.Stream.Concurrent as Async
1313
1414moduleName :: String
1515moduleName = "Data.Stream.ConcurrentOrdered"
benchmark/Streamly/Benchmark/Data/Stream/Eliminate.hs−2
@@ -132,14 +132,12 @@ foldableAny :: Int -> Int -> Bool
132132foldableAny value n =
133133 Prelude.any (> (value + 1)) (sourceUnfoldr value n :: Stream Identity Int)
134134
135−{- HLINT ignore "Use all"-}
136135{-# INLINE foldableAnd #-}
137136foldableAnd :: Int -> Int -> Bool
138137foldableAnd value n =
139138 Prelude.and $ fmap
140139 (<= (value + 1)) (sourceUnfoldr value n :: Stream Identity Int)
141140
142−{- HLINT ignore "Use any"-}
143141{-# INLINE foldableOr #-}
144142foldableOr :: Int -> Int -> Bool
145143foldableOr value n =
benchmark/Streamly/Benchmark/Data/Stream/Exceptions.hs+2−2
@@ -36,13 +36,13 @@ import System.IO (Handle, hClose, hPutChar)
3636import qualified Streamly.FileSystem.Handle as FH
3737import qualified Streamly.Internal.FileSystem.Handle as IFH
3838import qualified Streamly.Internal.Data.Unfold as IUF
39−import qualified Streamly.Internal.Data.Unfold.Prelude as IUF
39+import qualified Streamly.Internal.Data.Unfold.Exception as IUF
4040
4141#ifdef USE_PRELUDE
4242import qualified Streamly.Internal.Data.Stream.IsStream as Stream
4343#else
4444import qualified Streamly.Internal.Data.Stream as Stream
45−import qualified Streamly.Internal.Data.Stream.Prelude as Stream
45+import qualified Streamly.Internal.Data.Stream.Exception.Lifted as Stream
4646#endif
4747
4848import Test.Tasty.Bench hiding (env)
benchmark/Streamly/Benchmark/Data/Stream/Reduce.hs+1−1
@@ -48,7 +48,7 @@ import Streamly.Internal.Data.Stream (Stream)
4848import qualified Streamly.Internal.Data.Stream as S
4949#ifndef USE_STREAMLY_CORE
5050import qualified Streamly.Data.Stream.Prelude as S
51−import qualified Streamly.Internal.Data.Stream.Prelude as S
51+import qualified Streamly.Internal.Data.Stream.Time as S
5252#endif
5353
5454#ifdef USE_STREAMK
benchmark/Streamly/Benchmark/Data/Stream/StreamKAlt.hs+1−1
@@ -452,4 +452,4 @@ o_1_space =
452452 ]
453453
454454main :: IO ()
455−main = defaultMain [o_1_space]
455+main = defaultMain $ concat [o_1_space]
benchmark/Streamly/Benchmark/Data/Stream/ToStreamK.hs+1−1
@@ -120,7 +120,7 @@ fromFoldable streamLen n = S.fromFoldable [n..n+streamLen]
120120{-# INLINE fromFoldableM #-}
121121fromFoldableM :: Monad m => Int -> Int -> Stream m Int
122122fromFoldableM streamLen n =
123− Prelude.foldr (S.consM . return) S.nil [n .. n + streamLen]
123+ Prelude.foldr S.consM S.nil (Prelude.fmap return [n..n+streamLen])
124124
125125{-
126126{-# INLINABLE concatMapFoldableWith #-}
benchmark/Streamly/Benchmark/Data/Stream/Transform.hs+1−1
@@ -46,7 +46,7 @@ import Streamly.Internal.Data.Time.Units
4646import Streamly.Internal.Data.Stream (Stream)
4747import qualified Streamly.Internal.Data.Stream as Stream
4848#ifndef USE_STREAMLY_CORE
49−import qualified Streamly.Internal.Data.Stream.Prelude as Stream
49+import qualified Streamly.Internal.Data.Stream.Time as Stream
5050#endif
5151#ifdef USE_STREAMK
5252import Control.DeepSeq (NFData(..))
benchmark/Streamly/Benchmark/Data/Unfold.hs+1−1
@@ -31,7 +31,7 @@ import qualified Prelude
3131import qualified Streamly.FileSystem.Handle as FH
3232import qualified Streamly.Internal.Data.Fold as FL
3333import qualified Streamly.Internal.Data.Unfold as UF
34−import qualified Streamly.Internal.Data.Unfold.Prelude as UF
34+import qualified Streamly.Internal.Data.Unfold.Exception as UF
3535import qualified Streamly.Internal.Data.Stream as S
3636import qualified Streamly.Internal.Data.Stream as D
3737import qualified Streamly.Internal.Data.StreamK as K
benchmark/Streamly/Benchmark/FileSystem/Handle/Read.hs+8−7
@@ -33,6 +33,7 @@ import qualified Streamly.Data.Stream as Stream
3333import qualified Streamly.Data.Fold as Fold
3434import qualified Streamly.FileSystem.Handle as FH
3535import qualified Streamly.Internal.Data.Array as A
36+import qualified Streamly.Internal.Data.Array as AT
3637import qualified Streamly.Internal.Data.Fold as FL
3738import qualified Streamly.Internal.Data.Stream as IP
3839import qualified Streamly.Internal.FileSystem.Handle as IFH
@@ -47,7 +48,7 @@ import Streamly.Benchmark.Common.Handle
4748#ifdef INSPECTION
4849import Streamly.Internal.Data.Stream (Step(..), FoldMany)
4950
50−import qualified Streamly.Internal.Data.MutArray as MutArray
51+import qualified Streamly.Internal.Data.MutArray as MA
5152import qualified Streamly.Internal.Data.Stream as D
5253import qualified Streamly.Internal.Data.Unfold as IUF
5354
@@ -68,7 +69,7 @@ readLast = S.fold Fold.last . S.unfold FH.reader
6869inspect $ hasNoTypeClasses 'readLast
6970inspect $ 'readLast `hasNoType` ''Step -- S.unfold
7071inspect $ 'readLast `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
71−inspect $ 'readLast `hasNoType` ''MutArray.ArrayUnsafe -- FH.read/A.read
72+inspect $ 'readLast `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
7273#endif
7374
7475-- assert that flattenArrays constructors are not present
@@ -80,7 +81,7 @@ readCountBytes = S.fold Fold.length . S.unfold FH.reader
8081inspect $ hasNoTypeClasses 'readCountBytes
8182inspect $ 'readCountBytes `hasNoType` ''Step -- S.unfold
8283inspect $ 'readCountBytes `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
83−inspect $ 'readCountBytes `hasNoType` ''MutArray.ArrayUnsafe -- FH.read/A.read
84+inspect $ 'readCountBytes `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
8485#endif
8586
8687-- | Count the number of lines in a file.
@@ -95,7 +96,7 @@ readCountLines =
9596inspect $ hasNoTypeClasses 'readCountLines
9697inspect $ 'readCountLines `hasNoType` ''Step
9798inspect $ 'readCountLines `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
98−inspect $ 'readCountLines `hasNoType` ''MutArray.ArrayUnsafe -- FH.read/A.read
99+inspect $ 'readCountLines `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
99100#endif
100101
101102-- | Count the number of words in a file.
@@ -119,7 +120,7 @@ readSumBytes = S.fold Fold.sum . S.unfold FH.reader
119120inspect $ hasNoTypeClasses 'readSumBytes
120121inspect $ 'readSumBytes `hasNoType` ''Step
121122inspect $ 'readSumBytes `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
122−inspect $ 'readSumBytes `hasNoType` ''MutArray.ArrayUnsafe -- FH.read/A.read
123+inspect $ 'readSumBytes `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
123124#endif
124125
125126-- XXX When we mark this with INLINE and we have two benchmarks using S.drain
@@ -235,13 +236,13 @@ groupsOf :: Int -> Handle -> IO Int
235236groupsOf n inh =
236237 -- writeNUnsafe gives 2.5x boost here over writeN.
237238 S.fold Fold.length
238− $ IP.groupsOf n (A.writeNUnsafe n) (S.unfold FH.reader inh)
239+ $ IP.groupsOf n (AT.writeNUnsafe n) (S.unfold FH.reader inh)
239240
240241#ifdef INSPECTION
241242inspect $ hasNoTypeClasses 'groupsOf
242243inspect $ 'groupsOf `hasNoType` ''Step
243244inspect $ 'groupsOf `hasNoType` ''FoldMany
244−inspect $ 'groupsOf `hasNoType` ''MutArray.ArrayUnsafe -- AT.writeNUnsafe
245+inspect $ 'groupsOf `hasNoType` ''AT.ArrayUnsafe -- AT.writeNUnsafe
245246 -- FH.read/A.read
246247inspect $ 'groupsOf `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
247248#endif
benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs+9−8
@@ -42,7 +42,8 @@ import Streamly.Internal.Data.Stream (Step(..))
4242
4343import qualified Streamly.Internal.Data.Stream as D
4444import qualified Streamly.Internal.Data.Tuple.Strict as Strict
45−import qualified Streamly.Internal.Data.MutArray as MutArray
45+import qualified Streamly.Internal.Data.MutArray.Stream as MAS
46+import qualified Streamly.Internal.Data.Array as AT
4647
4748import Test.Inspection
4849#endif
@@ -82,7 +83,7 @@ copyStream inh outh = S.fold (FH.write outh) (S.unfold FH.reader inh)
8283inspect $ hasNoTypeClasses 'copyStream
8384inspect $ 'copyStream `hasNoType` ''Step -- S.unfold
8485inspect $ 'copyStream `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
85−inspect $ 'copyStream `hasNoType` ''MutArray.ArrayUnsafe -- FH.write/writeNUnsafe
86+inspect $ 'copyStream `hasNoType` ''AT.ArrayUnsafe -- FH.write/writeNUnsafe
8687 -- FH.read/A.read
8788inspect $ 'copyStream `hasNoType` ''Strict.Tuple3' -- FH.write/chunksOf
8889#endif
@@ -108,8 +109,8 @@ readFromBytesNull inh devNull = IFH.putBytes devNull $ S.unfold FH.reader inh
108109#ifdef INSPECTION
109110inspect $ hasNoTypeClasses 'readFromBytesNull
110111inspect $ 'readFromBytesNull `hasNoType` ''Step
111−inspect $ 'readFromBytesNull `hasNoType` ''MutArray.SpliceState
112−inspect $ 'readFromBytesNull `hasNoType` ''MutArray.ArrayUnsafe -- FH.fromBytes/S.chunksOf
112+inspect $ 'readFromBytesNull `hasNoType` ''MAS.SpliceState
113+inspect $ 'readFromBytesNull `hasNoType` ''AT.ArrayUnsafe -- FH.fromBytes/S.chunksOf
113114inspect $ 'readFromBytesNull `hasNoType` ''D.FoldMany
114115#endif
115116
@@ -122,8 +123,8 @@ readWithFromBytesNull inh devNull =
122123#ifdef INSPECTION
123124inspect $ hasNoTypeClasses 'readWithFromBytesNull
124125inspect $ 'readWithFromBytesNull `hasNoType` ''Step
125−inspect $ 'readWithFromBytesNull `hasNoType` ''MutArray.SpliceState
126−inspect $ 'readWithFromBytesNull `hasNoType` ''MutArray.ArrayUnsafe -- FH.fromBytes/S.chunksOf
126+inspect $ 'readWithFromBytesNull `hasNoType` ''MAS.SpliceState
127+inspect $ 'readWithFromBytesNull `hasNoType` ''AT.ArrayUnsafe -- FH.fromBytes/S.chunksOf
127128inspect $ 'readWithFromBytesNull `hasNoType` ''D.FoldMany
128129#endif
129130
@@ -170,7 +171,7 @@ writeReadWith inh devNull = IUF.fold fld unf (defaultChunkSize, inh)
170171inspect $ hasNoTypeClasses 'writeReadWith
171172inspect $ 'writeReadWith `hasNoType` ''Step
172173inspect $ 'writeReadWith `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
173−inspect $ 'writeReadWith `hasNoType` ''MutArray.ArrayUnsafe -- FH.write/writeNUnsafe
174+inspect $ 'writeReadWith `hasNoType` ''AT.ArrayUnsafe -- FH.write/writeNUnsafe
174175 -- FH.read/A.read
175176#endif
176177
@@ -187,7 +188,7 @@ writeRead inh devNull = IUF.fold fld unf inh
187188inspect $ hasNoTypeClasses 'writeRead
188189inspect $ 'writeRead `hasNoType` ''Step
189190inspect $ 'writeRead `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
190−inspect $ 'writeRead `hasNoType` ''MutArray.ArrayUnsafe -- FH.write/writeNUnsafe
191+inspect $ 'writeRead `hasNoType` ''AT.ArrayUnsafe -- FH.write/writeNUnsafe
191192 -- FH.read/A.read
192193#endif
193194
benchmark/Streamly/Benchmark/Unicode/Stream.hs+3−4
@@ -45,10 +45,9 @@ import Streamly.Benchmark.Common.Handle
4545#ifdef INSPECTION
4646import Streamly.Internal.Data.MutByteArray (Unbox)
4747import Streamly.Internal.Data.Stream (Step(..))
48−import qualified Streamly.Internal.Data.Array as Array
49−import qualified Streamly.Internal.Data.MutArray as MutArray
5048import qualified Streamly.Internal.Data.Fold as Fold
5149import qualified Streamly.Internal.Data.Tuple.Strict as Strict
50+import qualified Streamly.Internal.Data.Array as Array
5251
5352import Test.Inspection
5453#endif
@@ -224,7 +223,7 @@ inspect $ 'copyStreamLatin1' `hasNoType` ''Step
224223inspect $ 'copyStreamLatin1' `hasNoType` ''Unfold.ConcatState -- Handle.read/UF.many
225224
226225inspect $ 'copyStreamLatin1' `hasNoType` ''Fold.Step
227−inspect $ 'copyStreamLatin1' `hasNoType` ''MutArray.ArrayUnsafe -- Handle.write/writeNUnsafe
226+inspect $ 'copyStreamLatin1' `hasNoType` ''Array.ArrayUnsafe -- Handle.write/writeNUnsafe
228227 -- Handle.read/Array.read
229228inspect $ 'copyStreamLatin1' `hasNoType` ''Strict.Tuple3' -- Handle.write/chunksOf
230229#endif
@@ -245,7 +244,7 @@ inspect $ 'copyStreamLatin1 `hasNoType` ''Unfold.ConcatState -- Handle.read/UF.m
245244
246245inspect $ 'copyStreamLatin1 `hasNoType` ''Fold.ManyState
247246inspect $ 'copyStreamLatin1 `hasNoType` ''Fold.Step
248−inspect $ 'copyStreamLatin1 `hasNoType` ''MutArray.ArrayUnsafe -- Handle.write/writeNUnsafe
247+inspect $ 'copyStreamLatin1 `hasNoType` ''Array.ArrayUnsafe -- Handle.write/writeNUnsafe
249248 -- Handle.read/Array.read
250249inspect $ 'copyStreamLatin1 `hasNoType` ''Strict.Tuple3' -- Handle.write/chunksOf
251250#endif
benchmark/streamly-benchmarks.cabal+1−1
@@ -188,7 +188,7 @@ common bench-depends
188188 , unordered-containers >= 0.2 && < 0.3
189189 , process >= 1.4 && < 1.7
190190 , directory >= 1.2.2 && < 1.4
191− , filepath >= 1.4.1 && < 1.6
191+ , filepath >= 1.4.1 && < 1.5
192192 , ghc-prim >= 0.4 && < 0.12
193193 , tasty-bench >= 0.3 && < 0.4
194194 , tasty >= 1.4.1 && < 1.6
configure+9−9
@@ -1,6 +1,6 @@
11#! /bin/sh
22# Guess values for system-dependent variables and create Makefiles.
3−# Generated by GNU Autoconf 2.71 for streamly 0.10.1.
3+# Generated by GNU Autoconf 2.71 for streamly 0.10.0.
44#
55# Report bugs to <streamly@composewell.com>.
66#
@@ -610,8 +610,8 @@ MAKEFLAGS=
610610# Identity of this package.
611611PACKAGE_NAME='streamly'
612612PACKAGE_TARNAME='streamly'
613−PACKAGE_VERSION='0.10.1'
614−PACKAGE_STRING='streamly 0.10.1'
613+PACKAGE_VERSION='0.10.0'
614+PACKAGE_STRING='streamly 0.10.0'
615615PACKAGE_BUGREPORT='streamly@composewell.com'
616616PACKAGE_URL='https://streamly.composewell.com'
617617
@@ -1224,7 +1224,7 @@ if test "$ac_init_help" = "long"; then
12241224 # Omit some internal or obsolete options to make the list less imposing.
12251225 # This message is too long to be a string in the A/UX 3.1 sh.
12261226 cat <<_ACEOF
1227−\`configure' configures streamly 0.10.1 to adapt to many kinds of systems.
1227+\`configure' configures streamly 0.10.0 to adapt to many kinds of systems.
12281228
12291229Usage: $0 [OPTION]... [VAR=VALUE]...
12301230
@@ -1286,7 +1286,7 @@ fi
12861286
12871287if test -n "$ac_init_help"; then
12881288 case $ac_init_help in
1289− short | recursive ) echo "Configuration of streamly 0.10.1:";;
1289+ short | recursive ) echo "Configuration of streamly 0.10.0:";;
12901290 esac
12911291 cat <<\_ACEOF
12921292
@@ -1372,7 +1372,7 @@ fi
13721372test -n "$ac_init_help" && exit $ac_status
13731373if $ac_init_version; then
13741374 cat <<\_ACEOF
1375−streamly configure 0.10.1
1375+streamly configure 0.10.0
13761376generated by GNU Autoconf 2.71
13771377
13781378Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1500,7 +1500,7 @@ cat >config.log <<_ACEOF
15001500This file contains any messages produced by compilers while
15011501running configure, to aid debugging if configure makes a mistake.
15021502
1503−It was created by streamly $as_me 0.10.1, which was
1503+It was created by streamly $as_me 0.10.0, which was
15041504generated by GNU Autoconf 2.71. Invocation command line was
15051505
15061506 $ $0$ac_configure_args_raw
@@ -3800,7 +3800,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
38003800# report actual input values of CONFIG_FILES etc. instead of their
38013801# values after options handling.
38023802ac_log="
3803−This file was extended by streamly $as_me 0.10.1, which was
3803+This file was extended by streamly $as_me 0.10.0, which was
38043804generated by GNU Autoconf 2.71. Invocation command line was
38053805
38063806 CONFIG_FILES = $CONFIG_FILES
@@ -3856,7 +3856,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
38563856cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
38573857ac_cs_config='$ac_cs_config_escaped'
38583858ac_cs_version="\\
3859−streamly config.status 0.10.1
3859+streamly config.status 0.10.0
38603860configured by $0, generated by GNU Autoconf 2.71,
38613861 with options \\"\$ac_cs_config\\"
38623862
configure.ac+1−1
@@ -3,7 +3,7 @@
33# See https://www.gnu.org/software/autoconf/manual/autoconf.html for help on
44# the macros used in this file.
55
6−AC_INIT([streamly], [0.10.1], [streamly@composewell.com], [streamly], [https://streamly.composewell.com])
6+AC_INIT([streamly], [0.10.0], [streamly@composewell.com], [streamly], [https://streamly.composewell.com])
77
88# To suppress "WARNING: unrecognized options: --with-compiler"
99AC_ARG_WITH([compiler], [GHC])
core/configure+9−9
@@ -1,6 +1,6 @@
11#! /bin/sh
22# Guess values for system-dependent variables and create Makefiles.
3−# Generated by GNU Autoconf 2.71 for streamly-core 0.2.2.
3+# Generated by GNU Autoconf 2.71 for streamly-core 0.2.0.
44#
55# Report bugs to <streamly@composewell.com>.
66#
@@ -610,8 +610,8 @@ MAKEFLAGS=
610610# Identity of this package.
611611PACKAGE_NAME='streamly-core'
612612PACKAGE_TARNAME='streamly-core'
613−PACKAGE_VERSION='0.2.2'
614−PACKAGE_STRING='streamly-core 0.2.2'
613+PACKAGE_VERSION='0.2.0'
614+PACKAGE_STRING='streamly-core 0.2.0'
615615PACKAGE_BUGREPORT='streamly@composewell.com'
616616PACKAGE_URL='https://streamly.composewell.com'
617617
@@ -1256,7 +1256,7 @@ if test "$ac_init_help" = "long"; then
12561256 # Omit some internal or obsolete options to make the list less imposing.
12571257 # This message is too long to be a string in the A/UX 3.1 sh.
12581258 cat <<_ACEOF
1259−\`configure' configures streamly-core 0.2.2 to adapt to many kinds of systems.
1259+\`configure' configures streamly-core 0.2.0 to adapt to many kinds of systems.
12601260
12611261Usage: $0 [OPTION]... [VAR=VALUE]...
12621262
@@ -1318,7 +1318,7 @@ fi
13181318
13191319if test -n "$ac_init_help"; then
13201320 case $ac_init_help in
1321− short | recursive ) echo "Configuration of streamly-core 0.2.2:";;
1321+ short | recursive ) echo "Configuration of streamly-core 0.2.0:";;
13221322 esac
13231323 cat <<\_ACEOF
13241324
@@ -1404,7 +1404,7 @@ fi
14041404test -n "$ac_init_help" && exit $ac_status
14051405if $ac_init_version; then
14061406 cat <<\_ACEOF
1407−streamly-core configure 0.2.2
1407+streamly-core configure 0.2.0
14081408generated by GNU Autoconf 2.71
14091409
14101410Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1622,7 +1622,7 @@ cat >config.log <<_ACEOF
16221622This file contains any messages produced by compilers while
16231623running configure, to aid debugging if configure makes a mistake.
16241624
1625−It was created by streamly-core $as_me 0.2.2, which was
1625+It was created by streamly-core $as_me 0.2.0, which was
16261626generated by GNU Autoconf 2.71. Invocation command line was
16271627
16281628 $ $0$ac_configure_args_raw
@@ -3832,7 +3832,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
38323832# report actual input values of CONFIG_FILES etc. instead of their
38333833# values after options handling.
38343834ac_log="
3835−This file was extended by streamly-core $as_me 0.2.2, which was
3835+This file was extended by streamly-core $as_me 0.2.0, which was
38363836generated by GNU Autoconf 2.71. Invocation command line was
38373837
38383838 CONFIG_FILES = $CONFIG_FILES
@@ -3888,7 +3888,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
38883888cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
38893889ac_cs_config='$ac_cs_config_escaped'
38903890ac_cs_version="\\
3891−streamly-core config.status 0.2.2
3891+streamly-core config.status 0.2.0
38923892configured by $0, generated by GNU Autoconf 2.71,
38933893 with options \\"\$ac_cs_config\\"
38943894
core/configure.ac+1−1
@@ -3,7 +3,7 @@
33# See https://www.gnu.org/software/autoconf/manual/autoconf.html for help on
44# the macros used in this file.
55
6−AC_INIT([streamly-core], [0.2.2], [streamly@composewell.com], [streamly-core], [https://streamly.composewell.com])
6+AC_INIT([streamly-core], [0.2.0], [streamly@composewell.com], [streamly-core], [https://streamly.composewell.com])
77
88# To suppress "WARNING: unrecognized options: --with-compiler"
99AC_ARG_WITH([compiler], [GHC])
core/docs/ApiChangelogs/0.1.0-0.2.0.txtdeleted−1471
@@ -1,1471 +0,0 @@
1−---------------------------------
2−API Annotations
3−---------------------------------
4−
5−[A] : Added
6−[R] : Removed
7−[C] : Changed
8−[O] : Old definition
9−[N] : New definition
10−[D] : Deprecated
11−
12−---------------------------------
13−API diff
14−---------------------------------
15−
16−[C] Streamly.Unicode.Parser
17− [A] double :: Monad m => Parser Char m Double
18−[C] Streamly.FileSystem.Handle
19− [A] readWith :: MonadIO m => Int -> Handle -> Stream m Word8
20− [A] readChunksWith :: MonadIO m => Int -> Handle -> Stream m (Array Word8)
21−[C] Streamly.FileSystem.Dir
22− [C] readEither
23− [O] readEither :: MonadIO m => FilePath -> Stream m (Either FilePath FilePath)
24− [N] readEither :: (MonadIO m, MonadCatch m) => FilePath -> Stream m (Either FilePath FilePath)
25− [C] read
26− [O] read :: MonadIO m => FilePath -> Stream m FilePath
27− [N] read :: (MonadIO m, MonadCatch m) => FilePath -> Stream m FilePath
28−[C] Streamly.Data.Unfold
29− [A] class Enum a => Enumerable a
30− [A] second :: b -> Unfold m (a, b) c -> Unfold m a c
31− [A] first :: a -> Unfold m (a, b) c -> Unfold m b c
32− [A] enumerateFromTo :: (Enumerable a, Monad m) => Unfold m (a, a) a
33− [A] enumerateFromThenTo :: (Enumerable a, Monad m) => Unfold m (a, a, a) a
34− [A] enumerateFromThen :: (Enumerable a, Monad m) => Unfold m (a, a) a
35− [A] enumerateFrom :: (Enumerable a, Monad m) => Unfold m a a
36−[C] Streamly.Data.StreamK
37− [C] parseChunks
38− [O] parseChunks :: (Monad m, Unbox a) => ParserK a m b -> StreamK m (Array a) -> m (Either ParseError b)
39− [N] parseChunks :: (Monad m, Unbox a) => ParserK (Array a) m b -> StreamK m (Array a) -> m (Either ParseError b)
40− [C] parseBreakChunks
41− [O] parseBreakChunks :: (Monad m, Unbox a) => ParserK a m b -> StreamK m (Array a) -> m (Either ParseError b, StreamK m (Array a))
42− [N] parseBreakChunks :: (Monad m, Unbox a) => ParserK (Array a) m b -> StreamK m (Array a) -> m (Either ParseError b, StreamK m (Array a))
43− [A] parseBreak :: forall m a b. Monad m => ParserK a m b -> StreamK m a -> m (Either ParseError b, StreamK m a)
44− [A] parse :: Monad m => ParserK a m b -> StreamK m a -> m (Either ParseError b)
45− [A] handle :: (MonadCatch m, Exception e) => (e -> m (StreamK m a)) -> StreamK m a -> StreamK m a
46− [A] bracketIO :: (MonadIO m, MonadCatch m) => IO b -> (b -> IO c) -> (b -> StreamK m a) -> StreamK m a
47−[C] Streamly.Data.Stream
48− [A] wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
49− [A] splitOn :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
50− [C] handle
51− [O] handle :: (MonadCatch m, Exception e) => (e -> Stream m a) -> Stream m a -> Stream m a
52− [N] handle :: (MonadCatch m, Exception e) => (e -> m (Stream m a)) -> Stream m a -> Stream m a
53− [A] groupsOf :: Monad m => Int -> Fold m a b -> Stream m a -> Stream m b
54−[C] Streamly.Data.ParserK
55− [D] fromParser :: (MonadIO m, Unbox a) => Parser a m b -> ParserK (Array a) m b
56− [D] fromFold :: (MonadIO m, Unbox a) => Fold m a b -> ParserK (Array a) m b
57− [A] adaptCG :: Monad m => Parser a m b -> ParserK (Array a) m b
58− [A] adaptC :: (Monad m, Unbox a) => Parser a m b -> ParserK (Array a) m b
59− [A] adapt :: Monad m => Parser a m b -> ParserK a m b
60−[C] Streamly.Data.Parser
61− [A] groupByRollingEither :: Monad m => (a -> a -> Bool) -> Fold m a b -> Fold m a c -> Parser a m (Either b c)
62− [A] groupByRolling :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser a m b
63−[A] Streamly.Data.MutByteArray
64− [A] class Unbox a
65− [A] class Serialize a
66− [A] SerializeConfig
67− [A] MutByteArray
68− [A] unpin :: MutByteArray -> IO MutByteArray
69− [A] sizeOf :: (Unbox a, SizeOfRep (Rep a)) => Proxy a -> Int
70− [A] serializeAt :: Serialize a => Int -> MutByteArray -> a -> IO Int
71− [A] pokeAt :: (Unbox a, Generic a, PokeRep (Rep a)) => Int -> MutByteArray -> a -> IO ()
72− [A] pinnedNew :: Int -> IO MutByteArray
73− [A] pin :: MutByteArray -> IO MutByteArray
74− [A] peekAt :: (Unbox a, Generic a, PeekRep (Rep a)) => Int -> MutByteArray -> IO a
75− [A] new :: Int -> IO MutByteArray
76− [A] isPinned :: MutByteArray -> Bool
77− [A] inlineSerializeAt :: Maybe Inline -> SerializeConfig -> SerializeConfig
78− [A] inlineDeserializeAt :: Maybe Inline -> SerializeConfig -> SerializeConfig
79− [A] inlineAddSizeTo :: Maybe Inline -> SerializeConfig -> SerializeConfig
80− [A] deserializeAt :: Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
81− [A] deriveUnbox :: Q [Dec] -> Q [Dec]
82− [A] deriveSerializeWith :: (SerializeConfig -> SerializeConfig) -> Q [Dec] -> Q [Dec]
83− [A] deriveSerialize :: Q [Dec] -> Q [Dec]
84− [A] addSizeTo :: Serialize a => Int -> a -> Int
85−[C] Streamly.Data.MutArray.Generic
86− [A] write :: MonadIO m => Fold m a (MutArray a)
87− [A] readRev :: MonadIO m => MutArray a -> Stream m a
88− [A] read :: MonadIO m => MutArray a -> Stream m a
89− [A] putIndexUnsafe :: forall m a. MonadIO m => Int -> MutArray a -> a -> m ()
90− [A] modifyIndexUnsafe :: MonadIO m => Int -> MutArray a -> (a -> (a, b)) -> m b
91− [A] length :: MutArray a -> Int
92− [A] getIndexUnsafe :: MonadIO m => Int -> MutArray a -> m a
93− [C] getIndex
94− [O] getIndex :: MonadIO m => Int -> MutArray a -> m a
95− [N] getIndex :: MonadIO m => Int -> MutArray a -> m (Maybe a)
96− [A] fromListN :: MonadIO m => Int -> [a] -> m (MutArray a)
97− [A] fromList :: MonadIO m => [a] -> m (MutArray a)
98−[C] Streamly.Data.MutArray
99− [A] unpin :: MutArray a -> IO (MutArray a)
100− [A] readRev :: forall m a. (MonadIO m, Unbox a) => MutArray a -> Stream m a
101− [A] read :: forall m a. (MonadIO m, Unbox a) => MutArray a -> Stream m a
102− [A] putIndexUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> a -> m ()
103− [D] pokeByteIndex :: Unbox a => Int -> MutByteArray -> a -> IO ()
104− [A] pokeAt :: (Unbox a, Generic a, PokeRep (Rep a)) => Int -> MutByteArray -> a -> IO ()
105− [A] pinnedNew :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
106− [A] pin :: MutArray a -> IO (MutArray a)
107− [D] peekByteIndex :: Unbox a => Int -> MutByteArray -> IO a
108− [A] peekAt :: (Unbox a, Generic a, PeekRep (Rep a)) => Int -> MutByteArray -> IO a
109− [D] newPinned :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
110− [A] modifyIndexUnsafe :: forall m a b. (MonadIO m, Unbox a) => Int -> MutArray a -> (a -> (a, b)) -> m b
111− [A] modifyIndex :: forall m a b. (MonadIO m, Unbox a) => Int -> MutArray a -> (a -> (a, b)) -> m b
112− [A] modify :: forall m a. (MonadIO m, Unbox a) => MutArray a -> (a -> a) -> m ()
113− [A] isPinned :: MutArray a -> Bool
114− [A] getIndexUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m a
115− [C] getIndex
116− [O] getIndex :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m a
117− [N] getIndex :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (Maybe a)
118−[C] Streamly.Data.Array.Generic
119− [A] toList :: Array a -> [a]
120− [A] getIndex :: Int -> Array a -> Maybe a
121−[C] Streamly.Data.Array
122− [A] unpin :: Array a -> IO (Array a)
123− [D] pokeByteIndex :: Unbox a => Int -> MutByteArray -> a -> IO ()
124− [A] pokeAt :: (Unbox a, Generic a, PokeRep (Rep a)) => Int -> MutByteArray -> a -> IO ()
125− [A] pin :: Array a -> IO (Array a)
126− [D] peekByteIndex :: Unbox a => Int -> MutByteArray -> IO a
127− [A] peekAt :: (Unbox a, Generic a, PeekRep (Rep a)) => Int -> MutByteArray -> IO a
128− [A] isPinned :: Array a -> Bool
129−[C] Streamly.Console.Stdio
130−
131−---------------------------------
132−Internal API diff
133−---------------------------------
134−
135−[C] Streamly.Internal.Unicode.Stream
136− [C] writeCharUtf8'
137− [O] writeCharUtf8' :: Monad m => Fold m Word8 Char
138− [N] writeCharUtf8' :: Monad m => Parser Word8 m Char
139−[C] Streamly.Internal.Unicode.Parser
140− [A] number :: Monad m => Parser Char m (Integer, Int)
141− [A] mkDouble :: Integer -> Int -> Double
142− [A] doubleParser :: Monad m => Parser Char m (Int, Int)
143− [C] double
144− [O] double :: Parser Char m Double
145− [N] double :: Monad m => Parser Char m Double
146−[R] Streamly.Internal.Serialize.ToBytes
147−[R] Streamly.Internal.Serialize.FromBytes
148−[C] Streamly.Internal.FileSystem.File
149− [A] writeAppendWith :: (MonadIO m, MonadCatch m) => Int -> FilePath -> Stream m Word8 -> m ()
150− [A] writeAppendChunks :: (MonadIO m, MonadCatch m) => FilePath -> Stream m (Array a) -> m ()
151− [A] writeAppendArray :: FilePath -> Array a -> IO ()
152− [A] writeAppend :: (MonadIO m, MonadCatch m) => FilePath -> Stream m Word8 -> m ()
153− [R] appendWith :: (MonadIO m, MonadCatch m) => Int -> FilePath -> Stream m Word8 -> m ()
154− [R] appendChunks :: (MonadIO m, MonadCatch m) => FilePath -> Stream m (Array a) -> m ()
155− [R] appendArray :: FilePath -> Array a -> IO ()
156− [R] append :: (MonadIO m, MonadCatch m) => FilePath -> Stream m Word8 -> m ()
157−[C] Streamly.Internal.FileSystem.Dir
158− [C] reader
159− [O] reader :: MonadIO m => Unfold m FilePath FilePath
160− [N] reader :: (MonadIO m, MonadCatch m) => Unfold m FilePath FilePath
161− [C] readFiles
162− [O] readFiles :: MonadIO m => FilePath -> Stream m FilePath
163− [N] readFiles :: (MonadIO m, MonadCatch m) => FilePath -> Stream m FilePath
164− [C] readEitherPaths
165− [O] readEitherPaths :: MonadIO m => FilePath -> Stream m (Either FilePath FilePath)
166− [N] readEitherPaths :: (MonadIO m, MonadCatch m) => FilePath -> Stream m (Either FilePath FilePath)
167− [C] readEither
168− [O] readEither :: MonadIO m => FilePath -> Stream m (Either FilePath FilePath)
169− [N] readEither :: (MonadIO m, MonadCatch m) => FilePath -> Stream m (Either FilePath FilePath)
170− [C] readDirs
171− [O] readDirs :: MonadIO m => FilePath -> Stream m FilePath
172− [N] readDirs :: (MonadIO m, MonadCatch m) => FilePath -> Stream m FilePath
173− [C] read
174− [O] read :: MonadIO m => FilePath -> Stream m FilePath
175− [N] read :: (MonadIO m, MonadCatch m) => FilePath -> Stream m FilePath
176− [C] fileReader
177− [O] fileReader :: MonadIO m => Unfold m FilePath FilePath
178− [N] fileReader :: (MonadIO m, MonadCatch m) => Unfold m FilePath FilePath
179− [C] eitherReaderPaths
180− [O] eitherReaderPaths :: MonadIO m => Unfold m FilePath (Either FilePath FilePath)
181− [N] eitherReaderPaths :: (MonadIO m, MonadCatch m) => Unfold m FilePath (Either FilePath FilePath)
182− [C] eitherReader
183− [O] eitherReader :: MonadIO m => Unfold m FilePath (Either FilePath FilePath)
184− [N] eitherReader :: (MonadIO m, MonadCatch m) => Unfold m FilePath (Either FilePath FilePath)
185− [C] dirReader
186− [O] dirReader :: MonadIO m => Unfold m FilePath FilePath
187− [N] dirReader :: (MonadIO m, MonadCatch m) => Unfold m FilePath FilePath
188−[R] Streamly.Internal.Data.Unfold.Type
189−[R] Streamly.Internal.Data.Unfold.Enumeration
190−[C] Streamly.Internal.Data.Unfold
191− [C] Unfold
192− [A] Unfold :: (s -> m (Step s b)) -> (a -> m s) -> Unfold m a b
193− [A] takeWhileMWithInput :: Monad m => (a -> b -> m Bool) -> Unfold m a b -> Unfold m a b
194− [A] manyInterleave :: Monad m => Unfold m a b -> Unfold m c a -> Unfold m c b
195− [A] enumerateFromStepIntegral :: (Monad m, Integral a) => Unfold m (a, a) a
196− [A] crossApplySnd :: Unfold m a b -> Unfold m a c -> Unfold m a c
197− [A] crossApplyFst :: Unfold m a b -> Unfold m a c -> Unfold m a b
198− [A] concatMap :: Monad m => (b -> Unfold m a c) -> Unfold m a b -> Unfold m a c
199−[R] Streamly.Internal.Data.Unboxed
200−[C] Streamly.Internal.Data.Time.Units
201− [R] Streamly.Internal.Data.Unboxed.Unbox
202− [A] Streamly.Internal.Data.Unbox.Unbox
203− [A] instance Streamly.Internal.Data.Unbox.Unbox Streamly.Internal.Data.Time.Units.NanoSecond64
204− [A] instance Streamly.Internal.Data.Unbox.Unbox Streamly.Internal.Data.Time.Units.MilliSecond64
205− [A] instance Streamly.Internal.Data.Unbox.Unbox Streamly.Internal.Data.Time.Units.MicroSecond64
206−[R] Streamly.Internal.Data.Time.Clock.Type
207−[A] Streamly.Internal.Data.StreamK
208− [A] CrossStreamK
209− [A] (FixityR,6)
210− [A] (FixityR,6)
211− [A] (FixityR,6)
212− [A] (FixityR,5)
213− [A] (FixityR,5)
214− [A] (FixityR,6)
215− [A] (FixityR,5)
216− [A] StreamK
217− [A] MkStream :: (forall r. State StreamK m a -> (a -> StreamK m a -> m r) -> (a -> m r) -> m r -> m r) -> StreamK m a
218− [A] zipWithM :: Monad m => (a -> b -> m c) -> StreamK m a -> StreamK m b -> StreamK m c
219− [A] zipWith :: Monad m => (a -> b -> c) -> StreamK m a -> StreamK m b -> StreamK m c
220− [A] unfoldrMWith :: Monad m => (m a -> StreamK m a -> StreamK m a) -> (b -> m (Maybe (a, b))) -> b -> StreamK m a
221− [A] unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> StreamK m a
222− [A] unfoldr :: (b -> Maybe (a, b)) -> b -> StreamK m a
223− [A] uncons :: Applicative m => StreamK m a -> m (Maybe (a, StreamK m a))
224− [A] unShare :: StreamK m a -> StreamK m a
225− [A] unCross :: CrossStreamK m a -> StreamK m a
226− [A] toStream :: Applicative m => StreamK m a -> Stream m a
227− [A] toList :: Monad m => StreamK m a -> m [a]
228− [A] the :: (Eq a, Monad m) => StreamK m a -> m (Maybe a)
229− [A] takeWhile :: (a -> Bool) -> StreamK m a -> StreamK m a
230− [A] take :: Int -> StreamK m a -> StreamK m a
231− [A] tail :: Applicative m => StreamK m a -> m (Maybe (StreamK m a))
232− [A] sortBy :: Monad m => (a -> a -> Ordering) -> StreamK m a -> StreamK m a
233− [A] sequence :: Monad m => StreamK m (m a) -> StreamK m a
234− [A] scanlx' :: (x -> a -> x) -> x -> (x -> b) -> StreamK m a -> StreamK m b
235− [A] scanl' :: (b -> a -> b) -> b -> StreamK m a -> StreamK m b
236− [A] reverse :: StreamK m a -> StreamK m a
237− [A] replicateMWith :: (m a -> StreamK m a -> StreamK m a) -> Int -> m a -> StreamK m a
238− [A] replicateM :: Monad m => Int -> m a -> StreamK m a
239− [A] replicate :: Int -> a -> StreamK m a
240− [A] repeatMWith :: (m a -> t m a -> t m a) -> m a -> t m a
241− [A] repeatM :: Monad m => m a -> StreamK m a
242− [A] repeat :: a -> StreamK m a
243− [A] parseDBreak :: Monad m => Parser a m b -> StreamK m a -> m (Either ParseError b, StreamK m a)
244− [A] parseD :: Monad m => Parser a m b -> StreamK m a -> m (Either ParseError b)
245− [A] parseChunksGeneric :: Monad m => ParserK (Array a) m b -> StreamK m (Array a) -> m (Either ParseError b)
246− [A] parseChunks :: (Monad m, Unbox a) => ParserK (Array a) m b -> StreamK m (Array a) -> m (Either ParseError b)
247− [A] parseBreakChunksGeneric :: forall m a b. Monad m => ParserK (Array a) m b -> StreamK m (Array a) -> m (Either ParseError b, StreamK m (Array a))
248− [A] parseBreakChunks :: (Monad m, Unbox a) => ParserK (Array a) m b -> StreamK m (Array a) -> m (Either ParseError b, StreamK m (Array a))
249− [A] parseBreak :: forall m a b. Monad m => ParserK a m b -> StreamK m a -> m (Either ParseError b, StreamK m a)
250− [A] parse :: Monad m => ParserK a m b -> StreamK m a -> m (Either ParseError b)
251− [A] null :: Monad m => StreamK m a -> m Bool
252− [A] notElem :: (Monad m, Eq a) => a -> StreamK m a -> m Bool
253− [A] nilM :: Applicative m => m b -> StreamK m a
254− [A] nil :: StreamK m a
255− [A] mkStream :: (forall r. State StreamK m a -> (a -> StreamK m a -> m r) -> (a -> m r) -> m r -> m r) -> StreamK m a
256− [A] mkCross :: StreamK m a -> CrossStreamK m a
257− [A] minimumBy :: Monad m => (a -> a -> Ordering) -> StreamK m a -> m (Maybe a)
258− [A] minimum :: (Monad m, Ord a) => StreamK m a -> m (Maybe a)
259− [A] mfix :: Monad m => (m a -> StreamK m a) -> StreamK m a
260− [A] mergeMapWith :: (StreamK m b -> StreamK m b -> StreamK m b) -> (a -> StreamK m b) -> StreamK m a -> StreamK m b
261− [A] mergeIterateWith :: (StreamK m a -> StreamK m a -> StreamK m a) -> (a -> StreamK m a) -> StreamK m a -> StreamK m a
262− [A] mergeByM :: Monad m => (a -> a -> m Ordering) -> StreamK m a -> StreamK m a -> StreamK m a
263− [A] mergeBy :: (a -> a -> Ordering) -> StreamK m a -> StreamK m a -> StreamK m a
264− [A] maximumBy :: Monad m => (a -> a -> Ordering) -> StreamK m a -> m (Maybe a)
265− [A] maximum :: (Monad m, Ord a) => StreamK m a -> m (Maybe a)
266− [A] mapMaybe :: (a -> Maybe b) -> StreamK m a -> StreamK m b
267− [A] mapM_ :: Monad m => (a -> m b) -> StreamK m a -> m ()
268− [A] mapMWith :: (m b -> StreamK m b -> StreamK m b) -> (a -> m b) -> StreamK m a -> StreamK m b
269− [A] mapMSerial :: Monad m => (a -> m b) -> StreamK m a -> StreamK m b
270− [A] mapM :: Monad m => (a -> m b) -> StreamK m a -> StreamK m b
271− [A] map :: (a -> b) -> StreamK m a -> StreamK m b
272− [A] lookup :: (Monad m, Eq a) => a -> StreamK m (a, b) -> m (Maybe b)
273− [A] liftInner :: (Monad m, MonadTrans t, Monad (t m)) => StreamK m a -> StreamK (t m) a
274− [A] last :: Monad m => StreamK m a -> m (Maybe a)
275− [A] iterateMWith :: Monad m => (m a -> StreamK m a -> StreamK m a) -> (a -> m a) -> m a -> StreamK m a
276− [A] iterateM :: Monad m => (a -> m a) -> m a -> StreamK m a
277− [A] iterate :: (a -> a) -> a -> StreamK m a
278− [A] intersperseM :: Monad m => m a -> StreamK m a -> StreamK m a
279− [A] intersperse :: Monad m => a -> StreamK m a -> StreamK m a
280− [A] interleaveMin :: StreamK m a -> StreamK m a -> StreamK m a
281− [A] interleaveFst :: StreamK m a -> StreamK m a -> StreamK m a
282− [A] interleave :: StreamK m a -> StreamK m a -> StreamK m a
283− [A] insertBy :: (a -> a -> Ordering) -> a -> StreamK m a -> StreamK m a
284− [A] init :: Applicative m => StreamK m a -> m (Maybe (StreamK m a))
285− [A] hoist :: (Monad m, Monad n) => (forall x. m x -> n x) -> StreamK m a -> StreamK n a
286− [A] head :: Monad m => StreamK m a -> m (Maybe a)
287− [A] handle :: (MonadCatch m, Exception e) => (e -> m (StreamK m a)) -> StreamK m a -> StreamK m a
288− [A] fromYieldK :: YieldK m a -> StreamK m a
289− [A] fromStream :: Monad m => Stream m a -> StreamK m a
290− [A] fromStopK :: StopK m -> StreamK m a
291− [A] fromPure :: a -> StreamK m a
292− [A] fromList :: [a] -> StreamK m a
293− [A] fromIndicesMWith :: (m a -> StreamK m a -> StreamK m a) -> (Int -> m a) -> StreamK m a
294− [A] fromIndicesM :: Monad m => (Int -> m a) -> StreamK m a
295− [A] fromIndices :: (Int -> a) -> StreamK m a
296− [A] fromFoldableM :: (Foldable f, Monad m) => f (m a) -> StreamK m a
297− [A] fromFoldable :: Foldable f => f a -> StreamK m a
298− [A] fromEffect :: Monad m => m a -> StreamK m a
299− [A] foldrT :: (Monad m, Monad (s m), MonadTrans s) => (a -> s m b -> s m b) -> s m b -> StreamK m a -> s m b
300− [A] foldrSShared :: (a -> StreamK m b -> StreamK m b) -> StreamK m b -> StreamK m a -> StreamK m b
301− [A] foldrSM :: Monad m => (m a -> StreamK m b -> StreamK m b) -> StreamK m b -> StreamK m a -> StreamK m b
302− [A] foldrS :: (a -> StreamK m b -> StreamK m b) -> StreamK m b -> StreamK m a -> StreamK m b
303− [A] foldrM :: (a -> m b -> m b) -> m b -> StreamK m a -> m b
304− [A] foldr1 :: Monad m => (a -> a -> a) -> StreamK m a -> m (Maybe a)
305− [A] foldr :: Monad m => (a -> b -> b) -> b -> StreamK m a -> m b
306− [A] foldlx' :: forall m a b x. Monad m => (x -> a -> x) -> x -> (x -> b) -> StreamK m a -> m b
307− [A] foldlT :: (Monad m, Monad (s m), MonadTrans s) => (s m b -> a -> s m b) -> s m b -> StreamK m a -> s m b
308− [A] foldlS :: (StreamK m b -> a -> StreamK m b) -> StreamK m b -> StreamK m a -> StreamK m b
309− [A] foldlMx' :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> StreamK m a -> m b
310− [A] foldlM' :: Monad m => (b -> a -> m b) -> m b -> StreamK m a -> m b
311− [A] foldl' :: Monad m => (b -> a -> b) -> b -> StreamK m a -> m b
312− [A] foldStreamShared :: State StreamK m a -> (a -> StreamK m a -> m r) -> (a -> m r) -> m r -> StreamK m a -> m r
313− [A] foldStream :: State StreamK m a -> (a -> StreamK m a -> m r) -> (a -> m r) -> m r -> StreamK m a -> m r
314− [A] foldEither :: Monad m => Fold m a b -> StreamK m a -> m (Either (Fold m a b) (b, StreamK m a))
315− [A] foldConcat :: Monad m => Producer m a b -> Fold m b c -> StreamK m a -> m (c, StreamK m a)
316− [A] foldBreak :: Monad m => Fold m a b -> StreamK m a -> m (b, StreamK m a)
317− [A] fold :: Monad m => Fold m a b -> StreamK m a -> m b
318− [A] findM :: Monad m => (a -> m Bool) -> StreamK m a -> m (Maybe a)
319− [A] findIndices :: (a -> Bool) -> StreamK m a -> StreamK m Int
320− [A] find :: Monad m => (a -> Bool) -> StreamK m a -> m (Maybe a)
321− [A] filter :: (a -> Bool) -> StreamK m a -> StreamK m a
322− [A] evalStateT :: Monad m => m s -> StreamK (StateT s m) a -> StreamK m a
323− [A] elem :: (Monad m, Eq a) => a -> StreamK m a -> m Bool
324− [A] dropWhile :: (a -> Bool) -> StreamK m a -> StreamK m a
325− [A] drop :: Int -> StreamK m a -> StreamK m a
326− [A] drain :: Monad m => StreamK m a -> m ()
327− [A] deleteBy :: (a -> a -> Bool) -> a -> StreamK m a -> StreamK m a
328− [A] crossWith :: Monad m => (a -> b -> c) -> StreamK m a -> StreamK m b -> StreamK m c
329− [A] crossApplyWith :: (StreamK m b -> StreamK m b -> StreamK m b) -> StreamK m (a -> b) -> StreamK m a -> StreamK m b
330− [A] crossApplySnd :: StreamK m a -> StreamK m b -> StreamK m b
331− [A] crossApplyFst :: StreamK m a -> StreamK m b -> StreamK m a
332− [A] crossApply :: StreamK m (a -> b) -> StreamK m a -> StreamK m b
333− [A] cross :: Monad m => StreamK m a -> StreamK m b -> StreamK m (a, b)
334− [A] consMBy :: Monad m => (StreamK m a -> StreamK m a -> StreamK m a) -> m a -> StreamK m a -> StreamK m a
335− [A] consM :: Monad m => m a -> StreamK m a -> StreamK m a
336− [A] consK :: YieldK m a -> StreamK m a -> StreamK m a
337− [A] cons :: a -> StreamK m a -> StreamK m a
338− [A] conjoin :: Monad m => StreamK m a -> StreamK m a -> StreamK m a
339− [A] concatMapWith :: (StreamK m b -> StreamK m b -> StreamK m b) -> (a -> StreamK m b) -> StreamK m a -> StreamK m b
340− [A] concatMapEffect :: Monad m => (b -> StreamK m a) -> m b -> StreamK m a
341− [A] concatMap :: (a -> StreamK m b) -> StreamK m a -> StreamK m b
342− [A] concatIterateWith :: (StreamK m a -> StreamK m a -> StreamK m a) -> (a -> StreamK m a) -> StreamK m a -> StreamK m a
343− [A] concatIterateScanWith :: Monad m => (StreamK m a -> StreamK m a -> StreamK m a) -> (b -> a -> m (b, StreamK m a)) -> m b -> StreamK m a -> StreamK m a
344− [A] concatIterateLeftsWith :: b ~ Either a c => (StreamK m b -> StreamK m b -> StreamK m b) -> (a -> StreamK m b) -> StreamK m b -> StreamK m b
345− [A] concatEffect :: Monad m => m (StreamK m a) -> StreamK m a
346− [A] buildSM :: Monad m => ((m a -> StreamK m a -> StreamK m a) -> StreamK m a -> StreamK m a) -> StreamK m a
347− [A] buildS :: ((a -> StreamK m a -> StreamK m a) -> StreamK m a -> StreamK m a) -> StreamK m a
348− [A] buildM :: Monad m => (forall r. (a -> StreamK m a -> m r) -> (a -> m r) -> m r -> m r) -> StreamK m a
349− [A] build :: forall m a. (forall b. (a -> b -> b) -> b -> b) -> StreamK m a
350− [A] bracketIO :: (MonadIO m, MonadCatch m) => IO b -> (b -> IO c) -> (b -> StreamK m a) -> StreamK m a
351− [A] bindWith :: (StreamK m b -> StreamK m b -> StreamK m b) -> StreamK m a -> (a -> StreamK m b) -> StreamK m b
352− [A] before :: Monad m => m b -> StreamK m a -> StreamK m a
353− [A] augmentSM :: Monad m => ((m a -> StreamK m a -> StreamK m a) -> StreamK m a -> StreamK m a) -> StreamK m a -> StreamK m a
354− [A] augmentS :: ((a -> StreamK m a -> StreamK m a) -> StreamK m a -> StreamK m a) -> StreamK m a -> StreamK m a
355− [A] append :: StreamK m a -> StreamK m a -> StreamK m a
356− [A] any :: Monad m => (a -> Bool) -> StreamK m a -> m Bool
357− [A] all :: Monad m => (a -> Bool) -> StreamK m a -> m Bool
358− [A] (.:) :: a -> StreamK m a -> StreamK m a
359− [A] (!!) :: Monad m => StreamK m a -> Int -> m (Maybe a)
360−[R] Streamly.Internal.Data.Stream.StreamK.Type
361−[R] Streamly.Internal.Data.Stream.StreamK.Transformer
362−[R] Streamly.Internal.Data.Stream.StreamK
363−[R] Streamly.Internal.Data.Stream.StreamD.Type
364−[R] Streamly.Internal.Data.Stream.StreamD.Transformer
365−[R] Streamly.Internal.Data.Stream.StreamD.Transform
366−[R] Streamly.Internal.Data.Stream.StreamD.Top
367−[R] Streamly.Internal.Data.Stream.StreamD.Step
368−[R] Streamly.Internal.Data.Stream.StreamD.Nesting
369−[R] Streamly.Internal.Data.Stream.StreamD.Lift
370−[R] Streamly.Internal.Data.Stream.StreamD.Generate
371−[R] Streamly.Internal.Data.Stream.StreamD.Exception
372−[R] Streamly.Internal.Data.Stream.StreamD.Eliminate
373−[R] Streamly.Internal.Data.Stream.StreamD.Container
374−[D] Streamly.Internal.Data.Stream.StreamD
375−[R] Streamly.Internal.Data.Stream.Common
376−[R] Streamly.Internal.Data.Stream.Chunked
377−[C] Streamly.Internal.Data.Stream
378− [A] class Enum a => Enumerable a
379− [A] Stream
380− [A] UnStream :: (State StreamK m a -> s -> m (Step s a)) -> s -> Stream m a
381− [A] Step
382− [A] Yield :: a -> s -> Step s a
383− [A] Stop :: Step s a
384− [A] Skip :: s -> Step s a
385− [A] InterleaveState
386− [A] InterleaveSecondOnly :: s2 -> InterleaveState s1 s2
387− [A] InterleaveSecond :: s1 -> s2 -> InterleaveState s1 s2
388− [A] InterleaveFirstOnly :: s1 -> InterleaveState s1 s2
389− [A] InterleaveFirst :: s1 -> s2 -> InterleaveState s1 s2
390− [A] FoldManyPost
391− [A] FoldManyPostYield :: b -> FoldManyPost s fs b a -> FoldManyPost s fs b a
392− [A] FoldManyPostStart :: s -> FoldManyPost s fs b a
393− [A] FoldManyPostLoop :: s -> fs -> FoldManyPost s fs b a
394− [A] FoldManyPostDone :: FoldManyPost s fs b a
395− [A] FoldMany
396− [A] FoldManyYield :: b -> FoldMany s fs b a -> FoldMany s fs b a
397− [A] FoldManyStart :: s -> FoldMany s fs b a
398− [A] FoldManyLoop :: s -> fs -> FoldMany s fs b a
399− [A] FoldManyFirst :: fs -> s -> FoldMany s fs b a
400− [A] FoldManyDone :: FoldMany s fs b a
401− [A] CrossStream
402− [A] ConcatUnfoldInterleaveState
403− [A] ConcatUnfoldInterleaveOuter :: o -> [i] -> ConcatUnfoldInterleaveState o i
404− [A] ConcatUnfoldInterleaveInnerR :: [i] -> [i] -> ConcatUnfoldInterleaveState o i
405− [A] ConcatUnfoldInterleaveInnerL :: [i] -> [i] -> ConcatUnfoldInterleaveState o i
406− [A] ConcatUnfoldInterleaveInner :: o -> [i] -> ConcatUnfoldInterleaveState o i
407− [A] ConcatMapUState
408− [A] ConcatMapUOuter :: o -> ConcatMapUState o i
409− [A] ConcatMapUInner :: o -> i -> ConcatMapUState o i
410− [A] AppendState
411− [A] AppendSecond :: s2 -> AppendState s1 s2
412− [A] AppendFirst :: s1 -> AppendState s1 s2
413− [A] pattern Stream :: (State StreamK m a -> s -> m (Step s a)) -> s -> Stream m a
414− [A] zipWithM :: Monad m => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
415− [A] zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
416− [A] wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
417− [A] with :: Monad m => (Stream m a -> Stream m (s, a)) -> (((s, a) -> b) -> Stream m (s, a) -> Stream m (s, a)) -> ((s, a) -> b) -> Stream m a -> Stream m a
418− [A] usingStateT :: Monad m => m s -> (Stream (StateT s m) a -> Stream (StateT s m) a) -> Stream m a -> Stream m a
419− [A] usingReaderT :: Monad m => m r -> (Stream (ReaderT r m) a -> Stream (ReaderT r m) a) -> Stream m a -> Stream m a
420− [A] uniqBy :: Monad m => (a -> a -> Bool) -> Stream m a -> Stream m a
421− [A] uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
422− [A] unionWithStreamGenericBy :: MonadIO m => (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
423− [A] unionWithStreamAscBy :: (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
424− [A] unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
425− [A] unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
426− [A] unfoldRoundRobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
427− [A] unfoldMany :: Monad m => Unfold m a b -> Stream m a -> Stream m b
428− [A] unfoldIterateDfs :: Monad m => Unfold m a a -> Stream m a -> Stream m a
429− [A] unfoldIterateBfsRev :: Monad m => Unfold m a a -> Stream m a -> Stream m a
430− [A] unfoldIterateBfs :: Monad m => Unfold m a a -> Stream m a -> Stream m a
431− [A] unfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
432− [A] unfold :: Applicative m => Unfold m a b -> a -> Stream m b
433− [A] uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
434− [A] unCross :: CrossStream m a -> Stream m a
435− [A] transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
436− [A] trace_ :: Monad m => m b -> Stream m a -> Stream m a
437− [A] trace :: Monad m => (a -> m b) -> Stream m a -> Stream m a
438− [A] toStreamK :: Monad m => Stream m a -> StreamK m a
439− [A] toListRev :: Monad m => Stream m a -> m [a]
440− [A] toList :: Monad m => Stream m a -> m [a]
441− [A] timestamped :: MonadIO m => Stream m a -> Stream m (AbsTime, a)
442− [A] timestampWith :: MonadIO m => Double -> Stream m a -> Stream m (AbsTime, a)
443− [A] timesWith :: MonadIO m => Double -> Stream m (AbsTime, RelTime64)
444− [A] times :: MonadIO m => Stream m (AbsTime, RelTime64)
445− [A] timeout :: AbsTime -> t m ()
446− [A] timeIndexed :: MonadIO m => Stream m a -> Stream m (RelTime64, a)
447− [A] timeIndexWith :: MonadIO m => Double -> Stream m a -> Stream m (RelTime64, a)
448− [A] the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
449− [A] tapOffsetEvery :: Monad m => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
450− [A] tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
451− [A] takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
452− [A] takeWhileLast :: (a -> Bool) -> Stream m a -> Stream m a
453− [A] takeWhileAround :: (a -> Bool) -> Stream m a -> Stream m a
454− [A] takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
455− [A] takeEndByM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
456− [A] takeEndBy :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
457− [A] take :: Applicative m => Int -> Stream m a -> Stream m a
458− [A] tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
459− [A] stripSuffixUnbox :: (MonadIO m, Eq a, Unbox a) => Stream m a -> Stream m a -> m (Maybe (Stream m a))
460− [A] stripSuffix :: (Monad m, Eq a) => Stream m a -> Stream m a -> m (Maybe (Stream m a))
461− [A] stripPrefix :: (Monad m, Eq a) => Stream m a -> Stream m a -> m (Maybe (Stream m a))
462− [A] strideFromThen :: Monad m => Int -> Int -> Stream m a -> Stream m a
463− [A] splitOnSuffixSeqAny :: [Array a] -> Fold m a b -> Stream m a -> Stream m b
464− [A] splitOnSuffixSeq :: forall m a b. (MonadIO m, Storable a, Unbox a, Enum a, Eq a) => Bool -> Array a -> Fold m a b -> Stream m a -> Stream m b
465− [A] splitOnSeq :: forall m a b. (MonadIO m, Storable a, Unbox a, Enum a, Eq a) => Array a -> Fold m a b -> Stream m a -> Stream m b
466− [A] splitOnPrefix :: (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
467− [A] splitOnAny :: [Array a] -> Fold m a b -> Stream m a -> Stream m b
468− [A] splitOn :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
469− [A] splitInnerBySuffix :: (Monad m, Eq (f a), Monoid (f a)) => (f a -> m (f a, Maybe (f a))) -> (f a -> f a -> m (f a)) -> Stream m (f a) -> Stream m (f a)
470− [A] splitInnerBy :: Monad m => (f a -> m (f a, Maybe (f a))) -> (f a -> f a -> m (f a)) -> Stream m (f a) -> Stream m (f a)
471− [A] slicesBy :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
472− [A] sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
473− [A] sequence :: Monad m => Stream m (m a) -> Stream m a
474− [A] scanlx' :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
475− [A] scanlMx' :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
476− [A] scanlMAfter' :: Monad m => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
477− [A] scanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
478− [A] scanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
479− [A] scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
480− [A] scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
481− [A] scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
482− [A] scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
483− [A] scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
484− [A] scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
485− [A] scanMaybe :: Monad m => Fold m a (Maybe b) -> Stream m a -> Stream m b
486− [A] scanMany :: Monad m => Fold m a b -> Stream m a -> Stream m b
487− [A] scan :: Monad m => Fold m a b -> Stream m a -> Stream m b
488− [A] runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
489− [A] runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
490− [A] runInnerWithState :: Monad m => (forall b. s -> t m b -> m (b, s)) -> m s -> Stream (t m) a -> Stream m (s, a)
491− [A] runInnerWith :: Monad m => (forall b. t m b -> m b) -> Stream (t m) a -> Stream m a
492− [A] roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
493− [A] rollingMapM :: Monad m => (Maybe a -> a -> m b) -> Stream m a -> Stream m b
494− [A] rollingMap2 :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
495− [A] rollingMap :: Monad m => (Maybe a -> a -> b) -> Stream m a -> Stream m b
496− [A] reverseUnbox :: (MonadIO m, Unbox a) => Stream m a -> Stream m a
497− [A] reverse :: Monad m => Stream m a -> Stream m a
498− [A] replicateM :: Monad m => Int -> m a -> Stream m a
499− [A] replicate :: Monad m => Int -> a -> Stream m a
500− [A] repeated :: Stream m a -> Stream m a
501− [A] repeatM :: Monad m => m a -> Stream m a
502− [A] repeat :: Monad m => a -> Stream m a
503− [A] relTimesWith :: MonadIO m => Double -> Stream m RelTime64
504− [A] relTimes :: MonadIO m => Stream m RelTime64
505− [A] refoldMany :: Monad m => Refold m x a b -> m x -> Stream m a -> Stream m b
506− [A] refoldIterateM :: Monad m => Refold m b a b -> m b -> Stream m a -> Stream m b
507− [A] reduceIterateBfs :: Monad m => (a -> a -> m a) -> Stream m a -> m (Maybe a)
508− [A] reassembleBy :: Fold m a b -> (a -> a -> Int) -> Stream m a -> Stream m b
509− [A] prune :: (a -> Bool) -> Stream m a -> Stream m a
510− [A] prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
511− [A] prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
512− [A] postscanlx' :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
513− [A] postscanlMx' :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
514− [A] postscanlMAfter' :: Monad m => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
515− [A] postscanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
516− [A] postscanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
517− [A] postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
518− [A] postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
519− [A] postscan :: Monad m => Fold m a b -> Stream m a -> Stream m b
520− [A] parseSequence :: Stream m (Parser a m b) -> Stream m a -> Stream m b
521− [A] parseManyTill :: Parser a m b -> Parser a m x -> Stream m a -> Stream m b
522− [A] parseManyD :: Monad m => Parser a m b -> Stream m a -> Stream m (Either ParseError b)
523− [A] parseMany :: Monad m => Parser a m b -> Stream m a -> Stream m (Either ParseError b)
524− [A] parseIterateD :: Monad m => (b -> Parser a m b) -> b -> Stream m a -> Stream m (Either ParseError b)
525− [A] parseIterate :: Monad m => (b -> Parser a m b) -> b -> Stream m a -> Stream m (Either ParseError b)
526− [A] parseD :: Monad m => Parser a m b -> Stream m a -> m (Either ParseError b)
527− [A] parseBreakD :: Monad m => Parser a m b -> Stream m a -> m (Either ParseError b, Stream m a)
528− [A] parseBreak :: Monad m => Parser a m b -> Stream m a -> m (Either ParseError b, Stream m a)
529− [A] parse :: Monad m => Parser a m b -> Stream m a -> m (Either ParseError b)
530− [A] onException :: MonadCatch m => m b -> Stream m a -> Stream m a
531− [A] null :: Monad m => Stream m a -> m Bool
532− [A] nub :: (Monad m, Ord a) => Stream m a -> Stream m a
533− [A] notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
534− [A] nilM :: Applicative m => m b -> Stream m a
535− [A] nil :: Applicative m => Stream m a
536− [A] morphInner :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
537− [A] mkCross :: Stream m a -> CrossStream m a
538− [A] minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
539− [A] minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
540− [A] mergeMinBy :: (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
541− [A] mergeFstBy :: (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
542− [A] mergeByM :: Monad m => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
543− [A] mergeBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
544− [A] maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
545− [A] maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
546− [A] mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
547− [A] mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
548− [A] mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
549− [A] mapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
550− [A] map :: Monad m => (a -> b) -> Stream m a -> Stream m b
551− [A] lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
552− [A] liftInnerWith :: Monad (t m) => (forall b. m b -> t m b) -> Stream m a -> Stream (t m) a
553− [A] liftInner :: (Monad m, MonadTrans t, Monad (t m)) => Stream m a -> Stream (t m) a
554− [A] last :: Monad m => Stream m a -> m (Maybe a)
555− [A] joinOuterGeneric :: MonadIO m => (a -> b -> Bool) -> Stream m a -> Stream m b -> Stream m (Maybe a, Maybe b)
556− [A] joinOuterAscBy :: (a -> b -> Ordering) -> Stream m a -> Stream m b -> Stream m (Maybe a, Maybe b)
557− [A] joinOuter :: (Ord k, MonadIO m) => Stream m (k, a) -> Stream m (k, b) -> Stream m (k, Maybe a, Maybe b)
558− [A] joinLeftGeneric :: Monad m => (a -> b -> Bool) -> Stream m a -> Stream m b -> Stream m (a, Maybe b)
559− [A] joinLeftAscBy :: (a -> b -> Ordering) -> Stream m a -> Stream m b -> Stream m (a, Maybe b)
560− [A] joinLeft :: (Ord k, Monad m) => Stream m (k, a) -> Stream m (k, b) -> Stream m (k, a, Maybe b)
561− [A] joinInnerGeneric :: Monad m => (a -> b -> Bool) -> Stream m a -> Stream m b -> Stream m (a, b)
562− [A] joinInnerAscBy :: (a -> b -> Ordering) -> Stream m a -> Stream m b -> Stream m (a, b)
563− [A] joinInner :: (Monad m, Ord k) => Stream m (k, a) -> Stream m (k, b) -> Stream m (k, a, b)
564− [A] iterateM :: Monad m => (a -> m a) -> m a -> Stream m a
565− [A] iterate :: Monad m => (a -> a) -> a -> Stream m a
566− [A] isSuffixOfUnbox :: (MonadIO m, Eq a, Unbox a) => Stream m a -> Stream m a -> m Bool
567− [A] isSuffixOf :: (Monad m, Eq a) => Stream m a -> Stream m a -> m Bool
568− [A] isSubsequenceOf :: (Monad m, Eq a) => Stream m a -> Stream m a -> m Bool
569− [A] isPrefixOf :: (Monad m, Eq a) => Stream m a -> Stream m a -> m Bool
570− [A] isInfixOf :: (MonadIO m, Eq a, Enum a, Storable a, Unbox a) => Stream m a -> Stream m a -> m Bool
571− [A] intersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
572− [A] intersperseMWith :: Int -> m a -> Stream m a -> Stream m a
573− [A] intersperseMSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
574− [A] intersperseMSuffixWith :: forall m a. Monad m => Int -> m a -> Stream m a -> Stream m a
575− [A] intersperseMSuffix :: forall m a. Monad m => m a -> Stream m a -> Stream m a
576− [A] intersperseMPrefix_ :: Monad m => m b -> Stream m a -> Stream m a
577− [A] intersperseM :: Monad m => m a -> Stream m a -> Stream m a
578− [A] intersperse :: Monad m => a -> Stream m a -> Stream m a
579− [A] intersectBySorted :: Monad m => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
580− [A] interposeSuffixM :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
581− [A] interposeSuffix :: Monad m => c -> Unfold m b c -> Stream m b -> Stream m c
582− [A] interposeM :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
583− [A] interpose :: Monad m => c -> Unfold m b c -> Stream m b -> Stream m c
584− [A] interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
585− [A] interleaveFstSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
586− [A] interleaveFst :: Monad m => Stream m a -> Stream m a -> Stream m a
587− [A] interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
588− [A] intercalateSuffix :: Monad m => Unfold m b c -> b -> Stream m b -> Stream m c
589− [A] intercalate :: Monad m => Unfold m b c -> b -> Stream m b -> Stream m c
590− [A] insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
591− [A] indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
592− [A] indexed :: Monad m => Stream m a -> Stream m (Int, a)
593− [A] headElse :: Monad m => a -> Stream m a -> m a
594− [A] head :: Monad m => Stream m a -> m (Maybe a)
595− [A] handle :: (MonadCatch m, Exception e) => (e -> m (Stream m a)) -> Stream m a -> Stream m a
596− [A] groupsWhile :: Monad m => (a -> a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
597− [A] groupsRollingBy :: Monad m => (a -> a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
598− [A] groupsOf :: Monad m => Int -> Fold m a b -> Stream m a -> Stream m b
599− [A] gintercalateSuffix :: Monad m => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
600− [A] gintercalate :: Monad m => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
601− [A] ghandle :: (MonadCatch m, Exception e) => (e -> Stream m a -> m (Stream m a)) -> Stream m a -> Stream m a
602− [A] generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
603− [A] generate :: Monad m => Int -> (Int -> a) -> Stream m a
604− [A] generalizeInner :: Monad m => Stream Identity a -> Stream m a
605− [A] gbracket_ :: Monad m => m c -> (c -> m d) -> (c -> e -> Stream m b -> m (Stream m b)) -> (forall s. m s -> m (Either e s)) -> (c -> Stream m b) -> Stream m b
606− [A] gbracket :: MonadIO m => IO c -> (c -> IO d1) -> (c -> e -> Stream m b -> IO (Stream m b)) -> (c -> IO d2) -> (forall s. m s -> m (Either e s)) -> (c -> Stream m b) -> Stream m b
607− [A] fromStreamK :: Applicative m => StreamK m a -> Stream m a
608− [A] fromPure :: Applicative m => a -> Stream m a
609− [A] fromPtrN :: (Monad m, Storable a) => Int -> Ptr a -> Stream m a
610− [A] fromPtr :: forall m a. (Monad m, Storable a) => Ptr a -> Stream m a
611− [A] fromListM :: Monad m => [m a] -> Stream m a
612− [A] fromList :: Applicative m => [a] -> Stream m a
613− [A] fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
614− [A] fromIndices :: Monad m => (Int -> a) -> Stream m a
615− [A] fromFoldableM :: (Monad m, Foldable f) => f (m a) -> Stream m a
616− [A] fromFoldable :: (Monad m, Foldable f) => f a -> Stream m a
617− [A] fromEffect :: Applicative m => m a -> Stream m a
618− [A] fromByteStr# :: Monad m => Addr# -> Stream m Word8
619− [A] foldrT :: (Monad m, Monad (t m), MonadTrans t) => (a -> t m b -> t m b) -> t m b -> Stream m a -> t m b
620− [A] foldrS :: Monad m => (a -> Stream m b -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
621− [A] foldrMx :: Monad m => (a -> m x -> m x) -> m x -> (m x -> m b) -> Stream m a -> m b
622− [A] foldrM :: Monad m => (a -> m b -> m b) -> m b -> Stream m a -> m b
623− [A] foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
624− [A] foldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b
625− [A] foldlx' :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> m b
626− [A] foldlT :: (Monad m, Monad (s m), MonadTrans s) => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
627− [A] foldlS :: Monad m => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
628− [A] foldlMx' :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> m b
629− [A] foldlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> m b
630− [A] foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
631− [A] foldSequence :: Stream m (Fold m a b) -> Stream m a -> Stream m b
632− [A] foldManyPost :: Monad m => Fold m a b -> Stream m a -> Stream m b
633− [A] foldMany :: Monad m => Fold m a b -> Stream m a -> Stream m b
634− [A] foldIterateM :: Monad m => (b -> m (Fold m a b)) -> m b -> Stream m a -> Stream m b
635− [A] foldIterateBfs :: Fold m a (Either a a) -> Stream m a -> m (Maybe a)
636− [A] foldEither :: Monad m => Fold m a b -> Stream m a -> m (Either (Fold m a b) (b, Stream m a))
637− [A] foldBreak :: Monad m => Fold m a b -> Stream m a -> m (b, Stream m a)
638− [A] foldAddLazy :: Monad m => Fold m a b -> Stream m a -> Fold m a b
639− [A] foldAdd :: Monad m => Fold m a b -> Stream m a -> m (Fold m a b)
640− [A] fold :: Monad m => Fold m a b -> Stream m a -> m b
641− [A] findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
642− [A] findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
643− [A] find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
644− [A] finallyUnsafe :: MonadCatch m => m b -> Stream m a -> Stream m a
645− [A] finallyIO :: (MonadIO m, MonadCatch m) => IO b -> Stream m a -> Stream m a
646− [A] filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
647− [A] filterInStreamGenericBy :: Monad m => (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
648− [A] filterInStreamAscBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
649− [A] filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
650− [A] evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
651− [A] eqBy :: Monad m => (a -> b -> Bool) -> Stream m a -> Stream m b -> m Bool
652− [A] enumerateTo :: (Monad m, Bounded a, Enumerable a) => a -> Stream m a
653− [A] enumerateFromToSmall :: (Monad m, Enum a) => a -> a -> Stream m a
654− [A] enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
655− [A] enumerateFromToFractional :: (Monad m, Fractional a, Ord a) => a -> a -> Stream m a
656− [A] enumerateFromTo :: (Enumerable a, Monad m) => a -> a -> Stream m a
657− [A] enumerateFromThenToSmall :: (Monad m, Enum a) => a -> a -> a -> Stream m a
658− [A] enumerateFromThenToIntegral :: (Monad m, Integral a) => a -> a -> a -> Stream m a
659− [A] enumerateFromThenToFractional :: (Monad m, Fractional a, Ord a) => a -> a -> a -> Stream m a
660− [A] enumerateFromThenTo :: (Enumerable a, Monad m) => a -> a -> a -> Stream m a
661− [A] enumerateFromThenSmallBounded :: (Monad m, Enumerable a, Bounded a) => a -> a -> Stream m a
662− [A] enumerateFromThenNum :: (Monad m, Num a) => a -> a -> Stream m a
663− [A] enumerateFromThenIntegral :: (Monad m, Integral a, Bounded a) => a -> a -> Stream m a
664− [A] enumerateFromThenFractional :: (Monad m, Fractional a) => a -> a -> Stream m a
665− [A] enumerateFromThen :: (Enumerable a, Monad m) => a -> a -> Stream m a
666− [A] enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
667− [A] enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
668− [A] enumerateFromNum :: (Monad m, Num a) => a -> Stream m a
669− [A] enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
670− [A] enumerateFromFractional :: (Monad m, Fractional a) => a -> Stream m a
671− [A] enumerateFromBounded :: (Monad m, Enumerable a, Bounded a) => a -> Stream m a
672− [A] enumerateFrom :: (Enumerable a, Monad m) => a -> Stream m a
673− [A] enumerate :: (Monad m, Bounded a, Enumerable a) => Stream m a
674− [A] elemIndices :: (Monad m, Eq a) => a -> Stream m a -> Stream m Int
675− [A] elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
676− [A] durations :: Double -> t m RelTime64
677− [A] dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
678− [A] dropWhileLast :: (a -> Bool) -> Stream m a -> Stream m a
679− [A] dropWhileAround :: (a -> Bool) -> Stream m a -> Stream m a
680− [A] dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
681− [A] dropSuffix :: Stream m a -> Stream m a -> Stream m a
682− [A] dropPrefix :: Stream m a -> Stream m a -> Stream m a
683− [A] dropLast :: Int -> Stream m a -> Stream m a
684− [A] dropInfix :: Stream m a -> Stream m a -> Stream m a
685− [A] drop :: Monad m => Int -> Stream m a -> Stream m a
686− [A] drain :: Monad m => Stream m a -> m ()
687− [A] deleteInStreamGenericBy :: Monad m => (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
688− [A] deleteInStreamAscBy :: (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
689− [A] deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
690− [A] delayPre :: MonadIO m => Double -> Stream m a -> Stream m a
691− [A] delayPost :: MonadIO m => Double -> Stream m a -> Stream m a
692− [A] delay :: MonadIO m => Double -> Stream m a -> Stream m a
693− [A] crossWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
694− [A] crossApplySnd :: Functor f => Stream f a -> Stream f b -> Stream f b
695− [A] crossApplyFst :: Functor f => Stream f a -> Stream f b -> Stream f a
696− [A] crossApply :: Functor f => Stream f (a -> b) -> Stream f a -> Stream f b
697− [A] cross :: Monad m => Stream m a -> Stream m b -> Stream m (a, b)
698− [A] consM :: Applicative m => m a -> Stream m a -> Stream m a
699− [A] cons :: Applicative m => a -> Stream m a -> Stream m a
700− [A] concatMapM :: Monad m => (a -> m (Stream m b)) -> Stream m a -> Stream m b
701− [A] concatMap :: Monad m => (a -> Stream m b) -> Stream m a -> Stream m b
702− [A] concatIterateScan :: Monad m => (b -> a -> m b) -> (b -> m (Maybe (b, Stream m a))) -> b -> Stream m a
703− [A] concatIterateDfs :: Monad m => (a -> Maybe (Stream m a)) -> Stream m a -> Stream m a
704− [A] concatIterateBfsRev :: Monad m => (a -> Maybe (Stream m a)) -> Stream m a -> Stream m a
705− [A] concatIterateBfs :: Monad m => (a -> Maybe (Stream m a)) -> Stream m a -> Stream m a
706− [A] concatEffect :: Monad m => m (Stream m a) -> Stream m a
707− [A] concat :: Monad m => Stream m (Stream m a) -> Stream m a
708− [A] cmpBy :: Monad m => (a -> b -> Ordering) -> Stream m a -> Stream m b -> m Ordering
709− [A] catRights :: Monad m => Stream m (Either a b) -> Stream m b
710− [A] catMaybes :: Monad m => Stream m (Maybe a) -> Stream m a
711− [A] catLefts :: Monad m => Stream m (Either a b) -> Stream m a
712− [A] catEithers :: Monad m => Stream m (Either a a) -> Stream m a
713− [A] bracketUnsafe :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
714− [A] bracketIO3 :: (MonadIO m, MonadCatch m) => IO b -> (b -> IO c) -> (b -> IO d) -> (b -> IO e) -> (b -> Stream m a) -> Stream m a
715− [A] bracketIO :: (MonadIO m, MonadCatch m) => IO b -> (b -> IO c) -> (b -> Stream m a) -> Stream m a
716− [A] before :: Monad m => m b -> Stream m a -> Stream m a
717− [A] append :: Monad m => Stream m a -> Stream m a -> Stream m a
718− [A] any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
719− [A] all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
720− [A] afterUnsafe :: Monad m => m b -> Stream m a -> Stream m a
721− [A] afterIO :: MonadIO m => IO b -> Stream m a -> Stream m a
722− [A] absTimesWith :: MonadIO m => Double -> Stream m AbsTime
723− [A] absTimes :: MonadIO m => Stream m AbsTime
724− [A] (!!) :: Monad m => Stream m a -> Int -> m (Maybe a)
725−[R] Streamly.Internal.Data.Ring.Unboxed
726−[A] Streamly.Internal.Data.Ring.Generic
727− [A] Ring
728− [A] [ringMax] :: Ring a -> !Int
729− [A] [ringHead] :: Ring a -> !Int
730− [A] [ringArr] :: Ring a -> MutArray a
731− [A] Ring :: MutArray a -> !Int -> !Int -> Ring a
732− [A] writeLastN :: MonadIO m => Int -> Fold m a (Ring a)
733− [A] unsafeInsertRingWith :: Ring a -> a -> IO Int
734− [A] toStreamWith :: Int -> Ring a -> Stream m a
735− [A] toMutArray :: MonadIO m => Int -> Int -> Ring a -> m (MutArray a)
736− [A] seek :: MonadIO m => Int -> Ring a -> m (Ring a)
737− [A] createRing :: MonadIO m => Int -> m (Ring a)
738− [A] copyToMutArray :: MonadIO m => Int -> Int -> Ring a -> m (MutArray a)
739−[C] Streamly.Internal.Data.Ring
740− [C] Ring
741− [A] [ringStart] :: Ring a -> {-# UNPACK #-} !ForeignPtr a
742− [R] [ringMax] :: Ring a -> !Int
743− [R] [ringHead] :: Ring a -> !Int
744− [A] [ringBound] :: Ring a -> {-# UNPACK #-} !Ptr a
745− [R] [ringArr] :: Ring a -> MutArray a
746− [C] Ring
747− [O] Ring :: MutArray a -> !Int -> !Int -> Ring a
748− [N] Ring :: {-# UNPACK #-} !ForeignPtr a -> {-# UNPACK #-} !Ptr a -> Ring a
749− [A] GHC.Show.Show
750− [A] instance (GHC.Show.Show a, GHC.Show.Show b, GHC.Show.Show c, GHC.Show.Show d) => GHC.Show.Show (Streamly.Internal.Data.Ring.Tuple4' a b c d)
751− [A] writeN :: Int -> Fold m a (Ring a)
752− [R] writeLastN :: MonadIO m => Int -> Fold m a (Ring a)
753− [R] unsafeInsertRingWith :: Ring a -> a -> IO Int
754− [A] unsafeInsert :: Storable a => Ring a -> Ptr a -> a -> IO (Ptr a)
755− [A] unsafeFoldRingNM :: forall m a b. (MonadIO m, Storable a) => Int -> Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
756− [A] unsafeFoldRingM :: forall m a b. (MonadIO m, Storable a) => Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
757− [A] unsafeFoldRingFullM :: forall m a b. (MonadIO m, Storable a) => Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
758− [A] unsafeFoldRing :: forall a b. Storable a => Ptr a -> (b -> a -> b) -> b -> Ring a -> b
759− [A] unsafeEqArrayN :: Ring a -> Ptr a -> Array a -> Int -> Bool
760− [A] unsafeEqArray :: Ring a -> Ptr a -> Array a -> Bool
761− [R] toStreamWith :: Int -> Ring a -> Stream m a
762− [R] toMutArray :: MonadIO m => Int -> Int -> Ring a -> m (MutArray a)
763− [A] startOf :: Ring a -> Ptr a
764− [A] slidingWindowWith :: forall m a b. (MonadIO m, Storable a, Unbox a) => Int -> Fold m ((a, Maybe a), m (MutArray a)) b -> Fold m a b
765− [A] slidingWindow :: forall m a b. (MonadIO m, Storable a, Unbox a) => Int -> Fold m (a, Maybe a) b -> Fold m a b
766− [A] slide :: Ring a -> a -> m (Ring a)
767− [R] seek :: MonadIO m => Int -> Ring a -> m (Ring a)
768− [A] ringsOf :: Int -> Stream m a -> Stream m (MutArray a)
769− [A] readRev :: Unfold m (MutArray a) a
770− [A] read :: forall m a. (MonadIO m, Storable a) => Unfold m (Ring a, Ptr a, Int) a
771− [A] putIndex :: Ring a -> Int -> a -> m ()
772− [A] newRing :: Int -> m (Ring a)
773− [A] new :: forall a. Storable a => Int -> IO (Ring a, Ptr a)
774− [A] moveBy :: forall a. Storable a => Int -> Ring a -> Ptr a -> Ptr a
775− [A] modifyIndex :: Ring a -> Int -> (a -> (a, b)) -> m b
776− [A] length :: Ring a -> Int
777− [A] getIndexUnsafe :: Ring a -> Int -> m a
778− [A] getIndexRev :: Ring a -> Int -> m a
779− [A] getIndex :: Ring a -> Int -> m a
780− [A] fromArray :: MutArray a -> Ring a
781− [R] createRing :: MonadIO m => Int -> m (Ring a)
782− [A] castUnsafe :: Ring a -> Ring b
783− [A] cast :: forall a b. Storable b => Ring a -> Maybe (Ring b)
784− [A] bytesFree :: Ring a -> Int
785− [A] byteLength :: Ring a -> Int
786− [A] byteCapacity :: Ring a -> Int
787− [A] asBytes :: Ring a -> Ring Word8
788− [A] advance :: forall a. Storable a => Ring a -> Ptr a -> Ptr a
789−[R] Streamly.Internal.Data.Producer.Type
790−[R] Streamly.Internal.Data.Producer.Source
791−[C] Streamly.Internal.Data.Producer
792− [A] Source
793− [A] unread :: [b] -> Source a b -> Source a b
794− [A] translate :: Functor m => (a -> c) -> (c -> a) -> Producer m c b -> Producer m a b
795− [A] source :: Maybe a -> Source a b
796− [A] producer :: Monad m => Producer m a b -> Producer m (Source a b) b
797− [A] parseManyD :: Monad m => Parser a m b -> Producer m (Source x a) a -> Producer m (Source x a) (Either ParseError b)
798− [A] parseMany :: Monad m => Parser a m b -> Producer m (Source x a) a -> Producer m (Source x a) (Either ParseError b)
799− [A] parse :: Monad m => Parser a m b -> Producer m (Source s a) a -> Source s a -> m (Either ParseError b, Source s a)
800− [A] lmap :: (a -> a) -> Producer m a b -> Producer m a b
801− [A] isEmpty :: Source a b -> Bool
802−[R] Streamly.Internal.Data.Pipe.Type
803−[C] Streamly.Internal.Data.Pipe
804− [A] Step
805− [A] Yield :: a -> s -> Step s a
806− [A] Continue :: s -> Step s a
807− [A] PipeState
808− [A] Produce :: s2 -> PipeState s1 s2
809− [A] Consume :: s1 -> PipeState s1 s2
810− [C] Pipe
811− [A] Pipe :: (s1 -> a -> m (Step (PipeState s1 s2) b)) -> (s2 -> m (Step (PipeState s1 s2) b)) -> s1 -> Pipe m a b
812−[A] Streamly.Internal.Data.ParserK
813− [A] Step
814− [A] Partial :: !Int -> (Input a -> m (Step a m r)) -> Step a m r
815− [A] Error :: !Int -> String -> Step a m r
816− [A] Done :: !Int -> r -> Step a m r
817− [A] Continue :: !Int -> (Input a -> m (Step a m r)) -> Step a m r
818− [A] ParseResult
819− [A] Success :: !Int -> !b -> ParseResult b
820− [A] Failure :: !Int -> !String -> ParseResult b
821− [A] Input
822− [A] None :: Input a
823− [A] Chunk :: a -> Input a
824− [A] ParserK
825− [A] [runParser] :: ParserK a m b -> forall r. (ParseResult b -> Int -> Input a -> m (Step a m r)) -> Int -> Int -> Input a -> m (Step a m r)
826− [A] MkParser :: (forall r. (ParseResult b -> Int -> Input a -> m (Step a m r)) -> Int -> Int -> Input a -> m (Step a m r)) -> ParserK a m b
827− [A] fromPure :: b -> ParserK a m b
828− [A] fromEffect :: Monad m => m b -> ParserK a m b
829− [A] die :: String -> ParserK a m b
830− [A] adaptCG :: Monad m => Parser a m b -> ParserK (Array a) m b
831− [A] adaptC :: (Monad m, Unbox a) => Parser a m b -> ParserK (Array a) m b
832− [A] adapt :: Monad m => Parser a m b -> ParserK a m b
833−[R] Streamly.Internal.Data.Parser.ParserK.Type
834−[R] Streamly.Internal.Data.Parser.ParserD.Type
835−[R] Streamly.Internal.Data.Parser.ParserD.Tee
836−[R] Streamly.Internal.Data.Parser.ParserD
837−[C] Streamly.Internal.Data.Parser
838− [A] Step
839− [A] Partial :: !Int -> !s -> Step s b
840− [A] Error :: !String -> Step s b
841− [A] Done :: !Int -> !b -> Step s b
842− [A] Continue :: !Int -> !s -> Step s b
843− [A] Parser
844− [A] Parser :: (s -> a -> m (Step s b)) -> m (Initial s b) -> (s -> m (Step s b)) -> Parser a m b
845− [A] Initial
846− [A] IPartial :: !s -> Initial s b
847− [A] IError :: !String -> Initial s b
848− [A] IDone :: !b -> Initial s b
849− [A] GHC.Show.Show
850− [A] instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Streamly.Internal.Data.Parser.Tuple'Fused a b)
851− [A] ParseError
852− [A] ParseError :: String -> ParseError
853− [A] zipWithM :: Monad m => (a -> b -> m c) -> Stream m a -> Fold m c x -> Parser b m x
854− [A] zip :: Monad m => Stream m a -> Fold m (a, b) x -> Parser b m x
855− [A] wordWithQuotes :: (Monad m, Eq a) => Bool -> (a -> a -> Maybe a) -> a -> (a -> Maybe a) -> (a -> Bool) -> Fold m a b -> Parser a m b
856− [A] wordProcessQuotes :: (Monad m, Eq a) => a -> (a -> Maybe a) -> (a -> Bool) -> Fold m a b -> Parser a m b
857− [A] wordKeepQuotes :: (Monad m, Eq a) => a -> (a -> Maybe a) -> (a -> Bool) -> Fold m a b -> Parser a m b
858− [A] wordFramedBy :: Monad m => (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser a m b
859− [A] wordBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
860− [A] toFold :: Monad m => Parser a m b -> Fold m a b
861− [A] takeWhileP :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
862− [A] takeWhile1 :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
863− [A] takeWhile :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
864− [A] takeStartBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
865− [A] takeStartBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
866− [A] takeP :: Monad m => Int -> Parser a m b -> Parser a m b
867− [A] takeGE :: Monad m => Int -> Fold m a b -> Parser a m b
868− [A] takeFramedBy_ :: Monad m => (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser a m b
869− [A] takeFramedByGeneric :: Monad m => Maybe (a -> Bool) -> Maybe (a -> Bool) -> Maybe (a -> Bool) -> Fold m a b -> Parser a m b
870− [A] takeFramedByEsc_ :: Monad m => (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser a m b
871− [A] takeEndBy_ :: (a -> Bool) -> Parser a m b -> Parser a m b
872− [A] takeEndByEsc :: Monad m => (a -> Bool) -> (a -> Bool) -> Parser a m b -> Parser a m b
873− [A] takeEndBy :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
874− [A] takeEitherSepBy :: (a -> Bool) -> Fold m (Either a b) c -> Parser a m c
875− [A] takeEQ :: Monad m => Int -> Fold m a b -> Parser a m b
876− [A] takeBetween :: Monad m => Int -> Int -> Fold m a b -> Parser a m b
877− [A] subsequenceBy :: (a -> a -> Bool) -> Stream m a -> Parser a m ()
878− [A] streamEqBy :: Monad m => (a -> a -> Bool) -> Stream m a -> Parser a m ()
879− [A] split_ :: Monad m => Parser x m a -> Parser x m b -> Parser x m b
880− [A] splitWith :: Monad m => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
881− [A] splitSome :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
882− [A] splitManyPost :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
883− [A] splitMany :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
884− [A] spanByRolling :: Monad m => (a -> a -> Bool) -> Fold m a b -> Fold m a c -> Parser a m (b, c)
885− [A] spanBy :: Monad m => (a -> a -> Bool) -> Fold m a b -> Fold m a c -> Parser a m (b, c)
886− [A] span :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a c -> Parser a m (b, c)
887− [A] some :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
888− [A] sequence :: Monad m => Stream m (Parser a m b) -> Fold m b c -> Parser a m c
889− [A] sepByAll :: Monad m => Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
890− [A] sepBy1 :: Monad m => Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
891− [A] sepBy :: Monad m => Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
892− [A] satisfy :: Monad m => (a -> Bool) -> Parser a m a
893− [A] sampleFromthen :: Monad m => Int -> Int -> Fold m a b -> Parser a m b
894− [A] roundRobin :: t (Parser a m b) -> Fold m b c -> Parser a m c
895− [A] rmapM :: Monad m => (b -> m c) -> Parser a m b -> Parser a m c
896− [A] retryMaxTotal :: Int -> Parser a m b -> Fold m b c -> Parser a m c
897− [A] retryMaxSuccessive :: Int -> Parser a m b -> Fold m b c -> Parser a m c
898− [A] retry :: Parser a m b -> Parser a m b
899− [A] postscan :: Fold m a b -> Parser b m c -> Parser a m c
900− [A] peek :: Monad m => Parser a m a
901− [A] oneOf :: (Monad m, Eq a, Foldable f) => f a -> Parser a m a
902− [A] oneNotEq :: (Monad m, Eq a) => a -> Parser a m a
903− [A] oneEq :: (Monad m, Eq a) => a -> Parser a m a
904− [A] one :: Monad m => Parser a m a
905− [A] noneOf :: (Monad m, Eq a, Foldable f) => f a -> Parser a m a
906− [A] noErrorUnsafeSplit_ :: Monad m => Parser x m a -> Parser x m b -> Parser x m b
907− [A] noErrorUnsafeSplitWith :: Monad m => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
908− [A] noErrorUnsafeConcatMap :: Monad m => (b -> Parser a m c) -> Parser a m b -> Parser a m c
909− [A] maybe :: Monad m => (a -> Maybe b) -> Parser a m b
910− [A] manyTillP :: Parser a m b -> Parser a m x -> Parser b m c -> Parser a m c
911− [A] manyTill :: Monad m => Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
912− [A] manyThen :: Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
913− [A] manyP :: Parser a m b -> Parser b m c -> Parser a m c
914− [A] many :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
915− [A] makeIndexFilter :: (Fold m (s, a) b -> Parser a m b) -> (((s, a) -> Bool) -> Fold m (s, a) b -> Fold m (s, a) b) -> ((s, a) -> Bool) -> Fold m a b -> Parser a m b
916− [A] lookAhead :: Monad m => Parser a m b -> Parser a m b
917− [A] lmapM :: Monad m => (a -> m b) -> Parser b m r -> Parser a m r
918− [A] lmap :: (a -> b) -> Parser b m r -> Parser a m r
919− [A] listEqBy :: Monad m => (a -> a -> Bool) -> [a] -> Parser a m [a]
920− [A] listEq :: (Monad m, Eq a) => [a] -> Parser a m [a]
921− [A] indexed :: forall m a b. Monad m => Fold m (Int, a) b -> Parser a m b
922− [A] groupByRollingEither :: Monad m => (a -> a -> Bool) -> Fold m a b -> Fold m a c -> Parser a m (Either b c)
923− [A] groupByRolling :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser a m b
924− [A] groupBy :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser a m b
925− [A] fromPure :: Monad m => b -> Parser a m b
926− [A] fromFoldMaybe :: Monad m => String -> Fold m a (Maybe b) -> Parser a m b
927− [A] fromFold :: Monad m => Fold m a b -> Parser a m b
928− [A] fromEffect :: Monad m => m b -> Parser a m b
929− [A] filter :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
930− [A] extractStep :: Monad m => (s -> m (Step s1 b)) -> Step s b -> m (Step s1 b)
931− [A] eof :: Monad m => Parser a m ()
932− [A] either :: Monad m => (a -> Either String b) -> Parser a m b
933− [A] dropWhile :: Monad m => (a -> Bool) -> Parser a m ()
934− [A] dieM :: Monad m => m String -> Parser a m b
935− [A] die :: Monad m => String -> Parser a m b
936− [A] deintercalateAll :: Monad m => Parser a m x -> Parser a m y -> Fold m (Either x y) z -> Parser a m z
937− [A] deintercalate1 :: Monad m => Parser a m x -> Parser a m y -> Fold m (Either x y) z -> Parser a m z
938− [A] deintercalate :: Monad m => Parser a m x -> Parser a m y -> Fold m (Either x y) z -> Parser a m z
939− [A] countBetween :: Int -> Int -> Parser a m b -> Fold m b c -> Parser a m c
940− [A] count :: Int -> Parser a m b -> Fold m b c -> Parser a m c
941− [A] concatMap :: Monad m => (b -> Parser a m c) -> Parser a m b -> Parser a m c
942− [A] blockWithQuotes :: (Monad m, Eq a) => (a -> Bool) -> (a -> Bool) -> a -> a -> Fold m a b -> Parser a m b
943− [A] bimapOverrideCount :: Int -> (s -> s1) -> (b -> b1) -> Step s b -> Step s1 b1
944− [A] alt :: Monad m => Parser x m a -> Parser x m a -> Parser x m a
945−[A] Streamly.Internal.Data.MutByteArray
946− [A] class Unbox a
947− [A] class SizeOfRep (f :: Type -> Type)
948− [A] class Serialize a
949− [A] TypeOfType
950− [A] UnitType :: Name -> TypeOfType
951− [A] TheType :: SimpleDataCon -> TypeOfType
952− [A] MultiType :: [SimpleDataCon] -> TypeOfType
953− [A] SimpleDataCon
954− [A] SimpleDataCon :: Name -> [Field] -> SimpleDataCon
955− [A] SerializeConfig
956− [A] [cfgRecordSyntaxWithHeader] :: SerializeConfig -> Bool
957− [A] [cfgInlineSize] :: SerializeConfig -> Maybe Inline
958− [A] [cfgInlineSerialize] :: SerializeConfig -> Maybe Inline
959− [A] [cfgInlineDeserialize] :: SerializeConfig -> Maybe Inline
960− [A] [cfgConstructorTagAsString] :: SerializeConfig -> Bool
961− [A] SerializeConfig :: Maybe Inline -> Maybe Inline -> Maybe Inline -> Bool -> Bool -> SerializeConfig
962− [A] PinnedState
963− [A] Unpinned :: PinnedState
964− [A] Pinned :: PinnedState
965− [A] MutByteArray
966− [A] MutByteArray :: MutableByteArray# RealWorld -> MutByteArray
967− [A] DataType
968− [A] [dtTvs] :: DataType -> [Name]
969− [A] [dtName] :: DataType -> Name
970− [A] [dtCxt] :: DataType -> Cxt
971− [A] [dtCons] :: DataType -> [DataCon]
972− [A] DataType :: Name -> [Name] -> Cxt -> [DataCon] -> DataType
973− [A] DataCon
974− [A] [dcTvs] :: DataCon -> [Name]
975− [A] [dcName] :: DataCon -> Name
976− [A] [dcFields] :: DataCon -> [(Maybe Name, Type)]
977− [A] [dcCxt] :: DataCon -> Cxt
978− [A] DataCon :: Name -> [Name] -> Cxt -> [(Maybe Name, Type)] -> DataCon
979− [A] BoundedPtr
980− [A] BoundedPtr :: MutByteArray -> Int -> Int -> BoundedPtr
981− [A] Streamly.Internal.Data.Serialize.Type.Serialize
982− [A] instance Streamly.Internal.Data.Serialize.Type.Serialize Streamly.Internal.Data.MutByteArray.LiftedInteger
983− [A] instance Streamly.Internal.Data.Serialize.Type.Serialize GHC.Num.Integer.Integer
984− [A] instance Streamly.Internal.Data.Serialize.Type.Serialize a => Streamly.Internal.Data.Serialize.Type.Serialize (GHC.Maybe.Maybe a)
985− [A] instance Streamly.Internal.Data.Serialize.Type.Serialize (Data.Proxy.Proxy a)
986− [A] instance (Streamly.Internal.Data.Serialize.Type.Serialize a, Streamly.Internal.Data.Serialize.Type.Serialize b) => Streamly.Internal.Data.Serialize.Type.Serialize (Data.Either.Either a b)
987− [A] Peeker
988− [A] Peeker :: Builder BoundedPtr IO a -> Peeker a
989− [A] type Field = (Maybe Name, Type)
990− [A] xorCmp :: [Word8] -> Name -> Name -> Q Exp
991− [A] wListToString :: [Word8] -> String
992− [A] w8_int :: Word8 -> Int
993− [A] w32_int :: Word32 -> Int
994− [A] unpin :: MutByteArray -> IO MutByteArray
995− [A] typeOfType :: Type -> [DataCon] -> TypeOfType
996− [A] skipByte :: Peeker ()
997− [A] sizeOfRep :: SizeOfRep f => f x -> Int
998− [A] sizeOfMutableByteArray :: MutByteArray -> IO Int
999− [A] sizeOf :: (Unbox a, SizeOfRep (Rep a)) => Proxy a -> Int
1000− [A] simplifyDataCon :: DataCon -> SimpleDataCon
1001− [A] serializeW8List :: Name -> Name -> [Word8] -> Q Exp
1002− [A] serializeConfig :: SerializeConfig
1003− [A] serializeAt :: Serialize a => Int -> MutByteArray -> a -> IO Int
1004− [A] runPeeker :: Peeker a -> BoundedPtr -> IO a
1005− [A] reifyDataType :: Name -> Q DataType
1006− [A] readUnsafe :: Unbox a => Peeker a
1007− [A] read :: Unbox a => Peeker a
1008− [A] putSliceUnsafe :: MonadIO m => MutByteArray -> Int -> MutByteArray -> Int -> Int -> m ()
1009− [A] pokeRep :: PokeRep f => f a -> BoundedPtr -> IO BoundedPtr
1010− [A] pokeBoundedPtrUnsafe :: forall a. Unbox a => a -> BoundedPtr -> IO BoundedPtr
1011− [A] pokeBoundedPtr :: forall a. Unbox a => a -> BoundedPtr -> IO BoundedPtr
1012− [A] pokeAt :: (Unbox a, Generic a, PokeRep (Rep a)) => Int -> MutByteArray -> a -> IO ()
1013− [A] pinnedNewAlignedBytes :: Int -> Int -> IO MutByteArray
1014− [A] pinnedNew :: Int -> IO MutByteArray
1015− [A] pinnedCloneSliceUnsafe :: MonadIO m => Int -> Int -> MutByteArray -> m MutByteArray
1016− [A] pin :: MutByteArray -> IO MutByteArray
1017− [A] peekRep :: PeekRep f => Peeker (f x)
1018− [A] peekAt :: (Unbox a, Generic a, PeekRep (Rep a)) => Int -> MutByteArray -> IO a
1019− [A] openConstructor :: Name -> Int -> Q Pat
1020− [A] nil :: MutByteArray
1021− [A] newBytesAs :: PinnedState -> Int -> IO MutByteArray
1022− [A] new :: Int -> IO MutByteArray
1023− [A] mkSerializeExprFields :: Name -> [Field] -> Q Exp
1024− [A] mkRecSizeOfExpr :: SimpleDataCon -> Q Exp
1025− [A] mkRecSerializeExpr :: Name -> SimpleDataCon -> Q Exp
1026− [A] mkRecDeserializeExpr :: Name -> Name -> Name -> SimpleDataCon -> Q Exp
1027− [A] mkFieldName :: Int -> Name
1028− [A] mkDeserializeKeysDec :: Name -> Name -> SimpleDataCon -> Q [Dec]
1029− [A] mkDeserializeExprOne :: Name -> SimpleDataCon -> Q Exp
1030− [A] matchConstructor :: Name -> Int -> Q Exp -> Q Match
1031− [A] makeN :: Int -> Name
1032− [A] makeI :: Int -> Name
1033− [A] makeA :: Int -> Name
1034− [A] litProxy :: Unbox a => Proxy a -> Q Exp
1035− [A] litIntegral :: Integral a => a -> Q Exp
1036− [A] isUnitType :: [DataCon] -> Bool
1037− [A] isRecordSyntax :: SimpleDataCon -> Bool
1038− [A] isPinned :: MutByteArray -> Bool
1039− [A] int_w8 :: Int -> Word8
1040− [A] int_w32 :: Int -> Word32
1041− [A] inlineSerializeAt :: Maybe Inline -> SerializeConfig -> SerializeConfig
1042− [A] inlineDeserializeAt :: Maybe Inline -> SerializeConfig -> SerializeConfig
1043− [A] inlineAddSizeTo :: Maybe Inline -> SerializeConfig -> SerializeConfig
1044− [A] getMutableByteArray# :: MutByteArray -> MutableByteArray# RealWorld
1045− [A] genericSizeOf :: forall a. SizeOfRep (Rep a) => Proxy a -> Int
1046− [A] genericPokeByteIndex :: (Generic a, PokeRep (Rep a)) => MutByteArray -> Int -> a -> IO ()
1047− [A] genericPeekByteIndex :: (Generic a, PeekRep (Rep a)) => MutByteArray -> Int -> IO a
1048− [A] errorUnsupported :: String -> a
1049− [A] errorUnimplemented :: a
1050− [A] encodeRecordFields :: Bool -> SerializeConfig -> SerializeConfig
1051− [A] encodeConstrNames :: Bool -> SerializeConfig -> SerializeConfig
1052− [A] deserializeAt :: Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
1053− [A] deriveUnbox :: Q [Dec] -> Q [Dec]
1054− [A] deriveSerializeWith :: (SerializeConfig -> SerializeConfig) -> Q [Dec] -> Q [Dec]
1055− [A] deriveSerialize :: Q [Dec] -> Q [Dec]
1056− [A] conUpdateFuncDec :: Name -> [Field] -> Q [Dec]
1057− [A] cloneSliceUnsafeAs :: MonadIO m => PinnedState -> Int -> Int -> MutByteArray -> m MutByteArray
1058− [A] cloneSliceUnsafe :: MonadIO m => Int -> Int -> MutByteArray -> m MutByteArray
1059− [A] c2w :: Char -> Word8
1060− [A] asPtrUnsafe :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
1061− [A] addSizeTo :: Serialize a => Int -> a -> Int
1062− [A] _x :: Name
1063− [A] _val :: Name
1064− [A] _tag :: Name
1065− [A] _initialOffset :: Name
1066− [A] _endOffset :: Name
1067− [A] _arr :: Name
1068− [A] _acc :: Name
1069−[A] Streamly.Internal.Data.MutArray.Stream
1070− [A] SpliceState
1071− [A] SpliceYielding :: arr -> SpliceState s arr -> SpliceState s arr
1072− [A] SpliceInitial :: s -> SpliceState s arr
1073− [A] SpliceFinish :: SpliceState s arr
1074− [A] SpliceBuffering :: s -> arr -> SpliceState s arr
1075− [A] writeChunks :: (MonadIO m, Unbox a) => Int -> Fold m a (StreamK n (MutArray a))
1076− [A] splitOn :: (MonadIO m, Unbox a) => (a -> Bool) -> MutArray a -> Stream m (MutArray a)
1077− [A] pinnedChunksOf :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> Stream m (MutArray a)
1078− [A] packArraysChunksOf :: (MonadIO m, Unbox a) => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
1079− [A] lpackArraysChunksOf :: (MonadIO m, Unbox a) => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
1080− [A] fromArrayStreamK :: (Unbox a, MonadIO m) => StreamK m (MutArray a) -> m (MutArray a)
1081− [A] flattenArraysRev :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
1082− [A] flattenArrays :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
1083− [A] compactLE :: (MonadIO m, Unbox a) => Int -> Stream m (MutArray a) -> Stream m (Either ParseError (MutArray a))
1084− [A] compactGE :: (MonadIO m, Unbox a) => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
1085− [A] compactEQ :: Int -> Stream m (MutArray a) -> Stream m (MutArray a)
1086− [A] compact :: (MonadIO m, Unbox a) => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
1087− [A] chunksOf :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> Stream m (MutArray a)
1088−[A] Streamly.Internal.Data.MutArray.Generic
1089− [A] MutArray
1090− [A] [arrTrueLen] :: MutArray a -> {-# UNPACK #-} !Int
1091− [A] [arrStart] :: MutArray a -> {-# UNPACK #-} !Int
1092− [A] [arrLen] :: MutArray a -> {-# UNPACK #-} !Int
1093− [A] [arrContents#] :: MutArray a -> MutableArray# RealWorld a
1094− [A] MutArray :: MutableArray# RealWorld a -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> MutArray a
1095− [A] writeWith :: MonadIO m => Int -> Fold m a (MutArray a)
1096− [A] writeNUnsafe :: MonadIO m => Int -> Fold m a (MutArray a)
1097− [A] writeN :: MonadIO m => Int -> Fold m a (MutArray a)
1098− [A] write :: MonadIO m => Fold m a (MutArray a)
1099− [A] uninit :: MonadIO m => MutArray a -> Int -> m (MutArray a)
1100− [A] toStreamK :: MonadIO m => MutArray a -> StreamK m a
1101− [A] toList :: MonadIO m => MutArray a -> m [a]
1102− [A] strip :: MonadIO m => (a -> Bool) -> MutArray a -> m (MutArray a)
1103− [A] snocWith :: MonadIO m => (Int -> Int) -> MutArray a -> a -> m (MutArray a)
1104− [A] snocUnsafe :: MonadIO m => MutArray a -> a -> m (MutArray a)
1105− [A] snoc :: MonadIO m => MutArray a -> a -> m (MutArray a)
1106− [A] realloc :: MonadIO m => Int -> MutArray a -> m (MutArray a)
1107− [A] reader :: MonadIO m => Unfold m (MutArray a) a
1108− [A] readRev :: MonadIO m => MutArray a -> Stream m a
1109− [A] read :: MonadIO m => MutArray a -> Stream m a
1110− [A] putSliceUnsafe :: MonadIO m => MutArray a -> Int -> MutArray a -> Int -> Int -> m ()
1111− [A] putIndices :: MonadIO m => MutArray a -> Fold m (Int, a) ()
1112− [A] putIndexUnsafe :: forall m a. MonadIO m => Int -> MutArray a -> a -> m ()
1113− [A] putIndex :: MonadIO m => Int -> MutArray a -> a -> m ()
1114− [A] producerWith :: Monad m => (forall b. IO b -> m b) -> Producer m (MutArray a) a
1115− [A] producer :: MonadIO m => Producer m (MutArray a) a
1116− [A] nil :: MonadIO m => m (MutArray a)
1117− [A] new :: MonadIO m => Int -> m (MutArray a)
1118− [A] modifyIndexUnsafe :: MonadIO m => Int -> MutArray a -> (a -> (a, b)) -> m b
1119− [A] modifyIndex :: MonadIO m => Int -> MutArray a -> (a -> (a, b)) -> m b
1120− [A] length :: MutArray a -> Int
1121− [A] getSliceUnsafe :: Int -> Int -> MutArray a -> MutArray a
1122− [A] getSlice :: Int -> Int -> MutArray a -> MutArray a
1123− [A] getIndexUnsafeWith :: MonadIO m => MutableArray# RealWorld a -> Int -> m a
1124− [A] getIndexUnsafe :: MonadIO m => Int -> MutArray a -> m a
1125− [A] getIndex :: MonadIO m => Int -> MutArray a -> m (Maybe a)
1126− [A] fromStreamN :: MonadIO m => Int -> Stream m a -> m (MutArray a)
1127− [A] fromStream :: MonadIO m => Stream m a -> m (MutArray a)
1128− [A] fromPureStream :: MonadIO m => Stream Identity a -> m (MutArray a)
1129− [A] fromListN :: MonadIO m => Int -> [a] -> m (MutArray a)
1130− [A] fromList :: MonadIO m => [a] -> m (MutArray a)
1131− [A] eq :: (MonadIO m, Eq a) => MutArray a -> MutArray a -> m Bool
1132− [A] cmp :: (MonadIO m, Ord a) => MutArray a -> MutArray a -> m Ordering
1133− [A] clone :: MonadIO m => MutArray a -> m (MutArray a)
1134− [A] chunksOf :: forall m a. MonadIO m => Int -> Stream m a -> Stream m (MutArray a)
1135−[A] Streamly.Internal.Data.MutArray
1136− [A] MutByteArray
1137− [A] MutArray
1138− [A] [arrStart] :: MutArray a -> {-# UNPACK #-} !Int
1139− [A] [arrEnd] :: MutArray a -> {-# UNPACK #-} !Int
1140− [A] [arrContents] :: MutArray a -> {-# UNPACK #-} !MutByteArray
1141− [A] [arrBound] :: MutArray a -> {-# UNPACK #-} !Int
1142− [A] MutArray :: {-# UNPACK #-} !MutByteArray -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> MutArray a
1143− [A] IORef
1144− [A] ArrayUnsafe
1145− [A] ArrayUnsafe :: {-# UNPACK #-} !MutByteArray -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> ArrayUnsafe a
1146− [A] writeWith :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
1147− [A] writeRevN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
1148− [A] writeNWithUnsafe :: forall m a. (MonadIO m, Unbox a) => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
1149− [A] writeNWith :: forall m a. (MonadIO m, Unbox a) => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
1150− [A] writeNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
1151− [A] writeN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
1152− [A] writeIORef :: Unbox a => IORef a -> a -> IO ()
1153− [A] writeChunks :: (MonadIO m, Unbox a) => Int -> Fold m a (StreamK n (MutArray a))
1154− [A] writeAppendWith :: forall m a. (MonadIO m, Unbox a) => (Int -> Int) -> m (MutArray a) -> Fold m a (MutArray a)
1155− [A] writeAppendNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a) -> Fold m a (MutArray a)
1156− [A] writeAppendN :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a) -> Fold m a (MutArray a)
1157− [A] writeAppend :: forall m a. (MonadIO m, Unbox a) => m (MutArray a) -> Fold m a (MutArray a)
1158− [A] write :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
1159− [A] unsafeSwapIndices :: forall m a. (MonadIO m, Unbox a) => Int -> Int -> MutArray a -> m ()
1160− [A] unpin :: MutArray a -> IO (MutArray a)
1161− [A] toStreamKWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> MutArray a -> StreamK m a
1162− [A] toStreamKRevWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> MutArray a -> StreamK m a
1163− [A] toStreamKRev :: forall m a. (MonadIO m, Unbox a) => MutArray a -> StreamK m a
1164− [A] toStreamK :: forall m a. (MonadIO m, Unbox a) => MutArray a -> StreamK m a
1165− [A] toStreamDWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> MutArray a -> Stream m a
1166− [A] toStreamDRevWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> MutArray a -> Stream m a
1167− [A] toList :: forall m a. (MonadIO m, Unbox a) => MutArray a -> m [a]
1168− [A] swapIndices :: forall m a. (MonadIO m, Unbox a) => Int -> Int -> MutArray a -> m ()
1169− [A] strip :: forall a m. (Unbox a, MonadIO m) => (a -> Bool) -> MutArray a -> m (MutArray a)
1170− [A] splitOn :: (MonadIO m, Unbox a) => (a -> Bool) -> MutArray a -> Stream m (MutArray a)
1171− [A] splitAt :: forall a. Unbox a => Int -> MutArray a -> (MutArray a, MutArray a)
1172− [A] spliceWith :: forall m a. (MonadIO m, Unbox a) => (Int -> Int -> Int) -> MutArray a -> MutArray a -> m (MutArray a)
1173− [A] spliceUnsafe :: MonadIO m => MutArray a -> MutArray a -> m (MutArray a)
1174− [A] spliceExp :: (MonadIO m, Unbox a) => MutArray a -> MutArray a -> m (MutArray a)
1175− [A] spliceCopy :: forall m a. MonadIO m => MutArray a -> MutArray a -> m (MutArray a)
1176− [A] splice :: (MonadIO m, Unbox a) => MutArray a -> MutArray a -> m (MutArray a)
1177− [A] snocWith :: forall m a. (MonadIO m, Unbox a) => (Int -> Int) -> MutArray a -> a -> m (MutArray a)
1178− [A] snocUnsafe :: forall m a. (MonadIO m, Unbox a) => MutArray a -> a -> m (MutArray a)
1179− [A] snocMay :: forall m a. (MonadIO m, Unbox a) => MutArray a -> a -> m (Maybe (MutArray a))
1180− [A] snocLinear :: forall m a. (MonadIO m, Unbox a) => MutArray a -> a -> m (MutArray a)
1181− [A] snoc :: forall m a. (MonadIO m, Unbox a) => MutArray a -> a -> m (MutArray a)
1182− [A] shuffleBy :: (a -> a -> m Bool) -> MutArray a -> MutArray a -> m ()
1183− [A] roundUpToPower2 :: Int -> Int
1184− [A] rightSize :: forall m a. (MonadIO m, Unbox a) => MutArray a -> m (MutArray a)
1185− [A] reverse :: forall m a. (MonadIO m, Unbox a) => MutArray a -> m ()
1186− [A] resizeExp :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (MutArray a)
1187− [A] resize :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (MutArray a)
1188− [A] realloc :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (MutArray a)
1189− [A] readerRevWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> Unfold m (MutArray a) a
1190− [A] readerRev :: forall m a. (MonadIO m, Unbox a) => Unfold m (MutArray a) a
1191− [A] reader :: forall m a. (MonadIO m, Unbox a) => Unfold m (MutArray a) a
1192− [A] readRev :: forall m a. (MonadIO m, Unbox a) => MutArray a -> Stream m a
1193− [A] readIORef :: Unbox a => IORef a -> IO a
1194− [A] read :: forall m a. (MonadIO m, Unbox a) => MutArray a -> Stream m a
1195− [A] putIndices :: forall m a. (MonadIO m, Unbox a) => MutArray a -> Fold m (Int, a) ()
1196− [A] putIndexUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> a -> m ()
1197− [A] putIndex :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> a -> m ()
1198− [A] producerWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> Producer m (MutArray a) a
1199− [A] producer :: forall m a. (MonadIO m, Unbox a) => Producer m (MutArray a) a
1200− [A] pollIntIORef :: (MonadIO m, Unbox a) => IORef a -> Stream m a
1201− [A] pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
1202− [A] pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a) => Int -> Int -> Fold m a (MutArray a)
1203− [A] pinnedWriteN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
1204− [A] pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
1205− [A] pinnedNewBytes :: MonadIO m => Int -> m (MutArray a)
1206− [A] pinnedNewAligned :: (MonadIO m, Unbox a) => Int -> Int -> m (MutArray a)
1207− [A] pinnedNew :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
1208− [A] pinnedFromListN :: (MonadIO m, Unbox a) => Int -> [a] -> m (MutArray a)
1209− [A] pinnedFromList :: (MonadIO m, Unbox a) => [a] -> m (MutArray a)
1210− [A] pinnedClone :: MonadIO m => MutArray a -> m (MutArray a)
1211− [A] pinnedChunksOf :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> Stream m (MutArray a)
1212− [A] pin :: MutArray a -> IO (MutArray a)
1213− [A] permute :: MutArray a -> m Bool
1214− [A] partitionBy :: forall m a. (MonadIO m, Unbox a) => (a -> Bool) -> MutArray a -> m (MutArray a, MutArray a)
1215− [A] nil :: MutArray a
1216− [A] newIORef :: forall a. Unbox a => a -> IO (IORef a)
1217− [A] newArrayWith :: forall m a. (MonadIO m, Unbox a) => (Int -> Int -> m MutByteArray) -> Int -> Int -> m (MutArray a)
1218− [A] new :: (MonadIO m, Unbox a) => Int -> m (MutArray a)
1219− [A] modifyIndices :: forall m a. (MonadIO m, Unbox a) => MutArray a -> (Int -> a -> a) -> Fold m Int ()
1220− [A] modifyIndexUnsafe :: forall m a b. (MonadIO m, Unbox a) => Int -> MutArray a -> (a -> (a, b)) -> m b
1221− [A] modifyIndex :: forall m a b. (MonadIO m, Unbox a) => Int -> MutArray a -> (a -> (a, b)) -> m b
1222− [A] modifyIORef' :: Unbox a => IORef a -> (a -> a) -> IO ()
1223− [A] modify :: forall m a. (MonadIO m, Unbox a) => MutArray a -> (a -> a) -> m ()
1224− [A] mergeBy :: Int -> (MutArray a -> MutArray a -> m ()) -> MutArray a -> m ()
1225− [A] memcpy :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()
1226− [A] memcmp :: Ptr Word8 -> Ptr Word8 -> Int -> IO Bool
1227− [A] length :: forall a. Unbox a => MutArray a -> Int
1228− [A] isPinned :: MutArray a -> Bool
1229− [A] getSlicesFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (MutArray a) (MutArray a)
1230− [A] getSliceUnsafe :: forall a. Unbox a => Int -> Int -> MutArray a -> MutArray a
1231− [A] getSlice :: forall a. Unbox a => Int -> Int -> MutArray a -> MutArray a
1232− [A] getIndicesD :: (Monad m, Unbox a) => (forall b. IO b -> m b) -> Stream m Int -> Unfold m (MutArray a) a
1233− [A] getIndices :: (MonadIO m, Unbox a) => Stream m Int -> Unfold m (MutArray a) a
1234− [A] getIndexUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m a
1235− [A] getIndexRev :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m a
1236− [A] getIndex :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (Maybe a)
1237− [A] genSlicesFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (MutArray a) (Int, Int)
1238− [A] fromStreamDN :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> m (MutArray a)
1239− [A] fromStreamD :: (MonadIO m, Unbox a) => Stream m a -> m (MutArray a)
1240− [A] fromStream :: (MonadIO m, Unbox a) => Stream m a -> m (MutArray a)
1241− [A] fromPureStream :: (MonadIO m, Unbox a) => Stream Identity a -> m (MutArray a)
1242− [A] fromListRevN :: (MonadIO m, Unbox a) => Int -> [a] -> m (MutArray a)
1243− [A] fromListRev :: (MonadIO m, Unbox a) => [a] -> m (MutArray a)
1244− [A] fromListN :: (MonadIO m, Unbox a) => Int -> [a] -> m (MutArray a)
1245− [A] fromList :: (MonadIO m, Unbox a) => [a] -> m (MutArray a)
1246− [A] fromArrayStreamK :: (Unbox a, MonadIO m) => StreamK m (MutArray a) -> m (MutArray a)
1247− [A] foldr :: (MonadIO m, Unbox a) => (a -> b -> b) -> b -> MutArray a -> m b
1248− [A] foldl' :: (MonadIO m, Unbox a) => (b -> a -> b) -> b -> MutArray a -> m b
1249− [A] flattenArraysRev :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
1250− [A] flattenArrays :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
1251− [A] divideBy :: Int -> (MutArray a -> m (MutArray a, MutArray a)) -> MutArray a -> m ()
1252− [A] cmp :: MonadIO m => MutArray a -> MutArray a -> m Ordering
1253− [A] clone :: MonadIO m => MutArray a -> m (MutArray a)
1254− [A] chunksOf :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> Stream m (MutArray a)
1255− [A] castUnsafe :: MutArray a -> MutArray b
1256− [A] cast :: forall a b. Unbox b => MutArray a -> Maybe (MutArray b)
1257− [A] c_memchr :: Ptr Word8 -> Word8 -> CSize -> IO (Ptr Word8)
1258− [A] bytesFree :: MutArray a -> Int
1259− [A] byteLength :: MutArray a -> Int
1260− [A] byteCapacity :: MutArray a -> Int
1261− [A] bubble :: (MonadIO m, Unbox a) => (a -> a -> Ordering) -> MutArray a -> m ()
1262− [A] breakOn :: MonadIO m => Word8 -> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
1263− [A] blockSize :: Int
1264− [A] asPtrUnsafe :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
1265− [A] asBytes :: MutArray a -> MutArray Word8
1266− [A] arrayChunkBytes :: Int
1267− [A] allocBytesToElemCount :: Unbox a => a -> Int -> Int
1268−[C] Streamly.Internal.Data.IsMap
1269− [A] mapTraverseWithKey :: (IsMap f, Applicative t) => (Key f -> a -> t b) -> f a -> t (f b)
1270−[R] Streamly.Internal.Data.IORef.Unboxed
1271−[R] Streamly.Internal.Data.Fold.Window
1272−[R] Streamly.Internal.Data.Fold.Type
1273−[R] Streamly.Internal.Data.Fold.Tee
1274−[R] Streamly.Internal.Data.Fold.Step
1275−[R] Streamly.Internal.Data.Fold.Container
1276−[D] Streamly.Internal.Data.Fold.Chunked
1277−[C] Streamly.Internal.Data.Fold
1278− [A] ManyState
1279− [C] Fold
1280− [C] Fold
1281− [O] Fold :: (s -> a -> m (Step s b)) -> m (Step s b) -> (s -> m b) -> Fold m a b
1282− [N] Fold :: (s -> a -> m (Step s b)) -> m (Step s b) -> (s -> m b) -> (s -> m b) -> Fold m a b
1283− [A] windowSumInt :: forall m a. (Monad m, Integral a) => Fold m (a, Maybe a) a
1284− [A] windowSum :: forall m a. (Monad m, Num a) => Fold m (a, Maybe a) a
1285− [A] windowRollingMapM :: Monad m => (Maybe a -> a -> m (Maybe b)) -> Fold m (a, Maybe a) (Maybe b)
1286− [A] windowRollingMap :: Monad m => (Maybe a -> a -> Maybe b) -> Fold m (a, Maybe a) (Maybe b)
1287− [A] windowRange :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (Maybe (a, a))
1288− [A] windowPowerSumFrac :: (Monad m, Floating a) => a -> Fold m (a, Maybe a) a
1289− [A] windowPowerSum :: (Monad m, Num a) => Int -> Fold m (a, Maybe a) a
1290− [A] windowMinimum :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (Maybe a)
1291− [A] windowMean :: forall m a. (Monad m, Fractional a) => Fold m (a, Maybe a) a
1292− [A] windowMaximum :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (Maybe a)
1293− [A] windowLmap :: (c -> a) -> Fold m (a, Maybe a) b -> Fold m (c, Maybe c) b
1294− [A] windowLength :: (Monad m, Num b) => Fold m (a, Maybe a) b
1295− [A] toSet :: (Monad m, Ord a) => Fold m a (Set a)
1296− [A] toMapIO :: (MonadIO m, Ord k) => (a -> k) -> Fold m a b -> Fold m a (Map k b)
1297− [A] toMap :: (Monad m, Ord k) => (a -> k) -> Fold m a b -> Fold m a (Map k b)
1298− [A] toIntSet :: Monad m => Fold m Int IntSet
1299− [A] toContainerIO :: (MonadIO m, IsMap f, Traversable f, Ord (Key f)) => (a -> Key f) -> Fold m a b -> Fold m a (f b)
1300− [A] toContainer :: (Monad m, IsMap f, Traversable f, Ord (Key f)) => (a -> Key f) -> Fold m a b -> Fold m a (f b)
1301− [A] nubInt :: Monad m => Fold m Int (Maybe Int)
1302− [A] nub :: (Monad m, Ord a) => Fold m a (Maybe a)
1303− [A] mapMStep :: Applicative m => (a -> m b) -> Step s a -> m (Step s b)
1304− [A] kvToMap :: (Monad m, Ord k) => Fold m a b -> Fold m (k, a) (Map k b)
1305− [A] frequency :: (Monad m, Ord a) => Fold m a (Map a Int)
1306− [A] demuxToMapIO :: (MonadIO m, Ord k) => (a -> k) -> (a -> m (Fold m a b)) -> Fold m a (Map k b)
1307− [A] demuxToMap :: (Monad m, Ord k) => (a -> k) -> (a -> m (Fold m a b)) -> Fold m a (Map k b)
1308− [A] demuxToContainerIO :: (MonadIO m, IsMap f, Traversable f) => (a -> Key f) -> (a -> m (Fold m a b)) -> Fold m a (f b)
1309− [A] demuxToContainer :: (Monad m, IsMap f, Traversable f) => (a -> Key f) -> (a -> m (Fold m a b)) -> Fold m a (f b)
1310− [A] demuxKvToMap :: (Monad m, Ord k) => (k -> m (Fold m a b)) -> Fold m (k, a) (Map k b)
1311− [A] demuxKvToContainer :: (Monad m, IsMap f, Traversable f) => (Key f -> m (Fold m a b)) -> Fold m (Key f, a) (f b)
1312− [A] demuxIO :: (MonadIO m, Ord k) => (a -> k) -> (a -> m (Fold m a b)) -> Fold m a (m (Map k b), Maybe (k, b))
1313− [A] demuxGenericIO :: (MonadIO m, IsMap f, Traversable f) => (a -> Key f) -> (a -> m (Fold m a b)) -> Fold m a (m (f b), Maybe (Key f, b))
1314− [A] demuxGeneric :: (Monad m, IsMap f, Traversable f) => (a -> Key f) -> (a -> m (Fold m a b)) -> Fold m a (m (f b), Maybe (Key f, b))
1315− [A] demux :: (Monad m, Ord k) => (a -> k) -> (a -> m (Fold m a b)) -> Fold m a (m (Map k b), Maybe (k, b))
1316− [A] cumulative :: Fold m (a, Maybe a) b -> Fold m a b
1317− [A] countDistinctInt :: Monad m => Fold m Int Int
1318− [A] countDistinct :: (Monad m, Ord a) => Fold m a Int
1319− [A] classifyIO :: (MonadIO m, Ord k) => (a -> k) -> Fold m a b -> Fold m a (m (Map k b), Maybe (k, b))
1320− [A] classifyGenericIO :: (MonadIO m, IsMap f, Traversable f, Ord (Key f)) => (a -> Key f) -> Fold m a b -> Fold m a (m (f b), Maybe (Key f, b))
1321− [A] classifyGeneric :: (Monad m, IsMap f, Traversable f, Ord (Key f)) => (a -> Key f) -> Fold m a b -> Fold m a (m (f b), Maybe (Key f, b))
1322− [A] classify :: (Monad m, Ord k) => (a -> k) -> Fold m a b -> Fold m a (m (Map k b), Maybe (k, b))
1323− [A] chainStepM :: Applicative m => (s1 -> m s2) -> (a -> m (Step s2 b)) -> Step s1 a -> m (Step s2 b)
1324−[C] Streamly.Internal.Data.Builder
1325− [C] Builder
1326− [C] Builder
1327− [O] Builder :: (s -> m (s, a)) -> Builder s m a
1328− [N] Builder :: (s -> m (a, s)) -> Builder s m a
1329−[A] Streamly.Internal.Data.Binary.Stream
1330− [A] class ToBytes a
1331− [A] word8 :: Applicative m => Word8 -> Stream m Word8
1332− [A] word64le :: Monad m => Word64 -> Stream m Word8
1333− [A] word64host :: Monad m => Word64 -> Stream m Word8
1334− [A] word64be :: Monad m => Word64 -> Stream m Word8
1335− [A] word32le :: Monad m => Word32 -> Stream m Word8
1336− [A] word32be :: Monad m => Word32 -> Stream m Word8
1337− [A] word16le :: Monad m => Word16 -> Stream m Word8
1338− [A] word16be :: Monad m => Word16 -> Stream m Word8
1339− [A] unit :: Applicative m => Stream m Word8
1340− [A] toBytes :: ToBytes a => a -> Stream m Word8
1341− [A] ordering :: Applicative m => Ordering -> Stream m Word8
1342− [A] int8 :: Applicative m => Int8 -> Stream m Word8
1343− [A] int64le :: Monad m => Int64 -> Stream m Word8
1344− [A] int64be :: Monad m => Int64 -> Stream m Word8
1345− [A] int32le :: Monad m => Int32 -> Stream m Word8
1346− [A] int32be :: Monad m => Int32 -> Stream m Word8
1347− [A] int16le :: Monad m => Int16 -> Stream m Word8
1348− [A] int16be :: Monad m => Int16 -> Stream m Word8
1349− [A] float32le :: Monad m => Float -> Stream m Word8
1350− [A] float32be :: Monad m => Float -> Stream m Word8
1351− [A] double64le :: Monad m => Double -> Stream m Word8
1352− [A] double64be :: Monad m => Double -> Stream m Word8
1353− [A] charUtf8 :: Monad m => Char -> Stream m Word8
1354− [A] charLatin1 :: Applicative m => Char -> Stream m Word8
1355− [A] bool :: Applicative m => Bool -> Stream m Word8
1356−[A] Streamly.Internal.Data.Binary.Parser
1357− [A] class FromBytes a
1358− [A] word8 :: Monad m => Parser Word8 m Word8
1359− [A] word64le :: Monad m => Parser Word8 m Word64
1360− [A] word64host :: MonadIO m => Parser Word8 m Word64
1361− [A] word64be :: Monad m => Parser Word8 m Word64
1362− [A] word32le :: Monad m => Parser Word8 m Word32
1363− [A] word32be :: Monad m => Parser Word8 m Word32
1364− [A] word16le :: Monad m => Parser Word8 m Word16
1365− [A] word16be :: Monad m => Parser Word8 m Word16
1366− [A] unit :: Monad m => Parser Word8 m ()
1367− [A] ordering :: Monad m => Parser Word8 m Ordering
1368− [A] int8 :: Monad m => Parser Word8 m Int8
1369− [A] int64le :: Monad m => Parser Word8 m Int64
1370− [A] int64be :: Monad m => Parser Word8 m Int64
1371− [A] int32le :: Monad m => Parser Word8 m Int32
1372− [A] int32be :: Monad m => Parser Word8 m Int32
1373− [A] int16le :: Monad m => Parser Word8 m Int16
1374− [A] int16be :: Monad m => Parser Word8 m Int16
1375− [A] fromBytes :: FromBytes a => Parser Word8 m a
1376− [A] float32le :: MonadIO m => Parser Word8 m Float
1377− [A] float32be :: MonadIO m => Parser Word8 m Float
1378− [A] eqWord8 :: Monad m => Word8 -> Parser Word8 m Word8
1379− [A] double64le :: MonadIO m => Parser Word8 m Double
1380− [A] double64be :: MonadIO m => Parser Word8 m Double
1381− [A] charLatin1 :: Monad m => Parser Word8 m Char
1382− [A] bool :: Monad m => Parser Word8 m Bool
1383−[R] Streamly.Internal.Data.Array.Type
1384−[A] Streamly.Internal.Data.Array.Stream
1385− [A] unlines :: forall m a. (MonadIO m, Unbox a) => a -> Stream m (Array a) -> Stream m a
1386− [A] toArray :: (MonadIO m, Unbox a) => Stream m (Array a) -> m (Array a)
1387− [A] splitOnSuffix :: MonadIO m => Word8 -> Stream m (Array Word8) -> Stream m (Array Word8)
1388− [A] splitOn :: MonadIO m => Word8 -> Stream m (Array Word8) -> Stream m (Array Word8)
1389− [A] runArrayParserDBreak :: forall m a b. (MonadIO m, Unbox a) => Parser (Array a) m b -> Stream m (Array a) -> m (Either ParseError b, Stream m (Array a))
1390− [A] runArrayFoldMany :: (Monad m, Unbox a) => ChunkFold m a b -> StreamK m (Array a) -> StreamK m (Either ParseError b)
1391− [A] runArrayFoldBreak :: (MonadIO m, Unbox a) => ChunkFold m a b -> StreamK m (Array a) -> m (Either ParseError b, StreamK m (Array a))
1392− [A] runArrayFold :: (MonadIO m, Unbox a) => ChunkFold m a b -> StreamK m (Array a) -> m (Either ParseError b)
1393− [A] pinnedChunksOf :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> Stream m (Array a)
1394− [A] parseChunks :: (Monad m, Unbox a) => ParserK (Array a) m b -> StreamK m (Array a) -> m (Either ParseError b)
1395− [A] parseBreakChunks :: (Monad m, Unbox a) => ParserK (Array a) m b -> StreamK m (Array a) -> m (Either ParseError b, StreamK m (Array a))
1396− [A] parseBreak :: (MonadIO m, Unbox a) => Parser a m b -> StreamK m (Array a) -> m (Either ParseError b, StreamK m (Array a))
1397− [A] lpackArraysChunksOf :: (MonadIO m, Unbox a) => Int -> Fold m (Array a) () -> Fold m (Array a) ()
1398− [A] interposeSuffix :: (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
1399− [A] interpose :: (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
1400− [A] intercalateSuffix :: (Monad m, Unbox a) => Array a -> Stream m (Array a) -> Stream m a
1401− [A] foldBreakD :: forall m a b. (MonadIO m, Unbox a) => Fold m a b -> Stream m (Array a) -> m (b, Stream m (Array a))
1402− [A] foldBreak :: (MonadIO m, Unbox a) => Fold m a b -> StreamK m (Array a) -> m (b, StreamK m (Array a))
1403− [A] flattenArraysRev :: forall m a. (MonadIO m, Unbox a) => Stream m (Array a) -> Stream m a
1404− [A] flattenArrays :: forall m a. (MonadIO m, Unbox a) => Stream m (Array a) -> Stream m a
1405− [A] concatRev :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
1406− [A] concat :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
1407− [A] compact :: (MonadIO m, Unbox a) => Int -> Stream m (Array a) -> Stream m (Array a)
1408− [A] chunksOf :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> Stream m (Array a)
1409− [A] bufferChunks :: (MonadIO m, Unbox a) => Stream m a -> m (StreamK m (Array a))
1410−[R] Streamly.Internal.Data.Array.Mut.Type
1411−[R] Streamly.Internal.Data.Array.Mut.Stream
1412−[R] Streamly.Internal.Data.Array.Mut
1413−[R] Streamly.Internal.Data.Array.Generic.Mut.Type
1414−[C] Streamly.Internal.Data.Array.Generic
1415− [A] getIndex :: Int -> Array a -> Maybe a
1416− [A] fromPureStream :: Stream Identity a -> Array a
1417− [A] fromByteStr# :: Addr# -> Array Word8
1418− [A] chunksOf :: forall m a. MonadIO m => Int -> Stream m a -> Stream m (Array a)
1419−[C] Streamly.Internal.Data.Array
1420− [A] ArrayUnsafe
1421− [A] ArrayUnsafe :: {-# UNPACK #-} !MutByteArray -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> ArrayUnsafe a
1422− [C] Array
1423− [A] [arrStart] :: Array a -> {-# UNPACK #-} !Int
1424− [A] [arrEnd] :: Array a -> {-# UNPACK #-} !Int
1425− [A] [arrContents] :: Array a -> {-# UNPACK #-} !MutByteArray
1426− [A] Array :: {-# UNPACK #-} !MutByteArray -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Array a
1427− [A] writeWith :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
1428− [A] writeNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
1429− [R] writeNAligned :: forall m a. (MonadIO m, Unbox a) => Int -> Int -> Fold m a (Array a)
1430− [A] unsafeMakePure :: Monad m => Fold IO a b -> Fold m a b
1431− [A] unsafeIndexIO :: forall a. Unbox a => Int -> Array a -> IO a
1432− [D] unsafeIndex :: forall a. Unbox a => Int -> Array a -> a
1433− [A] unsafeFreezeWithShrink :: Unbox a => MutArray a -> Array a
1434− [A] unpin :: Array a -> IO (Array a)
1435− [A] toStreamKRev :: forall m a. (Monad m, Unbox a) => Array a -> StreamK m a
1436− [A] toStreamK :: forall m a. (Monad m, Unbox a) => Array a -> StreamK m a
1437− [A] toStreamDRev :: forall m a. (Monad m, Unbox a) => Array a -> Stream m a
1438− [A] toStreamD :: forall m a. (Monad m, Unbox a) => Array a -> Stream m a
1439− [A] splitAt :: Unbox a => Int -> Array a -> (Array a, Array a)
1440− [A] splice :: (MonadIO m, Unbox a) => Array a -> Array a -> m (Array a)
1441− [A] serialize :: Serialize a => a -> Array Word8
1442− [A] pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
1443− [A] pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a) => Int -> Int -> Fold m a (Array a)
1444− [A] pinnedWriteN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
1445− [A] pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
1446− [A] pinnedSerialize :: Serialize a => a -> Array Word8
1447− [A] pinnedFromListN :: Unbox a => Int -> [a] -> Array a
1448− [A] pinnedFromList :: Unbox a => [a] -> Array a
1449− [A] pinnedClone :: MonadIO m => Array a -> m (Array a)
1450− [A] pinnedChunksOf :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> Stream m (Array a)
1451− [A] pin :: Array a -> IO (Array a)
1452− [A] nil :: Array a
1453− [A] isPinned :: Array a -> Bool
1454− [A] getIndexUnsafe :: forall a. Unbox a => Int -> Array a -> a
1455− [A] fromStreamDN :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> m (Array a)
1456− [A] fromStreamD :: forall m a. (MonadIO m, Unbox a) => Stream m a -> m (Array a)
1457− [A] fromPureStream :: Unbox a => Stream Identity a -> Array a
1458− [A] fromListRevN :: Unbox a => Int -> [a] -> Array a
1459− [A] fromListRev :: Unbox a => [a] -> Array a
1460− [A] fromByteStr# :: Addr# -> Array Word8
1461− [A] foldr :: Unbox a => (a -> b -> b) -> b -> Array a -> b
1462− [A] foldl' :: forall a b. Unbox a => (b -> a -> b) -> b -> Array a -> b
1463− [A] flattenArraysRev :: forall m a. (MonadIO m, Unbox a) => Stream m (Array a) -> Stream m a
1464− [A] flattenArrays :: forall m a. (MonadIO m, Unbox a) => Stream m (Array a) -> Stream m a
1465− [A] encodeAs :: forall a. Serialize a => PinnedState -> a -> Array Word8
1466− [A] deserialize :: Serialize a => Array Word8 -> a
1467− [A] clone :: MonadIO m => Array a -> m (Array a)
1468− [A] chunksOf :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> Stream m (Array a)
1469− [A] byteLength :: Array a -> Int
1470− [A] bufferChunks :: (MonadIO m, Unbox a) => Stream m a -> m (StreamK m (Array a))
1471− [A] breakOn :: MonadIO m => Word8 -> Array Word8 -> m (Array Word8, Maybe (Array Word8))
core/docs/ApiChangelogs/0.2.0-0.2.2.txtdeleted−306
@@ -1,306 +0,0 @@
1−---------------------------------
2−API Annotations
3−---------------------------------
4−
5−[A] : Added
6−[R] : Removed
7−[C] : Changed
8−[O] : Old definition
9−[N] : New definition
10−[D] : Deprecated
11−
12−---------------------------------
13−API diff
14−---------------------------------
15−
16−[C] Streamly.Data.Stream
17− [A] (FixityR,5)
18− [A] (FixityR,5)
19−[C] Streamly.Data.MutArray.Generic
20− [A] emptyOf :: MonadIO m => Int -> m (MutArray a)
21− [A] createOf :: MonadIO m => Int -> Fold m a (MutArray a)
22− [A] create :: MonadIO m => Fold m a (MutArray a)
23−[C] Streamly.Data.MutArray
24− [A] pinnedEmptyOf :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
25− [A] emptyOf :: (MonadIO m, Unbox a) => Int -> m (MutArray a)
26− [A] createOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
27− [A] create :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
28− [A] appendN :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a) -> Fold m a (MutArray a)
29− [A] append :: forall m a. (MonadIO m, Unbox a) => m (MutArray a) -> Fold m a (MutArray a)
30−[C] Streamly.Data.Array.Generic
31− [A] createOf :: MonadIO m => Int -> Fold m a (Array a)
32− [A] create :: MonadIO m => Fold m a (Array a)
33−[C] Streamly.Data.Array
34− [A] class Serialize a
35− [A] serializeAt :: Serialize a => Int -> MutByteArray -> a -> IO Int
36− [A] pinnedSerialize :: Serialize a => a -> Array Word8
37− [A] deserializeAt :: Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
38− [A] deserialize :: Serialize a => Array Word8 -> a
39− [A] createOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
40− [A] create :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
41− [A] addSizeTo :: Serialize a => Int -> a -> Int
42−
43−---------------------------------
44−Internal API diff
45−---------------------------------
46−
47−[C] Streamly.Internal.Unicode.Stream
48− [A] encodeUtf16le' :: Stream m Char -> Stream m Word16
49− [A] decodeUtf16le' :: Stream m Word16 -> Stream m Char
50−[A] Streamly.Internal.FileSystem.Path
51− [A] class IsPath a
52− [A] Rel
53− [A] File
54− [A] Dir
55− [A] Abs
56− [A] Streamly.Internal.FileSystem.Path.IsPath
57− [A] instance Streamly.Internal.FileSystem.Path.IsPath Streamly.Internal.FileSystem.Path.Path
58− [A] instance Streamly.Internal.FileSystem.Path.IsPath (Streamly.Internal.FileSystem.Path.Rel Streamly.Internal.FileSystem.Path.Path)
59− [A] instance Streamly.Internal.FileSystem.Path.IsPath (Streamly.Internal.FileSystem.Path.Rel (Streamly.Internal.FileSystem.Path.File Streamly.Internal.FileSystem.Path.Path))
60− [A] instance Streamly.Internal.FileSystem.Path.IsPath (Streamly.Internal.FileSystem.Path.Rel (Streamly.Internal.FileSystem.Path.Dir Streamly.Internal.FileSystem.Path.Path))
61− [A] instance Streamly.Internal.FileSystem.Path.IsPath (Streamly.Internal.FileSystem.Path.File Streamly.Internal.FileSystem.Path.Path)
62− [A] instance Streamly.Internal.FileSystem.Path.IsPath (Streamly.Internal.FileSystem.Path.Dir Streamly.Internal.FileSystem.Path.Path)
63− [A] instance Streamly.Internal.FileSystem.Path.IsPath (Streamly.Internal.FileSystem.Path.Abs Streamly.Internal.FileSystem.Path.Path)
64− [A] instance Streamly.Internal.FileSystem.Path.IsPath (Streamly.Internal.FileSystem.Path.Abs (Streamly.Internal.FileSystem.Path.File Streamly.Internal.FileSystem.Path.Path))
65− [A] instance Streamly.Internal.FileSystem.Path.IsPath (Streamly.Internal.FileSystem.Path.Abs (Streamly.Internal.FileSystem.Path.Dir Streamly.Internal.FileSystem.Path.Path))
66− [A] GHC.Show.Show
67− [A] instance GHC.Show.Show Streamly.Internal.FileSystem.Path.PathException
68− [A] GHC.Exception.Type.Exception
69− [A] instance GHC.Exception.Type.Exception Streamly.Internal.FileSystem.Path.PathException
70− [A] GHC.Classes.Eq
71− [A] instance GHC.Classes.Eq Streamly.Internal.FileSystem.Path.PathException
72− [A] Path
73− [A] Path :: Array Word8 -> Path
74− [A] toString :: Path -> [Char]
75− [A] toPath :: IsPath a => a -> Path
76− [A] toChunk :: Path -> Array Word8
77− [A] toChars :: Monad m => Path -> Stream m Char
78− [A] relfile :: QuasiQuoter
79− [A] reldir :: QuasiQuoter
80− [A] rel :: QuasiQuoter
81− [A] primarySeparator :: Char
82− [A] path :: QuasiQuoter
83− [A] mkRelFile :: String -> Q Exp
84− [A] mkRelDir :: String -> Q Exp
85− [A] mkRel :: String -> Q Exp
86− [A] mkPath :: String -> Q Exp
87− [A] mkFile :: String -> Q Exp
88− [A] mkDir :: String -> Q Exp
89− [A] mkAbsFile :: String -> Q Exp
90− [A] mkAbsDir :: String -> Q Exp
91− [A] mkAbs :: String -> Q Exp
92− [A] isSeparator :: Char -> Bool
93− [A] fromString :: MonadThrow m => [Char] -> m Path
94− [A] fromPathUnsafe :: IsPath a => Path -> a
95− [A] fromPath :: (IsPath a, MonadThrow m) => Path -> m a
96− [A] fromChunkUnsafe :: Array Word8 -> Path
97− [A] fromChunk :: MonadThrow m => Array Word8 -> m Path
98− [A] fromChars :: MonadThrow m => Stream Identity Char -> m Path
99− [A] file :: QuasiQuoter
100− [A] extendPath :: Path -> Path -> Path
101− [A] extendDir :: (IsPath (a (Dir Path)), IsPath b, IsPath (a b)) => a (Dir Path) -> Rel b -> a b
102− [A] dir :: QuasiQuoter
103− [A] adaptPath :: (MonadThrow m, IsPath a, IsPath b) => a -> m b
104− [A] absfile :: QuasiQuoter
105− [A] absdir :: QuasiQuoter
106− [A] abs :: QuasiQuoter
107−[C] Streamly.Internal.Data.Stream
108− [A] (FixityR,5)
109− [A] (FixityR,5)
110− [C] splitInnerBySuffix
111− [O] splitInnerBySuffix :: (Monad m, Eq (f a), Monoid (f a)) => (f a -> m (f a, Maybe (f a))) -> (f a -> f a -> m (f a)) -> Stream m (f a) -> Stream m (f a)
112− [N] splitInnerBySuffix :: Monad m => (f a -> Bool) -> (f a -> m (f a, Maybe (f a))) -> (f a -> f a -> m (f a)) -> Stream m (f a) -> Stream m (f a)
113− [D] sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
114− [A] indexOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
115−[C] Streamly.Internal.Data.MutByteArray
116− [A] unsafePinnedAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
117− [A] unsafeAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
118− [D] nil :: MutByteArray
119− [A] empty :: MutByteArray
120− [D] asPtrUnsafe :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
121−[D] Streamly.Internal.Data.MutArray.Stream
122− [D] writeChunks :: (MonadIO m, Unbox a) => Int -> Fold m a (StreamK n (MutArray a))
123− [D] fromArrayStreamK :: (Unbox a, MonadIO m) => StreamK m (MutArray a) -> m (MutArray a)
124− [D] flattenArraysRev :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
125− [D] flattenArrays :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
126−[C] Streamly.Internal.Data.MutArray.Generic
127− [D] writeWith :: MonadIO m => Int -> Fold m a (MutArray a)
128− [D] writeNUnsafe :: MonadIO m => Int -> Fold m a (MutArray a)
129− [A] unsafeCreateOf :: MonadIO m => Int -> Fold m a (MutArray a)
130− [A] emptyOf :: MonadIO m => Int -> m (MutArray a)
131− [A] createWith :: MonadIO m => Int -> Fold m a (MutArray a)
132− [A] createOf :: MonadIO m => Int -> Fold m a (MutArray a)
133− [A] create :: MonadIO m => Fold m a (MutArray a)
134−[C] Streamly.Internal.Data.MutArray
135− [A] SpliceState
136− [A] SpliceYielding :: arr -> SpliceState s arr -> SpliceState s arr
137− [A] SpliceInitial :: s -> SpliceState s arr
138− [A] SpliceFinish :: SpliceState s arr
139− [A] SpliceBuffering :: s -> arr -> SpliceState s arr
140− [R] MutByteArray
141− [D] writeWith :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
142− [D] writeRevN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
143− [D] writeNWithUnsafe :: forall m a. (MonadIO m, Unbox a) => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
144− [D] writeNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
145− [D] writeChunks :: (MonadIO m, Unbox a) => Int -> Fold m a (StreamK n (MutArray a))
146− [D] writeAppendWith :: forall m a. (MonadIO m, Unbox a) => (Int -> Int) -> m (MutArray a) -> Fold m a (MutArray a)
147− [D] writeAppendNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a) -> Fold m a (MutArray a)
148− [A] unsafePinnedCreateOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
149− [A] unsafePinnedAsPtr :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
150− [A] unsafeCreateOfWith :: forall m a. (MonadIO m, Unbox a) => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
151− [A] unsafeCreateOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
152− [A] unsafeAsPtr :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
153− [A] unsafeAppendN :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a) -> Fold m a (MutArray a)
154− [A] toStreamWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> MutArray a -> Stream m a
155− [A] toStreamRevWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> MutArray a -> Stream m a
156− [R] toStreamDWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> MutArray a -> Stream m a
157− [R] toStreamDRevWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> MutArray a -> Stream m a
158− [A] slicerFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (MutArray a) (MutArray a)
159− [A] sliceIndexerFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (MutArray a) (Int, Int)
160− [A] revCreateOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
161− [D] resizeExp :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (MutArray a)
162− [D] resize :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (MutArray a)
163− [A] pokeSkipUnsafe :: Int -> MutArray Word8 -> MutArray Word8
164− [A] pokeAppendMay :: forall m a. (MonadIO m, Unbox a) => MutArray Word8 -> a -> m (Maybe (MutArray Word8))
165− [A] pokeAppend :: forall m a. (MonadIO m, Unbox a) => MutArray Word8 -> a -> m (MutArray Word8)
166− [D] pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
167− [D] pinnedWriteN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
168− [D] pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
169− [D] pinnedNewBytes :: MonadIO m => Int -> m (MutArray a)
170− [A] pinnedEmptyOf :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
171− [A] pinnedCreateOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
172− [A] pinnedCreate :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
173− [A] pinnedCompactLE :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
174− [A] peekUnconsUnsafe :: forall m a. (MonadIO m, Unbox a) => MutArray Word8 -> m (a, MutArray Word8)
175− [A] peekUncons :: forall m a. (MonadIO m, Unbox a) => MutArray Word8 -> m (Maybe a, MutArray Word8)
176− [A] peekSkipUnsafe :: Int -> MutArray Word8 -> MutArray Word8
177− [A] pPinnedCompactLE :: forall m a. (MonadIO m, Unbox a) => Int -> Parser (MutArray a) m (MutArray a)
178− [A] pCompactLE :: forall m a. (MonadIO m, Unbox a) => Int -> Parser (MutArray a) m (MutArray a)
179− [D] nil :: MutArray a
180− [A] lPinnedCompactGE :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
181− [A] lCompactGE :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
182− [A] indexReaderWith :: (Monad m, Unbox a) => (forall b. IO b -> m b) -> Stream m Int -> Unfold m (MutArray a) a
183− [A] indexReader :: (MonadIO m, Unbox a) => Stream m Int -> Unfold m (MutArray a) a
184− [A] growExp :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (MutArray a)
185− [A] grow :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (MutArray a)
186− [D] getSlicesFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (MutArray a) (MutArray a)
187− [R] getIndicesD :: (Monad m, Unbox a) => (forall b. IO b -> m b) -> Stream m Int -> Unfold m (MutArray a) a
188− [D] getIndices :: (MonadIO m, Unbox a) => Stream m Int -> Unfold m (MutArray a) a
189− [D] genSlicesFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (MutArray a) (Int, Int)
190− [A] fromStreamN :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> m (MutArray a)
191− [D] fromStreamDN :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> m (MutArray a)
192− [D] fromStreamD :: (MonadIO m, Unbox a) => Stream m a -> m (MutArray a)
193− [A] fromPureStreamN :: (MonadIO m, Unbox a) => Int -> Stream Identity a -> m (MutArray a)
194− [A] fromPtrN :: MonadIO m => Int -> Ptr Word8 -> m (MutArray Word8)
195− [A] fromChunksRealloced :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> m (MutArray a)
196− [A] fromChunksK :: (Unbox a, MonadIO m) => StreamK m (MutArray a) -> m (MutArray a)
197− [A] fromByteStr# :: MonadIO m => Addr# -> m (MutArray Word8)
198− [D] fromArrayStreamK :: (Unbox a, MonadIO m) => StreamK m (MutArray a) -> m (MutArray a)
199− [D] flattenArraysRev :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
200− [D] flattenArrays :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
201− [A] fPinnedCompactGE :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m (MutArray a) (MutArray a)
202− [A] fCompactGE :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m (MutArray a) (MutArray a)
203− [A] emptyOf :: (MonadIO m, Unbox a) => Int -> m (MutArray a)
204− [A] empty :: MutArray a
205− [A] createWith :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
206− [A] createOfWith :: forall m a. (MonadIO m, Unbox a) => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
207− [A] createOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
208− [A] create :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
209− [A] concatWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> Stream m (MutArray a) -> Stream m a
210− [A] concatRevWith :: forall m a. (Monad m, Unbox a) => (forall b. IO b -> m b) -> Stream m (MutArray a) -> Stream m a
211− [A] concatRev :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
212− [A] concat :: forall m a. (MonadIO m, Unbox a) => Stream m (MutArray a) -> Stream m a
213− [A] compactOnByteSuffix :: MonadIO m => Word8 -> Stream m (MutArray Word8) -> Stream m (MutArray Word8)
214− [A] compactOnByte :: MonadIO m => Word8 -> Stream m (MutArray Word8) -> Stream m (MutArray Word8)
215− [A] compactLeAs :: forall m a. (MonadIO m, Unbox a) => PinnedState -> Int -> Stream m (MutArray a) -> Stream m (MutArray a)
216− [A] compactLE :: (MonadIO m, Unbox a) => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
217− [A] compactGE :: (MonadIO m, Unbox a) => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
218− [A] compactEQ :: Int -> Stream m (MutArray a) -> Stream m (MutArray a)
219− [D] cmp :: MonadIO m => MutArray a -> MutArray a -> m Ordering
220− [A] byteEq :: MonadIO m => MutArray a -> MutArray a -> m Bool
221− [A] byteCmp :: MonadIO m => MutArray a -> MutArray a -> m Ordering
222− [A] buildChunks :: (MonadIO m, Unbox a) => Int -> Fold m a (StreamK n (MutArray a))
223− [D] asPtrUnsafe :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
224− [A] appendWith :: forall m a. (MonadIO m, Unbox a) => (Int -> Int) -> m (MutArray a) -> Fold m a (MutArray a)
225− [A] appendN :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a) -> Fold m a (MutArray a)
226− [A] append :: forall m a. (MonadIO m, Unbox a) => m (MutArray a) -> Fold m a (MutArray a)
227−[D] Streamly.Internal.Data.Array.Stream
228− [C] interposeSuffix
229− [O] interposeSuffix :: (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
230− [N] interposeSuffix :: forall m a. (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
231− [D] flattenArraysRev :: forall m a. (MonadIO m, Unbox a) => Stream m (Array a) -> Stream m a
232− [D] flattenArrays :: forall m a. (MonadIO m, Unbox a) => Stream m (Array a) -> Stream m a
233− [C] concatRev
234− [O] concatRev :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
235− [N] concatRev :: forall m a. (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
236− [D] bufferChunks :: (MonadIO m, Unbox a) => Stream m a -> m (StreamK m (Array a))
237−[C] Streamly.Internal.Data.Array.Generic
238− [A] createOf :: MonadIO m => Int -> Fold m a (Array a)
239− [A] create :: MonadIO m => Fold m a (Array a)
240−[C] Streamly.Internal.Data.Array
241− [R] ArrayUnsafe
242− [D] writeWith :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
243− [D] writeNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
244− [A] unsafePinnedCreateOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
245− [A] unsafePinnedAsPtr :: MonadIO m => Array a -> (Ptr a -> m b) -> m b
246− [A] unsafeCreateOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
247− [D] toStreamDRev :: forall m a. (Monad m, Unbox a) => Array a -> Stream m a
248− [D] toStreamD :: forall m a. (Monad m, Unbox a) => Array a -> Stream m a
249− [C] splice
250− [O] splice :: (MonadIO m, Unbox a) => Array a -> Array a -> m (Array a)
251− [N] splice :: MonadIO m => Array a -> Array a -> m (Array a)
252− [A] slicerFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (Array a) (Array a)
253− [A] sliceIndexerFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (Array a) (Int, Int)
254− [D] pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
255− [D] pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a) => Int -> Int -> Fold m a (Array a)
256− [D] pinnedWriteN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
257− [D] pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
258− [A] pinnedCreateOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
259− [A] pinnedCreate :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
260− [A] pinnedCompactLE :: (MonadIO m, Unbox a) => Int -> Stream m (Array a) -> Stream m (Array a)
261− [A] parseBreakChunksK :: forall m a b. (MonadIO m, Unbox a) => Parser a m b -> StreamK m (Array a) -> m (Either ParseError b, StreamK m (Array a))
262− [D] nil :: Array a
263− [A] lPinnedCompactGE :: (MonadIO m, Unbox a) => Int -> Fold m (Array a) () -> Fold m (Array a) ()
264− [A] lCompactGE :: (MonadIO m, Unbox a) => Int -> Fold m (Array a) () -> Fold m (Array a) ()
265− [A] interposeSuffix :: forall m a. (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
266− [A] interpose :: (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
267− [A] intercalateSuffix :: (Monad m, Unbox a) => Array a -> Stream m (Array a) -> Stream m a
268− [A] indexReaderFromThenTo :: Unfold m (Int, Int, Int, Array a) a
269− [A] indexReader :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
270− [A] indexFinder :: (a -> Bool) -> Unfold Identity (Array a) Int
271− [D] getSlicesFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (Array a) (Array a)
272− [R] getIndicesFromThenTo :: Unfold m (Int, Int, Int, Array a) a
273− [D] getIndices :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
274− [D] genSlicesFromLen :: forall m a. (Monad m, Unbox a) => Int -> Int -> Unfold m (Array a) (Int, Int)
275− [D] fromStreamDN :: forall m a. (MonadIO m, Unbox a) => Int -> Stream m a -> m (Array a)
276− [D] fromStreamD :: forall m a. (MonadIO m, Unbox a) => Stream m a -> m (Array a)
277− [A] fromPureStreamN :: Unbox a => Int -> Stream Identity a -> Array a
278− [A] fromPtrN :: Int -> Ptr Word8 -> Array Word8
279− [A] fromChunksK :: (MonadIO m, Unbox a) => StreamK m (Array a) -> m (Array a)
280− [A] fromChunks :: (MonadIO m, Unbox a) => Stream m (Array a) -> m (Array a)
281− [A] fromByteStr :: Ptr Word8 -> Array Word8
282− [A] foldChunks :: (MonadIO m, Unbox a) => Fold m a b -> Stream m (Array a) -> m b
283− [A] foldBreakChunksK :: forall m a b. (MonadIO m, Unbox a) => Fold m a b -> StreamK m (Array a) -> m (b, StreamK m (Array a))
284− [A] foldBreakChunks :: forall m a b. (MonadIO m, Unbox a) => Fold m a b -> Stream m (Array a) -> m (b, Stream m (Array a))
285− [D] flattenArraysRev :: forall m a. (MonadIO m, Unbox a) => Stream m (Array a) -> Stream m a
286− [D] flattenArrays :: forall m a. (MonadIO m, Unbox a) => Stream m (Array a) -> Stream m a
287− [C] findIndicesOf
288− [O] findIndicesOf :: (a -> Bool) -> Unfold Identity (Array a) Int
289− [N] findIndicesOf :: (a -> Bool) -> Array a -> Stream Identity Int
290− [A] fPinnedCompactGE :: (MonadIO m, Unbox a) => Int -> Fold m (Array a) (Array a)
291− [A] fCompactGE :: (MonadIO m, Unbox a) => Int -> Fold m (Array a) (Array a)
292− [A] empty :: Array a
293− [A] createWith :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
294− [A] createOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
295− [A] create :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
296− [A] concatRev :: forall m a. (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
297− [A] concat :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
298− [A] compactOnByteSuffix :: MonadIO m => Word8 -> Stream m (Array Word8) -> Stream m (Array Word8)
299− [A] compactOnByte :: MonadIO m => Word8 -> Stream m (Array Word8) -> Stream m (Array Word8)
300− [A] compactLE :: (MonadIO m, Unbox a) => Int -> Stream m (Array a) -> Stream m (Array a)
301− [A] compactGE :: (MonadIO m, Unbox a) => Int -> Stream m (Array a) -> Stream m (Array a)
302− [A] byteEq :: Array a -> Array a -> Bool
303− [A] byteCmp :: Array a -> Array a -> Ordering
304− [A] buildChunks :: (MonadIO m, Unbox a) => Stream m a -> m (StreamK m (Array a))
305− [D] bufferChunks :: (MonadIO m, Unbox a) => Stream m a -> m (StreamK m (Array a))
306− [D] asPtrUnsafe :: MonadIO m => Array a -> (Ptr a -> m b) -> m b
core/docs/Changelog.md+27−44
@@ -1,73 +1,56 @@
11# Changelog
22
3−## 0.2.2 (Jan 2024)
4−
5−* Add fixities `infixr 5` for `cons` and `consM` functions.
6−* Fix a bug in Array `Eq` instance when the type is a sum type with
7− differently sized constructors.
8−* lpackArraysChunksOf, compact, writeChunksWith, putChunksWith now take the
9− buffer size in number of array elements instead of bytes.
10−
11−## 0.2.1 (Dec 2023)
12−
13−* Make the serialization of the unit constructor deterministic.
14−* Expose `pinnedSerialize` & `deserialize` via `Streamly.Data.Array`.
15−
163## 0.2.0 (Nov 2023)
174
18−See [0.1.0-0.2.0 API Changelog](https://github.com/composewell/streamly/blob/streamly-0.10.0/core/docs/ApiChangelogs/0.1.0-0.2.0.txt)
19−for a full list of API changes in this release. Only a few significant
20−changes are mentioned here.
21−
22−### Breaking Changes
5+### Breaking
236
247* `ParserK` in `Streamly.Data.ParserK` is not implicitly specialized
258 to arrays anymore. To adapt to the new code, change `ParserK a m
269 b` to `ParserK (Array a) m b` where the `Array` type comes from
27− `Streamly.Data.Array`. This change also affected the signatures of
10+ `Streamly.Data.Array`. This change also changed the signatures of
2811 `parseChunks` and `parseBreakChunks`.
2912* Changed the signature of 'Streamly.Data.Stream.handle' to make the
3013 exception handler monadic.
14+* `getIndex` signature changed in `Streamly.Data.MutArray` and
15+ `Streamly.Data.MutArray.Generic`.
3116* Behavior change: Exceptions are now rethrown promptly in `bracketIO`.
3217
33−### Enhancements
34−
35−* __Serialization__: Added a `Streamly.Data.MutByteArray` module with a
36− `Serialize` type class for fast binary serialization. The Data.Array
37− module supplies the `serialize` and `deserialize` operations for arrays.
38−* __Unpinned Arrays__: Unboxed arrays are now created unpinned by default,
39− they were created pinned earlier. During IO operations, unpinned arrays
40− are automatically copied to pinned memory. When arrays are directly
41− passed to IO operations programmers can choose to create them pinned to
42− avoid a copy. To create pinned arrays, use the internal APIs with the
43− `pinned*` prefix.
44−* StreamK now supports native exception handling routines (handle, bracketIO).
45− Earlier we had to convert it to the `Stream` type for exception handling.
46−
47−### Deprecations
48−
49−See [0.1.0-0.2.0 API Changelog](https://github.com/composewell/streamly/blob/streamly-0.10.0/core/docs/ApiChangelogs/0.1.0-0.2.0.txt)
50−for a full list of deprecations.
51−
52−### Internal API Changes
18+### Internal Changes
5319
5420* Fold constructor has changed, added a `final` field to support
5521 finalization and cleanup of a chain of folds. The `extract` field is
5622 now used only for mapping the fold internal state to fold result for
57− scanning purposes. If your fold does not require cleanup you can just use
58− your existing `extract` function as `final` as well to adapt to this change.
59−* Many low level internal modules have been removed, they are entirely
23+ scanning purposes.
24+* Some low level internal modules have been removed, they are entirely
6025 exported from higher level internal modules. If you were importing any
61− of the missing low level modules then import the higher level modules instead.
26+ of the missing modules then import the higher level modules now.
6227* Internal module changes:
6328 * Streamly.Internal.Serialize.FromBytes -> Streamly.Internal.Data.Binary.Parser
6429 * Streamly.Internal.Serialize.ToBytes -> Streamly.Internal.Data.Binary.Stream
6530 * Streamly.Internal.Data.Unbox is now exported via Streamly.Internal.Data.Serialize
6631 * Streamly.Internal.Data.IORef.Unboxed is now exported via Streamly.Internal.Data.Serialize
6732
33+### Enhancements
34+
35+* Unboxed arrays are now created unpinned by default, they were
36+ created pinned earlier. During IO operations, unpinned arrays are
37+ automatically copied to pinned memory. When arrays are directly passed
38+ to IO operations programmers can choose to create them pinned to avoid a
39+ copy. To create pinned arrays, use the internal APIs with the `pinned*`
40+ prefix.
41+* Added a `Streamly.Data.Serialize` module for fast binary serialization.
42+* Added exception handling routines in StreamK (handle, bracketIO).
43+* More APIs added in `Streamly.Data.MutArray` and
44+ `Streamly.Data.MutArray.Generic`.
45+
46+### Deprecations
47+
48+* `Streamly.Data.MutArray.newUnpinned` is renamed to
49+ `Streamly.Data.MutArray.pinnedNew`
50+
6851## 0.1.0 (March 2023)
6952
70−Also see [streamly-core-0.1.0 API Changelog](https://github.com/composewell/streamly/blob/streamly-0.10.0/core/docs/ApiChangelogs/0.1.0.txt) or
53+Also see [streamly-core-0.1.0 API Changelog](/core/docs/ApiChangelogs/0.1.0.txt) or
7154https://hackage.haskell.org/package/streamly-core-0.1.0/docs/docs/ApiChangelogs/0.1.0.txt
7255
7356`streamly` package is split into two packages, (1) `streamly-core` that
core/src/DocTestDataArray.hs−3
@@ -11,12 +11,9 @@
1111
1212>>> import qualified Streamly.Data.Array as Array
1313>>> import qualified Streamly.Data.Fold as Fold
14−>>> import qualified Streamly.Data.ParserK as ParserK
1514>>> import qualified Streamly.Data.Stream as Stream
16−>>> import qualified Streamly.Data.StreamK as StreamK
1715
1816For APIs that have not been released yet.
1917
2018>>> import qualified Streamly.Internal.Data.Array as Array
21−>>> import qualified Streamly.Internal.Data.Stream as Stream
2219-}
core/src/DocTestDataStream.hs−2
@@ -6,7 +6,6 @@
66>>> import Control.Monad.IO.Class (MonadIO (liftIO))
77>>> import Control.Monad.Trans.Class (lift)
88>>> import Control.Monad.Trans.Identity (runIdentityT)
9−>>> import Data.Char (isSpace)
109>>> import Data.Either (fromLeft, fromRight, isLeft, isRight, either)
1110>>> import Data.Maybe (fromJust, isJust)
1211>>> import Data.Function (fix, (&))
@@ -33,7 +32,6 @@ For APIs that have not been released yet.
3332>>> import qualified Streamly.Internal.Data.Fold as Fold
3433>>> import qualified Streamly.Internal.Data.Parser as Parser
3534>>> import qualified Streamly.Internal.Data.Stream as Stream
36−>>> import qualified Streamly.Internal.Data.StreamK as StreamK
3735>>> import qualified Streamly.Internal.Data.Unfold as Unfold
3836>>> import qualified Streamly.Internal.FileSystem.Dir as Dir
3937-}
core/src/DocTestFileSystemHandle.hs+1−1
@@ -8,7 +8,7 @@
88
99For APIs that have not been released yet.
1010
11−>>> import qualified Streamly.Internal.Data.Array as Array (unsafeCreateOf)
11+>>> import qualified Streamly.Internal.Data.Array as Array (writeNUnsafe)
1212>>> import qualified Streamly.Internal.Data.Unfold as Unfold (first)
1313>>> import qualified Streamly.Internal.FileSystem.Handle as Handle
1414>>> import qualified Streamly.Internal.System.IO as IO (defaultChunkSize)
core/src/Streamly/Data/Array.hs+28−35
@@ -31,42 +31,42 @@ module Streamly.Data.Array
3131 -- * The Array Type
3232 Array
3333
34− -- * Pinning & Unpinning
35− -- | Arrays are created unpinned by default unless pinned versions of
36− -- creation APIs are used. Look for APIs with @pinned@ prefix in
37− -- "Streamly.Internal.Data.Array" for some unreleased pinned creation APIs.
38− -- If an array is to be sent to the OS without any further modification
39− -- then it should be created pinned in the first place instead of pinning
40− -- it later. Pinning an unpinned array has a copy overhead. OS interfacing
41− -- APIs create a pinned array directly or convert an unpinned array to
42− -- pinned array before sending it to the OS.
43− , pin
44− , unpin
45− , isPinned
46−
4734 -- * Construction
4835 -- | When performance matters, the fastest way to generate an array is
49− -- 'createOf'. 'IsList' and 'IsString' instances can be
36+ -- 'writeN'. 'IsList' and 'IsString' instances can be
5037 -- used to conveniently construct arrays from literal values.
5138 -- 'OverloadedLists' extension or 'fromList' can be used to construct an
5239 -- array from a list literal. Similarly, 'OverloadedStrings' extension or
5340 -- 'fromList' can be used to construct an array from a string literal.
5441
55− -- ** From Stream
56− , createOf
57− , create
58− , writeLastN -- drop old (ring buffer)
59−
60− -- ** From List
42+ -- Pure List APIs
6143 , fromListN
6244 , fromList
6345
64− -- * To List
46+ -- Monadic APIs
47+ , writeN -- drop new
48+ , write -- full buffer
49+ , writeLastN -- drop old (ring buffer)
50+
51+ -- * Conversion
6552 -- 'GHC.Exts.toList' from "GHC.Exts" can be used to convert an array to a
6653 -- list.
6754 , toList
6855
69− -- * To Stream
56+ -- * Pinning & Unpinning
57+ -- | Arrays are created unpinned by default unless pinned versions of
58+ -- creation APIs are used. Look for APIs with @pinned@ prefix in
59+ -- "Streamly.Internal.Data.Array" for some unreleased pinned creation APIs.
60+ -- If an array is to be sent to the OS without any further modification
61+ -- then it should be created pinned in the first place instead of pinning
62+ -- it later. Pinning an unpinned array has a copy overhead. OS interfacing
63+ -- APIs create a pinned array directly or convert an unpinned array to
64+ -- pinned array before sending it to the OS.
65+ , pin
66+ , unpin
67+ , isPinned
68+
69+ -- * Streams
7070 , read
7171 , readRev
7272
@@ -83,24 +83,16 @@ module Streamly.Data.Array
8383 -- , (!!)
8484 , getIndex
8585
86− -- * Serialization
87− , pinnedSerialize
88− , deserialize
89−
9086 -- * Re-exports
9187 , Unbox (..)
92− , Serialize(..)
9388
94− -- * Deprecated
95− , writeN -- drop new
96− , write -- full buffer
9789 )
9890where
9991
10092#include "inline.hs"
10193
10294import Streamly.Internal.Data.Array
103−import Streamly.Internal.Data.MutByteArray (Unbox(..), Serialize(..))
95+import Streamly.Internal.Data.Unbox (Unbox (..))
10496
10597import Prelude hiding (read, length)
10698
@@ -126,7 +118,7 @@ import Prelude hiding (read, length)
126118--
127119-- Convert array to stream, transform, and fold back to array:
128120--
129−-- >>> amap f arr = Array.read arr & fmap f & Stream.fold (Array.createOf (Array.length arr))
121+-- >>> amap f arr = Array.read arr & fmap f & Stream.fold Array.write
130122-- >>> amap (+1) (Array.fromList [1,2,3::Int])
131123-- fromList [2,3,4]
132124--
@@ -153,11 +145,12 @@ import Prelude hiding (read, length)
153145-- See the 'fromPureStream' unreleased API to generate an array from an
154146-- Identity stream safely without using MonadIO constraint.
155147--
148+--
156149-- Note that 'Identity' streams can be generalized to IO streams:
157150--
158−-- >>> stream = Stream.fromList [1,2,3] :: Stream Identity Int
159−-- >>> pure2IO s = Stream.morphInner (return . runIdentity) s :: Stream IO Int
160−-- >>> Stream.fold Array.create (pure2IO stream)
151+-- >>> pure = Stream.fromList [1,2,3] :: Stream Identity Int
152+-- >>> generally = Stream.morphInner (return . runIdentity)
153+-- >>> Stream.fold Array.write (generally pure :: Stream IO Int)
161154-- fromList [1,2,3]
162155--
163156-- == Programming Tips
core/src/Streamly/Data/Array/Generic.hs+13−16
@@ -15,37 +15,34 @@ module Streamly.Data.Array.Generic
1515 ( Array
1616
1717 -- * Construction
18− , fromListN
19− , fromList
18+ , A.fromListN
19+ , A.fromList
2020
2121 -- MonadicAPIs
22− , createOf
23− , create
22+ , A.writeN
23+ , A.write
2424
2525 -- * Conversion
26− , toList
26+ , A.toList
2727
2828 -- * Streams
29− , read
30− , readRev
29+ , A.read
30+ , A.readRev
3131
3232 -- * Unfolds
33− , reader
33+ , A.reader
3434 -- , A.readerRev
3535
3636 -- * Random Access
37− , length
38− , getIndex
37+ , A.length
38+ , A.getIndex
3939
4040 -- -- * Folding Arrays
4141 -- , A.streamFold
4242 -- , A.fold
43−
44− -- * Deprecated
45− , writeN
46− , write
4743 )
4844where
4945
50−import Streamly.Internal.Data.Array.Generic
51−import Prelude hiding (length, read)
46+import Streamly.Internal.Data.Array.Generic (Array)
47+
48+import qualified Streamly.Internal.Data.Array.Generic as A
core/src/Streamly/Data/MutArray.hs+6−12
@@ -32,14 +32,14 @@ module Streamly.Data.MutArray
3232 -- * Construction
3333
3434 -- Uninitialized Arrays
35− , emptyOf
36− , pinnedEmptyOf
35+ , new
36+ , pinnedNew
3737
3838 -- From containers
3939 , fromListN
4040 , fromList
41− , createOf
42− , create
41+ , writeN -- drop new
42+ , write -- full buffer
4343 -- writeLastN
4444
4545 -- * Pinning & Unpinning
@@ -51,8 +51,8 @@ module Streamly.Data.MutArray
5151 , snoc
5252
5353 -- * Appending streams
54− , appendN
55− , append
54+ , writeAppendN -- XXX Rename to writeSnocN?
55+ , writeAppend -- XXX Rename to writeSnoc?
5656
5757 -- * Inplace mutation
5858 , putIndex
@@ -88,12 +88,6 @@ module Streamly.Data.MutArray
8888
8989 -- * Deprecated
9090 , newPinned
91− , new
92− , pinnedNew
93− , writeN
94− , write
95− , writeAppendN
96− , writeAppend
9791 )
9892where
9993
core/src/Streamly/Data/MutArray/Generic.hs+3−8
@@ -23,11 +23,11 @@ module Streamly.Data.MutArray.Generic
2323 MutArray
2424
2525 -- * Construction
26− , emptyOf
26+ , new
2727 , fromListN
2828 , fromList
29− , createOf
30− , create
29+ , writeN
30+ , write
3131
3232 -- * Appending elements
3333 , snoc
@@ -56,11 +56,6 @@ module Streamly.Data.MutArray.Generic
5656
5757 -- * Size
5858 , length
59−
60− -- * Deprecated
61− , new
62− , writeN
63− , write
6459 )
6560where
6661
core/src/Streamly/Data/MutByteArray.hs+13−29
@@ -5,25 +5,18 @@
55-- Maintainer : streamly@composewell.com
66-- Portability : GHC
77--
8−-- A low level byte Array type 'MutByteArray', along with type classes 'Unbox'
9−-- and 'Serialize' for fast binary serialization and deserialization of Haskell
10−-- values. Serialization, deserialization performance is similar to, and in
11−-- some cases many times better than the store package. Conceptually, the
12−-- 'Serialize' type class works in the same way as store.
8+-- A low level byte Array type for fast binary serialization and
9+-- deserialization of Haskell values. Higher level unboxed array modules
10+-- "Streamly.Data.Array" and "Streamly.Data.MutArray" are built on top of this
11+-- module. This module provides two type classes for serialization, 'Unbox' and
12+-- 'Serialize'. The speed is similar to, and in some cases many times faster
13+-- than the store package. Conceptually, the 'Serialize' type class works in
14+-- the same way as store.
1315--
14−-- Serialize instances are configurable to use constructor names (see
15−-- 'Streamly.Internal.Data.MutByteArray.encodeConstrNames'), record field names (see
16−-- 'Streamly.Internal.Data.MutByteArray.encodeRecordFields') instead of binary
17−-- encoded values. This is an experimental feature which allows JSON like
18−-- properties with faster speed. For example, you can change the order of
19−-- constructors or record fields without affecting serialized value.
20−--
21−-- Higher level unboxed array modules "Streamly.Data.Array" and
22−-- "Streamly.Data.MutArray" are built on top of this module. Unboxed arrays are
23−-- essentially serialized Haskell values. Array modules provide higher level
24−-- serialization routines like 'Streamly.Internal.Data.Array.pinnedSerialize'
25−-- and 'Streamly.Internal.Data.Array.deserialize' from the
26−-- "Streamly.Internal.Data.Array" module.
16+-- You probably want the higher level
17+-- 'Streamly.Internal.Data.Array.pinnedSerialize' and
18+-- 'Streamly.Internal.Data.Array.deserialize' from the "Streamly.Data.Array"
19+-- module.
2720--
2821-- == Mutable Byte Array
2922--
@@ -59,15 +52,6 @@
5952-- 'Streamly.Internal.Data.Array.deserialize' for 'Array' type based
6053-- serialization.
6154--
62−-- == Comparing serialized values
63−--
64−-- When using the `Unbox` type class the same value may result in differing
65−-- serialized bytes because of unused uninitialized data in case of sum types.
66−-- Therefore, byte comparison of serialized values is not reliable.
67−--
68−-- However, the 'Serialize' type class guarantees that the serialized values
69−-- are always exactly the same and byte comparison of serialized is reliable.
70−--
7155module Streamly.Data.MutByteArray
7256 (
7357
@@ -88,13 +72,13 @@ module Streamly.Data.MutByteArray
8872 -- * Serialize
8973 , Serialize(..)
9074
91− -- ** Instance Config
75+ -- Deriving Serialize
9276 , SerializeConfig
77+ , serializeConfig
9378 , inlineAddSizeTo
9479 , inlineSerializeAt
9580 , inlineDeserializeAt
9681
97− -- ** Instance Deriving
9882 , deriveSerialize
9983 , deriveSerializeWith
10084 ) where
core/src/Streamly/Data/Stream.hs+20−129
@@ -70,15 +70,6 @@ module Streamly.Data.Stream
7070
7171 -- ** From Values
7272 -- | Generate a monadic stream from a seed value or values.
73− --
74− -- Non-empty pure streams can be cycled using repeat and unfold:
75− --
76− -- >>> cycle = Stream.unfoldMany Unfold.fromList . Stream.repeat
77− --
78− -- Non-empty StreamK can be cycled using append:
79− --
80− -- >>> cycle xs = let ys = xs `StreamK.append` ys in ys
81− --
8273 , fromPure
8374 , fromEffect
8475 , repeat
@@ -221,57 +212,21 @@ module Streamly.Data.Stream
221212 -- operations like mapping a function over the stream.
222213 , foldrM
223214 , foldr
224− -- foldr1
225215
226216 -- ** Specific Folds
227− -- | Streams are folded using folds in "Streamly.Data.Fold". Here are some
228− -- idioms and equivalents of Data.List APIs using folds:
217+ -- | Usually you can use the folds in "Streamly.Data.Fold". However, some
218+ -- folds that may be commonly used or may have an edge in performance in
219+ -- some cases are provided here.
220+ --
221+ -- Useful idioms:
229222 --
230223 -- >>> foldlM' f a = Stream.fold (Fold.foldlM' f a)
231− -- >>> foldl1' f = Stream.fold (Fold.foldl1' f)
224+ -- >>> foldl1 f = Stream.fold (Fold.foldl1' f)
232225 -- >>> foldl' f a = Stream.fold (Fold.foldl' f a)
233226 -- >>> drain = Stream.fold Fold.drain
234227 -- >>> mapM_ f = Stream.fold (Fold.drainMapM f)
235228 -- >>> length = Stream.fold Fold.length
236− -- >>> genericLength = Stream.fold Fold.lengthGeneric
237229 -- >>> head = Stream.fold Fold.one
238− -- >>> last = Stream.fold Fold.latest
239− -- >>> null = Stream.fold Fold.null
240− -- >>> and = Stream.fold Fold.and
241− -- >>> or = Stream.fold Fold.or
242− -- >>> any p = Stream.fold (Fold.any p)
243− -- >>> all p = Stream.fold (Fold.all p)
244− -- >>> sum = Stream.fold Fold.sum
245− -- >>> product = Stream.fold Fold.product
246− -- >>> maximum = Stream.fold Fold.maximum
247− -- >>> maximumBy cmp = Stream.fold (Fold.maximumBy cmp)
248− -- >>> minimum = Stream.fold Fold.minimum
249− -- >>> minimumBy cmp = Stream.fold (Fold.minimumBy cmp)
250− -- >>> elem x = Stream.fold (Fold.elem x)
251− -- >>> notElem x = Stream.fold (Fold.notElem x)
252− -- >>> lookup x = Stream.fold (Fold.lookup x)
253− -- >>> find p = Stream.fold (Fold.find p)
254− -- >>> (!?) i = Stream.fold (Fold.index i)
255− -- >>> genericIndex i = Stream.fold (Fold.indexGeneric i)
256− -- >>> elemIndex x = Stream.fold (Fold.elemIndex x)
257− -- >>> findIndex p = Stream.fold (Fold.findIndex p)
258− --
259− -- Some equivalents of Data.List APIs from the Stream module:
260− --
261− -- >>> head = fmap (fmap fst) . Stream.uncons
262− -- >>> tail = fmap (fmap snd) . Stream.uncons
263− -- >>> tail = Stream.tail -- unreleased API
264− -- >>> init = Stream.init -- unreleased API
265− --
266− -- A Stream based toList fold implementation is provided below because it
267− -- has a better performance compared to the fold.
268−
269− -- Functions in Data.List, missing here:
270− -- unsnoc = Stream.parseBreak (Parser.init Fold.toList)
271− -- genericTake
272− -- genericDrop
273− -- genericSplitAt
274− -- genericReplicate
275230 , toList
276231
277232 -- * Mapping
@@ -325,15 +280,6 @@ module Streamly.Data.Stream
325280 , scan
326281 , postscan
327282 -- XXX postscan1 can be implemented using Monoids or Refolds.
328− -- The following scans from Data.List are not provided.
329− -- XXX scanl
330− -- XXX scanl1
331− -- XXX scanr
332− -- XXX scanr1
333− -- XXX mapAccumL
334− -- XXX mapAccumR
335− -- XXX inits
336− -- XXX tails
337283
338284 -- ** Specific scans
339285 -- Indexing can be considered as a special type of zipping where we zip a
@@ -342,8 +288,6 @@ module Streamly.Data.Stream
342288
343289 -- * Insertion
344290 -- | Add elements to the stream.
345− --
346− -- >>> insert = Stream.insertBy compare
347291
348292 -- Inserting elements is a special case of interleaving/merging streams.
349293 , insertBy
@@ -379,15 +323,12 @@ module Streamly.Data.Stream
379323 -- "Streamly.Internal.Data.Fold" can be used along with 'scanMaybe' to
380324 -- perform stateful filtering operations in general.
381325 --
382− -- Idioms and equivalents of Data.List APIs:
326+ -- Useful idioms:
383327 --
384328 -- >>> deleteBy cmp x = Stream.scanMaybe (Fold.deleteBy cmp x)
385− -- >>> deleteBy = Stream.deleteBy -- unreleased API
386− -- >>> delete = deleteBy (==)
387329 -- >>> findIndices p = Stream.scanMaybe (Fold.findIndices p)
388330 -- >>> elemIndices a = findIndices (== a)
389331 -- >>> uniq = Stream.scanMaybe (Fold.uniqBy (==))
390− -- >>> partition p = Stream.fold (Fold.partition Fold.toList Fold.toList) . fmap (if p then Left else Right)
391332 , scanMaybe
392333 , take
393334 , takeWhile
@@ -395,8 +336,6 @@ module Streamly.Data.Stream
395336 , drop
396337 , dropWhile
397338 , dropWhileM
398− -- XXX write to an array in reverse and then read in reverse
399− -- > dropWhileEnd = reverse . dropWhile p . reverse
400339
401340 -- XXX These are available as scans in folds. We need to check the
402341 -- performance though. If these are common and we need convenient stream
@@ -433,9 +372,6 @@ module Streamly.Data.Stream
433372 -- >>> s = s1 `Stream.append` s2
434373
435374 -- ** Appending
436− -- | Equivalent of Data.List append:
437− --
438− -- >>> (++) = Stream.append
439375 , append
440376
441377 -- ** Interleaving
@@ -446,14 +382,8 @@ module Streamly.Data.Stream
446382 , mergeByM
447383
448384 -- ** Zipping
449− -- | Idioms and equivalents of Data.List APIs:
450− --
451− -- >>> zip = Stream.zipWith (,)
452− -- >>> unzip = Stream.fold (Fold.unzip Fold.toList Fold.toList)
453385 , zipWith
454386 , zipWithM
455− -- XXX zipWith3,4,5,6,7
456− -- XXX unzip3,4,5,6,7
457387 -- , ZipStream (..)
458388
459389 -- ** Cross Product
@@ -486,89 +416,48 @@ module Streamly.Data.Stream
486416 -- One dimension loops are just a special case of nested loops. For
487417 -- example, 'concatMap' can degenerate to a simple map operation:
488418 --
489− -- >>> map f m = Stream.concatMap (\x -> Stream.fromPure (f x)) m
419+ -- > map f m = S.concatMap (\x -> S.fromPure (f x)) m
490420 --
491421 -- Similarly, 'concatMap' can perform filtering by mapping an element to a
492422 -- 'nil' stream:
493423 --
494− -- >>> filter p m = Stream.concatMap (\x -> if p x then Stream.fromPure x else Stream.nil) m
495− --
496− -- Idioms and equivalents of Data.List APIs:
424+ -- > filter p m = S.concatMap (\x -> if p x then S.fromPure x else S.nil) m
497425 --
498− -- >>> concat = Stream.concatMap id
499− -- >>> unlines = Stream.interposeSuffix '\n'
500− -- >>> unlines = Stream.intercalateSuffix Unfold.fromList "\n"
501− -- >>> unwords = Stream.interpose ' '
502− -- >>> unwords = Stream.intercalate Unfold.fromList " "
503426
504427 , concatEffect
505428 , concatMap
506429 , concatMapM
507430
508431 -- * Repeated Fold
509− -- | Idioms and equivalents of Data.List APIs:
432+ -- | Useful idioms:
510433 --
511− -- >>> groupsOf n = Stream.foldMany (Fold.take n Fold.toList)
512− -- >>> groupBy eq = Stream.groupsWhile eq Fold.toList
513− -- >>> groupBy eq = Stream.parseMany (Parser.groupBy eq Fold.toList)
514− -- >>> groupsByRolling eq = Stream.parseMany (Parser.groupByRolling eq Fold.toList)
515− -- >>> groups = groupBy (==)
434+ -- >>> splitWithSuffix p f = Stream.foldMany (Fold.takeEndBy p f)
435+ -- >>> splitOnSuffix p f = Stream.foldMany (Fold.takeEndBy_ p f)
436+ -- >>> groupsBy eq f = Stream.parseMany (Parser.groupBy eq f)
437+ -- >>> groupsByRolling eq f = Stream.parseMany (Parser.groupByRolling eq f)
438+ -- >>> groupsOf n f = Stream.foldMany (Fold.take n f)
516439 , foldMany -- XXX Rename to foldRepeat
517440 , groupsOf
518441 , parseMany
519442
520443 -- * Splitting
521− -- | Idioms and equivalents of Data.List APIs:
522− --
523− -- >>> splitWithSuffix p f = Stream.foldMany (Fold.takeEndBy p f)
524− -- >>> splitOnSuffix p f = Stream.foldMany (Fold.takeEndBy_ p f)
525− -- >>> lines = splitOnSuffix (== '\n')
526− -- >>> words = Stream.wordsBy isSpace
527− -- >>> splitAt n = Stream.fold (Fold.splitAt n Fold.toList Fold.toList)
528− -- >>> span p = Parser.splitWith (,) (Parser.takeWhile p Fold.toList) (Parser.fromFold Fold.toList)
529− -- >>> break p = span (not . p)
530444 , splitOn
531445 , wordsBy
532446
533447 -- * Buffered Operations
534448 -- | Operations that require buffering of the stream.
535449 -- Reverse is essentially a left fold followed by an unfold.
536− --
537− -- Idioms and equivalents of Data.List APIs:
538− --
539− -- >>> nub = Stream.fold Fold.toList . Stream.scanMaybe Fold.nub
540− -- >>> nub = Stream.ordNub -- unreleased API
541− -- >>> sortBy = StreamK.sortBy
542− -- >>> sortOn f = StreamK.sortOn -- unreleased API
543− -- >>> deleteFirstsBy = Stream.deleteFirstsBy -- unreleased
544− -- >>> (\\) = Stream.deleteFirstsBy (==) -- unreleased
545− -- >>> intersectBy = Stream.intersectBy -- unreleased
546− -- >>> intersect = Stream.intersectBy (==) -- unreleased
547− -- >>> unionBy = Stream.unionBy -- unreleased
548− -- >>> union = Stream.unionBy (==) -- unreleased
549− --
550450 , reverse
551− -- XXX transpose: write the streams to arrays and then stream transposed.
552− -- XXX subsequences
553− -- XXX permutations
554− -- , nub
555− -- , ordNub
556− -- , nubBy
557451
558452 -- * Multi-Stream folds
559453 -- | Operations that consume multiple streams at the same time.
560454 , eqBy
561455 , cmpBy
562456 , isPrefixOf
563− , isInfixOf
564− -- , isSuffixOf
565− -- , isSuffixOfUnbox
566457 , isSubsequenceOf
567458
568459 -- trimming sequences
569− -- , stripPrefix
570− -- , stripSuffix
571− -- , stripSuffixUnbox
460+ , stripPrefix
572461
573462 -- Exceptions and resource management depend on the "exceptions" package
574463 -- XXX We can have IO Stream operations not depending on "exceptions"
@@ -632,8 +521,10 @@ where
632521import Streamly.Internal.Data.Stream
633522import Prelude
634523 hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
635− mapM, sequence, reverse, iterate, foldr1, repeat, replicate,
636− concatMap)
524+ foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
525+ notElem, maximum, minimum, head, last, tail, length, null,
526+ reverse, iterate, init, and, or, lookup, foldr1, (!!),
527+ scanl, scanl1, repeat, replicate, concatMap, span)
637528
638529import qualified Streamly.Internal.Data.Array.Type as Array
639530
core/src/Streamly/Internal/Data/Array.hs+128−559
@@ -2,6 +2,7 @@
22-- |
33-- Module : Streamly.Internal.Data.Array
44-- Copyright : (c) 2019 Composewell Technologies
5+--
56-- License : BSD3
67-- Maintainer : streamly@composewell.com
78-- Stability : experimental
@@ -19,21 +20,30 @@ module Streamly.Internal.Data.Array
1920 module Streamly.Internal.Data.Array.Type
2021
2122 -- * Construction
23+ -- Stream Folds
24+ , fromStreamN
25+ , fromStream
26+
2227 -- Monadic Folds
2328 , writeLastN
2429
30+ -- * Unfolds
31+ , reader
32+ , readerUnsafe
33+ , producer -- experimental
34+
2535 -- * Random Access
2636 -- , (!!)
2737 , getIndex
2838 , getIndexRev
29− , last -- XXX getLastIndex?
39+ , last -- XXX getIndexLast?
40+ , getIndices
41+ , getIndicesFromThenTo
3042 -- , getIndicesFrom -- read from a given position to the end of file
3143 -- , getIndicesUpto -- read from beginning up to the given position
3244 -- , getIndicesFromTo
3345 -- , getIndicesFromRev -- read from a given position to the beginning of file
3446 -- , getIndicesUptoRev -- read from end to the given position in file
35− , indexReader
36− , indexReaderFromThenTo
3747
3848 -- * Size
3949 , null
@@ -41,8 +51,6 @@ module Streamly.Internal.Data.Array
4151 -- * Search
4252 , binarySearch
4353 , findIndicesOf
44− -- getIndicesOf
45− , indexFinder -- see splitOn
4654 -- , findIndexOf
4755 -- , find
4856
@@ -55,8 +63,8 @@ module Streamly.Internal.Data.Array
5563 -- * Subarrays
5664 , getSliceUnsafe
5765 -- , getSlice
58− , sliceIndexerFromLen
59− , slicerFromLen
66+ , genSlicesFromLen
67+ , getSlicesFromLen
6068 , splitOn
6169
6270 -- * Streaming Operations
@@ -66,34 +74,11 @@ module Streamly.Internal.Data.Array
6674 , streamFold
6775 , fold
6876
69− -- * Stream of Arrays
70−
71− -- XXX these are probably not very useful to have in this module as we can
72− -- express these idiomatically using streams.
73− , interpose
74− , interposeSuffix
75− , intercalateSuffix
76−
77− , compactLE
78− , pinnedCompactLE
79− , compactOnByte
80− , compactOnByteSuffix
81−
82− , foldBreakChunks
83− , foldChunks
84− , foldBreakChunksK
85− , parseBreakChunksK
86−
8777 -- * Serialization
8878 , encodeAs
8979 , serialize
9080 , pinnedSerialize
9181 , deserialize
92−
93− -- * Deprecated
94− , genSlicesFromLen
95− , getSlicesFromLen
96− , getIndices
9782 )
9883where
9984
@@ -101,43 +86,37 @@ where
10186#include "inline.hs"
10287#include "ArrayMacros.h"
10388
89+import Control.Monad (when)
10490import Control.Monad.IO.Class (MonadIO(..))
105−-- import Data.Bifunctor (first)
106−-- import Data.Either (fromRight)
10791import Data.Functor.Identity (Identity)
10892import Data.Proxy (Proxy(..))
10993import Data.Word (Word8)
11094import Foreign.C.String (CString)
11195import Foreign.Ptr (castPtr)
11296import Foreign.Storable (Storable)
113−import GHC.Types (SPEC(..))
11497import Streamly.Internal.Data.Unbox (Unbox(..))
11598import Prelude hiding (length, null, last, map, (!!), read, concat)
11699
117−import Streamly.Internal.Data.MutByteArray.Type (PinnedState(..), MutByteArray)
100+import Streamly.Internal.Data.MutByteArray.Type (PinnedState(..))
118101import Streamly.Internal.Data.Serialize.Type (Serialize)
119102import Streamly.Internal.Data.Fold.Type (Fold(..))
120−import Streamly.Internal.Data.Parser (Parser(..), Initial(..), ParseError(..))
121−import Streamly.Internal.Data.Stream (Stream(..))
122−import Streamly.Internal.Data.StreamK (StreamK)
123−import Streamly.Internal.Data.SVar.Type (adaptState, defState)
124−import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3Fused'(..))
103+import Streamly.Internal.Data.Producer.Type (Producer(..))
104+import Streamly.Internal.Data.Stream (Stream)
105+import Streamly.Internal.Data.Tuple.Strict (Tuple3Fused'(..))
125106import Streamly.Internal.Data.Unfold.Type (Unfold(..))
126107import Streamly.Internal.System.IO (unsafeInlineIO)
127108
128−import qualified Streamly.Internal.Data.Fold.Type as Fold
129109import qualified Streamly.Internal.Data.Serialize.Type as Serialize
130110import qualified Streamly.Internal.Data.MutByteArray.Type as MBA
131111import qualified Streamly.Internal.Data.MutArray as MA
112+import qualified Streamly.Internal.Data.Array.Type as A
132113import qualified Streamly.Internal.Data.Fold as FL
114+import qualified Streamly.Internal.Data.Producer.Type as Producer
115+import qualified Streamly.Internal.Data.Producer as Producer
133116import qualified Streamly.Internal.Data.Ring as RB
134−import qualified Streamly.Internal.Data.Parser as Parser
135−-- import qualified Streamly.Internal.Data.ParserK as ParserK
136117import qualified Streamly.Internal.Data.Stream as D
137118import qualified Streamly.Internal.Data.Stream as Stream
138−import qualified Streamly.Internal.Data.StreamK as StreamK
139119import qualified Streamly.Internal.Data.Unfold as Unfold
140−import qualified Prelude
141120
142121import Streamly.Internal.Data.Array.Type
143122
@@ -166,10 +145,82 @@ import Streamly.Internal.Data.Array.Type
166145-- if we use one array for each chunk. This is still significant to add
167146-- pressure to GC.
168147
148+-------------------------------------------------------------------------------
149+-- Construction
150+-------------------------------------------------------------------------------
151+
152+-- | Create an 'Array' from the first N elements of a stream. The array is
153+-- allocated to size N, if the stream terminates before N elements then the
154+-- array may hold less than N elements.
155+--
156+-- /Pre-release/
157+{-# INLINE fromStreamN #-}
158+fromStreamN :: (MonadIO m, Unbox a) => Int -> Stream m a -> m (Array a)
159+fromStreamN n m = do
160+ when (n < 0) $ error "writeN: negative write count specified"
161+ A.fromStreamDN n m
162+
163+-- | Create an 'Array' from a stream. This is useful when we want to create a
164+-- single array from a stream of unknown size. 'writeN' is at least twice
165+-- as efficient when the size is already known.
166+--
167+-- Note that if the input stream is too large memory allocation for the array
168+-- may fail. When the stream size is not known, `chunksOf` followed by
169+-- processing of indvidual arrays in the resulting stream should be preferred.
170+--
171+-- /Pre-release/
172+{-# INLINE fromStream #-}
173+fromStream :: (MonadIO m, Unbox a) => Stream m a -> m (Array a)
174+fromStream = Stream.fold A.write
175+-- write m = A.fromStreamD $ D.fromStreamK m
176+
169177-------------------------------------------------------------------------------
170178-- Elimination
171179-------------------------------------------------------------------------------
172180
181+{-# INLINE_NORMAL producer #-}
182+producer :: forall m a. (Monad m, Unbox a) => Producer m (Array a) a
183+producer =
184+ Producer.translate A.unsafeThaw A.unsafeFreeze
185+ $ MA.producerWith (return . unsafeInlineIO)
186+
187+-- | Unfold an array into a stream.
188+--
189+{-# INLINE_NORMAL reader #-}
190+reader :: forall m a. (Monad m, Unbox a) => Unfold m (Array a) a
191+reader = Producer.simplify producer
192+
193+-- | Unfold an array into a stream, does not check the end of the array, the
194+-- user is responsible for terminating the stream within the array bounds. For
195+-- high performance application where the end condition can be determined by
196+-- a terminating fold.
197+--
198+-- Written in the hope that it may be faster than "read", however, in the case
199+-- for which this was written, "read" proves to be faster even though the core
200+-- generated with unsafeRead looks simpler.
201+--
202+-- /Pre-release/
203+--
204+{-# INLINE_NORMAL readerUnsafe #-}
205+readerUnsafe :: forall m a. (Monad m, Unbox a) => Unfold m (Array a) a
206+readerUnsafe = Unfold step inject
207+ where
208+
209+ inject (Array contents start end) =
210+ return (ArrayUnsafe contents end start)
211+
212+ {-# INLINE_LATE step #-}
213+ step (ArrayUnsafe contents end p) = do
214+ -- unsafeInlineIO allows us to run this in Identity monad for pure
215+ -- toList/foldr case which makes them much faster due to not
216+ -- accumulating the list and fusing better with the pure consumers.
217+ --
218+ -- This should be safe as the array contents are guaranteed to be
219+ -- evaluated/written to before we peek at them.
220+ let !x = unsafeInlineIO $ peekAt p contents
221+ let !p1 = INDEX_NEXT(p,a)
222+ return $ D.Yield x (ArrayUnsafe contents end p1)
223+
173224-- |
174225--
175226-- >>> null arr = Array.byteLength arr == 0
@@ -177,7 +228,7 @@ import Streamly.Internal.Data.Array.Type
177228-- /Pre-release/
178229{-# INLINE null #-}
179230null :: Array a -> Bool
180−null arr = byteLength arr == 0
231+null arr = A.byteLength arr == 0
181232
182233-- | Like 'getIndex' but indexes the array in reverse from the end.
183234--
@@ -205,8 +256,6 @@ last = getIndexRev 0
205256-- Folds with Array as the container
206257-------------------------------------------------------------------------------
207258
208−-- XXX We should generate this from Ring.
209−
210259-- | @writeLastN n@ folds a maximum of @n@ elements from the end of the input
211260-- stream to an 'Array'.
212261--
@@ -215,7 +264,7 @@ writeLastN ::
215264 (Storable a, Unbox a, MonadIO m) => Int -> Fold m a (Array a)
216265writeLastN n
217266 | n <= 0 = fmap (const mempty) FL.drain
218− | otherwise = unsafeFreeze <$> Fold step initial done done
267+ | otherwise = A.unsafeFreeze <$> Fold step initial done done
219268
220269 where
221270
@@ -228,9 +277,11 @@ writeLastN n
228277 in fmap f $ liftIO $ RB.new n
229278
230279 done (Tuple3Fused' rb rh i) = do
231− arr <- MA.new n
232− -- XXX We should write a read unfold for ring.
233− foldFunc i rh MA.snocUnsafe arr rb
280+ arr <- liftIO $ MA.new n
281+ foldFunc i rh snoc' arr rb
282+
283+ -- XXX We should write a read unfold for ring.
284+ snoc' b a = liftIO $ MA.snocUnsafe b a
234285
235286 foldFunc i
236287 | i < n = RB.unsafeFoldRingM
@@ -256,26 +307,19 @@ binarySearch = undefined
256307-- compared to streams by using SIMD instructions.
257308-- We can also return a bit array instead.
258309
259−-- Can use SIMD.
260−
261310-- | Perform a linear search to find all the indices where a given element is
262311-- present in an array.
263312--
264313-- /Unimplemented/
265−indexFinder :: (a -> Bool) -> Unfold Identity (Array a) Int
266−indexFinder = undefined
267−
268−-- |
269−-- /Unimplemented/
270−findIndicesOf :: (a -> Bool) -> Array a -> Stream Identity Int
271−findIndicesOf p = Stream.unfold (indexFinder p)
314+findIndicesOf :: (a -> Bool) -> Unfold Identity (Array a) Int
315+findIndicesOf = undefined
272316
273317{-
274318findIndexOf :: (a -> Bool) -> Array a -> Maybe Int
275−findIndexOf p = Unfold.fold Fold.one . Stream.unfold (indexFinder p)
319+findIndexOf p = Unfold.fold Fold.one . Stream.unfold (findIndicesOf p)
276320
277321find :: (a -> Bool) -> Array a -> Bool
278−find = Unfold.fold Fold.null . Stream.unfold (indexFinder p)
322+find = Unfold.fold Fold.null . Stream.unfold (findIndicesOf p)
279323-}
280324
281325-------------------------------------------------------------------------------
@@ -317,45 +361,29 @@ splitOn :: (Monad m, Unbox a) =>
317361 (a -> Bool) -> Array a -> Stream m (Array a)
318362splitOn predicate arr =
319363 fmap (\(i, len) -> getSliceUnsafe i len arr)
320− $ D.indexOnSuffix predicate (read arr)
321−
322−{-# INLINE sliceIndexerFromLen #-}
323−sliceIndexerFromLen :: forall m a. (Monad m, Unbox a)
324− => Int -- ^ from index
325− -> Int -- ^ length of the slice
326− -> Unfold m (Array a) (Int, Int)
327−sliceIndexerFromLen from len =
328− Unfold.lmap unsafeThaw (MA.sliceIndexerFromLen from len)
364+ $ D.sliceOnSuffix predicate (A.toStreamD arr)
329365
330−{-# DEPRECATED genSlicesFromLen "Please use sliceIndexerFromLen instead." #-}
331366{-# INLINE genSlicesFromLen #-}
332367genSlicesFromLen :: forall m a. (Monad m, Unbox a)
333368 => Int -- ^ from index
334369 -> Int -- ^ length of the slice
335370 -> Unfold m (Array a) (Int, Int)
336−genSlicesFromLen = sliceIndexerFromLen
371+genSlicesFromLen from len =
372+ Unfold.lmap A.unsafeThaw (MA.genSlicesFromLen from len)
337373
338374-- | Generate a stream of slices of specified length from an array, starting
339375-- from the supplied array index. The last slice may be shorter than the
340376-- requested length.
341377--
342378-- /Pre-release//
343−{-# INLINE slicerFromLen #-}
344−slicerFromLen :: forall m a. (Monad m, Unbox a)
345− => Int -- ^ from index
346− -> Int -- ^ length of the slice
347− -> Unfold m (Array a) (Array a)
348−slicerFromLen from len =
349− fmap unsafeFreeze
350− $ Unfold.lmap unsafeThaw (MA.slicerFromLen from len)
351−
352−{-# DEPRECATED getSlicesFromLen "Please use slicerFromLen instead." #-}
353379{-# INLINE getSlicesFromLen #-}
354380getSlicesFromLen :: forall m a. (Monad m, Unbox a)
355381 => Int -- ^ from index
356382 -> Int -- ^ length of the slice
357383 -> Unfold m (Array a) (Array a)
358−getSlicesFromLen = slicerFromLen
384+getSlicesFromLen from len =
385+ fmap A.unsafeFreeze
386+ $ Unfold.lmap A.unsafeThaw (MA.getSlicesFromLen from len)
359387
360388-------------------------------------------------------------------------------
361389-- Random reads and writes
@@ -385,25 +413,19 @@ getIndex i arr =
385413-- @
386414-- read =
387415-- let u = lmap (\arr -> (0, length arr - 1)) Unfold.enumerateFromTo
388−-- in Unfold.lmap f (indexReader arr)
416+-- in Unfold.lmap f (getIndices arr)
389417--
390418-- readRev =
391419-- let i = length arr - 1
392−-- in Unfold.lmap f (indexReaderFromThenTo i (i - 1) 0)
420+-- in Unfold.lmap f (getIndicesFromThenTo i (i - 1) 0)
393421-- @
394422--
395423-- /Pre-release/
396−{-# INLINE indexReader #-}
397−indexReader :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
398−indexReader m =
399− let unf = MA.indexReaderWith (return . unsafeInlineIO) m
400− in Unfold.lmap unsafeThaw unf
401−
402−-- XXX DO NOT REMOVE, change the signature to use Stream instead of unfold
403−{-# DEPRECATED getIndices "Please use getIndices instead." #-}
404424{-# INLINE getIndices #-}
405425getIndices :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
406−getIndices = indexReader
426+getIndices m =
427+ let unf = MA.getIndicesD (return . unsafeInlineIO) m
428+ in Unfold.lmap A.unsafeThaw unf
407429
408430-- | Unfolds @(from, then, to, array)@ generating a finite stream whose first
409431-- element is the array value from the index @from@ and the successive elements
@@ -419,9 +441,9 @@ getIndices = indexReader
419441-- @
420442--
421443-- /Unimplemented/
422−{-# INLINE indexReaderFromThenTo #-}
423−indexReaderFromThenTo :: Unfold m (Int, Int, Int, Array a) a
424−indexReaderFromThenTo = undefined
444+{-# INLINE getIndicesFromThenTo #-}
445+getIndicesFromThenTo :: Unfold m (Int, Int, Int, Array a) a
446+getIndicesFromThenTo = undefined
425447
426448-------------------------------------------------------------------------------
427449-- Transform via stream operations
@@ -438,7 +460,7 @@ indexReaderFromThenTo = undefined
438460{-# INLINE runPipe #-}
439461runPipe :: (MonadIO m, Unbox a, Unbox b)
440462 => Pipe m a b -> Array a -> m (Array b)
441−runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (read arr)
463+runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (A.read arr)
442464-}
443465
444466-- XXX For transformations that cannot change the number of elements e.g. "map"
@@ -452,7 +474,7 @@ runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (read arr)
452474streamTransform :: forall m a b. (MonadIO m, Unbox a, Unbox b)
453475 => (Stream m a -> Stream m b) -> Array a -> m (Array b)
454476streamTransform f arr =
455− Stream.fold (createWith (length arr)) $ f (read arr)
477+ Stream.fold (A.writeWith (length arr)) $ f (A.read arr)
456478
457479-------------------------------------------------------------------------------
458480-- Casts
@@ -486,7 +508,7 @@ asBytes = castUnsafe
486508--
487509cast :: forall a b. (Unbox b) => Array a -> Maybe (Array b)
488510cast arr =
489− let len = byteLength arr
511+ let len = A.byteLength arr
490512 r = len `mod` SIZE_OF(b)
491513 in if r /= 0
492514 then Nothing
@@ -504,9 +526,9 @@ cast arr =
504526--
505527asCStringUnsafe :: Array a -> (CString -> IO b) -> IO b
506528asCStringUnsafe arr act = do
507− let arr1 = asBytes arr <> fromList [0]
508− -- unsafePinnedAsPtr makes sure the array is pinned
509− unsafePinnedAsPtr arr1 $ \ptr -> act (castPtr ptr)
529+ let arr1 = asBytes arr <> A.fromList [0]
530+ -- asPtrUnsafe makes sure the array is pinned
531+ asPtrUnsafe arr1 $ \ptr -> act (castPtr ptr)
510532
511533-------------------------------------------------------------------------------
512534-- Folds
@@ -519,14 +541,14 @@ asCStringUnsafe arr act = do
519541-- /Pre-release/
520542{-# INLINE fold #-}
521543fold :: forall m a b. (Monad m, Unbox a) => Fold m a b -> Array a -> m b
522−fold f arr = Stream.fold f (read arr)
544+fold f arr = Stream.fold f (A.read arr)
523545
524546-- | Fold an array using a stream fold operation.
525547--
526548-- /Pre-release/
527549{-# INLINE streamFold #-}
528550streamFold :: (Monad m, Unbox a) => (Stream m a -> m b) -> Array a -> m b
529−streamFold f arr = f (read arr)
551+streamFold f arr = f (A.read arr)
530552
531553--------------------------------------------------------------------------------
532554-- Serialization
@@ -542,10 +564,6 @@ encodeAs ps a =
542564 assertM(len == off)
543565 pure $ Array mbarr 0 off
544566
545−-- |
546−-- Properties:
547−-- 1. Identity: @deserialize . serialize == id@
548−-- 2. Encoded equivalence: @serialize a == serialize a@
549567{-# INLINE serialize #-}
550568serialize :: Serialize a => a -> Array Word8
551569serialize = encodeAs Unpinned
@@ -553,10 +571,6 @@ serialize = encodeAs Unpinned
553571-- | Serialize a Haskell type to a pinned byte array. The array is allocated
554572-- using pinned memory so that it can be used directly in OS APIs for writing
555573-- to file or sending over the network.
556−--
557−-- Properties:
558−-- 1. Identity: @deserialize . pinnedSerialize == id@
559−-- 2. Encoded equivalence: @pinnedSerialize a == pinnedSerialize a@
560574{-# INLINE pinnedSerialize #-}
561575pinnedSerialize :: Serialize a => a -> Array Word8
562576pinnedSerialize = encodeAs Pinned
@@ -571,448 +585,3 @@ deserialize arr@(Array {..}) = unsafeInlineIO $ do
571585 Serialize.deserializeAt arrStart arrContents (arrStart + lenArr)
572586 assertM(off == arrStart + lenArr)
573587 pure val
574−
575−-------------------------------------------------------------------------------
576−-- Streams of Arrays
577−-------------------------------------------------------------------------------
578−
579−-- TODO: efficiently compare two streams of arrays. Two streams can have chunks
580−-- of different sizes, we can handle that in the stream comparison abstraction.
581−-- This could be useful e.g. to fast compare whether two files differ.
582−
583−-- | Insert the given element between arrays and flatten.
584−--
585−-- >>> interpose x = Stream.interpose x Array.reader
586−--
587−{-# INLINE interpose #-}
588−interpose :: (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
589−interpose x = D.interpose x reader
590−
591−data FlattenState s =
592− OuterLoop s
593− | InnerLoop s !MutByteArray !Int !Int
594−
595−-- | Insert the given element after each array and flatten. This is similar to
596−-- unlines.
597−--
598−-- >>> interposeSuffix x = Stream.interposeSuffix x Array.reader
599−--
600−{-# INLINE_NORMAL interposeSuffix #-}
601−interposeSuffix :: forall m a. (Monad m, Unbox a)
602− => a -> Stream m (Array a) -> Stream m a
603−-- This does not require MonadIO constraint.
604−-- interposeSuffix x = D.interposeSuffix x reader
605−interposeSuffix sep (D.Stream step state) = D.Stream step' (OuterLoop state)
606−
607− where
608−
609− {-# INLINE_LATE step' #-}
610− step' gst (OuterLoop st) = do
611− r <- step (adaptState gst) st
612− return $ case r of
613− D.Yield Array{..} s ->
614− D.Skip (InnerLoop s arrContents arrStart arrEnd)
615− D.Skip s -> D.Skip (OuterLoop s)
616− D.Stop -> D.Stop
617−
618− step' _ (InnerLoop st _ p end) | p == end =
619− return $ D.Yield sep $ OuterLoop st
620−
621− step' _ (InnerLoop st contents p end) = do
622− x <- pure $ unsafeInlineIO $ peekAt p contents
623− return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
624−
625−-- | Insert the given array after each array and flatten.
626−--
627−-- >>> intercalateSuffix = Stream.intercalateSuffix Array.reader
628−--
629−{-# INLINE intercalateSuffix #-}
630−intercalateSuffix :: (Monad m, Unbox a)
631− => Array a -> Stream m (Array a) -> Stream m a
632−intercalateSuffix = D.intercalateSuffix reader
633−
634−-- | @compactLE n@ coalesces adjacent arrays in the input stream
635−-- only if the combined size would be less than or equal to n.
636−--
637−-- Generates unpinned arrays irrespective of the pinning status of input
638−-- arrays.
639−{-# INLINE_NORMAL compactLE #-}
640−compactLE :: (MonadIO m, Unbox a)
641− => Int -> Stream m (Array a) -> Stream m (Array a)
642−compactLE n stream =
643− D.map unsafeFreeze $ MA.compactLE n $ D.map unsafeThaw stream
644−
645−-- | Pinned version of 'compactLE'.
646−{-# INLINE_NORMAL pinnedCompactLE #-}
647−pinnedCompactLE :: (MonadIO m, Unbox a)
648− => Int -> Stream m (Array a) -> Stream m (Array a)
649−pinnedCompactLE n stream =
650− D.map unsafeFreeze $ MA.pinnedCompactLE n $ D.map unsafeThaw stream
651−
652−-- | Split a stream of arrays on a given separator byte, dropping the separator
653−-- and coalescing all the arrays between two separators into a single array.
654−--
655−{-# INLINE compactOnByte #-}
656−compactOnByte
657− :: (MonadIO m)
658− => Word8
659− -> Stream m (Array Word8)
660− -> Stream m (Array Word8)
661−compactOnByte byte =
662− fmap unsafeFreeze . MA.compactOnByte byte . fmap unsafeThaw
663−
664−-- | Like 'compactOnByte' considers the separator in suffix position instead of
665−-- infix position.
666−{-# INLINE compactOnByteSuffix #-}
667−compactOnByteSuffix
668− :: (MonadIO m)
669− => Word8
670− -> Stream m (Array Word8)
671− -> Stream m (Array Word8)
672−compactOnByteSuffix byte =
673− fmap unsafeFreeze . MA.compactOnByteSuffix byte . fmap unsafeThaw
674−
675−-------------------------------------------------------------------------------
676−-- Folding Streams of Arrays
677−-------------------------------------------------------------------------------
678−
679−-- XXX This should not be used for breaking a stream as the D.cons used in
680−-- reconstructing the stream could be very bad for performance. This can only
681−-- be useful in folding without breaking.
682−{-# INLINE_NORMAL foldBreakChunks #-}
683−foldBreakChunks :: forall m a b. (MonadIO m, Unbox a) =>
684− Fold m a b -> Stream m (Array a) -> m (b, Stream m (Array a))
685−foldBreakChunks (Fold fstep initial _ final) stream@(Stream step state) = do
686− res <- initial
687− case res of
688− Fold.Partial fs -> go SPEC state fs
689− Fold.Done fb -> return $! (fb, stream)
690−
691− where
692−
693− {-# INLINE go #-}
694− go !_ st !fs = do
695− r <- step defState st
696− case r of
697− Stream.Yield (Array contents start end) s ->
698− let fp = Tuple' end contents
699− in goArray SPEC s fp start fs
700− Stream.Skip s -> go SPEC s fs
701− Stream.Stop -> do
702− b <- final fs
703− return (b, D.nil)
704−
705− goArray !_ s (Tuple' end _) !cur !fs
706− | cur == end = do
707− go SPEC s fs
708− goArray !_ st fp@(Tuple' end contents) !cur !fs = do
709− x <- liftIO $ peekAt cur contents
710− res <- fstep fs x
711− let next = INDEX_NEXT(cur,a)
712− case res of
713− Fold.Done b -> do
714− let arr = Array contents next end
715− return $! (b, D.cons arr (D.Stream step st))
716− Fold.Partial fs1 -> goArray SPEC st fp next fs1
717−
718−-- This may be more robust wrt fusion compared to unfoldMany?
719−
720−-- | Fold a stream of arrays using a 'Fold'. This is equivalent to the
721−-- following:
722−--
723−-- >>> foldChunks f = Stream.fold f . Stream.unfoldMany Array.reader
724−--
725−foldChunks :: (MonadIO m, Unbox a) => Fold m a b -> Stream m (Array a) -> m b
726−foldChunks f s = fmap fst (foldBreakChunks f s)
727−-- foldStream f = Stream.fold f . Stream.unfoldMany reader
728−
729−-- | Fold a stream of arrays using a 'Fold' and return the remaining stream.
730−--
731−-- The following alternative to this function allows composing the fold using
732−-- the parser Monad:
733−--
734−-- @
735−-- foldBreakStreamK f s =
736−-- fmap (first (fromRight undefined))
737−-- $ StreamK.parseBreakChunks (ParserK.adaptC (Parser.fromFold f)) s
738−-- @
739−--
740−-- We can compare perf and remove this one or define it in terms of that.
741−--
742−foldBreakChunksK :: forall m a b. (MonadIO m, Unbox a) =>
743− Fold m a b -> StreamK m (Array a) -> m (b, StreamK m (Array a))
744−{-
745−foldBreakChunksK f s =
746− fmap (first (fromRight undefined))
747− $ StreamK.parseBreakChunks (ParserK.adaptC (Parser.fromFold f)) s
748−-}
749−foldBreakChunksK (Fold fstep initial _ final) stream = do
750− res <- initial
751− case res of
752− Fold.Partial fs -> go fs stream
753− Fold.Done fb -> return (fb, stream)
754−
755− where
756−
757− {-# INLINE go #-}
758− go !fs st = do
759− let stop = (, StreamK.nil) <$> final fs
760− single a = yieldk a StreamK.nil
761− yieldk (Array contents start end) r =
762− let fp = Tuple' end contents
763− in goArray fs r fp start
764− in StreamK.foldStream defState yieldk single stop st
765−
766− goArray !fs st (Tuple' end _) !cur
767− | cur == end = do
768− go fs st
769− goArray !fs st fp@(Tuple' end contents) !cur = do
770− x <- liftIO $ peekAt cur contents
771− res <- fstep fs x
772− let next = INDEX_NEXT(cur,a)
773− case res of
774− Fold.Done b -> do
775− let arr = Array contents next end
776− return $! (b, StreamK.cons arr st)
777− Fold.Partial fs1 -> goArray fs1 st fp next
778−
779−{-
780−-- This can be generalized to any type provided it can be unfolded to a stream
781−-- and it can be combined using a semigroup operation.
782−--
783−{-# INLINE_NORMAL parseBreakD #-}
784−parseBreakD ::
785− forall m a b. (MonadIO m, MonadThrow m, Unbox a)
786− => PRD.Parser a m b
787− -> D.Stream m (Array.Array a)
788− -> m (b, D.Stream m (Array.Array a))
789−parseBreakD
790− (PRD.Parser pstep initial extract) stream@(D.Stream step state) = do
791−
792− res <- initial
793− case res of
794− PRD.IPartial s -> go SPEC state (List []) s
795− PRD.IDone b -> return (b, stream)
796− PRD.IError err -> throwM $ ParseError err
797−
798− where
799−
800− -- "backBuf" contains last few items in the stream that we may have to
801− -- backtrack to.
802− --
803− -- XXX currently we are using a dumb list based approach for backtracking
804− -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
805− -- That will allow us more efficient random back and forth movement.
806− go !_ st backBuf !pst = do
807− r <- step defState st
808− case r of
809− D.Yield (Array contents start end) s ->
810− gobuf SPEC s backBuf
811− (Tuple' end contents) start pst
812− D.Skip s -> go SPEC s backBuf pst
813− D.Stop -> do
814− b <- extract pst
815− return (b, D.nil)
816−
817− -- Use strictness on "cur" to keep it unboxed
818− gobuf !_ s backBuf (Tuple' end _) !cur !pst
819− | cur == end = do
820− go SPEC s backBuf pst
821− gobuf !_ s backBuf fp@(Tuple' end contents) !cur !pst = do
822− x <- liftIO $ peekByteIndex contents cur
823− pRes <- pstep pst x
824− let next = INDEX_NEXT(cur,a)
825− case pRes of
826− PR.Partial 0 pst1 ->
827− gobuf SPEC s (List []) fp next pst1
828− PR.Partial n pst1 -> do
829− assert (n <= Prelude.length (x:getList backBuf)) (return ())
830− let src0 = Prelude.take n (x:getList backBuf)
831− arr0 = A.fromListN n (Prelude.reverse src0)
832− arr1 = Array contents next end
833− src = arr0 <> arr1
834− let !(Array cont1 start end1) = src
835− fp1 = Tuple' end1 cont1
836− gobuf SPEC s (List []) fp1 start pst1
837− PR.Continue 0 pst1 ->
838− gobuf SPEC s (List (x:getList backBuf)) fp next pst1
839− PR.Continue n pst1 -> do
840− assert (n <= Prelude.length (x:getList backBuf)) (return ())
841− let (src0, buf1) = splitAt n (x:getList backBuf)
842− arr0 = A.fromListN n (Prelude.reverse src0)
843− arr1 = Array contents next end
844− src = arr0 <> arr1
845− let !(Array cont1 start end1) = src
846− fp1 = Tuple' end1 cont1
847− gobuf SPEC s (List buf1) fp1 start pst1
848− PR.Done 0 b -> do
849− let arr = Array contents next end
850− return (b, D.cons arr (D.Stream step s))
851− PR.Done n b -> do
852− assert (n <= Prelude.length (x:getList backBuf)) (return ())
853− let src0 = Prelude.take n (x:getList backBuf)
854− -- XXX create the array in reverse instead
855− arr0 = A.fromListN n (Prelude.reverse src0)
856− arr1 = Array contents next end
857− -- XXX Use StreamK to avoid adding arbitrary layers of
858− -- constructors every time.
859− str = D.cons arr0 (D.cons arr1 (D.Stream step s))
860− return (b, str)
861− PR.Error err -> throwM $ ParseError err
862−-}
863−
864−-- | Parse an array stream using the supplied 'Parser'. Returns the parse
865−-- result and the unconsumed stream. Throws 'ParseError' if the parse fails.
866−--
867−-- The following alternative to this function allows composing the parser using
868−-- the parser Monad:
869−--
870−-- >>> parseBreakStreamK p = StreamK.parseBreakChunks (ParserK.adaptC p)
871−--
872−-- We can compare perf and remove this one or define it in terms of that.
873−--
874−-- /Internal/
875−--
876−{-# INLINE_NORMAL parseBreakChunksK #-}
877−parseBreakChunksK ::
878− forall m a b. (MonadIO m, Unbox a)
879− => Parser a m b
880− -> StreamK m (Array a)
881− -> m (Either ParseError b, StreamK m (Array a))
882−-- parseBreakStreamK p = StreamK.parseBreakChunks (ParserK.adaptC p)
883−parseBreakChunksK (Parser pstep initial extract) stream = do
884− res <- initial
885− case res of
886− IPartial s -> go s stream []
887− IDone b -> return (Right b, stream)
888− IError err -> return (Left (ParseError err), stream)
889−
890− where
891−
892− -- "backBuf" contains last few items in the stream that we may have to
893− -- backtrack to.
894− --
895− -- XXX currently we are using a dumb list based approach for backtracking
896− -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
897− -- That will allow us more efficient random back and forth movement.
898− go !pst st backBuf = do
899− let stop = goStop pst backBuf -- (, K.nil) <$> extract pst
900− single a = yieldk a StreamK.nil
901− yieldk arr r = goArray pst backBuf r arr
902− in StreamK.foldStream defState yieldk single stop st
903−
904− -- Use strictness on "cur" to keep it unboxed
905− goArray !pst backBuf st (Array _ cur end) | cur == end = go pst st backBuf
906− goArray !pst backBuf st (Array contents cur end) = do
907− x <- liftIO $ peekAt cur contents
908− pRes <- pstep pst x
909− let next = INDEX_NEXT(cur,a)
910− case pRes of
911− Parser.Partial 0 s ->
912− goArray s [] st (Array contents next end)
913− Parser.Partial n s -> do
914− assert (n <= Prelude.length (x:backBuf)) (return ())
915− let src0 = Prelude.take n (x:backBuf)
916− arr0 = fromListN n (Prelude.reverse src0)
917− arr1 = Array contents next end
918− src = arr0 <> arr1
919− goArray s [] st src
920− Parser.Continue 0 s ->
921− goArray s (x:backBuf) st (Array contents next end)
922− Parser.Continue n s -> do
923− assert (n <= Prelude.length (x:backBuf)) (return ())
924− let (src0, buf1) = Prelude.splitAt n (x:backBuf)
925− arr0 = fromListN n (Prelude.reverse src0)
926− arr1 = Array contents next end
927− src = arr0 <> arr1
928− goArray s buf1 st src
929− Parser.Done 0 b -> do
930− let arr = Array contents next end
931− return (Right b, StreamK.cons arr st)
932− Parser.Done n b -> do
933− assert (n <= Prelude.length (x:backBuf)) (return ())
934− let src0 = Prelude.take n (x:backBuf)
935− -- XXX Use fromListRevN once implemented
936− -- arr0 = A.fromListRevN n src0
937− arr0 = fromListN n (Prelude.reverse src0)
938− arr1 = Array contents next end
939− str = StreamK.cons arr0 (StreamK.cons arr1 st)
940− return (Right b, str)
941− Parser.Error err -> do
942− let n = Prelude.length backBuf
943− arr0 = fromListN n (Prelude.reverse backBuf)
944− arr1 = Array contents cur end
945− str = StreamK.cons arr0 (StreamK.cons arr1 stream)
946− return (Left (ParseError err), str)
947−
948− -- This is a simplified goArray
949− goExtract !pst backBuf (Array _ cur end)
950− | cur == end = goStop pst backBuf
951− goExtract !pst backBuf (Array contents cur end) = do
952− x <- liftIO $ peekAt cur contents
953− pRes <- pstep pst x
954− let next = INDEX_NEXT(cur,a)
955− case pRes of
956− Parser.Partial 0 s ->
957− goExtract s [] (Array contents next end)
958− Parser.Partial n s -> do
959− assert (n <= Prelude.length (x:backBuf)) (return ())
960− let src0 = Prelude.take n (x:backBuf)
961− arr0 = fromListN n (Prelude.reverse src0)
962− arr1 = Array contents next end
963− src = arr0 <> arr1
964− goExtract s [] src
965− Parser.Continue 0 s ->
966− goExtract s backBuf (Array contents next end)
967− Parser.Continue n s -> do
968− assert (n <= Prelude.length (x:backBuf)) (return ())
969− let (src0, buf1) = Prelude.splitAt n (x:backBuf)
970− arr0 = fromListN n (Prelude.reverse src0)
971− arr1 = Array contents next end
972− src = arr0 <> arr1
973− goExtract s buf1 src
974− Parser.Done 0 b -> do
975− let arr = Array contents next end
976− return (Right b, StreamK.fromPure arr)
977− Parser.Done n b -> do
978− assert (n <= Prelude.length backBuf) (return ())
979− let src0 = Prelude.take n backBuf
980− -- XXX Use fromListRevN once implemented
981− -- arr0 = A.fromListRevN n src0
982− arr0 = fromListN n (Prelude.reverse src0)
983− arr1 = Array contents next end
984− str = StreamK.cons arr0 (StreamK.fromPure arr1)
985− return (Right b, str)
986− Parser.Error err -> do
987− let n = Prelude.length backBuf
988− arr0 = fromListN n (Prelude.reverse backBuf)
989− arr1 = Array contents cur end
990− str = StreamK.cons arr0 (StreamK.cons arr1 stream)
991− return (Left (ParseError err), str)
992−
993− -- This is a simplified goExtract
994− {-# INLINE goStop #-}
995− goStop !pst backBuf = do
996− pRes <- extract pst
997− case pRes of
998− Parser.Partial _ _ -> error "Bug: parseBreak: Partial in extract"
999− Parser.Continue 0 s ->
1000− goStop s backBuf
1001− Parser.Continue n s -> do
1002− assert (n <= Prelude.length backBuf) (return ())
1003− let (src0, buf1) = Prelude.splitAt n backBuf
1004− arr = fromListN n (Prelude.reverse src0)
1005− goExtract s buf1 arr
1006− Parser.Done 0 b ->
1007− return (Right b, StreamK.nil)
1008− Parser.Done n b -> do
1009− assert (n <= Prelude.length backBuf) (return ())
1010− let src0 = Prelude.take n backBuf
1011− -- XXX Use fromListRevN once implemented
1012− -- arr0 = A.fromListRevN n src0
1013− arr0 = fromListN n (Prelude.reverse src0)
1014− return (Right b, StreamK.fromPure arr0)
1015− Parser.Error err -> do
1016− let n = Prelude.length backBuf
1017− arr0 = fromListN n (Prelude.reverse backBuf)
1018− return (Left (ParseError err), StreamK.fromPure arr0)
core/src/Streamly/Internal/Data/Array/Generic.hs+6−22
@@ -11,8 +11,8 @@ module Streamly.Internal.Data.Array.Generic
1111
1212 -- * Construction
1313 , nil
14− , createOf
15− , create
14+ , writeN
15+ , write
1616 , writeWith
1717 , writeLastN
1818
@@ -44,10 +44,6 @@ module Streamly.Internal.Data.Array.Generic
4444 , getIndex
4545 , getSliceUnsafe
4646 , strip
47−
48− -- * Deprecated
49− , writeN
50− , write
5147 )
5248where
5349
@@ -108,33 +104,21 @@ nil = unsafePerformIO $ unsafeFreeze <$> MArray.nil
108104-- Construction - Folds
109105-------------------------------------------------------------------------------
110106
111−{-# INLINE_NORMAL createOf #-}
112−createOf :: MonadIO m => Int -> Fold m a (Array a)
113−createOf = fmap unsafeFreeze <$> MArray.createOf
114−
115−-- XXX Deprecate in major
116−-- {-# DEPRECATED writeN "Please use createOf instead." #-}
117−{-# INLINE writeN #-}
107+{-# INLINE_NORMAL writeN #-}
118108writeN :: MonadIO m => Int -> Fold m a (Array a)
119−writeN = createOf
109+writeN = fmap unsafeFreeze <$> MArray.writeN
120110
121111{-# INLINE_NORMAL writeWith #-}
122112writeWith :: MonadIO m => Int -> Fold m a (Array a)
123−writeWith elemCount = unsafeFreeze <$> MArray.createWith elemCount
113+writeWith elemCount = unsafeFreeze <$> MArray.writeWith elemCount
124114
125115-- | Fold the whole input to a single array.
126116--
127117-- /Caution! Do not use this on infinite streams./
128118--
129−{-# INLINE create #-}
130−create :: MonadIO m => Fold m a (Array a)
131−create = fmap unsafeFreeze MArray.create
132−
133−-- XXX Deprecate in major
134−-- {-# DEPRECATED write "Please use create instead." #-}
135119{-# INLINE write #-}
136120write :: MonadIO m => Fold m a (Array a)
137−write = create
121+write = fmap unsafeFreeze MArray.write
138122
139123fromPureStream :: Stream Identity a -> Array a
140124fromPureStream x =
core/src/Streamly/Internal/Data/Array/Stream.hs+564−57
@@ -12,7 +12,6 @@
1212-- keep this as a separate module and release it.
1313--
1414module Streamly.Internal.Data.Array.Stream
15−{-# DEPRECATED "Please use \"Streamly.Internal.Data.Array\" instead." #-}
1615 (
1716 -- * Creation
1817 Array.chunksOf
@@ -20,13 +19,13 @@ module Streamly.Internal.Data.Array.Stream
2019 , Array.bufferChunks
2120
2221 -- * Flattening to elements
23− , Array.concat
22+ , concat
2423 , Array.flattenArrays
25− , Array.concatRev
24+ , concatRev
2625 , Array.flattenArraysRev
27− , Array.interpose
28− , Array.interposeSuffix
29− , Array.intercalateSuffix
26+ , interpose
27+ , interposeSuffix
28+ , intercalateSuffix
3029 , unlines
3130
3231 -- * Elimination
@@ -37,11 +36,10 @@ module Streamly.Internal.Data.Array.Stream
3736 -- could also be implemented using parseBreak.
3837 , foldBreak
3938 , foldBreakD
40− -- This is chunked parseBreak. A byte level parseBreak cannot work
41− -- efficiently. Because the stream will have to be a StreamK for
42− -- backtracking, StreamK at byte level would not be efficient.
43− -- parseBreak p = K.parseBreakChunks (ParserK.adaptC p)
44− , parseBreak
39+ -- The byte level parseBreak cannot work efficiently. Because the stream
40+ -- will have to be a StreamK for backtracking, StreamK at byte level would
41+ -- not be efficient.
42+ , parseBreak -- StreamK.parseBreakChunks
4543 -- , parseBreakD
4644 -- , foldManyChunks
4745 -- , parseManyChunks
@@ -79,8 +77,6 @@ where
7977import Data.Bifunctor (second)
8078import Control.Exception (assert)
8179import Control.Monad.IO.Class (MonadIO(..))
82−-- import Data.Bifunctor (first)
83−-- import Data.Either (fromRight)
8480import Data.Proxy (Proxy(..))
8581import Data.Word (Word8)
8682import Streamly.Internal.Data.Unbox (Unbox(..))
@@ -96,32 +92,127 @@ import Streamly.Internal.Data.Parser (ParseError(..))
9692import Streamly.Internal.Data.Stream (Stream)
9793import Streamly.Internal.Data.StreamK (StreamK, fromStream, toStream)
9894import Streamly.Internal.Data.SVar.Type (adaptState, defState)
95+import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
9996
97+import qualified Streamly.Data.Fold as FL
10098import qualified Streamly.Internal.Data.Array as A
10199import qualified Streamly.Internal.Data.Array as Array
100+import qualified Streamly.Internal.Data.MutArray.Type as MA
101+import qualified Streamly.Internal.Data.MutArray.Stream as AS
102+import qualified Streamly.Internal.Data.Fold.Type as FL (Fold(..), Step(..))
102103import qualified Streamly.Internal.Data.Parser as PR
103104import qualified Streamly.Internal.Data.Parser as PRD
104105 (Parser(..), Initial(..))
105−-- import qualified Streamly.Internal.Data.ParserK as ParserK
106106import qualified Streamly.Internal.Data.Stream as D
107107import qualified Streamly.Internal.Data.StreamK as K
108108
109109-- XXX Since these are immutable arrays MonadIO constraint can be removed from
110110-- most places.
111111
112+-------------------------------------------------------------------------------
113+-- Append
114+-------------------------------------------------------------------------------
115+
116+-- XXX efficiently compare two streams of arrays. Two streams can have chunks
117+-- of different sizes, we can handle that in the stream comparison abstraction.
118+-- This could be useful e.g. to fast compare whether two files differ.
119+
120+-- | Convert a stream of arrays into a stream of their elements.
121+--
122+-- Same as the following:
123+--
124+-- > concat = Stream.unfoldMany Array.read
125+--
126+-- @since 0.7.0
127+{-# INLINE concat #-}
128+concat :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
129+-- concat m = fromStreamD $ A.flattenArrays (toStreamD m)
130+-- concat m = fromStreamD $ D.concatMap A.toStreamD (toStreamD m)
131+concat = D.unfoldMany A.reader
132+
133+-- | Convert a stream of arrays into a stream of their elements reversing the
134+-- contents of each array before flattening.
135+--
136+-- > concatRev = Stream.unfoldMany Array.readerRev
137+--
138+-- @since 0.7.0
139+{-# INLINE concatRev #-}
140+concatRev :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
141+-- concatRev m = fromStreamD $ A.flattenArraysRev (toStreamD m)
142+concatRev = D.unfoldMany A.readerRev
143+
112144-------------------------------------------------------------------------------
113145-- Intersperse and append
114146-------------------------------------------------------------------------------
115147
148+-- | Flatten a stream of arrays after inserting the given element between
149+-- arrays.
150+--
151+-- /Pre-release/
152+{-# INLINE interpose #-}
153+interpose :: (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
154+interpose x = D.interpose x A.reader
155+
156+{-# INLINE intercalateSuffix #-}
157+intercalateSuffix :: (Monad m, Unbox a)
158+ => Array a -> Stream m (Array a) -> Stream m a
159+intercalateSuffix = D.intercalateSuffix A.reader
160+
161+-- | Flatten a stream of arrays appending the given element after each
162+-- array.
163+--
164+-- @since 0.7.0
165+{-# INLINE interposeSuffix #-}
166+interposeSuffix :: (Monad m, Unbox a)
167+ => a -> Stream m (Array a) -> Stream m a
168+-- interposeSuffix x = fromStreamD . A.unlines x . toStreamD
169+interposeSuffix x = D.interposeSuffix x A.reader
170+
171+data FlattenState s =
172+ OuterLoop s
173+ | InnerLoop s !MA.MutableByteArray !Int !Int
174+
175+-- XXX This is a special case of interposeSuffix, can be removed.
176+-- XXX Remove monadIO constraint
116177{-# INLINE_NORMAL unlines #-}
117178unlines :: forall m a. (MonadIO m, Unbox a)
118179 => a -> D.Stream m (Array a) -> D.Stream m a
119−unlines = Array.interposeSuffix
180+unlines sep (D.Stream step state) = D.Stream step' (OuterLoop state)
181+ where
182+ {-# INLINE_LATE step' #-}
183+ step' gst (OuterLoop st) = do
184+ r <- step (adaptState gst) st
185+ return $ case r of
186+ D.Yield Array{..} s ->
187+ D.Skip (InnerLoop s arrContents arrStart arrEnd)
188+ D.Skip s -> D.Skip (OuterLoop s)
189+ D.Stop -> D.Stop
190+
191+ step' _ (InnerLoop st _ p end) | p == end =
192+ return $ D.Yield sep $ OuterLoop st
193+
194+ step' _ (InnerLoop st contents p end) = do
195+ x <- liftIO $ peekByteIndex p contents
196+ return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
120197
121198-------------------------------------------------------------------------------
122199-- Compact
123200-------------------------------------------------------------------------------
124201
202+-- XXX These would not be needed once we implement compactLEFold, see
203+-- module Streamly.Internal.Data.Stream.MutChunked
204+--
205+-- XXX Note that this thaws immutable arrays for appending, that may be
206+-- problematic if multiple users do the same thing, however, immutable arrays
207+-- would usually have no capacity to append, therefore, a copy will be forced
208+-- anyway. Confirm this. We can forcefully trim the array capacity before thaw
209+-- to ensure this.
210+{-# INLINE_NORMAL packArraysChunksOf #-}
211+packArraysChunksOf :: (MonadIO m, Unbox a)
212+ => Int -> D.Stream m (Array a) -> D.Stream m (Array a)
213+packArraysChunksOf n str =
214+ D.map A.unsafeFreeze $ AS.packArraysChunksOf n $ D.map A.unsafeThaw str
215+
125216-- XXX instead of writing two different versions of this operation, we should
126217-- write it as a pipe.
127218--
@@ -129,7 +220,8 @@ unlines = Array.interposeSuffix
129220{-# INLINE_NORMAL lpackArraysChunksOf #-}
130221lpackArraysChunksOf :: (MonadIO m, Unbox a)
131222 => Int -> Fold m (Array a) () -> Fold m (Array a) ()
132−lpackArraysChunksOf = Array.lCompactGE
223+lpackArraysChunksOf n fld =
224+ FL.lmap A.unsafeThaw $ AS.lpackArraysChunksOf n (FL.lmap A.unsafeFreeze fld)
133225
134226-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
135227-- maximum specified size in bytes.
@@ -138,20 +230,69 @@ lpackArraysChunksOf = Array.lCompactGE
138230{-# INLINE compact #-}
139231compact :: (MonadIO m, Unbox a)
140232 => Int -> Stream m (Array a) -> Stream m (Array a)
141−compact = Array.compactLE
142−
143−-- | Given a stream of arrays, splice them all together to generate a single
144−-- array. The stream must be /finite/.
145−--
146−-- @since 0.7.0
147−{-# INLINE toArray #-}
148−toArray :: (MonadIO m, Unbox a) => Stream m (Array a) -> m (Array a)
149−toArray = Array.fromChunks
233+compact = packArraysChunksOf
150234
151235-------------------------------------------------------------------------------
152236-- Split
153237-------------------------------------------------------------------------------
154238
239+data SplitState s arr
240+ = Initial s
241+ | Buffering s arr
242+ | Splitting s arr
243+ | Yielding arr (SplitState s arr)
244+ | Finishing
245+
246+-- | Split a stream of arrays on a given separator byte, dropping the separator
247+-- and coalescing all the arrays between two separators into a single array.
248+--
249+-- @since 0.7.0
250+{-# INLINE_NORMAL _splitOn #-}
251+_splitOn
252+ :: MonadIO m
253+ => Word8
254+ -> D.Stream m (Array Word8)
255+ -> D.Stream m (Array Word8)
256+_splitOn byte (D.Stream step state) = D.Stream step' (Initial state)
257+
258+ where
259+
260+ {-# INLINE_LATE step' #-}
261+ step' gst (Initial st) = do
262+ r <- step gst st
263+ case r of
264+ D.Yield arr s -> do
265+ (arr1, marr2) <- A.breakOn byte arr
266+ return $ case marr2 of
267+ Nothing -> D.Skip (Buffering s arr1)
268+ Just arr2 -> D.Skip (Yielding arr1 (Splitting s arr2))
269+ D.Skip s -> return $ D.Skip (Initial s)
270+ D.Stop -> return D.Stop
271+
272+ step' gst (Buffering st buf) = do
273+ r <- step gst st
274+ case r of
275+ D.Yield arr s -> do
276+ (arr1, marr2) <- A.breakOn byte arr
277+ buf' <- A.splice buf arr1
278+ return $ case marr2 of
279+ Nothing -> D.Skip (Buffering s buf')
280+ Just x -> D.Skip (Yielding buf' (Splitting s x))
281+ D.Skip s -> return $ D.Skip (Buffering s buf)
282+ D.Stop -> return $
283+ if A.byteLength buf == 0
284+ then D.Stop
285+ else D.Skip (Yielding buf Finishing)
286+
287+ step' _ (Splitting st buf) = do
288+ (arr1, marr2) <- A.breakOn byte buf
289+ return $ case marr2 of
290+ Nothing -> D.Skip $ Buffering st arr1
291+ Just arr2 -> D.Skip $ Yielding arr1 (Splitting st arr2)
292+
293+ step' _ (Yielding arr next) = return $ D.Yield arr next
294+ step' _ Finishing = return D.Stop
295+
155296-- XXX Remove MonadIO constraint.
156297-- | Split a stream of arrays on a given separator byte, dropping the separator
157298-- and coalescing all the arrays between two separators into a single array.
@@ -163,7 +304,7 @@ splitOn
163304 => Word8
164305 -> Stream m (Array Word8)
165306 -> Stream m (Array Word8)
166−splitOn = Array.compactOnByte
307+splitOn byte = D.splitInnerBy (A.breakOn byte) A.splice
167308
168309{-# INLINE splitOnSuffix #-}
169310splitOnSuffix
@@ -171,7 +312,8 @@ splitOnSuffix
171312 => Word8
172313 -> Stream m (Array Word8)
173314 -> Stream m (Array Word8)
174−splitOnSuffix = Array.compactOnByteSuffix
315+-- splitOn byte s = fromStreamD $ A.splitOn byte $ toStreamD s
316+splitOnSuffix byte = D.splitInnerBySuffix (A.breakOn byte) A.splice
175317
176318-------------------------------------------------------------------------------
177319-- Elimination - Running folds
@@ -180,24 +322,77 @@ splitOnSuffix = Array.compactOnByteSuffix
180322{-# INLINE_NORMAL foldBreakD #-}
181323foldBreakD :: forall m a b. (MonadIO m, Unbox a) =>
182324 Fold m a b -> D.Stream m (Array a) -> m (b, D.Stream m (Array a))
183−foldBreakD = Array.foldBreakChunks
325+foldBreakD (FL.Fold fstep initial _ final) stream@(D.Stream step state) = do
326+ res <- initial
327+ case res of
328+ FL.Partial fs -> go SPEC state fs
329+ FL.Done fb -> return $! (fb, stream)
330+
331+ where
332+
333+ {-# INLINE go #-}
334+ go !_ st !fs = do
335+ r <- step defState st
336+ case r of
337+ D.Yield (Array contents start end) s ->
338+ let fp = Tuple' end contents
339+ in goArray SPEC s fp start fs
340+ D.Skip s -> go SPEC s fs
341+ D.Stop -> do
342+ b <- final fs
343+ return (b, D.nil)
344+
345+ goArray !_ s (Tuple' end _) !cur !fs
346+ | cur == end = do
347+ go SPEC s fs
348+ goArray !_ st fp@(Tuple' end contents) !cur !fs = do
349+ x <- liftIO $ peekByteIndex cur contents
350+ res <- fstep fs x
351+ let next = INDEX_NEXT(cur,a)
352+ case res of
353+ FL.Done b -> do
354+ let arr = Array contents next end
355+ return $! (b, D.cons arr (D.Stream step st))
356+ FL.Partial fs1 -> goArray SPEC st fp next fs1
357+
358+{-# INLINE_NORMAL foldBreakK #-}
359+foldBreakK :: forall m a b. (MonadIO m, Unbox a) =>
360+ Fold m a b -> K.StreamK m (Array a) -> m (b, K.StreamK m (Array a))
361+foldBreakK (FL.Fold fstep initial _ final) stream = do
362+ res <- initial
363+ case res of
364+ FL.Partial fs -> go fs stream
365+ FL.Done fb -> return (fb, stream)
366+
367+ where
368+
369+ {-# INLINE go #-}
370+ go !fs st = do
371+ let stop = (, K.nil) <$> final fs
372+ single a = yieldk a K.nil
373+ yieldk (Array contents start end) r =
374+ let fp = Tuple' end contents
375+ in goArray fs r fp start
376+ in K.foldStream defState yieldk single stop st
377+
378+ goArray !fs st (Tuple' end _) !cur
379+ | cur == end = do
380+ go fs st
381+ goArray !fs st fp@(Tuple' end contents) !cur = do
382+ x <- liftIO $ peekByteIndex cur contents
383+ res <- fstep fs x
384+ let next = INDEX_NEXT(cur,a)
385+ case res of
386+ FL.Done b -> do
387+ let arr = Array contents next end
388+ return $! (b, K.cons arr st)
389+ FL.Partial fs1 -> goArray fs1 st fp next
184390
185391-- | Fold an array stream using the supplied 'Fold'. Returns the fold result
186392-- and the unconsumed stream.
187393--
188394-- > foldBreak f = runArrayFoldBreak (ChunkFold.fromFold f)
189395--
190−-- Instead of using this we can adapt the fold to ParserK and use
191−-- parseBreakChunks instead. ParserK allows composing using Monad as well.
192−--
193−-- @
194−-- foldBreak f s =
195−-- fmap (first (fromRight undefined))
196−-- $ K.parseBreakChunks (ParserK.adaptC (PR.fromFold f)) s
197−-- @
198−--
199−-- We can compare perf and remove this one or define it in terms of that.
200−--
201396-- /Internal/
202397--
203398{-# INLINE_NORMAL foldBreak #-}
@@ -206,20 +401,14 @@ foldBreak ::
206401 => Fold m a b
207402 -> StreamK m (A.Array a)
208403 -> m (b, StreamK m (A.Array a))
209−foldBreak = Array.foldBreakChunksK
210−--
211404-- foldBreak f s = fmap fromStreamD <$> foldBreakD f (toStreamD s)
212−--
213−-- foldBreak f s =
214−-- fmap (first (fromRight undefined))
215−-- $ K.parseBreakChunks (ParserK.adaptC (PR.fromFold f)) s
216−--
405+foldBreak = foldBreakK
217406-- If foldBreak performs better than runArrayFoldBreak we can use a rewrite
218407-- rule to rewrite runArrayFoldBreak to fold.
219408-- foldBreak f = runArrayFoldBreak (ChunkFold.fromFold f)
220409
221410-------------------------------------------------------------------------------
222−-- Elimination - running element parsers
411+-- Fold to a single Array
223412-------------------------------------------------------------------------------
224413
225414-- When we have to take an array partially, take the last part of the array.
@@ -265,22 +454,341 @@ splitAtArrayListRev n ls
265454 arr1 = Array contents end1 end
266455 in ([arr1], arr2:xs)
267456
457+-------------------------------------------------------------------------------
458+-- Fold to a single Array
459+-------------------------------------------------------------------------------
460+
461+{-
462+
463+-- XXX Both of these implementations of splicing seem to perform equally well.
464+-- We need to perform benchmarks over a range of sizes though.
465+
466+-- CAUTION! length must more than equal to lengths of all the arrays in the
467+-- stream.
468+{-# INLINE spliceArraysLenUnsafe #-}
469+spliceArraysLenUnsafe :: (MonadIO m, Unbox a)
470+ => Int -> Stream m (MutArray a) -> m (MutArray a)
471+spliceArraysLenUnsafe len buffered = do
472+ -- XXX The new array's pinned state should depend on the first element
473+ -- of the stream. We should uncons the stream and do the required.
474+ arr <- undefined
475+ D.foldlM' MA.spliceUnsafe (return arr) buffered
476+
477+{-# INLINE _spliceArrays #-}
478+_spliceArrays :: (MonadIO m, Unbox a)
479+ => Stream m (Array a) -> m (Array a)
480+_spliceArrays s = do
481+ buffered <- D.foldr K.cons K.nil s
482+ len <- K.fold FL.sum (fmap Array.length buffered)
483+ -- XXX The new array's pinned state should depend on the first element
484+ -- of the stream. We should uncons the stream and do the required.
485+ arr <- undefined
486+ final <- D.foldlM' writeArr (return arr) (toStream buffered)
487+ return $ A.unsafeFreeze final
488+
489+ where
490+
491+ writeArr dst arr = MA.spliceUnsafe dst (A.unsafeThaw arr)
492+
493+{-# INLINE _spliceArraysBuffered #-}
494+_spliceArraysBuffered :: (MonadIO m, Unbox a)
495+ => Stream m (Array a) -> m (Array a)
496+_spliceArraysBuffered s = do
497+ buffered <- D.foldr K.cons K.nil s
498+ len <- K.fold FL.sum (fmap Array.length buffered)
499+ A.unsafeFreeze <$>
500+ spliceArraysLenUnsafe len (fmap A.unsafeThaw (toStream buffered))
501+
502+-}
503+
504+{-# INLINE spliceArraysRealloced #-}
505+spliceArraysRealloced :: forall m a. (MonadIO m, Unbox a)
506+ => Stream m (Array a) -> m (Array a)
507+spliceArraysRealloced s = do
508+ res <- D.uncons s
509+ case res of
510+ Just (a, strm) -> do
511+ arr <-
512+ D.foldlM'
513+ MA.spliceExp
514+ (pure (A.unsafeThaw a))
515+ (fmap A.unsafeThaw strm)
516+ liftIO $ A.unsafeFreeze <$> MA.rightSize arr
517+ Nothing -> pure A.nil
518+
519+-- XXX This should just be "fold A.write"
520+--
521+-- | Given a stream of arrays, splice them all together to generate a single
522+-- array. The stream must be /finite/.
523+--
524+-- @since 0.7.0
525+{-# INLINE toArray #-}
526+toArray :: (MonadIO m, Unbox a) => Stream m (Array a) -> m (Array a)
527+toArray = spliceArraysRealloced
528+-- spliceArrays = _spliceArraysBuffered
529+
530+-- exponentially increasing sizes of the chunks upto the max limit.
531+-- XXX this will be easier to implement with parsers/terminating folds
532+-- With this we should be able to reduce the number of chunks/allocations.
533+-- The reallocation/copy based toArray can also be implemented using this.
534+--
535+{-
536+{-# INLINE toArraysInRange #-}
537+toArraysInRange :: (MonadIO m, Unbox a)
538+ => Int -> Int -> Fold m (Array a) b -> Fold m a b
539+toArraysInRange low high (Fold step initial extract) =
540+-}
541+
542+{-
543+-- | Fold the input to a pure buffered stream (List) of arrays.
544+{-# INLINE _toArraysOf #-}
545+_toArraysOf :: (MonadIO m, Unbox a)
546+ => Int -> Fold m a (Stream Identity (Array a))
547+_toArraysOf n = FL.groupsOf n (A.writeNF n) FL.toStream
548+-}
549+
550+-------------------------------------------------------------------------------
551+-- Elimination - running element parsers
552+-------------------------------------------------------------------------------
553+
268554-- GHC parser does not accept {-# ANN type [] NoSpecConstr #-}, so we need
269555-- to make a newtype.
270556{-# ANN type List NoSpecConstr #-}
271557newtype List a = List {getList :: [a]}
272558
559+{-
560+-- This can be generalized to any type provided it can be unfolded to a stream
561+-- and it can be combined using a semigroup operation.
562+--
563+-- XXX This should be written using CPS (as parseK) if we want it to scale wrt
564+-- to the number of times it can be called on the same stream.
565+{-# INLINE_NORMAL parseBreakD #-}
566+parseBreakD ::
567+ forall m a b. (MonadIO m, MonadThrow m, Unbox a)
568+ => PRD.Parser a m b
569+ -> D.Stream m (Array.Array a)
570+ -> m (b, D.Stream m (Array.Array a))
571+parseBreakD
572+ (PRD.Parser pstep initial extract) stream@(D.Stream step state) = do
573+
574+ res <- initial
575+ case res of
576+ PRD.IPartial s -> go SPEC state (List []) s
577+ PRD.IDone b -> return (b, stream)
578+ PRD.IError err -> throwM $ ParseError err
579+
580+ where
581+
582+ -- "backBuf" contains last few items in the stream that we may have to
583+ -- backtrack to.
584+ --
585+ -- XXX currently we are using a dumb list based approach for backtracking
586+ -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
587+ -- That will allow us more efficient random back and forth movement.
588+ go !_ st backBuf !pst = do
589+ r <- step defState st
590+ case r of
591+ D.Yield (Array contents start end) s ->
592+ gobuf SPEC s backBuf
593+ (Tuple' end contents) start pst
594+ D.Skip s -> go SPEC s backBuf pst
595+ D.Stop -> do
596+ b <- extract pst
597+ return (b, D.nil)
598+
599+ -- Use strictness on "cur" to keep it unboxed
600+ gobuf !_ s backBuf (Tuple' end _) !cur !pst
601+ | cur == end = do
602+ go SPEC s backBuf pst
603+ gobuf !_ s backBuf fp@(Tuple' end contents) !cur !pst = do
604+ x <- liftIO $ peekByteIndex contents cur
605+ pRes <- pstep pst x
606+ let next = INDEX_NEXT(cur,a)
607+ case pRes of
608+ PR.Partial 0 pst1 ->
609+ gobuf SPEC s (List []) fp next pst1
610+ PR.Partial n pst1 -> do
611+ assert (n <= Prelude.length (x:getList backBuf)) (return ())
612+ let src0 = Prelude.take n (x:getList backBuf)
613+ arr0 = A.fromListN n (Prelude.reverse src0)
614+ arr1 = Array contents next end
615+ src = arr0 <> arr1
616+ let !(Array cont1 start end1) = src
617+ fp1 = Tuple' end1 cont1
618+ gobuf SPEC s (List []) fp1 start pst1
619+ PR.Continue 0 pst1 ->
620+ gobuf SPEC s (List (x:getList backBuf)) fp next pst1
621+ PR.Continue n pst1 -> do
622+ assert (n <= Prelude.length (x:getList backBuf)) (return ())
623+ let (src0, buf1) = splitAt n (x:getList backBuf)
624+ arr0 = A.fromListN n (Prelude.reverse src0)
625+ arr1 = Array contents next end
626+ src = arr0 <> arr1
627+ let !(Array cont1 start end1) = src
628+ fp1 = Tuple' end1 cont1
629+ gobuf SPEC s (List buf1) fp1 start pst1
630+ PR.Done 0 b -> do
631+ let arr = Array contents next end
632+ return (b, D.cons arr (D.Stream step s))
633+ PR.Done n b -> do
634+ assert (n <= Prelude.length (x:getList backBuf)) (return ())
635+ let src0 = Prelude.take n (x:getList backBuf)
636+ -- XXX create the array in reverse instead
637+ arr0 = A.fromListN n (Prelude.reverse src0)
638+ arr1 = Array contents next end
639+ -- XXX Use StreamK to avoid adding arbitrary layers of
640+ -- constructors every time.
641+ str = D.cons arr0 (D.cons arr1 (D.Stream step s))
642+ return (b, str)
643+ PR.Error err -> throwM $ ParseError err
644+-}
645+
646+{-# INLINE_NORMAL parseBreakK #-}
647+parseBreakK ::
648+ forall m a b. (MonadIO m, Unbox a)
649+ => PRD.Parser a m b
650+ -> K.StreamK m (Array.Array a)
651+ -> m (Either ParseError b, K.StreamK m (Array.Array a))
652+parseBreakK (PRD.Parser pstep initial extract) stream = do
653+ res <- initial
654+ case res of
655+ PRD.IPartial s -> go s stream []
656+ PRD.IDone b -> return (Right b, stream)
657+ PRD.IError err -> return (Left (ParseError err), stream)
658+
659+ where
660+
661+ -- "backBuf" contains last few items in the stream that we may have to
662+ -- backtrack to.
663+ --
664+ -- XXX currently we are using a dumb list based approach for backtracking
665+ -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
666+ -- That will allow us more efficient random back and forth movement.
667+ go !pst st backBuf = do
668+ let stop = goStop pst backBuf -- (, K.nil) <$> extract pst
669+ single a = yieldk a K.nil
670+ yieldk arr r = goArray pst backBuf r arr
671+ in K.foldStream defState yieldk single stop st
672+
673+ -- Use strictness on "cur" to keep it unboxed
674+ goArray !pst backBuf st (Array _ cur end) | cur == end = go pst st backBuf
675+ goArray !pst backBuf st (Array contents cur end) = do
676+ x <- liftIO $ peekByteIndex cur contents
677+ pRes <- pstep pst x
678+ let next = INDEX_NEXT(cur,a)
679+ case pRes of
680+ PR.Partial 0 s ->
681+ goArray s [] st (Array contents next end)
682+ PR.Partial n s -> do
683+ assert (n <= Prelude.length (x:backBuf)) (return ())
684+ let src0 = Prelude.take n (x:backBuf)
685+ arr0 = A.fromListN n (Prelude.reverse src0)
686+ arr1 = Array contents next end
687+ src = arr0 <> arr1
688+ goArray s [] st src
689+ PR.Continue 0 s ->
690+ goArray s (x:backBuf) st (Array contents next end)
691+ PR.Continue n s -> do
692+ assert (n <= Prelude.length (x:backBuf)) (return ())
693+ let (src0, buf1) = splitAt n (x:backBuf)
694+ arr0 = A.fromListN n (Prelude.reverse src0)
695+ arr1 = Array contents next end
696+ src = arr0 <> arr1
697+ goArray s buf1 st src
698+ PR.Done 0 b -> do
699+ let arr = Array contents next end
700+ return (Right b, K.cons arr st)
701+ PR.Done n b -> do
702+ assert (n <= Prelude.length (x:backBuf)) (return ())
703+ let src0 = Prelude.take n (x:backBuf)
704+ -- XXX Use fromListRevN once implemented
705+ -- arr0 = A.fromListRevN n src0
706+ arr0 = A.fromListN n (Prelude.reverse src0)
707+ arr1 = Array contents next end
708+ str = K.cons arr0 (K.cons arr1 st)
709+ return (Right b, str)
710+ PR.Error err -> do
711+ let n = Prelude.length backBuf
712+ arr0 = A.fromListN n (Prelude.reverse backBuf)
713+ arr1 = Array contents cur end
714+ str = K.cons arr0 (K.cons arr1 stream)
715+ return (Left (ParseError err), str)
716+
717+ -- This is a simplified goArray
718+ goExtract !pst backBuf (Array _ cur end)
719+ | cur == end = goStop pst backBuf
720+ goExtract !pst backBuf (Array contents cur end) = do
721+ x <- liftIO $ peekByteIndex cur contents
722+ pRes <- pstep pst x
723+ let next = INDEX_NEXT(cur,a)
724+ case pRes of
725+ PR.Partial 0 s ->
726+ goExtract s [] (Array contents next end)
727+ PR.Partial n s -> do
728+ assert (n <= Prelude.length (x:backBuf)) (return ())
729+ let src0 = Prelude.take n (x:backBuf)
730+ arr0 = A.fromListN n (Prelude.reverse src0)
731+ arr1 = Array contents next end
732+ src = arr0 <> arr1
733+ goExtract s [] src
734+ PR.Continue 0 s ->
735+ goExtract s backBuf (Array contents next end)
736+ PR.Continue n s -> do
737+ assert (n <= Prelude.length (x:backBuf)) (return ())
738+ let (src0, buf1) = splitAt n (x:backBuf)
739+ arr0 = A.fromListN n (Prelude.reverse src0)
740+ arr1 = Array contents next end
741+ src = arr0 <> arr1
742+ goExtract s buf1 src
743+ PR.Done 0 b -> do
744+ let arr = Array contents next end
745+ return (Right b, K.fromPure arr)
746+ PR.Done n b -> do
747+ assert (n <= Prelude.length backBuf) (return ())
748+ let src0 = Prelude.take n backBuf
749+ -- XXX Use fromListRevN once implemented
750+ -- arr0 = A.fromListRevN n src0
751+ arr0 = A.fromListN n (Prelude.reverse src0)
752+ arr1 = Array contents next end
753+ str = K.cons arr0 (K.fromPure arr1)
754+ return (Right b, str)
755+ PR.Error err -> do
756+ let n = Prelude.length backBuf
757+ arr0 = A.fromListN n (Prelude.reverse backBuf)
758+ arr1 = Array contents cur end
759+ str = K.cons arr0 (K.cons arr1 stream)
760+ return (Left (ParseError err), str)
761+
762+ -- This is a simplified goExtract
763+ {-# INLINE goStop #-}
764+ goStop !pst backBuf = do
765+ pRes <- extract pst
766+ case pRes of
767+ PR.Partial _ _ -> error "Bug: parseBreak: Partial in extract"
768+ PR.Continue 0 s ->
769+ goStop s backBuf
770+ PR.Continue n s -> do
771+ assert (n <= Prelude.length backBuf) (return ())
772+ let (src0, buf1) = splitAt n backBuf
773+ arr = A.fromListN n (Prelude.reverse src0)
774+ goExtract s buf1 arr
775+ PR.Done 0 b ->
776+ return (Right b, K.nil)
777+ PR.Done n b -> do
778+ assert (n <= Prelude.length backBuf) (return ())
779+ let src0 = Prelude.take n backBuf
780+ -- XXX Use fromListRevN once implemented
781+ -- arr0 = A.fromListRevN n src0
782+ arr0 = A.fromListN n (Prelude.reverse src0)
783+ return (Right b, K.fromPure arr0)
784+ PR.Error err -> do
785+ let n = Prelude.length backBuf
786+ arr0 = A.fromListN n (Prelude.reverse backBuf)
787+ return (Left (ParseError err), K.fromPure arr0)
788+
273789-- | Parse an array stream using the supplied 'Parser'. Returns the parse
274790-- result and the unconsumed stream. Throws 'ParseError' if the parse fails.
275791--
276−-- >> parseBreak p = K.parseBreakChunks (ParserK.adaptC p)
277−--
278−-- This is redundant and we can just use parseBreakChunks, as ParserK can be
279−-- composed using Monad. The only advantage of this is that we do not need to
280−-- adapt.
281−--
282−-- We can compare perf and remove this one or define it in terms of that.
283−--
284792-- /Internal/
285793--
286794{-# INLINE_NORMAL parseBreak #-}
@@ -293,8 +801,7 @@ parseBreak ::
293801parseBreak p s =
294802 fmap fromStreamD <$> parseBreakD (PRD.fromParserK p) (toStreamD s)
295803-}
296−parseBreak = Array.parseBreakChunksK
297−-- parseBreak p = K.parseBreakChunks (ParserK.adaptC p)
804+parseBreak = parseBreakK
298805
299806-------------------------------------------------------------------------------
300807-- Elimination - Running Array Folds and parsers
core/src/Streamly/Internal/Data/Array/Type.hs+98−503
@@ -1,11 +1,8 @@
11{-# LANGUAGE CPP #-}
2−{-# LANGUAGE TypeFamilies #-}
3−-- Must come after TypeFamilies, otherwise it is re-enabled.
4−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
5−{-# LANGUAGE NoMonoLocalBinds #-}
62-- |
73-- Module : Streamly.Internal.Data.Array.Type
84-- Copyright : (c) 2020 Composewell Technologies
5+--
96-- License : BSD3-3-Clause
107-- Maintainer : streamly@composewell.com
118-- Stability : experimental
@@ -13,146 +10,87 @@
1310--
1411-- See notes in "Streamly.Internal.Data.MutArray.Type"
1512--
16−
1713module Streamly.Internal.Data.Array.Type
1814 (
1915 -- ** Type
2016 -- $arrayNotes
2117 Array (..)
18+ , asPtrUnsafe
19+ , nil
2220
23− -- ** Conversion
24− -- *** Mutable and Immutable
21+ -- ** Freezing and Thawing
2522 , unsafeFreeze
2623 , unsafeFreezeWithShrink
2724 , unsafeThaw
2825
29− -- *** Pinned and Unpinned
26+ -- ** Pinning and Unpinning
3027 , pin
3128 , unpin
3229 , isPinned
3330
34− -- *** Casting
35− , unsafePinnedAsPtr
36−
3731 -- ** Construction
38− , empty
39−
40− -- *** Cloning
41− -- XXX Why would we clone an immutable array?
42− , clone
43− , pinnedClone
44−
45− -- *** Slicing
46− -- | Get a subarray without copying
47− , splitAt
48− , breakOn -- XXX requires MonadIO
32+ , splice
4933
50− -- *** Stream Folds
51− , unsafeMakePure
52− , createOf
53− , pinnedCreateOf
54− , unsafeCreateOf
55− , unsafePinnedCreateOf
56− , create
57− , pinnedCreate
58− , createWith
59−
60− -- *** From containers
61− , fromListN
62− , pinnedFromListN
6334 , fromList
6435 , pinnedFromList
65− , fromListRevN
36+ , fromListN
37+ , pinnedFromListN
6638 , fromListRev
67− , fromStreamN
68− , fromStream
69− , fromPureStreamN
39+ , fromListRevN
40+ , fromStreamDN
41+ , fromStreamD
7042 , fromPureStream
7143 , fromByteStr#
72− , fromByteStr
73− , fromPtrN
74− , fromChunks
75− , fromChunksK
7644
77− -- ** Reading
45+ -- ** Split
46+ , breakOn
7847
79− -- *** Indexing
80− , unsafeIndexIO -- XXX unsafeGetIndexIO
81− , getIndexUnsafe -- XXX unsafeGetIndex
82−
83− -- *** To Streams
84− , read
85− , readRev
86− , toStreamK
87− , toStreamKRev
88−
89− -- *** To Containers
90− , toList
91−
92− -- *** Unfolds
93− , producer -- experimental
94− , readerUnsafe
95− , reader
96− , readerRev
48+ -- ** Cloning arrays
49+ , clone
50+ , pinnedClone
9751
98− -- *** Size
99− , length
52+ -- ** Elimination
53+ , unsafeIndexIO
54+ , getIndexUnsafe
10055 , byteLength
56+ , length
10157
102− -- ** Folding
10358 , foldl'
10459 , foldr
105− , byteCmp
106− , byteEq
107−
108− -- ** Appending
109− , splice -- XXX requires MonadIO
110−
111− -- ** Streams of arrays
112− -- *** Chunk
113− -- | Group a stream into arrays.
114− , chunksOf
115− , pinnedChunksOf
116− , buildChunks
117−
118− -- *** Split
119− -- | Split an array into slices.
120−
121− -- *** Concat
122− -- | Append the arrays in a stream to form a stream of elements.
123− , concat
124− , concatRev
125−
126− -- *** Compact
127− -- | Append the arrays in a stream to form a stream of larger arrays.
128− , fCompactGE
129− , fPinnedCompactGE
130− , lCompactGE
131− , lPinnedCompactGE
132− , compactGE
60+ , splitAt
13361
134− -- ** Deprecated
135− , asPtrUnsafe
136− , unsafeIndex
137− , bufferChunks
138− , flattenArrays
139− , flattenArraysRev
140− , fromArrayStreamK
141− , fromStreamDN
142− , fromStreamD
14362 , toStreamD
14463 , toStreamDRev
64+ , toStreamK
65+ , toStreamKRev
14566 , toStream
14667 , toStreamRev
147− , nil
68+ , read
69+ , readRev
70+ , readerRev
71+ , toList
72+
73+ -- ** Folds
14874 , writeWith
14975 , writeN
15076 , pinnedWriteN
15177 , writeNUnsafe
15278 , pinnedWriteNUnsafe
79+ , MA.ArrayUnsafe (..)
15380 , pinnedWriteNAligned
15481 , write
15582 , pinnedWrite
83+ , unsafeMakePure
84+
85+ -- ** Streams of arrays
86+ , chunksOf
87+ , pinnedChunksOf
88+ , bufferChunks
89+ , flattenArrays
90+ , flattenArraysRev
91+
92+ -- ** Deprecated
93+ , unsafeIndex
15694 )
15795where
15896
@@ -160,36 +98,31 @@ where
16098#include "inline.hs"
16199
162100import Control.Exception (assert)
163−import Control.Monad (replicateM, when)
101+import Control.Monad (replicateM)
164102import Control.Monad.IO.Class (MonadIO(..))
165103import Data.Functor.Identity (Identity(..))
166−import Data.Int (Int8, Int16, Int32, Int64)
167104import Data.Proxy (Proxy(..))
168−import Data.Word (Word8, Word16, Word32, Word64)
105+import Data.Word (Word8)
169106import GHC.Base (build)
170107import GHC.Exts (IsList, IsString(..), Addr#)
171108
172109import GHC.IO (unsafePerformIO)
173110import GHC.Ptr (Ptr(..))
174−import Streamly.Internal.Data.Producer.Type (Producer(..))
175−import Streamly.Internal.Data.MutArray.Type (MutArray(..))
176−import Streamly.Internal.Data.MutByteArray.Type (MutByteArray)
111+import Streamly.Internal.Data.MutArray.Type (MutArray(..), MutByteArray)
177112import Streamly.Internal.Data.Fold.Type (Fold(..))
178113import Streamly.Internal.Data.Stream.Type (Stream)
179−import Streamly.Internal.Data.StreamK.Type (StreamK)
180114import Streamly.Internal.Data.Unbox (Unbox(..))
181115import Streamly.Internal.Data.Unfold.Type (Unfold(..))
182116import Text.Read (readPrec)
183117
184−import Prelude hiding (Foldable(..), concat, read, unlines, splitAt)
118+import Prelude hiding (Foldable(..), read, unlines, splitAt)
185119
186120import qualified GHC.Exts as Exts
187−import qualified Streamly.Internal.Data.Fold.Type as Fold
188121import qualified Streamly.Internal.Data.MutArray.Type as MA
189122import qualified Streamly.Internal.Data.Stream.Type as D
123+import qualified Streamly.Internal.Data.Stream.Generate as D
190124import qualified Streamly.Internal.Data.StreamK.Type as K
191125import qualified Streamly.Internal.Data.MutByteArray.Type as Unboxed
192−import qualified Streamly.Internal.Data.Producer as Producer
193126import qualified Streamly.Internal.Data.Unfold.Type as Unfold
194127import qualified Text.ParserCombinators.ReadPrec as ReadPrec
195128
@@ -243,20 +176,15 @@ data Array a =
243176
244177-- | Use an @Array a@ as @Ptr a@.
245178--
246−-- See 'MA.unsafePinnedAsPtr' in the Mutable array module for more details.
179+-- See 'MA.asPtrUnsafe' in the Mutable array module for more details.
247180--
248181-- /Unsafe/
249182--
250183-- /Pre-release/
251184--
252−{-# INLINE unsafePinnedAsPtr #-}
253−unsafePinnedAsPtr :: MonadIO m => Array a -> (Ptr a -> m b) -> m b
254−unsafePinnedAsPtr arr = MA.unsafePinnedAsPtr (unsafeThaw arr)
255−
256−{-# DEPRECATED asPtrUnsafe "Please use unsafePinnedAsPtr instead." #-}
257185{-# INLINE asPtrUnsafe #-}
258186asPtrUnsafe :: MonadIO m => Array a -> (Ptr a -> m b) -> m b
259−asPtrUnsafe = unsafePinnedAsPtr
187+asPtrUnsafe arr = MA.asPtrUnsafe (unsafeThaw arr)
260188
261189-------------------------------------------------------------------------------
262190-- Freezing and Thawing
@@ -324,14 +252,11 @@ isPinned = MA.isPinned . unsafeThaw
324252-- Construction
325253-------------------------------------------------------------------------------
326254
327−-- | Copy two immutable arrays into a new array. If you want to splice more
328−-- than two arrays then this operation would be highly inefficient because it
329−-- would make a copy on every splice operation, instead use the
330−-- 'fromChunksK' operation to combine n immutable arrays.
255+-- Splice two immutable arrays creating a new array.
331256{-# INLINE splice #-}
332−splice :: MonadIO m => Array a -> Array a -> m (Array a)
257+splice :: (MonadIO m, Unbox a) => Array a -> Array a -> m (Array a)
333258splice arr1 arr2 =
334− unsafeFreeze <$> MA.spliceCopy (unsafeThaw arr1) (unsafeThaw arr2)
259+ unsafeFreeze <$> MA.splice (unsafeThaw arr1) (unsafeThaw arr2)
335260
336261-- | Create an 'Array' from the first N elements of a list. The array is
337262-- allocated to size N, if the list terminates before N elements then the
@@ -375,83 +300,36 @@ pinnedFromList xs = unsafePerformIO $ unsafeFreeze <$> MA.pinnedFromList xs
375300fromListRev :: Unbox a => [a] -> Array a
376301fromListRev xs = unsafePerformIO $ unsafeFreeze <$> MA.fromListRev xs
377302
378−-- | Create an 'Array' from the first N elements of a stream. The array is
379−-- allocated to size N, if the stream terminates before N elements then the
380−-- array may hold less than N elements.
381−--
382−-- >>> fromStreamN n = Stream.fold (Array.writeN n)
383−--
384−-- /Pre-release/
385−{-# INLINE_NORMAL fromStreamN #-}
386−fromStreamN :: (MonadIO m, Unbox a) => Int -> Stream m a -> m (Array a)
387−fromStreamN n m = do
388− when (n < 0) $ error "writeN: negative write count specified"
389− unsafeFreeze <$> MA.fromStreamN n m
390−-- fromStreamN n = D.fold (writeN n)
391−
392−{-# DEPRECATED fromStreamDN "Please use fromStreamN instead." #-}
303+{-# INLINE_NORMAL fromStreamDN #-}
393304fromStreamDN :: forall m a. (MonadIO m, Unbox a)
394305 => Int -> D.Stream m a -> m (Array a)
395−fromStreamDN = fromStreamN
306+fromStreamDN limit str = unsafeFreeze <$> MA.fromStreamDN limit str
396307
397−-- | Create an 'Array' from a stream. This is useful when we want to create a
398−-- single array from a stream of unknown size. 'writeN' is at least twice
399−-- as efficient when the size is already known.
400−--
401−-- >>> fromStream = Stream.fold Array.write
402−--
403−-- Note that if the input stream is too large memory allocation for the array
404−-- may fail. When the stream size is not known, `chunksOf` followed by
405−-- processing of indvidual arrays in the resulting stream should be preferred.
406−--
407−-- /Pre-release/
408308{-# INLINE_NORMAL fromStreamD #-}
409−fromStream :: (MonadIO m, Unbox a) => Stream m a -> m (Array a)
410−fromStream = D.fold write
411−-- fromStreamD str = unsafeFreeze <$> MA.fromStream str
412−
413−{-# DEPRECATED fromStreamD "Please use fromStream instead." #-}
414309fromStreamD :: forall m a. (MonadIO m, Unbox a)
415310 => D.Stream m a -> m (Array a)
416−fromStreamD = fromStream
311+fromStreamD str = unsafeFreeze <$> MA.fromStreamD str
417312
418313-------------------------------------------------------------------------------
419314-- Cloning
420315-------------------------------------------------------------------------------
421316
422317{-# INLINE clone #-}
423−clone ::
424− ( MonadIO m
425−#ifdef DEVBUILD
426− , Unbox a
427−#endif
428− )
429− => Array a -> m (Array a)
318+clone :: MonadIO m => Array a -> m (Array a)
430319clone = fmap unsafeFreeze . MA.clone . unsafeThaw
431320
432321{-# INLINE pinnedClone #-}
433−pinnedClone ::
434− ( MonadIO m
435−#ifdef DEVBUILD
436− , Unbox a
437−#endif
438− )
439− => Array a -> m (Array a)
322+pinnedClone :: MonadIO m => Array a -> m (Array a)
440323pinnedClone = fmap unsafeFreeze . MA.pinnedClone . unsafeThaw
441324
442325-------------------------------------------------------------------------------
443326-- Streams of arrays
444327-------------------------------------------------------------------------------
445328
446−{-# INLINE buildChunks #-}
447−buildChunks :: (MonadIO m, Unbox a) =>
448− D.Stream m a -> m (K.StreamK m (Array a))
449−buildChunks m = D.foldr K.cons K.nil $ chunksOf defaultChunkSize m
450−
451−{-# DEPRECATED bufferChunks "Please use buildChunks instead." #-}
329+{-# INLINE bufferChunks #-}
452330bufferChunks :: (MonadIO m, Unbox a) =>
453331 D.Stream m a -> m (K.StreamK m (Array a))
454−bufferChunks = buildChunks
332+bufferChunks m = D.foldr K.cons K.nil $ chunksOf defaultChunkSize m
455333
456334-- | @chunksOf n stream@ groups the elements in the input stream into arrays of
457335-- @n@ elements each.
@@ -472,100 +350,27 @@ pinnedChunksOf :: forall m a. (MonadIO m, Unbox a)
472350 => Int -> D.Stream m a -> D.Stream m (Array a)
473351pinnedChunksOf n str = D.map unsafeFreeze $ MA.pinnedChunksOf n str
474352
475−-- | Convert a stream of arrays into a stream of their elements.
353+-- | Use the "read" unfold instead.
476354--
477−-- >>> concat = Stream.unfoldMany Array.reader
355+-- @flattenArrays = unfoldMany read@
478356--
479−{-# INLINE_NORMAL concat #-}
480−concat :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
481−-- XXX this requires MonadIO whereas the unfoldMany version does not
482−concat = MA.concatWith (pure . unsafeInlineIO) . D.map unsafeThaw
483−-- concat = D.unfoldMany reader
484−
485−{-# DEPRECATED flattenArrays "Please use \"unfoldMany reader\" instead." #-}
486−{-# INLINE flattenArrays #-}
357+-- We can try this if there are any fusion issues in the unfold.
358+--
359+{-# INLINE_NORMAL flattenArrays #-}
487360flattenArrays :: forall m a. (MonadIO m, Unbox a)
488361 => D.Stream m (Array a) -> D.Stream m a
489−flattenArrays = concat
362+flattenArrays = MA.flattenArrays . D.map unsafeThaw
490363
491−-- | Convert a stream of arrays into a stream of their elements reversing the
492−-- contents of each array before flattening.
364+-- | Use the "readRev" unfold instead.
493365--
494−-- >>> concatRev = Stream.unfoldMany Array.readerRev
366+-- @flattenArrays = unfoldMany readRev@
495367--
496−{-# INLINE_NORMAL concatRev #-}
497−concatRev :: forall m a. (Monad m, Unbox a)
498− => D.Stream m (Array a) -> D.Stream m a
499−-- XXX this requires MonadIO whereas the unfoldMany version does not
500−concatRev = MA.concatRevWith (pure . unsafeInlineIO) . D.map unsafeThaw
501−-- concatRev = D.unfoldMany readerRev
502−
503−{-# DEPRECATED flattenArraysRev "Please use \"unfoldMany readerRev\" instead." #-}
504−{-# INLINE flattenArraysRev #-}
368+-- We can try this if there are any fusion issues in the unfold.
369+--
370+{-# INLINE_NORMAL flattenArraysRev #-}
505371flattenArraysRev :: forall m a. (MonadIO m, Unbox a)
506372 => D.Stream m (Array a) -> D.Stream m a
507−flattenArraysRev = concatRev
508−
509−-------------------------------------------------------------------------------
510−-- Compact
511−-------------------------------------------------------------------------------
512−
513−-- XXX Note that this thaws immutable arrays for appending, that may be
514−-- problematic if multiple users do the same thing, however, thawed immutable
515−-- arrays would have no capacity to append, therefore, a copy will be forced
516−-- anyway.
517−
518−-- | Fold @fCompactGE n@ coalesces adjacent arrays in the input stream
519−-- until the size becomes greater than or equal to n.
520−--
521−-- Generates unpinned arrays irrespective of the pinning status of input
522−-- arrays.
523−{-# INLINE_NORMAL fCompactGE #-}
524−fCompactGE :: (MonadIO m, Unbox a) => Int -> Fold m (Array a) (Array a)
525−fCompactGE n = fmap unsafeFreeze $ Fold.lmap unsafeThaw $ MA.fCompactGE n
526−
527−-- | PInned version of 'fCompactGE'.
528−{-# INLINE_NORMAL fPinnedCompactGE #-}
529−fPinnedCompactGE :: (MonadIO m, Unbox a) => Int -> Fold m (Array a) (Array a)
530−fPinnedCompactGE n =
531− fmap unsafeFreeze $ Fold.lmap unsafeThaw $ MA.fPinnedCompactGE n
532−
533−-- | @compactGE n stream@ coalesces adjacent arrays in the @stream@ until
534−-- the size becomes greater than or equal to @n@.
535−--
536−-- >>> compactGE n = Stream.foldMany (Array.fCompactGE n)
537−--
538−-- Generates unpinned arrays irrespective of the pinning status of input
539−-- arrays.
540−{-# INLINE compactGE #-}
541−compactGE ::
542− (MonadIO m, Unbox a)
543− => Int -> Stream m (Array a) -> Stream m (Array a)
544−compactGE n stream =
545− D.map unsafeFreeze $ MA.compactGE n $ D.map unsafeThaw stream
546−
547−-- | Like 'compactGE' but for transforming folds instead of stream.
548−--
549−-- >>> lCompactGE n = Fold.many (Array.fCompactGE n)
550−--
551−-- Generates unpinned arrays irrespective of the pinning status of input
552−-- arrays.
553−{-# INLINE_NORMAL lCompactGE #-}
554−lCompactGE :: (MonadIO m, Unbox a)
555− => Int -> Fold m (Array a) () -> Fold m (Array a) ()
556−lCompactGE n fld =
557− Fold.lmap unsafeThaw $ MA.lCompactGE n (Fold.lmap unsafeFreeze fld)
558−
559−-- | Pinned version of 'lCompactGE'.
560−{-# INLINE_NORMAL lPinnedCompactGE #-}
561−lPinnedCompactGE :: (MonadIO m, Unbox a)
562− => Int -> Fold m (Array a) () -> Fold m (Array a) ()
563−lPinnedCompactGE n fld =
564− Fold.lmap unsafeThaw $ MA.lPinnedCompactGE n (Fold.lmap unsafeFreeze fld)
565−
566−-------------------------------------------------------------------------------
567−-- Splitting
568−-------------------------------------------------------------------------------
373+flattenArraysRev = MA.flattenArraysRev . D.map unsafeThaw
569374
570375-- Drops the separator byte
571376{-# INLINE breakOn #-}
@@ -609,68 +414,24 @@ byteLength = MA.byteLength . unsafeThaw
609414length :: Unbox a => Array a -> Int
610415length arr = MA.length (unsafeThaw arr)
611416
612−{-# INLINE_NORMAL producer #-}
613−producer :: forall m a. (Monad m, Unbox a) => Producer m (Array a) a
614−producer =
615− Producer.translate unsafeThaw unsafeFreeze
616− $ MA.producerWith (return . unsafeInlineIO)
617−
618−-- | Unfold an array into a stream.
619−--
620−{-# INLINE_NORMAL reader #-}
621−reader :: forall m a. (Monad m, Unbox a) => Unfold m (Array a) a
622−reader = Producer.simplify producer
623−
624−-- | Unfold an array into a stream, does not check the end of the array, the
625−-- user is responsible for terminating the stream within the array bounds. For
626−-- high performance application where the end condition can be determined by
627−-- a terminating fold.
628−--
629−-- Written in the hope that it may be faster than "read", however, in the case
630−-- for which this was written, "read" proves to be faster even though the core
631−-- generated with unsafeRead looks simpler.
632−--
633−-- /Pre-release/
634−--
635−{-# INLINE_NORMAL readerUnsafe #-}
636−readerUnsafe :: forall m a. (Monad m, Unbox a) => Unfold m (Array a) a
637−readerUnsafe = Unfold step inject
638− where
639−
640− inject (Array contents start end) =
641− return (MA.ArrayUnsafe contents end start)
642−
643− {-# INLINE_LATE step #-}
644− step (MA.ArrayUnsafe contents end p) = do
645− -- unsafeInlineIO allows us to run this in Identity monad for pure
646− -- toList/foldr case which makes them much faster due to not
647− -- accumulating the list and fusing better with the pure consumers.
648− --
649− -- This should be safe as the array contents are guaranteed to be
650− -- evaluated/written to before we peek at them.
651− let !x = unsafeInlineIO $ peekAt p contents
652− let !p1 = INDEX_NEXT(p,a)
653− return $ D.Yield x (MA.ArrayUnsafe contents end p1)
654−
655417-- | Unfold an array into a stream in reverse order.
656418--
657419{-# INLINE_NORMAL readerRev #-}
658420readerRev :: forall m a. (Monad m, Unbox a) => Unfold m (Array a) a
659421readerRev = Unfold.lmap unsafeThaw $ MA.readerRevWith (return . unsafeInlineIO)
660422
661−{-# DEPRECATED toStreamD "Please use 'read' instead." #-}
662423{-# INLINE_NORMAL toStreamD #-}
663424toStreamD :: forall m a. (Monad m, Unbox a) => Array a -> D.Stream m a
664−toStreamD = read
425+toStreamD arr = MA.toStreamDWith (return . unsafeInlineIO) (unsafeThaw arr)
665426
666427{-# INLINE toStreamK #-}
667428toStreamK :: forall m a. (Monad m, Unbox a) => Array a -> K.StreamK m a
668429toStreamK arr = MA.toStreamKWith (return . unsafeInlineIO) (unsafeThaw arr)
669430
670−{-# DEPRECATED toStreamDRev "Please use 'readRev' instead." #-}
671431{-# INLINE_NORMAL toStreamDRev #-}
672432toStreamDRev :: forall m a. (Monad m, Unbox a) => Array a -> D.Stream m a
673−toStreamDRev = readRev
433+toStreamDRev arr =
434+ MA.toStreamDRevWith (return . unsafeInlineIO) (unsafeThaw arr)
674435
675436{-# INLINE toStreamKRev #-}
676437toStreamKRev :: forall m a. (Monad m, Unbox a) => Array a -> K.StreamK m a
@@ -682,7 +443,7 @@ toStreamKRev arr =
682443-- /Pre-release/
683444{-# INLINE_EARLY read #-}
684445read :: (Monad m, Unbox a) => Array a -> Stream m a
685−read arr = MA.toStreamWith (return . unsafeInlineIO) (unsafeThaw arr)
446+read = toStreamD
686447
687448-- | Same as 'read'
688449--
@@ -699,7 +460,7 @@ toStream = read
699460-- /Pre-release/
700461{-# INLINE_EARLY readRev #-}
701462readRev :: (Monad m, Unbox a) => Array a -> Stream m a
702−readRev arr = MA.toStreamRevWith (return . unsafeInlineIO) (unsafeThaw arr)
463+readRev = toStreamDRev
703464
704465-- | Same as 'readRev'
705466--
@@ -723,7 +484,6 @@ foldr f z arr = runIdentity $ D.foldr f z $ toStreamD arr
723484-- | Create two slices of an array without copying the original array. The
724485-- specified index @i@ is the first index of the second slice.
725486--
726−{-# INLINE splitAt #-}
727487splitAt :: Unbox a => Int -> Array a -> (Array a, Array a)
728488splitAt i arr = (unsafeFreeze a, unsafeFreeze b)
729489 where
@@ -757,28 +517,17 @@ toList s = build (\c n -> toListFB c n s)
757517-- Folds
758518-------------------------------------------------------------------------------
759519
760−-- | @createOf n@ folds a maximum of @n@ elements from the input stream to an
520+-- | @writeN n@ folds a maximum of @n@ elements from the input stream to an
761521-- 'Array'.
762522--
763−{-# INLINE_NORMAL createOf #-}
764−createOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
765−createOf = fmap unsafeFreeze . MA.createOf
766−
767−-- XXX Deprecate in major
768−-- {-# DEPRECATED writeN "Please use createOf instead." #-}
769−{-# INLINE writeN #-}
523+{-# INLINE_NORMAL writeN #-}
770524writeN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
771−writeN = createOf
772−
773−-- | Like 'createOf' but creates a pinned array.
774−{-# INLINE_NORMAL pinnedCreateOf #-}
775−pinnedCreateOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
776−pinnedCreateOf = fmap unsafeFreeze . MA.pinnedCreateOf
525+writeN = fmap unsafeFreeze . MA.writeN
777526
778−{-# DEPRECATED pinnedWriteN "Please use pinnedCreateOf instead." #-}
779−{-# INLINE pinnedWriteN #-}
527+-- | Like 'fromListN' but creates a pinned array.
528+{-# INLINE_NORMAL pinnedWriteN #-}
780529pinnedWriteN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
781−pinnedWriteN = pinnedCreateOf
530+pinnedWriteN = fmap unsafeFreeze . MA.pinnedWriteN
782531
783532-- | @pinnedWriteNAligned alignment n@ folds a maximum of @n@ elements from the input
784533-- stream to an 'Array' aligned to the given size.
@@ -786,74 +535,44 @@ pinnedWriteN = pinnedCreateOf
786535-- /Pre-release/
787536--
788537{-# INLINE_NORMAL pinnedWriteNAligned #-}
789−{-# DEPRECATED pinnedWriteNAligned "To be removed." #-}
790538pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a)
791539 => Int -> Int -> Fold m a (Array a)
792540pinnedWriteNAligned alignSize = fmap unsafeFreeze . MA.pinnedWriteNAligned alignSize
793541
794−-- | Like 'createOf' but does not check the array bounds when writing. The fold
542+-- | Like 'writeN' but does not check the array bounds when writing. The fold
795543-- driver must not call the step function more than 'n' times otherwise it will
796544-- corrupt the memory and crash. This function exists mainly because any
797545-- conditional in the step function blocks fusion causing 10x performance
798546-- slowdown.
799547--
800−{-# INLINE_NORMAL unsafeCreateOf #-}
801−unsafeCreateOf :: forall m a. (MonadIO m, Unbox a)
802− => Int -> Fold m a (Array a)
803−unsafeCreateOf n = unsafeFreeze <$> MA.unsafeCreateOf n
804−
805−{-# DEPRECATED writeNUnsafe "Please use unsafeCreateOf instead." #-}
806−{-# INLINE writeNUnsafe #-}
548+{-# INLINE_NORMAL writeNUnsafe #-}
807549writeNUnsafe :: forall m a. (MonadIO m, Unbox a)
808550 => Int -> Fold m a (Array a)
809−writeNUnsafe = unsafeCreateOf
551+writeNUnsafe n = unsafeFreeze <$> MA.writeNUnsafe n
810552
811−{-# INLINE_NORMAL unsafePinnedCreateOf #-}
812−unsafePinnedCreateOf :: forall m a. (MonadIO m, Unbox a)
813− => Int -> Fold m a (Array a)
814−unsafePinnedCreateOf n = unsafeFreeze <$> MA.unsafePinnedCreateOf n
815−
816−{-# DEPRECATED pinnedWriteNUnsafe "Please use unsafePinnedCreateOf instead." #-}
817−{-# INLINE pinnedWriteNUnsafe #-}
553+{-# INLINE_NORMAL pinnedWriteNUnsafe #-}
818554pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a)
819555 => Int -> Fold m a (Array a)
820−pinnedWriteNUnsafe = unsafePinnedCreateOf
556+pinnedWriteNUnsafe n = unsafeFreeze <$> MA.pinnedWriteNUnsafe n
821557
822−{-# INLINE_NORMAL createWith #-}
823−createWith :: forall m a. (MonadIO m, Unbox a)
824− => Int -> Fold m a (Array a)
825−-- createWith n = FL.rmapM spliceArrays $ toArraysOf n
826−createWith elemCount = unsafeFreeze <$> MA.createWith elemCount
827−
828−{-# DEPRECATED writeWith "Please use createWith instead." #-}
829−{-# INLINE writeWith #-}
558+{-# INLINE_NORMAL writeWith #-}
830559writeWith :: forall m a. (MonadIO m, Unbox a)
831560 => Int -> Fold m a (Array a)
832−writeWith = createWith
561+-- writeWith n = FL.rmapM spliceArrays $ toArraysOf n
562+writeWith elemCount = unsafeFreeze <$> MA.writeWith elemCount
833563
834564-- | Fold the whole input to a single array.
835565--
836566-- /Caution! Do not use this on infinite streams./
837567--
838−{-# INLINE create #-}
839−create :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
840−create = fmap unsafeFreeze MA.create
841−
842−-- XXX Deprecate in major
843−-- {-# DEPRECATED write "Please use create instead." #-}
844568{-# INLINE write #-}
845569write :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
846−write = create
570+write = fmap unsafeFreeze MA.write
847571
848−-- | Like 'create' but creates a pinned array.
849−{-# INLINE pinnedCreate #-}
850−pinnedCreate :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
851−pinnedCreate = fmap unsafeFreeze MA.pinnedCreate
852−
853−{-# DEPRECATED pinnedWrite "Please use pinnedCreate instead." #-}
572+-- | Like 'write' but creates a pinned array.
854573{-# INLINE pinnedWrite #-}
855574pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
856−pinnedWrite = pinnedCreate
575+pinnedWrite = fmap unsafeFreeze MA.pinnedWrite
857576
858577-- | Fold "step" has a dependency on "initial", and each step is dependent on
859578-- the previous invocation of step due to state passing, finally extract
@@ -885,11 +604,6 @@ unsafeMakePure (Fold step initial extract final) =
885604 (\s -> return $! unsafeInlineIO $ extract s)
886605 (\s -> return $! unsafeInlineIO $ final s)
887606
888−{-# INLINE fromPureStreamN #-}
889−fromPureStreamN :: Unbox a => Int -> Stream Identity a -> Array a
890−fromPureStreamN n x =
891− unsafePerformIO $ fmap unsafeFreeze (MA.fromPureStreamN n x)
892−
893607-- | Convert a pure stream in Identity monad to an immutable array.
894608--
895609-- Same as the following but with better performance:
@@ -901,19 +615,6 @@ fromPureStream x = unsafePerformIO $ fmap (unsafeFreeze) (MA.fromPureStream x)
901615-- fromPureStream = runIdentity . D.fold (unsafeMakePure write)
902616-- fromPureStream = fromList . runIdentity . D.toList
903617
904−-- XXX This should be monadic.
905−
906−-- | Copy an immutable 'Ptr Word8' sequence into an array.
907−--
908−-- /Unsafe:/ The caller is responsible for safe addressing.
909−--
910−-- Note that this should be evaluated strictly to ensure that we do not hold
911−-- the reference to the pointer in a lazy thunk.
912−fromPtrN :: Int -> Ptr Word8 -> Array Word8
913−fromPtrN n addr = unsafePerformIO $ fmap unsafeFreeze (MA.fromPtrN n addr)
914−
915−-- XXX This should be monadic.
916−
917618-- | Copy a null terminated immutable 'Addr#' Word8 sequence into an array.
918619--
919620-- /Unsafe:/ The caller is responsible for safe addressing.
@@ -924,46 +625,8 @@ fromPtrN n addr = unsafePerformIO $ fmap unsafeFreeze (MA.fromPtrN n addr)
924625-- >>> Array.toList $ Array.fromByteStr# "\1\2\3\0"#
925626-- [1,2,3]
926627--
927−-- Note that this should be evaluated strictly to ensure that we do not hold
928−-- the reference to the pointer in a lazy thunk.
929628fromByteStr# :: Addr# -> Array Word8
930−fromByteStr# addr = unsafePerformIO $ fmap unsafeFreeze (MA.fromByteStr# addr)
931−
932−-- XXX This should be monadic.
933−
934−-- | Note that this should be evaluated strictly to ensure that we do not hold
935−-- the reference to the pointer in a lazy thunk.
936−fromByteStr :: Ptr Word8 -> Array Word8
937−fromByteStr (Ptr addr#) = fromByteStr# addr#
938−
939−-- XXX implement fromChunks/fromChunkList instead?
940−
941−-- | Convert an array stream to an array. Note that this requires peak memory
942−-- that is double the size of the array stream.
943−--
944−{-# INLINE fromChunksK #-}
945−fromChunksK :: (MonadIO m, Unbox a) => StreamK m (Array a) -> m (Array a)
946−fromChunksK stream =
947− -- We buffer the entire stream and then allocate the target array of the
948− -- same size, thus requiring double the memory.
949− fmap unsafeFreeze $ MA.fromChunksK $ fmap unsafeThaw stream
950−
951−{-# DEPRECATED fromArrayStreamK "Please use fromChunksK instead." #-}
952−fromArrayStreamK :: (Unbox a, MonadIO m) => StreamK m (Array a) -> m (Array a)
953−fromArrayStreamK = fromChunksK
954−
955−-- | Given a stream of arrays, splice them all together to generate a single
956−-- array. The stream must be /finite/.
957−--
958−{-# INLINE fromChunks #-}
959−fromChunks :: (MonadIO m, Unbox a) => Stream m (Array a) -> m (Array a)
960−fromChunks s =
961− -- XXX Check which implementation is better
962− -- This may also require double the memory as we double the space every
963− -- time, when copying the last array we may have reallocated almost double
964− -- the space required before we right size it.
965− fmap unsafeFreeze $ MA.fromChunksRealloced (fmap unsafeThaw s)
966− -- fromChunkStreamK $ D.toStreamK s
629+fromByteStr# addr = fromPureStream (D.fromByteStr# addr)
967630
968631-------------------------------------------------------------------------------
969632-- Instances
@@ -995,66 +658,12 @@ instance Unbox a => IsList (Array a) where
995658 {-# INLINE toList #-}
996659 toList = toList
997660
998−-- | Byte compare two arrays. Compare the length of the arrays. If the length
999−-- is equal, compare the lexicographical ordering of two underlying byte arrays
1000−-- otherwise return the result of length comparison.
1001−--
1002−-- /Unsafe/: Note that the 'Unbox' instance of sum types with constructors of
1003−-- different sizes may leave some memory uninitialized which can make byte
1004−-- comparison unreliable.
1005−--
1006−-- /Pre-release/
1007−{-# INLINE byteCmp #-}
1008−byteCmp :: Array a -> Array a -> Ordering
1009−byteCmp arr1 arr2 =
1010− -- unsafePerformIO?
1011− unsafeInlineIO $! unsafeThaw arr1 `MA.byteCmp` unsafeThaw arr2
1012−
1013−-- | Byte equality of two arrays.
1014−--
1015−-- >>> byteEq arr1 arr2 = (==) EQ $ Array.byteCmp arr1 arr2
1016−--
1017−-- /Unsafe/: See 'byteCmp'.
1018−{-# INLINE byteEq #-}
1019−byteEq :: Array a -> Array a -> Bool
1020−byteEq arr1 arr2 = (==) EQ $ byteCmp arr1 arr2
1021−
1022−#define MK_EQ_INSTANCE(typ) \
1023−instance {-# OVERLAPPING #-} Eq (Array typ) where { \
1024−; {-# INLINE (==) #-} \
1025−; (==) = byteEq \
1026−}
1027−
1028−MK_EQ_INSTANCE(Char)
1029−MK_EQ_INSTANCE(Word8)
1030−MK_EQ_INSTANCE(Word16)
1031−MK_EQ_INSTANCE(Word32)
1032−
1033−-- XXX The Word64 default instance should be as fast because we are comparing
1034−-- 64-bit at a time.
1035−MK_EQ_INSTANCE(Word64)
1036−MK_EQ_INSTANCE(Int)
1037−MK_EQ_INSTANCE(Int8)
1038−MK_EQ_INSTANCE(Int16)
1039−MK_EQ_INSTANCE(Int32)
1040−
1041−-- XXX The Int64 default instance should be as fast.
1042−MK_EQ_INSTANCE(Int64)
1043−
1044−-- | If the type allows a byte-by-byte comparison this instance can be
1045−-- overlapped by a more specific instance that uses 'byteCmp'. Byte comparison
1046−-- can be significantly faster.
1047−--
1048−instance {-# OVERLAPPABLE #-} (Unbox a, Eq a) => Eq (Array a) where
661+-- XXX we are assuming that Unboxed equality means element equality. This may
662+-- or may not be correct? arrcmp is 40% faster compared to stream equality.
663+instance (Unbox a, Eq a) => Eq (Array a) where
1049664 {-# INLINE (==) #-}
1050665 arr1 == arr2 =
1051− -- Does unboxed byte equality mean element equality?
1052− -- XXX This is incorrect for sum types, as we may have some
1053− -- uninitialized memory in that case. If we always initialize the
1054− -- unused memory to zero we can use this.
1055− -- Byte comparison is 40% faster compared to stream equality.
1056− -- (==) EQ $ unsafeInlineIO $! unsafeThaw arr1 `MA.cmp` unsafeThaw arr2
1057− (toStreamD arr1 :: Stream Identity a) == toStreamD arr2
666+ (==) EQ $ unsafeInlineIO $! unsafeThaw arr1 `MA.cmp` unsafeThaw arr2
1058667
1059668instance (Unbox a, Ord a) => Ord (Array a) where
1060669 {-# INLINE compare #-}
@@ -1119,29 +728,15 @@ instance Foldable Array where
1119728-- Semigroup and Monoid
1120729-------------------------------------------------------------------------------
1121730
1122−-- XXX Deprecate and remove the Semigroup and Monoid instances because of
1123−-- potential misuse chances.
1124−
1125−-- | This should not be used for combining many or N arrays as it would copy
1126−-- the two arrays everytime to a new array. For coalescing multiple arrays use
1127−-- 'fromChunksK' instead.
1128731instance Unbox a => Semigroup (Array a) where
1129732 arr1 <> arr2 = unsafePerformIO $ splice arr1 arr2
1130733
1131−empty ::
1132−#ifdef DEVBUILD
1133− Unbox a =>
1134−#endif
1135− Array a
1136−empty = Array Unboxed.empty 0 0
1137−
1138−{-# DEPRECATED nil "Please use empty instead." #-}
1139734nil ::
1140735#ifdef DEVBUILD
1141736 Unbox a =>
1142737#endif
1143738 Array a
1144−nil = empty
739+nil = Array Unboxed.nil 0 0
1145740
1146741instance Unbox a => Monoid (Array a) where
1147742 mempty = nil
core/src/Streamly/Internal/Data/Fold/Combinators.hs+92
@@ -30,6 +30,8 @@ module Streamly.Internal.Data.Fold.Combinators
3030 -- *** Reducers
3131 , drainMapM
3232 , the
33+ , length
34+ , lengthGeneric
3335 , mean
3436 , rollingHash
3537 , defaultSalt
@@ -164,6 +166,8 @@ module Streamly.Internal.Data.Fold.Combinators
164166 -- ** Trimming
165167
166168 -- By elements
169+ , takeEndBy
170+ , takeEndBy_
167171 , takeEndBySeq
168172 , takeEndBySeq_
169173 {-
@@ -705,6 +709,30 @@ the = foldt' step initial id
705709-- To Summary
706710------------------------------------------------------------------------------
707711
712+-- | Like 'length', except with a more general 'Num' return value
713+--
714+-- Definition:
715+--
716+-- >>> lengthGeneric = fmap getSum $ Fold.foldMap (Sum . const 1)
717+-- >>> lengthGeneric = Fold.foldl' (\n _ -> n + 1) 0
718+--
719+-- /Pre-release/
720+{-# INLINE lengthGeneric #-}
721+lengthGeneric :: (Monad m, Num b) => Fold m a b
722+lengthGeneric = foldl' (\n _ -> n + 1) 0
723+
724+-- | Determine the length of the input stream.
725+--
726+-- Definition:
727+--
728+-- >>> length = Fold.lengthGeneric
729+-- >>> length = fmap getSum $ Fold.foldMap (Sum . const 1)
730+--
731+{-# INLINE length #-}
732+length :: Monad m => Fold m a Int
733+length = lengthGeneric
734+
735+
708736-- | Determine the sum of all elements of a stream of numbers. Returns additive
709737-- identity (@0@) when the stream is empty. Note that this is not numerically
710738-- stable for floating point numbers.
@@ -1482,6 +1510,70 @@ droppingWhileM p = Fold step initial extract extract
14821510droppingWhile :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
14831511droppingWhile p = droppingWhileM (return . p)
14841512
1513+-- Note: Keep this consistent with S.splitOn. In fact we should eliminate
1514+-- S.splitOn in favor of the fold.
1515+--
1516+-- XXX Use Fold.many instead once it is fixed.
1517+-- > Stream.splitOnSuffix p f = Stream.foldMany (Fold.takeEndBy_ p f)
1518+
1519+-- | Like 'takeEndBy' but drops the element on which the predicate succeeds.
1520+--
1521+-- Example:
1522+--
1523+-- >>> input = Stream.fromList "hello\nthere\n"
1524+-- >>> line = Fold.takeEndBy_ (== '\n') Fold.toList
1525+-- >>> Stream.fold line input
1526+-- "hello"
1527+--
1528+-- >>> Stream.fold Fold.toList $ Stream.foldMany line input
1529+-- ["hello","there"]
1530+--
1531+{-# INLINE takeEndBy_ #-}
1532+takeEndBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
1533+-- takeEndBy_ predicate = scanMaybe (takingEndBy_ predicate)
1534+takeEndBy_ predicate (Fold fstep finitial fextract ffinal) =
1535+ Fold step finitial fextract ffinal
1536+
1537+ where
1538+
1539+ step s a =
1540+ if not (predicate a)
1541+ then fstep s a
1542+ else Done <$> ffinal s
1543+
1544+-- Note:
1545+-- > Stream.splitWithSuffix p f = Stream.foldMany (Fold.takeEndBy p f)
1546+
1547+-- | Take the input, stop when the predicate succeeds taking the succeeding
1548+-- element as well.
1549+--
1550+-- Example:
1551+--
1552+-- >>> input = Stream.fromList "hello\nthere\n"
1553+-- >>> line = Fold.takeEndBy (== '\n') Fold.toList
1554+-- >>> Stream.fold line input
1555+-- "hello\n"
1556+--
1557+-- >>> Stream.fold Fold.toList $ Stream.foldMany line input
1558+-- ["hello\n","there\n"]
1559+--
1560+{-# INLINE takeEndBy #-}
1561+takeEndBy :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
1562+-- takeEndBy predicate = scanMaybe (takingEndBy predicate)
1563+takeEndBy predicate (Fold fstep finitial fextract ffinal) =
1564+ Fold step finitial fextract ffinal
1565+
1566+ where
1567+
1568+ step s a = do
1569+ res <- fstep s a
1570+ if not (predicate a)
1571+ then return res
1572+ else do
1573+ case res of
1574+ Partial s1 -> Done <$> ffinal s1
1575+ Done b -> return $ Done b
1576+
14851577------------------------------------------------------------------------------
14861578-- Binary splitting on a separator
14871579------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Fold/Type.hs−91
@@ -367,8 +367,6 @@ module Streamly.Internal.Data.Fold.Type
367367 , toList
368368 , toStreamK
369369 , toStreamKRev
370− , lengthGeneric
371− , length
372370
373371 -- * Combinators
374372
@@ -393,8 +391,6 @@ module Streamly.Internal.Data.Fold.Type
393391 -- ** Trimming
394392 , take
395393 , taking
396− , takeEndBy_
397− , takeEndBy
398394 , dropping
399395
400396 -- ** Sequential application
@@ -771,29 +767,6 @@ toStreamKRev = foldl' (flip K.cons) K.nil
771767toStreamK :: Monad m => Fold m a (K.StreamK n a)
772768toStreamK = foldr K.cons K.nil
773769
774−-- | Like 'length', except with a more general 'Num' return value
775−--
776−-- Definition:
777−--
778−-- >>> lengthGeneric = fmap getSum $ Fold.foldMap (Sum . const 1)
779−-- >>> lengthGeneric = Fold.foldl' (\n _ -> n + 1) 0
780−--
781−-- /Pre-release/
782−{-# INLINE lengthGeneric #-}
783−lengthGeneric :: (Monad m, Num b) => Fold m a b
784−lengthGeneric = foldl' (\n _ -> n + 1) 0
785−
786−-- | Determine the length of the input stream.
787−--
788−-- Definition:
789−--
790−-- >>> length = Fold.lengthGeneric
791−-- >>> length = fmap getSum $ Fold.foldMap (Sum . const 1)
792−--
793−{-# INLINE length #-}
794−length :: Monad m => Fold m a Int
795−length = lengthGeneric
796−
797770------------------------------------------------------------------------------
798771-- Instances
799772------------------------------------------------------------------------------
@@ -1544,70 +1517,6 @@ take n (Fold fstep finitial fextract ffinal) = Fold step initial extract final
15441517
15451518 final (Tuple'Fused _ r) = ffinal r
15461519
1547−-- Note: Keep this consistent with S.splitOn. In fact we should eliminate
1548−-- S.splitOn in favor of the fold.
1549−--
1550−-- XXX Use Fold.many instead once it is fixed.
1551−-- > Stream.splitOnSuffix p f = Stream.foldMany (Fold.takeEndBy_ p f)
1552−
1553−-- | Like 'takeEndBy' but drops the element on which the predicate succeeds.
1554−--
1555−-- Example:
1556−--
1557−-- >>> input = Stream.fromList "hello\nthere\n"
1558−-- >>> line = Fold.takeEndBy_ (== '\n') Fold.toList
1559−-- >>> Stream.fold line input
1560−-- "hello"
1561−--
1562−-- >>> Stream.fold Fold.toList $ Stream.foldMany line input
1563−-- ["hello","there"]
1564−--
1565−{-# INLINE takeEndBy_ #-}
1566−takeEndBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
1567−-- takeEndBy_ predicate = scanMaybe (takingEndBy_ predicate)
1568−takeEndBy_ predicate (Fold fstep finitial fextract ffinal) =
1569− Fold step finitial fextract ffinal
1570−
1571− where
1572−
1573− step s a =
1574− if not (predicate a)
1575− then fstep s a
1576− else Done <$> ffinal s
1577−
1578−-- Note:
1579−-- > Stream.splitWithSuffix p f = Stream.foldMany (Fold.takeEndBy p f)
1580−
1581−-- | Take the input, stop when the predicate succeeds taking the succeeding
1582−-- element as well.
1583−--
1584−-- Example:
1585−--
1586−-- >>> input = Stream.fromList "hello\nthere\n"
1587−-- >>> line = Fold.takeEndBy (== '\n') Fold.toList
1588−-- >>> Stream.fold line input
1589−-- "hello\n"
1590−--
1591−-- >>> Stream.fold Fold.toList $ Stream.foldMany line input
1592−-- ["hello\n","there\n"]
1593−--
1594−{-# INLINE takeEndBy #-}
1595−takeEndBy :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
1596−-- takeEndBy predicate = scanMaybe (takingEndBy predicate)
1597−takeEndBy predicate (Fold fstep finitial fextract ffinal) =
1598− Fold step finitial fextract ffinal
1599−
1600− where
1601−
1602− step s a = do
1603− res <- fstep s a
1604− if not (predicate a)
1605− then return res
1606− else do
1607− case res of
1608− Partial s1 -> Done <$> ffinal s1
1609− Done b -> return $ Done b
1610−
16111520------------------------------------------------------------------------------
16121521-- Nesting
16131522------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/IsMap.hs−4
@@ -1,7 +1,3 @@
1−{-# LANGUAGE TypeFamilies #-}
2−-- Must come after TypeFamilies, otherwise it is re-enabled.
3−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
4−{-# LANGUAGE NoMonoLocalBinds #-}
51-- |
62-- Module : Streamly.Internal.Data.IsMap
73-- Copyright : (c) 2022 Composewell Technologies
core/src/Streamly/Internal/Data/MutArray.hs+35−151
@@ -11,197 +11,81 @@ module Streamly.Internal.Data.MutArray
1111 -- * MutArray.Type module
1212 module Streamly.Internal.Data.MutArray.Type
1313 -- * MutArray module
14− , sliceIndexerFromLen
15− , slicerFromLen
16− , compactLE
17− , pinnedCompactLE
18− , compactOnByte
19− , compactOnByteSuffix
20− -- * Unboxed IORef
21− , module Streamly.Internal.Data.IORef.Unboxed
22−
23− -- * Deprecated
14+ , splitOn
2415 , genSlicesFromLen
2516 , getSlicesFromLen
17+ , fromStream
18+ -- * Unboxed IORef
19+ , module Streamly.Internal.Data.IORef.Unboxed
2620 )
2721where
2822
2923#include "inline.hs"
3024
3125import Control.Monad.IO.Class (MonadIO(..))
32−import Data.Word (Word8)
33−import Streamly.Internal.Data.MutByteArray.Type (PinnedState(..))
34−import Streamly.Internal.Data.Stream.Type (Stream)
3526import Streamly.Internal.Data.Unbox (Unbox)
27+import Streamly.Internal.Data.Stream (Stream)
3628import Streamly.Internal.Data.Unfold.Type (Unfold(..))
3729
38−import qualified Streamly.Internal.Data.Stream.Type as Stream
39−import qualified Streamly.Internal.Data.Stream.Nesting as Stream
40−-- import qualified Streamly.Internal.Data.Stream.Transform as Stream
30+import qualified Streamly.Internal.Data.Stream as D
4131import qualified Streamly.Internal.Data.Unfold as Unfold
4232
4333import Prelude hiding (foldr, length, read, splitAt)
4434import Streamly.Internal.Data.MutArray.Type
4535import Streamly.Internal.Data.IORef.Unboxed
4636
37+-- | Split the array into a stream of slices using a predicate. The element
38+-- matching the predicate is dropped.
39+--
40+-- /Pre-release/
41+{-# INLINE splitOn #-}
42+splitOn :: (MonadIO m, Unbox a) =>
43+ (a -> Bool) -> MutArray a -> Stream m (MutArray a)
44+splitOn predicate arr =
45+ fmap (\(i, len) -> getSliceUnsafe i len arr)
46+ $ D.sliceOnSuffix predicate (read arr)
47+
4748-- | Generate a stream of array slice descriptors ((index, len)) of specified
4849-- length from an array, starting from the supplied array index. The last slice
4950-- may be shorter than the requested length depending on the array length.
5051--
5152-- /Pre-release/
52−{-# INLINE sliceIndexerFromLen #-}
53−sliceIndexerFromLen :: forall m a. (Monad m, Unbox a)
53+{-# INLINE genSlicesFromLen #-}
54+genSlicesFromLen :: forall m a. (Monad m, Unbox a)
5455 => Int -- ^ from index
5556 -> Int -- ^ length of the slice
5657 -> Unfold m (MutArray a) (Int, Int)
57−sliceIndexerFromLen from len =
58+genSlicesFromLen from len =
5859 let fromThenTo n = (from, from + len, n - 1)
5960 mkSlice n i = return (i, min len (n - i))
6061 in Unfold.lmap length
6162 $ Unfold.mapM2 mkSlice
6263 $ Unfold.lmap fromThenTo Unfold.enumerateFromThenTo
6364
64−{-# DEPRECATED genSlicesFromLen "Please use sliceIndexerFromLen instead." #-}
65−genSlicesFromLen :: forall m a. (Monad m, Unbox a)
66− => Int -- ^ from index
67− -> Int -- ^ length of the slice
68− -> Unfold m (MutArray a) (Int, Int)
69−genSlicesFromLen = sliceIndexerFromLen
70−
7165-- | Generate a stream of slices of specified length from an array, starting
7266-- from the supplied array index. The last slice may be shorter than the
7367-- requested length depending on the array length.
7468--
7569-- /Pre-release/
76−{-# INLINE slicerFromLen #-}
77−slicerFromLen :: forall m a. (Monad m, Unbox a)
78− => Int -- ^ from index
79− -> Int -- ^ length of the slice
80− -> Unfold m (MutArray a) (MutArray a)
81−slicerFromLen from len =
82− let mkSlice arr (i, n) = return $ getSliceUnsafe i n arr
83− in Unfold.mapM2 mkSlice (sliceIndexerFromLen from len)
84−
85−{-# DEPRECATED getSlicesFromLen "Please use slicerFromLen instead." #-}
70+{-# INLINE getSlicesFromLen #-}
8671getSlicesFromLen :: forall m a. (Monad m, Unbox a)
8772 => Int -- ^ from index
8873 -> Int -- ^ length of the slice
8974 -> Unfold m (MutArray a) (MutArray a)
90−getSlicesFromLen = slicerFromLen
91−
92−-------------------------------------------------------------------------------
93−-- Compacting Streams of Arrays
94−-------------------------------------------------------------------------------
75+getSlicesFromLen from len =
76+ let mkSlice arr (i, n) = return $ getSliceUnsafe i n arr
77+ in Unfold.mapM2 mkSlice (genSlicesFromLen from len)
9578
96−-- | @compactLE maxElems@ coalesces adjacent arrays in the input stream
97−-- only if the combined size would be less than or equal to @maxElems@
98−-- elements. Note that it won't split an array if the original array is already
99−-- larger than maxElems.
79+-- | Create an 'Array' from a stream. This is useful when we want to create a
80+-- single array from a stream of unknown size. 'writeN' is at least twice
81+-- as efficient when the size is already known.
10082--
101−-- @maxElems@ must be greater than 0.
83+-- Note that if the input stream is too large memory allocation for the array
84+-- may fail. When the stream size is not known, `chunksOf` followed by
85+-- processing of indvidual arrays in the resulting stream should be preferred.
10286--
103−-- Generates unpinned arrays irrespective of the pinning status of input
104−-- arrays.
105−{-# INLINE compactLE #-}
106−compactLE :: (MonadIO m, Unbox a) =>
107− Int -> Stream m (MutArray a) -> Stream m (MutArray a)
108−-- XXX compactLE can be moved to MutArray/Type if we are not using the parser
109−-- to implement it.
110−compactLE = compactLeAs Unpinned
111−-- The parser version turns out to be a little bit slower.
112−-- compactLE n = Stream.catRights . Stream.parseManyD (pCompactLE n)
113−
114−-- | Pinned version of 'compactLE'.
115−{-# INLINE pinnedCompactLE #-}
116−pinnedCompactLE :: forall m a. (MonadIO m, Unbox a)
117− => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
118−pinnedCompactLE = compactLeAs Pinned
119−-- pinnedCompactLE n = Stream.catRights . Stream.parseManyD (pPinnedCompactLE n)
120−
121−data SplitState s arr
122− = Initial s
123− | Buffering s arr
124− | Splitting s arr
125− | Yielding arr (SplitState s arr)
126− | Finishing
127−
128−-- | Split a stream of arrays on a given separator byte, dropping the separator
129−-- and coalescing all the arrays between two separators into a single array.
130−--
131−{-# INLINE_NORMAL _compactOnByteCustom #-}
132−_compactOnByteCustom
133− :: MonadIO m
134− => Word8
135− -> Stream m (MutArray Word8)
136− -> Stream m (MutArray Word8)
137−_compactOnByteCustom byte (Stream.Stream step state) =
138− Stream.Stream step' (Initial state)
139−
140− where
141−
142− {-# INLINE_LATE step' #-}
143− step' gst (Initial st) = do
144− r <- step gst st
145− case r of
146− Stream.Yield arr s -> do
147− (arr1, marr2) <- breakOn byte arr
148− return $ case marr2 of
149− Nothing -> Stream.Skip (Buffering s arr1)
150− Just arr2 -> Stream.Skip (Yielding arr1 (Splitting s arr2))
151− Stream.Skip s -> return $ Stream.Skip (Initial s)
152− Stream.Stop -> return Stream.Stop
153−
154− step' gst (Buffering st buf) = do
155− r <- step gst st
156− case r of
157− Stream.Yield arr s -> do
158− (arr1, marr2) <- breakOn byte arr
159− -- XXX Use spliceExp instead and then rightSize?
160− buf1 <- splice buf arr1
161− return $ case marr2 of
162− Nothing -> Stream.Skip (Buffering s buf1)
163− Just x -> Stream.Skip (Yielding buf1 (Splitting s x))
164− Stream.Skip s -> return $ Stream.Skip (Buffering s buf)
165− Stream.Stop -> return $
166− if byteLength buf == 0
167− then Stream.Stop
168− else Stream.Skip (Yielding buf Finishing)
169−
170− step' _ (Splitting st buf) = do
171− (arr1, marr2) <- breakOn byte buf
172− return $ case marr2 of
173− Nothing -> Stream.Skip $ Buffering st arr1
174− Just arr2 -> Stream.Skip $ Yielding arr1 (Splitting st arr2)
175−
176− step' _ (Yielding arr next) = return $ Stream.Yield arr next
177− step' _ Finishing = return Stream.Stop
178−
179−-- XXX implement predicate based version of this
180−-- XXX Naming of predicate based vs custom version
181−
182−-- | Split a stream of arrays on a given separator byte, dropping the separator
183−-- and coalescing all the arrays between two separators into a single array.
184−--
185−{-# INLINE compactOnByte #-}
186−compactOnByte
187− :: (MonadIO m)
188− => Word8
189− -> Stream m (MutArray Word8)
190− -> Stream m (MutArray Word8)
191−-- XXX compare perf of custom vs idiomatic version
192−-- compactOnByte = _compactOnByteCustom
193−-- XXX use spliceExp and rightSize?
194−compactOnByte byte = Stream.splitInnerBy (breakOn byte) splice
195−
196−-- | Like 'compactOnByte' considers the separator in suffix position instead of
197−-- infix position.
198−{-# INLINE compactOnByteSuffix #-}
199−compactOnByteSuffix
200− :: (MonadIO m)
201− => Word8
202− -> Stream m (MutArray Word8)
203− -> Stream m (MutArray Word8)
204−compactOnByteSuffix byte =
205− -- XXX use spliceExp and rightSize?
206− Stream.splitInnerBySuffix
207− (\arr -> byteLength arr == 0) (breakOn byte) splice
87+-- /Pre-release/
88+{-# INLINE fromStream #-}
89+fromStream :: (MonadIO m, Unbox a) => Stream m a -> m (MutArray a)
90+fromStream = fromStreamD
91+-- fromStream (Stream m) = P.fold write m
core/src/Streamly/Internal/Data/MutArray/Generic.hs+30−65
@@ -19,14 +19,14 @@ module Streamly.Internal.Data.MutArray.Generic
1919 , nil
2020
2121 -- *** Uninitialized Arrays
22− , emptyOf
22+ , new
2323 -- , newArrayWith
2424
2525 -- *** From streams
26− , unsafeCreateOf
27− , createOf
28− , createWith -- createOfMin/createMin/createGE?
29− , create
26+ , writeNUnsafe
27+ , writeN
28+ , writeWith
29+ , write
3030 , fromStreamN
3131 , fromStream
3232 , fromPureStream
@@ -160,13 +160,6 @@ module Streamly.Internal.Data.MutArray.Generic
160160 -- , appendSliceFrom
161161
162162 , clone
163−
164− -- * Deprecated
165− , new
166− , writeNUnsafe
167− , writeN
168− , writeWith
169− , write
170163 )
171164where
172165
@@ -243,13 +236,13 @@ bottomElement =
243236-- XXX Would be nice if GHC can provide something like newUninitializedArray# so
244237-- that we do not have to write undefined or error in the whole array.
245238
246−-- | @emptyOf count@ allocates a zero length array that can be extended to hold
239+-- | @new count@ allocates a zero length array that can be extended to hold
247240-- up to 'count' items without reallocating.
248241--
249242-- /Pre-release/
250−{-# INLINE emptyOf #-}
251−emptyOf :: MonadIO m => Int -> m (MutArray a)
252−emptyOf n@(I# n#) =
243+{-# INLINE new #-}
244+new :: MonadIO m => Int -> m (MutArray a)
245+new n@(I# n#) =
253246 liftIO
254247 $ IO
255248 $ \s# ->
@@ -258,12 +251,6 @@ emptyOf n@(I# n#) =
258251 let ma = MutArray arr# 0 0 n
259252 in (# s1#, ma #)
260253
261−-- XXX Deprecate in major
262−-- {-# DEPRECATED new "Please use emptyOf instead." #-}
263−{-# INLINE new #-}
264−new :: MonadIO m => Int -> m (MutArray a)
265−new = emptyOf
266−
267254-- XXX This could be pure?
268255
269256-- |
@@ -331,7 +318,7 @@ putIndices arr = FL.foldlM' step (return ())
331318
332319 where
333320
334− step () (i, x) = putIndex i arr x
321+ step () (i, x) = liftIO (putIndex i arr x)
335322
336323-- | Modify a given index of an array using a modifier function without checking
337324-- the bounds.
@@ -602,16 +589,16 @@ readRev arr@MutArray{..} =
602589arrayChunkSize :: Int
603590arrayChunkSize = 1024
604591
605−-- | Like 'createOf' but does not check the array bounds when writing. The fold
592+-- | Like 'writeN' but does not check the array bounds when writing. The fold
606593-- driver must not call the step function more than 'n' times otherwise it will
607594-- corrupt the memory and crash. This function exists mainly because any
608595-- conditional in the step function blocks fusion causing 10x performance
609596-- slowdown.
610597--
611598-- /Pre-release/
612−{-# INLINE_NORMAL unsafeCreateOf #-}
613−unsafeCreateOf :: MonadIO m => Int -> Fold m a (MutArray a)
614−unsafeCreateOf n = Fold step initial return return
599+{-# INLINE_NORMAL writeNUnsafe #-}
600+writeNUnsafe :: MonadIO m => Int -> Fold m a (MutArray a)
601+writeNUnsafe n = Fold step initial return return
615602
616603 where
617604
@@ -619,81 +606,59 @@ unsafeCreateOf n = Fold step initial return return
619606
620607 step arr x = FL.Partial <$> snocUnsafe arr x
621608
622−{-# DEPRECATED writeNUnsafe "Please use unsafeCreateOf instead." #-}
623−{-# INLINE writeNUnsafe #-}
624−writeNUnsafe :: MonadIO m => Int -> Fold m a (MutArray a)
625−writeNUnsafe = unsafeCreateOf
626−
627−-- | @createOf n@ folds a maximum of @n@ elements from the input stream to an
609+-- | @writeN n@ folds a maximum of @n@ elements from the input stream to an
628610-- 'Array'.
629611--
630−-- >>> createOf n = Fold.take n (MutArray.unsafeCreateOf n)
612+-- >>> writeN n = Fold.take n (MutArray.writeNUnsafe n)
631613--
632614-- /Pre-release/
633−{-# INLINE_NORMAL createOf #-}
634−createOf :: MonadIO m => Int -> Fold m a (MutArray a)
635−createOf n = FL.take n $ unsafeCreateOf n
636−
637−-- XXX Deprecate in major
638−-- {-# DEPRECATED writeN "Please use createOf instead." #-}
639−{-# INLINE writeN #-}
615+{-# INLINE_NORMAL writeN #-}
640616writeN :: MonadIO m => Int -> Fold m a (MutArray a)
641−writeN = createOf
617+writeN n = FL.take n $ writeNUnsafe n
642618
643619-- >>> f n = MutArray.writeAppendWith (* 2) (MutArray.pinnedNew n)
644620-- >>> writeWith n = Fold.rmapM MutArray.rightSize (f n)
645621-- >>> writeWith n = Fold.rmapM MutArray.fromArrayStreamK (MutArray.writeChunks n)
646622
647−-- | @createWith minCount@ folds the whole input to a single array. The array
623+-- | @writeWith minCount@ folds the whole input to a single array. The array
648624-- starts at a size big enough to hold minCount elements, the size is doubled
649625-- every time the array needs to be grown.
650626--
651627-- /Caution! Do not use this on infinite streams./
652628--
653629-- /Pre-release/
654−{-# INLINE_NORMAL createWith #-}
655−createWith :: MonadIO m => Int -> Fold m a (MutArray a)
630+{-# INLINE_NORMAL writeWith #-}
631+writeWith :: MonadIO m => Int -> Fold m a (MutArray a)
656632-- writeWith n = FL.rmapM rightSize $ writeAppendWith (* 2) (pinnedNew n)
657−createWith elemCount = FL.rmapM extract $ FL.foldlM' step initial
633+writeWith elemCount = FL.rmapM extract $ FL.foldlM' step initial
658634
659635 where
660636
661637 initial = do
662− when (elemCount < 0) $ error "createWith: elemCount is negative"
663− new elemCount
638+ when (elemCount < 0) $ error "writeWith: elemCount is negative"
639+ liftIO $ new elemCount
664640
665641 step arr@(MutArray _ start end bound) x
666642 | end == bound = do
667643 let oldSize = end - start
668644 newSize = max (oldSize * 2) 1
669− arr1 <- realloc newSize arr
645+ arr1 <- liftIO $ realloc newSize arr
670646 snocUnsafe arr1 x
671647 step arr x = snocUnsafe arr x
672648
673− -- extract = rightSize
649+ -- extract = liftIO . rightSize
674650 extract = return
675651
676−{-# DEPRECATED writeWith "Please use createWith instead." #-}
677−{-# INLINE writeWith #-}
678−writeWith :: MonadIO m => Int -> Fold m a (MutArray a)
679−writeWith = createWith
680−
681652-- | Fold the whole input to a single array.
682653--
683−-- Same as 'createWith' using an initial array size of 'arrayChunkSize' bytes
654+-- Same as 'writeWith' using an initial array size of 'arrayChunkSize' bytes
684655-- rounded up to the element size.
685656--
686657-- /Caution! Do not use this on infinite streams./
687658--
688−{-# INLINE create #-}
689−create :: MonadIO m => Fold m a (MutArray a)
690−create = writeWith arrayChunkSize
691−
692−-- XXX Deprecate in major
693−-- {-# DEPRECATED write "Please use create instead." #-}
694659{-# INLINE write #-}
695660write :: MonadIO m => Fold m a (MutArray a)
696−write = create
661+write = writeWith arrayChunkSize
697662
698663-- | Create a 'MutArray' from the first @n@ elements of a stream. The
699664-- array is allocated to size @n@, if the stream terminates before @n@
@@ -718,7 +683,7 @@ fromList xs = fromStream $ D.fromList xs
718683{-# INLINABLE fromPureStream #-}
719684fromPureStream :: MonadIO m => Stream Identity a -> m (MutArray a)
720685fromPureStream xs =
721− D.fold write $ D.morphInner (return . runIdentity) xs
686+ liftIO $ D.fold write $ D.morphInner (return . runIdentity) xs
722687
723688-------------------------------------------------------------------------------
724689-- Chunking
@@ -850,7 +815,7 @@ putSliceUnsafe src srcStart dst dstStart len = liftIO $ do
850815
851816{-# INLINE clone #-}
852817clone :: MonadIO m => MutArray a -> m (MutArray a)
853−clone src = do
818+clone src = liftIO $ do
854819 let len = arrLen src
855820 dst <- new len
856821 putSliceUnsafe src 0 dst 0 len
core/src/Streamly/Internal/Data/MutArray/Stream.hs+195−11
@@ -12,7 +12,6 @@
1212-- keep this as a separate module and release it.
1313--
1414module Streamly.Internal.Data.MutArray.Stream
15−{-# DEPRECATED "Please use \"Streamly.Internal.Data.MutArray\" instead." #-}
1615 (
1716 -- * Generation
1817 MArray.chunksOf
@@ -22,7 +21,7 @@ module Streamly.Internal.Data.MutArray.Stream
2221
2322 -- * Compaction
2423 , packArraysChunksOf
25− , MArray.SpliceState (..)
24+ , SpliceState (..)
2625 , lpackArraysChunksOf
2726 , compact -- chunksCompact
2827 , compactLE
@@ -36,12 +35,19 @@ module Streamly.Internal.Data.MutArray.Stream
3635 )
3736where
3837
38+#include "inline.hs"
39+#include "ArrayMacros.h"
40+
3941import Control.Monad.IO.Class (MonadIO(..))
40−import Streamly.Internal.Data.Unbox (Unbox)
42+import Control.Monad (when)
43+import Data.Bifunctor (first)
44+import Data.Proxy (Proxy(..))
45+import Streamly.Internal.Data.Unbox (Unbox, sizeOf)
4146import Streamly.Internal.Data.MutArray.Type (MutArray(..))
4247import Streamly.Internal.Data.Fold.Type (Fold(..))
4348import Streamly.Internal.Data.Parser (ParseError)
4449import Streamly.Internal.Data.Stream.Type (Stream)
50+import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
4551
4652import qualified Streamly.Internal.Data.MutArray as MArray
4753import qualified Streamly.Internal.Data.Fold.Type as FL
@@ -52,6 +58,12 @@ import qualified Streamly.Internal.Data.Stream as D
5258-- Compact
5359-------------------------------------------------------------------------------
5460
61+data SpliceState s arr
62+ = SpliceInitial s
63+ | SpliceBuffering s arr
64+ | SpliceYielding arr (SpliceState s arr)
65+ | SpliceFinish
66+
5567-- XXX This can be removed once compactLEFold/compactLE are implemented.
5668--
5769-- | This mutates the first array (if it has space) to append values from the
@@ -66,18 +78,117 @@ import qualified Streamly.Internal.Data.Stream as D
6678-- actual array size may be less than the specified chunk size.
6779--
6880-- @since 0.7.0
69−{-# INLINE packArraysChunksOf #-}
81+{-# INLINE_NORMAL packArraysChunksOf #-}
7082packArraysChunksOf :: (MonadIO m, Unbox a)
7183 => Int -> D.Stream m (MutArray a) -> D.Stream m (MutArray a)
72−packArraysChunksOf = MArray.compactLE
84+packArraysChunksOf n (D.Stream step state) =
85+ D.Stream step' (SpliceInitial state)
86+
87+ where
88+
89+ {-# INLINE_LATE step' #-}
90+ step' gst (SpliceInitial st) = do
91+ when (n <= 0) $
92+ -- XXX we can pass the module string from the higher level API
93+ error $ "Streamly.Internal.Data.MutArray.Type.packArraysChunksOf: the size of "
94+ ++ "arrays [" ++ show n ++ "] must be a natural number"
95+ r <- step gst st
96+ case r of
97+ D.Yield arr s -> return $
98+ let len = MArray.byteLength arr
99+ in if len >= n
100+ then D.Skip (SpliceYielding arr (SpliceInitial s))
101+ else D.Skip (SpliceBuffering s arr)
102+ D.Skip s -> return $ D.Skip (SpliceInitial s)
103+ D.Stop -> return D.Stop
104+
105+ step' gst (SpliceBuffering st buf) = do
106+ r <- step gst st
107+ case r of
108+ D.Yield arr s -> do
109+ let len = MArray.byteLength buf + MArray.byteLength arr
110+ if len > n
111+ then return $
112+ D.Skip (SpliceYielding buf (SpliceBuffering s arr))
113+ else do
114+ buf' <- if MArray.byteCapacity buf < n
115+ then liftIO $ MArray.realloc n buf
116+ else return buf
117+ buf'' <- MArray.splice buf' arr
118+ return $ D.Skip (SpliceBuffering s buf'')
119+ D.Skip s -> return $ D.Skip (SpliceBuffering s buf)
120+ D.Stop -> return $ D.Skip (SpliceYielding buf SpliceFinish)
121+
122+ step' _ SpliceFinish = return D.Stop
123+
124+ step' _ (SpliceYielding arr next) = return $ D.Yield arr next
73125
74126-- XXX Remove this once compactLEFold is implemented
75127-- lpackArraysChunksOf = Fold.many compactLEFold
76128--
77−{-# INLINE lpackArraysChunksOf #-}
129+{-# INLINE_NORMAL lpackArraysChunksOf #-}
78130lpackArraysChunksOf :: (MonadIO m, Unbox a)
79131 => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
80−lpackArraysChunksOf = MArray.lCompactGE
132+lpackArraysChunksOf n (Fold step1 initial1 _ final1) =
133+ Fold step initial extract final
134+
135+ where
136+
137+ initial = do
138+ when (n <= 0) $
139+ -- XXX we can pass the module string from the higher level API
140+ error $ "Streamly.Internal.Data.MutArray.Type.packArraysChunksOf: the size of "
141+ ++ "arrays [" ++ show n ++ "] must be a natural number"
142+
143+ r <- initial1
144+ return $ first (Tuple' Nothing) r
145+
146+ step (Tuple' Nothing r1) arr =
147+ let len = MArray.byteLength arr
148+ in if len >= n
149+ then do
150+ r <- step1 r1 arr
151+ case r of
152+ FL.Done _ -> return $ FL.Done ()
153+ FL.Partial s -> do
154+ _ <- final1 s
155+ res <- initial1
156+ return $ first (Tuple' Nothing) res
157+ else return $ FL.Partial $ Tuple' (Just arr) r1
158+
159+ step (Tuple' (Just buf) r1) arr = do
160+ let len = MArray.byteLength buf + MArray.byteLength arr
161+ buf' <- if MArray.byteCapacity buf < len
162+ then liftIO $ MArray.realloc (max n len) buf
163+ else return buf
164+ buf'' <- MArray.splice buf' arr
165+
166+ -- XXX this is common in both the equations of step
167+ if len >= n
168+ then do
169+ r <- step1 r1 buf''
170+ case r of
171+ FL.Done _ -> return $ FL.Done ()
172+ FL.Partial s -> do
173+ _ <- final1 s
174+ res <- initial1
175+ return $ first (Tuple' Nothing) res
176+ else return $ FL.Partial $ Tuple' (Just buf'') r1
177+
178+ -- XXX Several folds do extract >=> final, therefore, we need to make final
179+ -- return "m b" rather than using extract post it if we want extract to be
180+ -- partial.
181+ --
182+ -- extract forces the pending buffer to be sent to the fold which is not
183+ -- what we want.
184+ extract _ = error "lpackArraysChunksOf: not designed for scanning"
185+
186+ final (Tuple' Nothing r1) = final1 r1
187+ final (Tuple' (Just buf) r1) = do
188+ r <- step1 r1 buf
189+ case r of
190+ FL.Partial rr -> final1 rr
191+ FL.Done _ -> return ()
81192
82193-- XXX Same as compactLE, to be removed once that is implemented.
83194--
@@ -97,11 +208,48 @@ compact = packArraysChunksOf
97208-- actual array size may be less than the specified chunk size.
98209--
99210-- /Internal/
100−{-# INLINE compactLEParserD #-}
211+{-# INLINE_NORMAL compactLEParserD #-}
101212compactLEParserD ::
102213 forall m a. (MonadIO m, Unbox a)
103214 => Int -> ParserD.Parser (MutArray a) m (MutArray a)
104−compactLEParserD = MArray.pCompactLE
215+compactLEParserD n = ParserD.Parser step initial extract
216+
217+ where
218+
219+ nBytes = n * SIZE_OF(a)
220+
221+ initial =
222+ return
223+ $ if n <= 0
224+ then error
225+ $ functionPath
226+ ++ ": the size of arrays ["
227+ ++ show n ++ "] must be a natural number"
228+ else ParserD.IPartial Nothing
229+
230+ step Nothing arr =
231+ return
232+ $ let len = MArray.byteLength arr
233+ in if len >= nBytes
234+ then ParserD.Done 0 arr
235+ else ParserD.Partial 0 (Just arr)
236+ step (Just buf) arr =
237+ let len = MArray.byteLength buf + MArray.byteLength arr
238+ in if len > nBytes
239+ then return $ ParserD.Done 1 buf
240+ else do
241+ buf1 <-
242+ if MArray.byteCapacity buf < nBytes
243+ then liftIO $ MArray.realloc nBytes buf
244+ else return buf
245+ buf2 <- MArray.splice buf1 arr
246+ return $ ParserD.Partial 0 (Just buf2)
247+
248+ extract Nothing = return $ ParserD.Done 0 MArray.nil
249+ extract (Just buf) = return $ ParserD.Done 0 buf
250+
251+ functionPath =
252+ "Streamly.Internal.Data.Stream.MutChunked.compactLEParserD"
105253
106254-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
107255-- minimum specified size. Note that if all the arrays in the stream together
@@ -110,11 +258,47 @@ compactLEParserD = MArray.pCompactLE
110258-- the specified size we stop coalescing further.
111259--
112260-- /Internal/
113−{-# INLINE compactGEFold #-}
261+{-# INLINE_NORMAL compactGEFold #-}
114262compactGEFold ::
115263 forall m a. (MonadIO m, Unbox a)
116264 => Int -> FL.Fold m (MutArray a) (MutArray a)
117−compactGEFold = MArray.fCompactGE
265+compactGEFold n = Fold step initial extract extract
266+
267+ where
268+
269+ nBytes = n * SIZE_OF(a)
270+
271+ initial =
272+ return
273+ $ if n < 0
274+ then error
275+ $ functionPath
276+ ++ ": the size of arrays ["
277+ ++ show n ++ "] must be a natural number"
278+ else FL.Partial Nothing
279+
280+ step Nothing arr =
281+ return
282+ $ let len = MArray.byteLength arr
283+ in if len >= nBytes
284+ then FL.Done arr
285+ else FL.Partial (Just arr)
286+ step (Just buf) arr = do
287+ let len = MArray.byteLength buf + MArray.byteLength arr
288+ buf1 <-
289+ if MArray.byteCapacity buf < len
290+ then liftIO $ MArray.realloc (max len nBytes) buf
291+ else return buf
292+ buf2 <- MArray.splice buf1 arr
293+ if len >= n
294+ then return $ FL.Done buf2
295+ else return $ FL.Partial (Just buf2)
296+
297+ extract Nothing = return MArray.nil
298+ extract (Just buf) = return buf
299+
300+ functionPath =
301+ "Streamly.Internal.Data.Stream.MutChunked.compactGEFold"
118302
119303-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
120304-- maximum specified size in bytes.
core/src/Streamly/Internal/Data/MutArray/Type.hs+342−1199
@@ -31,57 +31,39 @@ module Streamly.Internal.Data.MutArray.Type
3131 -- ** Type
3232 -- $arrayNotes
3333 MutArray (..)
34−
35− -- ** Conversion
36− -- *** Pinned and Unpinned
34+ , MutByteArray
35+ , MutableByteArray
3736 , pin
3837 , unpin
3938 , isPinned
4039
41− -- ** Casting
42− , cast
43− , castUnsafe -- XXX unsafeCast
44− , asBytes
45− , unsafePinnedAsPtr
46− , unsafeAsPtr
47−
40+ -- -- * Constructing and Writing
4841 -- ** Construction
49− , empty
50−
51− -- *** New
52− -- | New arrays are always empty arrays with some reserve capacity to
53− -- extend the length without reallocating.
54− , emptyOf
55− , newArrayWith -- emptyAlignedWith
56− , pinnedEmptyOf
57− , pinnedNewAligned -- XXX not required
58− -- , new -- uninitialized array of specified length
59−
60− -- *** Cloning
61− , clone
62− , pinnedClone
42+ , nil
6343
64− -- *** Slicing
65− -- | Get a subarray without copying
66− , getSliceUnsafe -- XXX unsafeGetSlice
67− , getSlice
68− , splitAt -- XXX should be able to express using getSlice
69− , breakOn
44+ -- *** Uninitialized Arrays
45+ , pinnedNew
46+ , pinnedNewBytes
47+ , pinnedNewAligned
48+ , new
49+ , newArrayWith
7050
71− -- *** Stream Folds
51+ -- *** From streams
7252 , ArrayUnsafe (..)
73− , unsafeCreateOfWith
74− , unsafeCreateOf
75− , unsafePinnedCreateOf
76− , pinnedCreateOf
77− , createOfWith
78− , createOf
79− , revCreateOf
80−
81− , pinnedCreate
82− , createWith
83− , create
84− -- , revCreate
53+ , writeNWithUnsafe
54+ , writeNWith
55+ , writeNUnsafe
56+ , pinnedWriteNUnsafe
57+ , writeN
58+ , pinnedWriteN
59+ , pinnedWriteNAligned
60+
61+ , writeWith
62+ , write
63+ , pinnedWrite
64+
65+ , writeRevN
66+ -- , writeRev
8567
8668 -- *** From containers
8769 , fromListN
@@ -90,18 +72,13 @@ module Streamly.Internal.Data.MutArray.Type
9072 , pinnedFromList
9173 , fromListRevN
9274 , fromListRev
93− , fromStreamN
94− , fromStream
95− , fromPureStreamN
75+ , fromStreamDN
76+ , fromStreamD
9677 , fromPureStream
97− , fromByteStr#
98− , fromPtrN
99− , fromChunksK
100− , fromChunksRealloced -- fromSmallChunks
10178
10279 -- ** Random writes
10380 , putIndex
104− , putIndexUnsafe -- XXX unsafePutIndex
81+ , putIndexUnsafe
10582 , putIndices
10683 -- , putFromThenTo
10784 -- , putFrom -- start writing at the given position
@@ -109,69 +86,76 @@ module Streamly.Internal.Data.MutArray.Type
10986 -- , putFromTo
11087 -- , putFromRev
11188 -- , putUptoRev
112− , modifyIndexUnsafe -- XXX unsafeModifyIndex
89+ , modifyIndexUnsafe
11390 , modifyIndex
11491 , modifyIndices
11592 , modify
11693 , swapIndices
11794 , unsafeSwapIndices
11895
119− -- ** Reading
96+ -- ** Growing and Shrinking
97+ -- | Arrays grow only at the end, though it is possible to grow on both sides
98+ -- and therefore have a cons as well as snoc. But that will require two
99+ -- bounds in the array representation.
120100
121− -- *** Indexing
122− , getIndex
123− , getIndexUnsafe -- XXX unsafeGetIndex
124− -- , getFromThenTo
125− , getIndexRev -- getRevIndex?
126− , indexReader
127− , indexReaderWith
101+ -- *** Appending elements
102+ , snocWith
103+ , snoc
104+ , snocLinear
105+ , snocMay
106+ , snocUnsafe
128107
129− -- *** To Streams
108+ -- *** Appending streams
109+ , writeAppendNUnsafe
110+ , writeAppendN
111+ , writeAppendWith
112+ , writeAppend
113+
114+ -- ** Eliminating and Reading
115+
116+ -- *** To streams
117+ , reader
118+ , readerRevWith
119+ , readerRev
120+
121+ -- *** To containers
122+ , toStreamDWith
123+ , toStreamDRevWith
124+ , toStreamKWith
125+ , toStreamKRevWith
130126 , read
131127 , readRev
132− , toStreamWith
133− , toStreamRevWith
134128 , toStreamK
135− , toStreamKWith
136129 , toStreamKRev
137− , toStreamKRevWith
138−
139− -- *** To Containers
140130 , toList
141131
142− -- *** Unfolds
143132 -- experimental
144133 , producerWith
145134 , producer
146135
147− , reader
148− , readerRevWith
149− , readerRev
150−
151− -- ** Size and Capacity
152− -- *** Size
153− , length
154− , byteLength
155−
156− -- *** Capacity
157− -- , capacity
158− , byteCapacity
159− , bytesFree
136+ -- *** Random reads
137+ , getIndex
138+ , getIndexUnsafe
139+ , getIndices
140+ , getIndicesD
141+ -- , getFromThenTo
142+ , getIndexRev
160143
161− -- *** Capacity Management
144+ -- ** Memory Management
162145 , blockSize
163146 , arrayChunkBytes
164147 , allocBytesToElemCount
165− , realloc -- this is "resize"
166− , grow
167− , growExp
148+ , realloc
149+ , resize
150+ , resizeExp
168151 , rightSize
169152
170− -- ** Folding
171− , foldl'
172− , foldr
173− , byteCmp
174− , byteEq
153+ -- ** Size
154+ , length
155+ , byteLength
156+ -- , capacity
157+ , byteCapacity
158+ , bytesFree
175159
176160 -- ** In-place Mutation Algorithms
177161 , strip
@@ -183,121 +167,62 @@ module Streamly.Internal.Data.MutArray.Type
183167 , mergeBy
184168 , bubble
185169
186− -- ** Growing and Shrinking
187− -- | Arrays grow only at the end, though it is possible to grow on both
188− -- sides and therefore have a cons as well as snoc. But that will require
189− -- both lower and upper bound in the array representation.
190−
191− -- *** Appending elements
192− , snocWith
193− , snoc
194− , snocLinear
195− , snocMay
196− , snocUnsafe -- XXX unsafeSnoc
197−
198− -- *** Appending streams
199− , unsafeAppendN
200− , appendN
201− , appendWith
202− , append
203−
204− -- *** Appending arrays
205− , spliceCopy
206− , spliceWith
207− , splice
208− , spliceExp
209− , spliceUnsafe -- XXX unsafeSplice
210− -- , putSlice
211− -- , appendSlice
212− -- , appendSliceFrom
213−
214− -- ** Serialization using Unbox
215− , pokeAppend
216− , pokeAppendMay
217− , pokeSkipUnsafe -- unsafePokeSkip
170+ -- ** Casting
171+ , cast
172+ , castUnsafe
173+ , asBytes
174+ , asPtrUnsafe
218175
219− -- ** Deserialization using Unbox
220− , peekUncons
221− , peekUnconsUnsafe -- unsafePeekUncons
222− , peekSkipUnsafe -- unsafePeekSkip
176+ -- ** Folding
177+ , foldl'
178+ , foldr
179+ , cmp
223180
224− -- Arrays of arrays
181+ -- ** Arrays of arrays
225182 -- We can add dimensionality parameter to the array type to get
226183 -- multidimensional arrays. Multidimensional arrays would just be a
227184 -- convenience wrapper on top of single dimensional arrays.
228185
229− -- ** Streams of Arrays
230− -- *** Chunk
231− -- | Group a stream into arrays.
186+ -- | Operations dealing with multiple arrays, streams of arrays or
187+ -- multidimensional array representations.
188+
189+ -- *** Construct from streams
232190 , chunksOf
233191 , pinnedChunksOf
234− , buildChunks
192+ , writeChunks
235193
236− -- *** Split
237− -- | Split an array into slices.
194+ -- *** Eliminate to streams
195+ , flattenArrays
196+ , flattenArraysRev
197+ , fromArrayStreamK
238198
199+ -- *** Construct from arrays
200+ -- get chunks without copying
201+ , getSliceUnsafe
202+ , getSlice
239203 -- , getSlicesFromLenN
240− , splitOn
241− -- , slicesOf
242−
243− -- *** Concat
244− -- | Append the arrays in a stream to form a stream of elements.
245− , concatWith
246− , concatRevWith
247− , concat
248− , concatRev
249−
250− -- *** Compact
251− -- | Append the arrays in a stream to form a stream of larger arrays.
252− , SpliceState (..)
253− , pCompactLE
254− , pPinnedCompactLE
255− , compactLeAs
256− , fCompactGE
257− , fPinnedCompactGE
258− , lCompactGE
259− , lPinnedCompactGE
260− , compactGE
261− , compactEQ
204+ , splitAt -- XXX should be able to express using getSlice
205+ , breakOn
206+
207+ -- ** Cloning arrays
208+ , clone
209+ , pinnedClone
210+
211+ -- ** Appending arrays
212+ , spliceCopy
213+ , spliceWith
214+ , splice
215+ , spliceExp
216+ , spliceUnsafe
217+ -- , putSlice
218+ -- , appendSlice
219+ -- , appendSliceFrom
262220
263221 -- ** Utilities
264222 , roundUpToPower2
265223 , memcpy
266224 , memcmp
267225 , c_memchr
268−
269− -- * Deprecated
270− , asPtrUnsafe
271− , writeChunks
272− , flattenArrays
273− , flattenArraysRev
274− , fromArrayStreamK
275− , fromStreamDN
276− , fromStreamD
277− , cmp
278− , getIndices
279− , getIndicesWith
280− , resize
281− , resizeExp
282− , nil
283− , new
284− , pinnedNew
285− , pinnedNewBytes
286− , writeAppendNUnsafe
287− , writeAppendN
288− , writeAppendWith
289− , writeAppend
290− , writeNWithUnsafe
291− , writeNWith
292− , writeNUnsafe
293− , pinnedWriteNUnsafe
294− , writeN
295− , pinnedWriteN
296− , pinnedWriteNAligned -- XXX not required
297− , writeWith
298− , write
299− , pinnedWrite
300− , writeRevN
301226 )
302227where
303228
@@ -308,7 +233,6 @@ where
308233
309234import Control.Monad (when, void)
310235import Control.Monad.IO.Class (MonadIO(..))
311−import Data.Bifunctor (first)
312236import Data.Bits (shiftR, (.|.), (.&.))
313237import Data.Functor.Identity (Identity(..))
314238import Data.Proxy (Proxy(..))
@@ -317,6 +241,7 @@ import Foreign.C.Types (CSize(..), CInt(..))
317241import Foreign.Ptr (plusPtr, minusPtr, nullPtr)
318242import Streamly.Internal.Data.MutByteArray.Type
319243 ( MutByteArray(..)
244+ , MutableByteArray
320245 , PinnedState(..)
321246 , getMutableByteArray#
322247 , putSliceUnsafe
@@ -329,23 +254,19 @@ import GHC.Base
329254 , copyMutableByteArray#
330255 )
331256import GHC.Base (noinline)
332−import GHC.Exts (unsafeCoerce#, Addr#)
257+import GHC.Exts (unsafeCoerce#)
333258import GHC.Ptr (Ptr(..))
334259
335260import Streamly.Internal.Data.Fold.Type (Fold(..))
336261import Streamly.Internal.Data.Producer.Type (Producer (..))
337262import Streamly.Internal.Data.Stream.Type (Stream)
338−import Streamly.Internal.Data.Parser.Type (Parser (..))
339263import Streamly.Internal.Data.StreamK.Type (StreamK)
340264import Streamly.Internal.Data.SVar.Type (adaptState, defState)
341−import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
342265import Streamly.Internal.Data.Unfold.Type (Unfold(..))
343266import Streamly.Internal.System.IO (arrayPayloadSize, defaultChunkSize)
344267
345268import qualified Streamly.Internal.Data.Fold.Type as FL
346269import qualified Streamly.Internal.Data.MutByteArray.Type as Unboxed
347−import qualified Streamly.Internal.Data.Parser.Type as Parser
348−-- import qualified Streamly.Internal.Data.Fold.Type as Fold
349270import qualified Streamly.Internal.Data.Producer as Producer
350271import qualified Streamly.Internal.Data.Stream.Type as D
351272import qualified Streamly.Internal.Data.Stream.Lift as D
@@ -353,7 +274,7 @@ import qualified Streamly.Internal.Data.StreamK.Type as K
353274import qualified Prelude
354275
355276import Prelude hiding
356− (Foldable(..), concat, read, unlines, splitAt, reverse, truncate)
277+ (Foldable(..), read, unlines, splitAt, reverse, truncate)
357278
358279#include "DocTestDataMutArray.hs"
359280
@@ -361,7 +282,6 @@ import Prelude hiding
361282-- Foreign helpers
362283-------------------------------------------------------------------------------
363284
364−-- NOTE: Have to be "ccall unsafe" so that we can pass unpinned memory to these
365285foreign import ccall unsafe "string.h memcpy" c_memcpy
366286 :: Ptr Word8 -> Ptr Word8 -> CSize -> IO (Ptr Word8)
367287
@@ -371,9 +291,6 @@ foreign import ccall unsafe "string.h memchr" c_memchr
371291foreign import ccall unsafe "string.h memcmp" c_memcmp
372292 :: Ptr Word8 -> Ptr Word8 -> CSize -> IO CInt
373293
374−foreign import ccall unsafe "string.h strlen" c_strlen
375− :: Ptr Word8 -> IO CSize
376−
377294-- | Given an 'Unboxed' type (unused first arg) and a number of bytes, return
378295-- how many elements of that type will completely fit in those bytes.
379296--
@@ -479,8 +396,6 @@ isPinned MutArray{..} = Unboxed.isPinned arrContents
479396-- we need more than that. See stg_pinnedNewAlignedByteArrayzh and
480397-- allocatePinned in GHC source.
481398
482−-- XXX Rename to emptyAlignedWith, alignSize should be first arg.
483−
484399-- | @newArrayWith allocator alignment count@ allocates a new array of zero
485400-- length and with a capacity to hold @count@ elements, using @allocator
486401-- size alignment@ as the memory allocator function.
@@ -504,25 +419,12 @@ newArrayWith alloc alignSize count = do
504419 , arrBound = size
505420 }
506421
507−-- For arrays "nil" sounds a bit odd. empty is better. The only problem with
508−-- empty is that it is also used by the Alternative type class. But assuming we
509−-- will mostly import the Array module qualified this should be fine.
510−
511−-- | Create an empty array.
512−empty ::
513−#ifdef DEVBUILD
514− Unbox a =>
515−#endif
516− MutArray a
517−empty = MutArray Unboxed.empty 0 0 0
518−
519−{-# DEPRECATED nil "Please use empty instead." #-}
520422nil ::
521423#ifdef DEVBUILD
522424 Unbox a =>
523425#endif
524426 MutArray a
525−nil = empty
427+nil = MutArray Unboxed.nil 0 0 0
526428
527429{-# INLINE newBytesAs #-}
528430newBytesAs :: MonadIO m =>
@@ -539,13 +441,12 @@ newBytesAs ps bytes = do
539441 , arrBound = bytes
540442 }
541443
542−-- | Allocates a pinned empty array that with a reserved capacity of bytes.
543−-- The memory of the array is uninitialized and the allocation is aligned as
544−-- per the 'Unboxed' instance of the type.
444+-- | Allocates a pinned empty array that can hold 'count' items. The memory of
445+-- the array is uninitialized and the allocation is aligned as per the
446+-- 'Unboxed' instance of the type.
545447--
546448-- /Pre-release/
547449{-# INLINE pinnedNewBytes #-}
548−{-# DEPRECATED pinnedNewBytes "Please use pinnedEmptyOf with appropriate calculation" #-}
549450pinnedNewBytes :: MonadIO m =>
550451#ifdef DEVBUILD
551452 Unbox a =>
@@ -570,31 +471,21 @@ newAs ps =
570471 (error "new: alignment is not used in unpinned arrays.")
571472
572473-- XXX can unaligned allocation be more efficient when alignment is not needed?
573−
574−-- | Allocates a pinned array of zero length but growable to the specified
575−-- capacity without reallocation.
576−{-# INLINE pinnedEmptyOf #-}
577−pinnedEmptyOf :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
578−pinnedEmptyOf = newAs Pinned
579−
580−-- XXX Deprecate in major
581−-- {-# DEPRECATED pinnedNew "Please use pinnedEmptyOf instead." #-}
474+--
475+-- | Allocates an empty pinned array that can hold 'count' items. The memory of
476+-- the array is uninitialized and the allocation is aligned as per the 'Unboxed'
477+-- instance of the type.
478+--
582479{-# INLINE pinnedNew #-}
583480pinnedNew :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
584−pinnedNew = pinnedEmptyOf
481+pinnedNew = newAs Pinned
585482
586−-- | Allocates an unpinned array of zero length but growable to the specified
587−-- capacity without reallocation.
483+-- | Allocates an empty unpinned array that can hold 'count' items. The memory
484+-- of the array is uninitialized.
588485--
589−{-# INLINE emptyOf #-}
590−emptyOf :: (MonadIO m, Unbox a) => Int -> m (MutArray a)
591−emptyOf = newAs Unpinned
592−
593−-- XXX Deprecate in major
594−-- {-# DEPRECATED new "Please use emptyOf instead." #-}
595486{-# INLINE new #-}
596487new :: (MonadIO m, Unbox a) => Int -> m (MutArray a)
597−new = emptyOf
488+new = newAs Unpinned
598489
599490-------------------------------------------------------------------------------
600491-- Random writes
@@ -642,7 +533,7 @@ putIndices arr = FL.foldlM' step (return ())
642533
643534 where
644535
645− step () (i, x) = putIndex i arr x
536+ step () (i, x) = liftIO (putIndex i arr x)
646537
647538-- | Modify a given index of an array using a modifier function.
648539--
@@ -838,19 +729,22 @@ arrayChunkBytes = 1024
838729roundDownTo :: Int -> Int -> Int
839730roundDownTo elemSize size = size - (size `mod` elemSize)
840731
732+-- XXX See if resizing can be implemented by reading the old array as a stream
733+-- and then using writeN to the new array.
734+--
841735-- NOTE: we are passing elemSize explicitly to avoid an Unboxed constraint.
842736-- Since this is not inlined Unboxed consrraint leads to dictionary passing
843737-- which complicates some inspection tests.
844738--
845−{-# NOINLINE reallocExplicitAs #-}
846−reallocExplicitAs :: PinnedState -> Int -> Int -> MutArray a -> IO (MutArray a)
847−reallocExplicitAs ps elemSize newCapacityInBytes MutArray{..} = do
739+{-# NOINLINE reallocExplicit #-}
740+reallocExplicit :: Int -> Int -> MutArray a -> IO (MutArray a)
741+reallocExplicit elemSize newCapacityInBytes MutArray{..} = do
848742 assertM(arrEnd <= arrBound)
849743
850744 -- Allocate new array
851745 let newCapMaxInBytes = roundUpLargeArray newCapacityInBytes
852746 contents <-
853− if ps == Pinned
747+ if Unboxed.isPinned arrContents
854748 then Unboxed.pinnedNew newCapMaxInBytes
855749 else Unboxed.new newCapMaxInBytes
856750 let !(MutByteArray mbarrFrom#) = arrContents
@@ -875,10 +769,6 @@ reallocExplicitAs ps elemSize newCapacityInBytes MutArray{..} = do
875769 , arrBound = newCapInBytes
876770 }
877771
878−-- XXX Should these be called reallocBytes etc?
879−-- XXX We may also need reallocAs to allocate as pinned/unpinned explicitly. In
880−-- fact clone/pinnedClone can be implemented using reallocAs.
881−
882772-- | @realloc newCapacity array@ reallocates the array to the specified
883773-- capacity in bytes.
884774--
@@ -890,12 +780,7 @@ reallocExplicitAs ps elemSize newCapacityInBytes MutArray{..} = do
890780-- If the original array is pinned, the newly allocated array is also pinned.
891781{-# INLINABLE realloc #-}
892782realloc :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (MutArray a)
893−realloc bytes arr =
894− let ps =
895− if isPinned arr
896− then Pinned
897− else Unpinned
898− in liftIO $ reallocExplicitAs ps (SIZE_OF(a)) bytes arr
783+realloc bytes arr = liftIO $ reallocExplicit (SIZE_OF(a)) bytes arr
899784
900785-- | @reallocWith label capSizer minIncrBytes array@. The label is used
901786-- in error messages and the capSizer is used to determine the capacity of the
@@ -918,14 +803,14 @@ reallocWith label capSizer minIncrBytes arr = do
918803 where
919804
920805 badSize newSize =
921− Prelude.concat
806+ concat
922807 [ label
923808 , ": new array size (in bytes) is less than required size "
924809 , show newSize
925810 , ". Please check the sizing function passed."
926811 ]
927812
928−-- | @grow newCapacity array@ changes the total capacity of the array so that
813+-- | @resize newCapacity array@ changes the total capacity of the array so that
929814-- it is enough to hold the specified number of elements. Nothing is done if
930815-- the specified capacity is less than the length of the array.
931816--
@@ -933,46 +818,34 @@ reallocWith label capSizer minIncrBytes arr = do
933818-- the block size (4K).
934819--
935820-- /Pre-release/
936−{-# INLINE grow #-}
937−grow :: forall m a. (MonadIO m, Unbox a) =>
821+{-# INLINE resize #-}
822+resize :: forall m a. (MonadIO m, Unbox a) =>
938823 Int -> MutArray a -> m (MutArray a)
939−grow nElems arr@MutArray{..} = do
824+resize nElems arr@MutArray{..} = do
940825 let req = SIZE_OF(a) * nElems
941− cap = arrBound - arrStart
942− if req < cap
826+ len = arrEnd - arrStart
827+ if req < len
943828 then return arr
944829 else realloc req arr
945830
946−{-# DEPRECATED resize "Please use grow instead." #-}
947−{-# INLINE resize #-}
948−resize :: forall m a. (MonadIO m, Unbox a) =>
949− Int -> MutArray a -> m (MutArray a)
950−resize = grow
951−
952−-- | Like 'grow' but if the requested byte capacity is more than
953−-- 'largeObjectThreshold' then it is rounded up to the closest power of 2.
831+-- | Like 'resize' but if the byte capacity is more than 'largeObjectThreshold'
832+-- then it is rounded up to the closest power of 2.
954833--
955834-- /Pre-release/
956−{-# INLINE growExp #-}
957−growExp :: forall m a. (MonadIO m, Unbox a) =>
835+{-# INLINE resizeExp #-}
836+resizeExp :: forall m a. (MonadIO m, Unbox a) =>
958837 Int -> MutArray a -> m (MutArray a)
959−growExp nElems arr@MutArray{..} = do
838+resizeExp nElems arr@MutArray{..} = do
960839 let req = roundUpLargeArray (SIZE_OF(a) * nElems)
961840 req1 =
962841 if req > largeObjectThreshold
963842 then roundUpToPower2 req
964843 else req
965− cap = arrBound - arrStart
966− if req1 < cap
844+ len = arrEnd - arrStart
845+ if req1 < len
967846 then return arr
968847 else realloc req1 arr
969848
970−{-# DEPRECATED resizeExp "Please use growExp instead." #-}
971−{-# INLINE resizeExp #-}
972−resizeExp :: forall m a. (MonadIO m, Unbox a) =>
973− Int -> MutArray a -> m (MutArray a)
974−resizeExp = growExp
975−
976849-- | Resize the allocated memory to drop any reserved free space at the end of
977850-- the array and reallocate it to reduce wastage.
978851--
@@ -1037,7 +910,7 @@ snocUnsafe arr@MutArray{..} = snocNewEnd (INDEX_NEXT(arrEnd,a)) arr
1037910{-# INLINE snocMay #-}
1038911snocMay :: forall m a. (MonadIO m, Unbox a) =>
1039912 MutArray a -> a -> m (Maybe (MutArray a))
1040−snocMay arr@MutArray{..} x = do
913+snocMay arr@MutArray{..} x = liftIO $ do
1041914 let newEnd = INDEX_NEXT(arrEnd,a)
1042915 if newEnd <= arrBound
1043916 then Just <$> snocNewEnd newEnd arr x
@@ -1051,7 +924,7 @@ snocWithRealloc :: forall m a. (MonadIO m, Unbox a) =>
1051924 -> a
1052925 -> m (MutArray a)
1053926snocWithRealloc sizer arr x = do
1054− arr1 <- reallocWith "snocWith" sizer (SIZE_OF(a)) arr
927+ arr1 <- liftIO $ reallocWith "snocWith" sizer (SIZE_OF(a)) arr
1055928 snocUnsafe arr1 x
1056929
1057930-- | @snocWith sizer arr elem@ mutates @arr@ to append @elem@. The length of
@@ -1073,7 +946,7 @@ snocWith :: forall m a. (MonadIO m, Unbox a) =>
1073946 -> MutArray a
1074947 -> a
1075948 -> m (MutArray a)
1076−snocWith allocSize arr x = do
949+snocWith allocSize arr x = liftIO $ do
1077950 let newEnd = INDEX_NEXT(arrEnd arr,a)
1078951 if newEnd <= arrBound arr
1079952 then snocNewEnd newEnd arr x
@@ -1117,126 +990,6 @@ snoc = snocWith f
1117990 then oldSize * 2
1118991 else roundUpToPower2 oldSize * 2
1119992
1120−-------------------------------------------------------------------------------
1121−-- Serialization/Deserialization
1122−-------------------------------------------------------------------------------
1123−
1124−{-# INLINE pokeNewEnd #-}
1125−pokeNewEnd :: (MonadIO m, Unbox a) =>
1126− Int -> MutArray Word8 -> a -> m (MutArray Word8)
1127−pokeNewEnd newEnd arr@MutArray{..} x = liftIO $ do
1128− assert (newEnd <= arrBound) (return ())
1129− liftIO $ pokeAt arrEnd arrContents x
1130− return $ arr {arrEnd = newEnd}
1131−
1132−-- | Really really unsafe, unboxes a Haskell type and appends the resulting
1133−-- bytes to the byte array, may cause silent data corruption or if you are
1134−-- lucky a segfault if the array does not have enough space to append the
1135−-- element.
1136−--
1137−-- /Internal/
1138−{-# INLINE pokeAppendUnsafe #-}
1139−pokeAppendUnsafe :: forall m a. (MonadIO m, Unbox a) =>
1140− MutArray Word8 -> a -> m (MutArray Word8)
1141−pokeAppendUnsafe arr@MutArray{..} = pokeNewEnd (arrEnd + SIZE_OF(a)) arr
1142−
1143−-- | Skip the specified number of bytes in the array. The data in the skipped
1144−-- region remains uninitialzed.
1145−{-# INLINE pokeSkipUnsafe #-}
1146−pokeSkipUnsafe :: Int -> MutArray Word8 -> MutArray Word8
1147−pokeSkipUnsafe n arr@MutArray{..} = do
1148− let newEnd = arrEnd + n
1149− in assert (newEnd <= arrBound) (arr {arrEnd = newEnd})
1150−
1151−-- | Like 'pokeAppend' but does not grow the array when pre-allocated array
1152−-- capacity becomes full.
1153−--
1154−-- /Internal/
1155−{-# INLINE pokeAppendMay #-}
1156−pokeAppendMay :: forall m a. (MonadIO m, Unbox a) =>
1157− MutArray Word8 -> a -> m (Maybe (MutArray Word8))
1158−pokeAppendMay arr@MutArray{..} x = liftIO $ do
1159− let newEnd = arrEnd + SIZE_OF(a)
1160− if newEnd <= arrBound
1161− then Just <$> pokeNewEnd newEnd arr x
1162− else return Nothing
1163−
1164−{-# NOINLINE pokeWithRealloc #-}
1165−pokeWithRealloc :: forall m a. (MonadIO m, Unbox a) =>
1166− (Int -> Int)
1167− -> MutArray Word8
1168− -> a
1169− -> m (MutArray Word8)
1170−pokeWithRealloc sizer arr x = do
1171− arr1 <- liftIO $ reallocWith "pokeWithRealloc" sizer (SIZE_OF(a)) arr
1172− pokeAppendUnsafe arr1 x
1173−
1174−{-# INLINE pokeAppendWith #-}
1175−pokeAppendWith :: forall m a. (MonadIO m, Unbox a) =>
1176− (Int -> Int)
1177− -> MutArray Word8
1178− -> a
1179− -> m (MutArray Word8)
1180−pokeAppendWith allocSize arr x = liftIO $ do
1181− let newEnd = arrEnd arr + SIZE_OF(a)
1182− if newEnd <= arrBound arr
1183− then pokeNewEnd newEnd arr x
1184− else pokeWithRealloc allocSize arr x
1185−
1186−-- | Unbox a Haskell type and append the resulting bytes to a mutable byte
1187−-- array. The array is grown exponentially when more space is needed.
1188−--
1189−-- Definition:
1190−--
1191−-- >>> pokeAppend arr x = MutArray.castUnsafe <$> MutArray.snoc (MutArray.castUnsafe arr) x
1192−--
1193−{-# INLINE pokeAppend #-}
1194−pokeAppend :: forall m a. (MonadIO m, Unbox a) =>
1195− MutArray Word8 -> a -> m (MutArray Word8)
1196−pokeAppend = pokeAppendWith f
1197−
1198− where
1199−
1200− f oldSize =
1201− if isPower2 oldSize
1202− then oldSize * 2
1203− else roundUpToPower2 oldSize * 2
1204−
1205−-- | Really really unsafe, create a Haskell value from an unboxed byte array,
1206−-- does not check if the array is big enough, may return garbage or if you are
1207−-- lucky may cause a segfault.
1208−--
1209−-- /Internal/
1210−{-# INLINE peekUnconsUnsafe #-}
1211−peekUnconsUnsafe :: forall m a. (MonadIO m, Unbox a) =>
1212− MutArray Word8 -> m (a, MutArray Word8)
1213−peekUnconsUnsafe MutArray{..} = do
1214− let start1 = arrStart + SIZE_OF(a)
1215− assert (start1 <= arrEnd) (return ())
1216− liftIO $ do
1217− r <- peekAt arrStart arrContents
1218− return (r, MutArray arrContents start1 arrEnd arrBound)
1219−
1220−-- | Discard the specified number of bytes in the array.
1221−{-# INLINE peekSkipUnsafe #-}
1222−peekSkipUnsafe :: Int -> MutArray Word8 -> MutArray Word8
1223−peekSkipUnsafe n MutArray{..} =
1224− let start1 = arrStart + n
1225− in assert (start1 <= arrEnd) (MutArray arrContents start1 arrEnd arrBound)
1226−
1227−-- | Create a Haskell value from its unboxed representation from the head of a
1228−-- byte array, return the value and the remaining array.
1229−{-# INLINE peekUncons #-}
1230−peekUncons :: forall m a. (MonadIO m, Unbox a) =>
1231− MutArray Word8 -> m (Maybe a, MutArray Word8)
1232−peekUncons arr@MutArray{..} = do
1233− let start1 = arrStart + SIZE_OF(a)
1234− if start1 > arrEnd
1235− then return (Nothing, arr)
1236− else liftIO $ do
1237− r <- peekAt arrStart arrContents
1238− return (Just r, MutArray arrContents start1 arrEnd arrBound)
1239−
1240993-------------------------------------------------------------------------------
1241994-- Random reads
1242995-------------------------------------------------------------------------------
@@ -1279,10 +1032,15 @@ getIndexRev i MutArray{..} = do
12791032data GetIndicesState contents start end st =
12801033 GetIndicesState contents start end st
12811034
1282−{-# INLINE indexReaderWith #-}
1283−indexReaderWith :: (Monad m, Unbox a) =>
1035+-- | Given an unfold that generates array indices, read the elements on those
1036+-- indices from the supplied MutArray. An error is thrown if an index is out of
1037+-- bounds.
1038+--
1039+-- /Pre-release/
1040+{-# INLINE getIndicesD #-}
1041+getIndicesD :: (Monad m, Unbox a) =>
12841042 (forall b. IO b -> m b) -> D.Stream m Int -> Unfold m (MutArray a) a
1285−indexReaderWith liftio (D.Stream stepi sti) = Unfold step inject
1043+getIndicesD liftio (D.Stream stepi sti) = Unfold step inject
12861044
12871045 where
12881046
@@ -1301,26 +1059,9 @@ indexReaderWith liftio (D.Stream stepi sti) = Unfold step inject
13011059 D.Skip s -> return $ D.Skip (GetIndicesState contents start end s)
13021060 D.Stop -> return D.Stop
13031061
1304−{-# DEPRECATED getIndicesWith "Please use indexReaderWith instead." #-}
1305−{-# INLINE getIndicesWith #-}
1306−getIndicesWith :: (Monad m, Unbox a) =>
1307− (forall b. IO b -> m b) -> D.Stream m Int -> Unfold m (MutArray a) a
1308−getIndicesWith = indexReaderWith
1309−
1310−-- | Given an unfold that generates array indices, read the elements on those
1311−-- indices from the supplied MutArray. An error is thrown if an index is out of
1312−-- bounds.
1313−--
1314−-- /Pre-release/
1315−{-# INLINE indexReader #-}
1316−indexReader :: (MonadIO m, Unbox a) => Stream m Int -> Unfold m (MutArray a) a
1317−indexReader = indexReaderWith liftIO
1318−
1319−-- XXX DO NOT REMOVE, change the signature to use Stream instead of unfold
1320−{-# DEPRECATED getIndices "Please use indexReader instead." #-}
13211062{-# INLINE getIndices #-}
13221063getIndices :: (MonadIO m, Unbox a) => Stream m Int -> Unfold m (MutArray a) a
1323−getIndices = indexReader
1064+getIndices = getIndicesD liftIO
13241065
13251066-------------------------------------------------------------------------------
13261067-- Subarrays
@@ -1615,7 +1356,7 @@ chunksOfAs ps n (D.Stream step state) =
16151356--
16161357-- Same as the following but may be more efficient:
16171358--
1618−-- >>> chunksOf n = Stream.foldMany (MutArray.createOf n)
1359+-- >>> chunksOf n = Stream.foldMany (MutArray.writeN n)
16191360--
16201361-- /Pre-release/
16211362{-# INLINE_NORMAL chunksOf #-}
@@ -1624,29 +1365,17 @@ chunksOf :: forall m a. (MonadIO m, Unbox a)
16241365-- XXX the idiomatic implementation leads to large regression in the D.reverse'
16251366-- benchmark. It seems it has difficulty producing optimized code when
16261367-- converting to StreamK. Investigate GHC optimizations.
1627−-- chunksOf n = D.foldMany (createOf n)
1368+-- chunksOf n = D.foldMany (writeN n)
16281369chunksOf = chunksOfAs Unpinned
16291370
16301371-- | Like 'chunksOf' but creates pinned arrays.
16311372{-# INLINE_NORMAL pinnedChunksOf #-}
16321373pinnedChunksOf :: forall m a. (MonadIO m, Unbox a)
16331374 => Int -> D.Stream m a -> D.Stream m (MutArray a)
1634−-- pinnedChunksOf n = D.foldMany (pinnedCreateOf n)
1375+-- pinnedChunksOf n = D.foldMany (pinnedWriteN n)
16351376pinnedChunksOf = chunksOfAs Pinned
16361377
1637−-- | When we are buffering a stream of unknown size into an array we do not
1638−-- know how much space to pre-allocate. So we start with the min size and emit
1639−-- the array then keep on doubling the size every time. Thus we do not need to
1640−-- guess the optimum chunk size.
1641−--
1642−-- We can incorporate this in chunksOfAs if the additional size parameter does
1643−-- not impact perf.
1644−--
1645−{-# INLINE _chunksOfRange #-}
1646−_chunksOfRange :: -- (MonadIO m, Unbox a) =>
1647− PinnedState -> Int -> Int -> D.Stream m a -> D.Stream m (MutArray a)
1648−_chunksOfRange _ps _low _hi = undefined
1649−
1378+-- XXX This should take a PinnedState
16501379-- XXX buffer to a list instead?
16511380-- | Buffer the stream into arrays in memory.
16521381{-# INLINE arrayStreamKFromStreamDAs #-}
@@ -1664,10 +1393,16 @@ data FlattenState s contents a =
16641393 OuterLoop s
16651394 | InnerLoop s contents !Int !Int
16661395
1667−{-# INLINE_NORMAL concatWith #-}
1668−concatWith :: forall m a. (Monad m, Unbox a)
1669− => (forall b. IO b -> m b) -> D.Stream m (MutArray a) -> D.Stream m a
1670−concatWith liftio (D.Stream step state) = D.Stream step' (OuterLoop state)
1396+-- | Use the "reader" unfold instead.
1397+--
1398+-- @flattenArrays = unfoldMany reader@
1399+--
1400+-- We can try this if there are any fusion issues in the unfold.
1401+--
1402+{-# INLINE_NORMAL flattenArrays #-}
1403+flattenArrays :: forall m a. (MonadIO m, Unbox a)
1404+ => D.Stream m (MutArray a) -> D.Stream m a
1405+flattenArrays (D.Stream step state) = D.Stream step' (OuterLoop state)
16711406
16721407 where
16731408
@@ -1684,30 +1419,19 @@ concatWith liftio (D.Stream step state) = D.Stream step' (OuterLoop state)
16841419 return $ D.Skip $ OuterLoop st
16851420
16861421 step' _ (InnerLoop st contents p end) = do
1687− x <- liftio $ peekAt p contents
1422+ x <- liftIO $ peekAt p contents
16881423 return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
16891424
1690−-- | Use the "reader" unfold instead.
1425+-- | Use the "readerRev" unfold instead.
16911426--
1692−-- @concat = unfoldMany reader@
1427+-- @flattenArrays = unfoldMany readerRev@
16931428--
16941429-- We can try this if there are any fusion issues in the unfold.
16951430--
1696−{-# INLINE_NORMAL concat #-}
1697−concat :: forall m a. (MonadIO m, Unbox a)
1698− => D.Stream m (MutArray a) -> D.Stream m a
1699−concat = concatWith liftIO
1700−
1701−{-# DEPRECATED flattenArrays "Please use \"unfoldMany reader\" instead." #-}
1702−{-# INLINE flattenArrays #-}
1703−flattenArrays :: forall m a. (MonadIO m, Unbox a)
1431+{-# INLINE_NORMAL flattenArraysRev #-}
1432+flattenArraysRev :: forall m a. (MonadIO m, Unbox a)
17041433 => D.Stream m (MutArray a) -> D.Stream m a
1705−flattenArrays = concat
1706−
1707−{-# INLINE_NORMAL concatRevWith #-}
1708−concatRevWith :: forall m a. (Monad m, Unbox a)
1709− => (forall b. IO b -> m b) -> D.Stream m (MutArray a) -> D.Stream m a
1710−concatRevWith liftio (D.Stream step state) = D.Stream step' (OuterLoop state)
1434+flattenArraysRev (D.Stream step state) = D.Stream step' (OuterLoop state)
17111435
17121436 where
17131437
@@ -1725,27 +1449,10 @@ concatRevWith liftio (D.Stream step state) = D.Stream step' (OuterLoop state)
17251449 return $ D.Skip $ OuterLoop st
17261450
17271451 step' _ (InnerLoop st contents p start) = do
1728− x <- liftio $ peekAt p contents
1452+ x <- liftIO $ peekAt p contents
17291453 let cur = INDEX_PREV(p,a)
17301454 return $ D.Yield x (InnerLoop st contents cur start)
17311455
1732−-- | Use the "readerRev" unfold instead.
1733−--
1734−-- @concat = unfoldMany readerRev@
1735−--
1736−-- We can try this if there are any fusion issues in the unfold.
1737−--
1738−{-# INLINE_NORMAL concatRev #-}
1739−concatRev :: forall m a. (MonadIO m, Unbox a)
1740− => D.Stream m (MutArray a) -> D.Stream m a
1741−concatRev = concatRevWith liftIO
1742−
1743−{-# DEPRECATED flattenArraysRev "Please use \"unfoldMany readerRev\" instead." #-}
1744−{-# INLINE flattenArraysRev #-}
1745−flattenArraysRev :: forall m a. (MonadIO m, Unbox a)
1746− => D.Stream m (MutArray a) -> D.Stream m a
1747−flattenArraysRev = concatRev
1748−
17491456-------------------------------------------------------------------------------
17501457-- Unfolds
17511458-------------------------------------------------------------------------------
@@ -1863,11 +1570,11 @@ toList MutArray{..} = liftIO $ go arrStart
18631570 x <- peekAt p arrContents
18641571 (:) x <$> go (INDEX_NEXT(p,a))
18651572
1866−{-# INLINE_NORMAL toStreamWith #-}
1867−toStreamWith ::
1573+{-# INLINE_NORMAL toStreamDWith #-}
1574+toStreamDWith ::
18681575 forall m a. (Monad m, Unbox a)
18691576 => (forall b. IO b -> m b) -> MutArray a -> D.Stream m a
1870−toStreamWith liftio MutArray{..} = D.Stream step arrStart
1577+toStreamDWith liftio MutArray{..} = D.Stream step arrStart
18711578
18721579 where
18731580
@@ -1883,7 +1590,7 @@ toStreamWith liftio MutArray{..} = D.Stream step arrStart
18831590--
18841591{-# INLINE_NORMAL read #-}
18851592read :: forall m a. (MonadIO m, Unbox a) => MutArray a -> D.Stream m a
1886−read = toStreamWith liftIO
1593+read = toStreamDWith liftIO
18871594
18881595{-# INLINE toStreamKWith #-}
18891596toStreamKWith ::
@@ -1902,11 +1609,11 @@ toStreamKWith liftio MutArray{..} = go arrStart
19021609toStreamK :: forall m a. (MonadIO m, Unbox a) => MutArray a -> StreamK m a
19031610toStreamK = toStreamKWith liftIO
19041611
1905−{-# INLINE_NORMAL toStreamRevWith #-}
1906−toStreamRevWith ::
1612+{-# INLINE_NORMAL toStreamDRevWith #-}
1613+toStreamDRevWith ::
19071614 forall m a. (Monad m, Unbox a)
19081615 => (forall b. IO b -> m b) -> MutArray a -> D.Stream m a
1909−toStreamRevWith liftio MutArray{..} =
1616+toStreamDRevWith liftio MutArray{..} =
19101617 let p = INDEX_PREV(arrEnd,a)
19111618 in D.Stream step p
19121619
@@ -1924,7 +1631,7 @@ toStreamRevWith liftio MutArray{..} =
19241631--
19251632{-# INLINE_NORMAL readRev #-}
19261633readRev :: forall m a. (MonadIO m, Unbox a) => MutArray a -> D.Stream m a
1927−readRev = toStreamRevWith liftIO
1634+readRev = toStreamDRevWith liftIO
19281635
19291636{-# INLINE toStreamKRevWith #-}
19301637toStreamKRevWith ::
@@ -1973,7 +1680,7 @@ foldr f z arr = D.foldr f z $ read arr
19731680
19741681-- XXX Keep the bound intact to not lose any free space? Perf impact?
19751682
1976−-- | @unsafeAppendN n arr@ appends up to @n@ input items to the supplied
1683+-- | @writeAppendNUnsafe n arr@ appends up to @n@ input items to the supplied
19771684-- array.
19781685--
19791686-- Unsafe: Do not drive the fold beyond @n@ elements, it will lead to memory
@@ -1982,12 +1689,13 @@ foldr f z arr = D.foldr f z $ read arr
19821689-- Any free space left in the array after appending @n@ elements is lost.
19831690--
19841691-- /Internal/
1985−{-# INLINE_NORMAL unsafeAppendN #-}
1986−unsafeAppendN :: forall m a. (MonadIO m, Unbox a) =>
1692+{-# INLINE_NORMAL writeAppendNUnsafe #-}
1693+writeAppendNUnsafe :: forall m a. (MonadIO m, Unbox a) =>
19871694 Int
19881695 -> m (MutArray a)
19891696 -> Fold m a (MutArray a)
1990−unsafeAppendN n action = fmap fromArrayUnsafe $ FL.foldlM' step initial
1697+writeAppendNUnsafe n action =
1698+ fmap fromArrayUnsafe $ FL.foldlM' step initial
19911699
19921700 where
19931701
@@ -2000,7 +1708,7 @@ unsafeAppendN n action = fmap fromArrayUnsafe $ FL.foldlM' step initial
20001708 -- otherwise we lose that space.
20011709 arr1 <-
20021710 if free < needed
2003− then noinline reallocWith "unsafeAppendN" (+ needed) needed arr
1711+ then noinline reallocWith "writeAppendNUnsafeWith" (+ needed) needed arr
20041712 else return arr
20051713 return $ toArrayUnsafe arr1
20061714
@@ -2008,51 +1716,30 @@ unsafeAppendN n action = fmap fromArrayUnsafe $ FL.foldlM' step initial
20081716 liftIO $ pokeAt end contents x
20091717 return $ ArrayUnsafe contents start (INDEX_NEXT(end,a))
20101718
2011−{-# DEPRECATED writeAppendNUnsafe "Please use unsafeAppendN instead." #-}
2012−{-# INLINE writeAppendNUnsafe #-}
2013−writeAppendNUnsafe :: forall m a. (MonadIO m, Unbox a) =>
2014− Int
2015− -> m (MutArray a)
2016− -> Fold m a (MutArray a)
2017−writeAppendNUnsafe = unsafeAppendN
2018−
20191719-- | Append @n@ elements to an existing array. Any free space left in the array
20201720-- after appending @n@ elements is lost.
20211721--
2022−-- >>> appendN n initial = Fold.take n (MutArray.unsafeAppendN n initial)
1722+-- >>> writeAppendN n initial = Fold.take n (MutArray.writeAppendNUnsafe n initial)
20231723--
2024−{-# INLINE_NORMAL appendN #-}
2025−appendN :: forall m a. (MonadIO m, Unbox a) =>
2026− Int -> m (MutArray a) -> Fold m a (MutArray a)
2027−appendN n initial = FL.take n (unsafeAppendN n initial)
2028−
2029−-- XXX Deprecate in major
2030−-- {-# DEPRECATED writeAppendN "Please use appendN instead." #-}
2031−{-# INLINE writeAppendN #-}
1724+{-# INLINE_NORMAL writeAppendN #-}
20321725writeAppendN :: forall m a. (MonadIO m, Unbox a) =>
20331726 Int -> m (MutArray a) -> Fold m a (MutArray a)
2034−writeAppendN = appendN
1727+writeAppendN n initial = FL.take n (writeAppendNUnsafe n initial)
20351728
2036−-- | @appendWith realloc action@ mutates the array generated by @action@ to
1729+-- | @writeAppendWith realloc action@ mutates the array generated by @action@ to
20371730-- append the input stream. If there is no reserved space available in the
20381731-- array it is reallocated to a size in bytes determined by @realloc oldSize@,
20391732-- where @oldSize@ is the current size of the array in bytes.
20401733--
20411734-- Note that the returned array may be a mutated version of original array.
20421735--
2043−-- >>> appendWith sizer = Fold.foldlM' (MutArray.snocWith sizer)
1736+-- >>> writeAppendWith sizer = Fold.foldlM' (MutArray.snocWith sizer)
20441737--
20451738-- /Pre-release/
2046−{-# INLINE appendWith #-}
2047−appendWith :: forall m a. (MonadIO m, Unbox a) =>
2048− (Int -> Int) -> m (MutArray a) -> Fold m a (MutArray a)
2049−appendWith sizer = FL.foldlM' (snocWith sizer)
2050−
2051−{-# DEPRECATED writeAppendWith "Please use appendWith instead." #-}
20521739{-# INLINE writeAppendWith #-}
20531740writeAppendWith :: forall m a. (MonadIO m, Unbox a) =>
20541741 (Int -> Int) -> m (MutArray a) -> Fold m a (MutArray a)
2055−writeAppendWith = appendWith
1742+writeAppendWith sizer = FL.foldlM' (snocWith sizer)
20561743
20571744-- | @append action@ mutates the array generated by @action@ to append the
20581745-- input stream. If there is no reserved space available in the array it is
@@ -2060,33 +1747,26 @@ writeAppendWith = appendWith
20601747--
20611748-- Note that the returned array may be a mutated version of original array.
20621749--
2063−-- >>> append = MutArray.appendWith (* 2)
1750+-- >>> writeAppend = MutArray.writeAppendWith (* 2)
20641751--
2065−{-# INLINE append #-}
2066−append :: forall m a. (MonadIO m, Unbox a) =>
2067− m (MutArray a) -> Fold m a (MutArray a)
2068−append = appendWith (* 2)
2069−
2070−-- XXX Deprecate in major
2071−-- {-# DEPRECATED writeAppend "Please use append instead." #-}
20721752{-# INLINE writeAppend #-}
20731753writeAppend :: forall m a. (MonadIO m, Unbox a) =>
20741754 m (MutArray a) -> Fold m a (MutArray a)
2075−writeAppend = append
1755+writeAppend = writeAppendWith (* 2)
20761756
20771757-- XXX We can carry bound as well in the state to make sure we do not lose the
20781758-- remaining capacity. Need to check perf impact.
20791759--
2080−-- | Like 'unsafeCreateOf' but takes a new array allocator @alloc size@
2081−-- function as argument.
1760+-- | Like 'writeNUnsafe' but takes a new array allocator @alloc size@ function
1761+-- as argument.
20821762--
2083−-- >>> unsafeCreateOfWith alloc n = MutArray.unsafeAppendN (alloc n) n
1763+-- >>> writeNWithUnsafe alloc n = MutArray.writeAppendNUnsafe (alloc n) n
20841764--
20851765-- /Pre-release/
2086−{-# INLINE_NORMAL unsafeCreateOfWith #-}
2087−unsafeCreateOfWith :: forall m a. (MonadIO m, Unbox a)
1766+{-# INLINE_NORMAL writeNWithUnsafe #-}
1767+writeNWithUnsafe :: forall m a. (MonadIO m, Unbox a)
20881768 => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
2089−unsafeCreateOfWith alloc n = fromArrayUnsafe <$> FL.foldlM' step initial
1769+writeNWithUnsafe alloc n = fromArrayUnsafe <$> FL.foldlM' step initial
20901770
20911771 where
20921772
@@ -2097,64 +1777,40 @@ unsafeCreateOfWith alloc n = fromArrayUnsafe <$> FL.foldlM' step initial
20971777 return
20981778 $ ArrayUnsafe contents start (INDEX_NEXT(end,a))
20991779
2100−{-# DEPRECATED writeNWithUnsafe "Please use unsafeCreateOfWith instead." #-}
2101−{-# INLINE writeNWithUnsafe #-}
2102−writeNWithUnsafe :: forall m a. (MonadIO m, Unbox a)
2103− => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
2104−writeNWithUnsafe = unsafeCreateOfWith
2105−
21061780{-# INLINE_NORMAL writeNUnsafeAs #-}
21071781writeNUnsafeAs :: forall m a. (MonadIO m, Unbox a)
21081782 => PinnedState -> Int -> Fold m a (MutArray a)
2109−writeNUnsafeAs ps = unsafeCreateOfWith (newAs ps)
1783+writeNUnsafeAs ps = writeNWithUnsafe (newAs ps)
21101784
2111−-- | Like 'createOf' but does not check the array bounds when writing. The fold
1785+-- | Like 'writeN' but does not check the array bounds when writing. The fold
21121786-- driver must not call the step function more than 'n' times otherwise it will
21131787-- corrupt the memory and crash. This function exists mainly because any
21141788-- conditional in the step function blocks fusion causing 10x performance
21151789-- slowdown.
21161790--
2117−-- >>> unsafeCreateOf = MutArray.unsafeCreateOfWith MutArray.emptyOf
1791+-- >>> writeNUnsafe = MutArray.writeNWithUnsafe MutArray.new
21181792--
2119−{-# INLINE_NORMAL unsafeCreateOf #-}
2120−unsafeCreateOf :: forall m a. (MonadIO m, Unbox a)
2121− => Int -> Fold m a (MutArray a)
2122−unsafeCreateOf = writeNUnsafeAs Unpinned
2123−
2124−{-# DEPRECATED writeNUnsafe "Please use unsafeCreateOf instead." #-}
2125−{-# INLINE writeNUnsafe #-}
1793+{-# INLINE_NORMAL writeNUnsafe #-}
21261794writeNUnsafe :: forall m a. (MonadIO m, Unbox a)
21271795 => Int -> Fold m a (MutArray a)
2128−writeNUnsafe = unsafeCreateOf
1796+writeNUnsafe = writeNUnsafeAs Unpinned
21291797
2130−-- | Like 'unsafeCreateOf' but creates a pinned array.
2131−{-# INLINE_NORMAL unsafePinnedCreateOf #-}
2132−unsafePinnedCreateOf :: forall m a. (MonadIO m, Unbox a)
2133− => Int -> Fold m a (MutArray a)
2134−unsafePinnedCreateOf = writeNUnsafeAs Pinned
2135−
2136−{-# DEPRECATED pinnedWriteNUnsafe "Please use unsafePinnedCreateOf instead." #-}
2137−{-# INLINE pinnedWriteNUnsafe #-}
1798+-- | Like 'writeNUnsafe' but creates a pinned array.
1799+{-# INLINE_NORMAL pinnedWriteNUnsafe #-}
21381800pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a)
21391801 => Int -> Fold m a (MutArray a)
2140−pinnedWriteNUnsafe = unsafePinnedCreateOf
1802+pinnedWriteNUnsafe = writeNUnsafeAs Pinned
21411803
2142−-- | @createOfWith alloc n@ folds a maximum of @n@ elements into an array
1804+-- | @writeNWith alloc n@ folds a maximum of @n@ elements into an array
21431805-- allocated using the @alloc@ function.
21441806--
2145−-- >>> createOfWith alloc n = Fold.take n (MutArray.unsafeCreateOfWith alloc n)
2146−-- >>> createOfWith alloc n = MutArray.appendN (alloc n) n
1807+-- >>> writeNWith alloc n = Fold.take n (MutArray.writeNWithUnsafe alloc n)
1808+-- >>> writeNWith alloc n = MutArray.writeAppendN (alloc n) n
21471809--
2148−{-# INLINE_NORMAL createOfWith #-}
2149−createOfWith :: forall m a. (MonadIO m, Unbox a)
2150− => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
2151−createOfWith alloc n = FL.take n (unsafeCreateOfWith alloc n)
2152−
2153−-- {-# DEPRECATED writeNWith "Please use createOfWith instead." #-}
2154−{-# INLINE writeNWith #-}
1810+{-# INLINE_NORMAL writeNWith #-}
21551811writeNWith :: forall m a. (MonadIO m, Unbox a)
21561812 => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
2157−writeNWith = createOfWith
1813+writeNWith alloc n = FL.take n (writeNWithUnsafe alloc n)
21581814
21591815{-# INLINE_NORMAL writeNAs #-}
21601816writeNAs ::
@@ -2162,42 +1818,28 @@ writeNAs ::
21621818 => PinnedState
21631819 -> Int
21641820 -> Fold m a (MutArray a)
2165−writeNAs ps = createOfWith (newAs ps)
1821+writeNAs ps = writeNWith (newAs ps)
21661822
2167−-- | @createOf n@ folds a maximum of @n@ elements from the input stream to an
1823+-- | @writeN n@ folds a maximum of @n@ elements from the input stream to an
21681824-- 'MutArray'.
21691825--
2170−-- >>> createOf = MutArray.createOfWith MutArray.new
2171−-- >>> createOf n = Fold.take n (MutArray.unsafeCreateOf n)
2172−-- >>> createOf n = MutArray.appendN n (MutArray.emptyOf n)
1826+-- >>> writeN = MutArray.writeNWith MutArray.new
1827+-- >>> writeN n = Fold.take n (MutArray.writeNUnsafe n)
1828+-- >>> writeN n = MutArray.writeAppendN n (MutArray.new n)
21731829--
2174−{-# INLINE_NORMAL createOf #-}
2175−createOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
2176−createOf = writeNAs Unpinned
2177−
2178−-- XXX Deprecate in major
2179−-- {-# DEPRECATED writeN "Please use createOf instead." #-}
2180−{-# INLINE writeN #-}
1830+{-# INLINE_NORMAL writeN #-}
21811831writeN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
2182−writeN = createOf
2183−
2184−-- | Like 'createOf' but creates a pinned array.
2185−{-# INLINE_NORMAL pinnedCreateOf #-}
2186−pinnedCreateOf ::
2187− forall m a. (MonadIO m, Unbox a)
2188− => Int
2189− -> Fold m a (MutArray a)
2190−pinnedCreateOf = writeNAs Pinned
1832+writeN = writeNAs Unpinned
21911833
2192−{-# DEPRECATED pinnedWriteN "Please use pinnedCreateOf instead." #-}
2193−{-# INLINE pinnedWriteN #-}
1834+-- | Like 'writeN' but creates a pinned array.
1835+{-# INLINE_NORMAL pinnedWriteN #-}
21941836pinnedWriteN ::
21951837 forall m a. (MonadIO m, Unbox a)
21961838 => Int
21971839 -> Fold m a (MutArray a)
2198−pinnedWriteN = pinnedCreateOf
1840+pinnedWriteN = writeNAs Pinned
21991841
2200−-- | Like unsafeCreateOfWith but writes the array in reverse order.
1842+-- | Like writeNWithUnsafe but writes the array in reverse order.
22011843--
22021844-- /Internal/
22031845{-# INLINE_NORMAL writeRevNWithUnsafe #-}
@@ -2218,7 +1860,7 @@ writeRevNWithUnsafe alloc n = fromArrayUnsafe <$> FL.foldlM' step initial
22181860 return
22191861 $ ArrayUnsafe contents ptr end
22201862
2221−-- | Like createOfWith but writes the array in reverse order.
1863+-- | Like writeNWith but writes the array in reverse order.
22221864--
22231865-- /Internal/
22241866{-# INLINE_NORMAL writeRevNWith #-}
@@ -2226,36 +1868,31 @@ writeRevNWith :: forall m a. (MonadIO m, Unbox a)
22261868 => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
22271869writeRevNWith alloc n = FL.take n (writeRevNWithUnsafe alloc n)
22281870
2229−-- | Like 'createOf' but writes the array in reverse order.
1871+-- | Like writeN but writes the array in reverse order.
22301872--
22311873-- /Pre-release/
2232−{-# INLINE_NORMAL revCreateOf #-}
2233−revCreateOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
2234−revCreateOf = writeRevNWith new
2235−
2236−{-# DEPRECATED writeRevN "Please use revCreateOf instead." #-}
2237−{-# INLINE writeRevN #-}
1874+{-# INLINE_NORMAL writeRevN #-}
22381875writeRevN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
2239−writeRevN = revCreateOf
1876+writeRevN = writeRevNWith new
22401877
22411878-- | @pinnedWriteNAligned align n@ folds a maximum of @n@ elements from the
22421879-- input stream to a 'MutArray' aligned to the given size.
22431880--
2244−-- >>> pinnedWriteNAligned align = MutArray.createOfWith (MutArray.pinnedNewAligned align)
2245−-- >>> pinnedWriteNAligned align n = MutArray.appendN n (MutArray.pinnedNewAligned align n)
1881+-- >>> pinnedWriteNAligned align = MutArray.writeNWith (MutArray.pinnedNewAligned align)
1882+-- >>> pinnedWriteNAligned align n = MutArray.writeAppendN n (MutArray.pinnedNewAligned align n)
22461883--
22471884-- /Pre-release/
22481885--
22491886{-# INLINE_NORMAL pinnedWriteNAligned #-}
22501887pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a)
22511888 => Int -> Int -> Fold m a (MutArray a)
2252−pinnedWriteNAligned align = createOfWith (pinnedNewAligned align)
1889+pinnedWriteNAligned align = writeNWith (pinnedNewAligned align)
22531890
22541891-- XXX Buffer to a list instead?
22551892
22561893-- | Buffer a stream into a stream of arrays.
22571894--
2258−-- >>> buildChunks n = Fold.many (MutArray.createOf n) Fold.toStreamK
1895+-- >>> writeChunks n = Fold.many (MutArray.writeN n) Fold.toStreamK
22591896--
22601897-- Breaking an array into an array stream can be useful to consume a large
22611898-- array sequentially such that memory of the array is released incrementatlly.
@@ -2264,43 +1901,37 @@ pinnedWriteNAligned align = createOfWith (pinnedNewAligned align)
22641901--
22651902-- /Unimplemented/
22661903--
2267−{-# INLINE_NORMAL buildChunks #-}
2268−buildChunks :: (MonadIO m, Unbox a) =>
2269− Int -> Fold m a (StreamK n (MutArray a))
2270−buildChunks n = FL.many (createOf n) FL.toStreamK
2271−
2272−{-# DEPRECATED writeChunks "Please use buildChunks instead." #-}
2273−{-# INLINE writeChunks #-}
1904+{-# INLINE_NORMAL writeChunks #-}
22741905writeChunks :: (MonadIO m, Unbox a) =>
22751906 Int -> Fold m a (StreamK n (MutArray a))
2276−writeChunks = buildChunks
1907+writeChunks n = FL.many (writeN n) FL.toStreamK
22771908
22781909{-# INLINE_NORMAL writeWithAs #-}
22791910writeWithAs :: forall m a. (MonadIO m, Unbox a)
22801911 => PinnedState -> Int -> Fold m a (MutArray a)
2281−-- writeWithAs ps n = FL.rmapM rightSize $ appendWith (* 2) (newAs ps n)
1912+-- writeWithAs ps n = FL.rmapM rightSize $ writeAppendWith (* 2) (newAs ps n)
22821913writeWithAs ps elemCount =
22831914 FL.rmapM extract $ FL.foldlM' step initial
22841915
22851916 where
22861917
22871918 initial = do
2288− when (elemCount < 0) $ error "createWith: elemCount is negative"
2289− newAs ps elemCount
1919+ when (elemCount < 0) $ error "writeWith: elemCount is negative"
1920+ liftIO $ newAs ps elemCount
22901921
22911922 step arr@(MutArray _ start end bound) x
22921923 | INDEX_NEXT(end,a) > bound = do
22931924 let oldSize = end - start
22941925 newSize = max (oldSize * 2) 1
2295− arr1 <- liftIO $ reallocExplicitAs ps (SIZE_OF(a)) newSize arr
1926+ arr1 <- liftIO $ reallocExplicit (SIZE_OF(a)) newSize arr
22961927 snocUnsafe arr1 x
22971928 step arr x = snocUnsafe arr x
22981929
22991930 extract = liftIO . rightSize
23001931
2301−-- XXX Compare createWith with fromStreamD which uses an array of streams
2302−-- implementation. We can write this using buildChunks above if that is faster.
2303−-- If createWith is faster then we should use that to implement
1932+-- XXX Compare writeWith with fromStreamD which uses an array of streams
1933+-- implementation. We can write this using writeChunks above if that is faster.
1934+-- If writeWith is faster then we should use that to implement
23041935-- fromStreamD.
23051936--
23061937-- XXX The realloc based implementation needs to make one extra copy if we use
@@ -2315,56 +1946,39 @@ writeWithAs ps elemCount =
23151946-- XXX check if GHC's memory allocator is efficient enough. We can try the C
23161947-- malloc to compare against.
23171948
2318−-- | @createWith minCount@ folds the whole input to a single array. The array
1949+-- | @writeWith minCount@ folds the whole input to a single array. The array
23191950-- starts at a size big enough to hold minCount elements, the size is doubled
23201951-- every time the array needs to be grown.
23211952--
23221953-- /Caution! Do not use this on infinite streams./
23231954--
2324−-- >>> f n = MutArray.appendWith (* 2) (MutArray.emptyOf n)
2325−-- >>> createWith n = Fold.rmapM MutArray.rightSize (f n)
2326−-- >>> createWith n = Fold.rmapM MutArray.fromChunksK (MutArray.buildChunks n)
1955+-- >>> f n = MutArray.writeAppendWith (* 2) (MutArray.new n)
1956+-- >>> writeWith n = Fold.rmapM MutArray.rightSize (f n)
1957+-- >>> writeWith n = Fold.rmapM MutArray.fromArrayStreamK (MutArray.writeChunks n)
23271958--
23281959-- /Pre-release/
2329−{-# INLINE_NORMAL createWith #-}
2330−createWith :: forall m a. (MonadIO m, Unbox a)
2331− => Int -> Fold m a (MutArray a)
2332−-- createWith n = FL.rmapM rightSize $ appendWith (* 2) (emptyOf n)
2333−createWith = writeWithAs Unpinned
2334−
2335−{-# DEPRECATED writeWith "Please use createWith instead." #-}
2336−{-# INLINE writeWith #-}
1960+{-# INLINE_NORMAL writeWith #-}
23371961writeWith :: forall m a. (MonadIO m, Unbox a)
23381962 => Int -> Fold m a (MutArray a)
2339−writeWith = createWith
1963+-- writeWith n = FL.rmapM rightSize $ writeAppendWith (* 2) (new n)
1964+writeWith = writeWithAs Unpinned
23401965
23411966-- | Fold the whole input to a single array.
23421967--
2343−-- Same as 'createWith' using an initial array size of 'arrayChunkBytes' bytes
1968+-- Same as 'writeWith' using an initial array size of 'arrayChunkBytes' bytes
23441969-- rounded up to the element size.
23451970--
23461971-- /Caution! Do not use this on infinite streams./
23471972--
2348−{-# INLINE create #-}
2349−create :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
2350−create = createWith (allocBytesToElemCount (undefined :: a) arrayChunkBytes)
2351−
2352−-- XXX Deprecate in major
2353−-- {-# DEPRECATED write "Please use create instead." #-}
23541973{-# INLINE write #-}
23551974write :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
2356−write = create
2357−
2358−-- | Like 'create' but creates a pinned array.
2359−{-# INLINE pinnedCreate #-}
2360−pinnedCreate :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
2361−pinnedCreate =
2362− writeWithAs Pinned (allocBytesToElemCount (undefined :: a) arrayChunkBytes)
1975+write = writeWith (allocBytesToElemCount (undefined :: a) arrayChunkBytes)
23631976
2364−{-# DEPRECATED pinnedWrite "Please use pinnedCreate instead." #-}
1977+-- | Like 'write' but creates a pinned array.
23651978{-# INLINE pinnedWrite #-}
23661979pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
2367−pinnedWrite = pinnedCreate
1980+pinnedWrite =
1981+ writeWithAs Pinned (allocBytesToElemCount (undefined :: a) arrayChunkBytes)
23681982
23691983-------------------------------------------------------------------------------
23701984-- construct from streams, known size
@@ -2374,7 +1988,7 @@ pinnedWrite = pinnedCreate
23741988fromStreamDNAs :: forall m a. (MonadIO m, Unbox a)
23751989 => PinnedState -> Int -> D.Stream m a -> m (MutArray a)
23761990fromStreamDNAs ps limit str = do
2377− (arr :: MutArray a) <- newAs ps limit
1991+ (arr :: MutArray a) <- liftIO $ newAs ps limit
23781992 end <- D.foldlM' (fwrite (arrContents arr)) (return $ arrEnd arr) $ D.take limit str
23791993 return $ arr {arrEnd = end}
23801994
@@ -2384,21 +1998,15 @@ fromStreamDNAs ps limit str = do
23841998 liftIO $ pokeAt ptr arrContents x
23851999 return $ INDEX_NEXT(ptr,a)
23862000
2387−-- | Use the 'createOf' fold instead.
2001+-- | Use the 'writeN' fold instead.
23882002--
2389−-- >>> fromStreamN n = Stream.fold (MutArray.createOf n)
2003+-- >>> fromStreamDN n = Stream.fold (MutArray.writeN n)
23902004--
2391−{-# INLINE_NORMAL fromStreamN #-}
2392−fromStreamN :: forall m a. (MonadIO m, Unbox a)
2393− => Int -> D.Stream m a -> m (MutArray a)
2394−-- fromStreamDN n = D.fold (createOf n)
2395−fromStreamN = fromStreamDNAs Unpinned
2396−
2397−{-# DEPRECATED fromStreamDN "Please use fromStreamN instead." #-}
2398−{-# INLINE fromStreamDN #-}
2005+{-# INLINE_NORMAL fromStreamDN #-}
23992006fromStreamDN :: forall m a. (MonadIO m, Unbox a)
24002007 => Int -> D.Stream m a -> m (MutArray a)
2401−fromStreamDN = fromStreamN
2008+-- fromStreamDN n = D.fold (writeN n)
2009+fromStreamDN = fromStreamDNAs Unpinned
24022010
24032011-- | Create a 'MutArray' from the first N elements of a list. The array is
24042012-- allocated to size N, if the list terminates before N elements then the
@@ -2418,70 +2026,16 @@ pinnedFromListN n xs = fromStreamDNAs Pinned n $ D.fromList xs
24182026-- /Pre-release/
24192027{-# INLINE fromListRevN #-}
24202028fromListRevN :: (MonadIO m, Unbox a) => Int -> [a] -> m (MutArray a)
2421−fromListRevN n xs = D.fold (revCreateOf n) $ D.fromList xs
2422−
2423−-- | Convert a pure stream in Identity monad to a mutable array.
2424−{-# INLINABLE fromPureStreamN #-}
2425−fromPureStreamN :: (MonadIO m, Unbox a) =>
2426− Int -> Stream Identity a -> m (MutArray a)
2427−fromPureStreamN n xs =
2428− D.fold (createOf n) $ D.morphInner (return . runIdentity) xs
2029+fromListRevN n xs = D.fold (writeRevN n) $ D.fromList xs
24292030
24302031-- | Convert a pure stream in Identity monad to a mutable array.
24312032{-# INLINABLE fromPureStream #-}
24322033fromPureStream :: (MonadIO m, Unbox a) => Stream Identity a -> m (MutArray a)
24332034fromPureStream xs =
2434− D.fold create $ D.morphInner (return . runIdentity) xs
2435−
2436−{-# INLINABLE fromPtrN #-}
2437−fromPtrN :: MonadIO m => Int -> Ptr Word8 -> m (MutArray Word8)
2438−fromPtrN len addr = do
2439− -- memcpy is better than stream copy when the size is known.
2440− -- XXX We can implement a stream copy in a similar way by streaming Word64
2441− -- first and then remaining Word8.
2442− arr <- new len
2443− _ <- unsafeAsPtr arr
2444− (\ptr -> liftIO $ c_memcpy ptr addr (fromIntegral len))
2445− return (arr {arrEnd = len})
2446−
2447−{-# INLINABLE fromByteStr# #-}
2448−fromByteStr# :: MonadIO m => Addr# -> m (MutArray Word8)
2449−fromByteStr# addr = do
2450− -- It is better to count the size first and allocate exact space.
2451− -- Also, memcpy is better than stream copy when the size is known.
2452− -- C strlen compares 4 bytes at a time, so is better than the stream
2453− -- version. https://github.com/bminor/glibc/blob/master/string/strlen.c
2454− -- XXX We can possibly use a stream of Word64 to do the same.
2455− -- fromByteStr# addr = fromPureStream (D.fromByteStr# addr)
2456− len <- liftIO $ c_strlen (Ptr addr)
2457− let lenInt = fromIntegral len
2458− arr <- new lenInt
2459− _ <- unsafeAsPtr arr (\ptr -> liftIO $ c_memcpy ptr (Ptr addr) len)
2460− return (arr {arrEnd = lenInt})
2035+ liftIO $ D.fold write $ D.morphInner (return . runIdentity) xs
24612036
24622037-------------------------------------------------------------------------------
2463−-- convert a stream of arrays to a single array by reallocating and copying
2464−-------------------------------------------------------------------------------
2465−
2466−-- XXX Both of these implementations of splicing seem to perform equally well.
2467−-- We need to perform benchmarks over a range of sizes though.
2468−
2469−-- | Also see 'fromChunksK'.
2470−{-# INLINE fromChunksRealloced #-}
2471−fromChunksRealloced :: forall m a. (MonadIO m, Unbox a)
2472− => Stream m (MutArray a) -> m (MutArray a)
2473−fromChunksRealloced s = do
2474− res <- D.uncons s
2475− case res of
2476− Just (a, strm) -> do
2477− arr <- D.foldlM' spliceExp (pure a) strm
2478− -- Reallocation is exponential so there may be 50% empty space in
2479− -- worst case. One more reallocation to reclaim the space.
2480− rightSize arr
2481− Nothing -> pure nil
2482−
2483−-------------------------------------------------------------------------------
2484−-- convert a stream of arrays to a single array by buffering arrays first
2038+-- convert stream to a single array
24852039-------------------------------------------------------------------------------
24862040
24872041{-# INLINE arrayStreamKLength #-}
@@ -2491,72 +2045,34 @@ arrayStreamKLength as = K.foldl' (+) 0 (K.map length as)
24912045-- | Convert an array stream to an array. Note that this requires peak memory
24922046-- that is double the size of the array stream.
24932047--
2494−{-# INLINE fromChunkskAs #-}
2495−fromChunkskAs :: (Unbox a, MonadIO m) =>
2496− PinnedState -> StreamK m (MutArray a) -> m (MutArray a)
2497−fromChunkskAs ps as = do
2498− len <- arrayStreamKLength as
2499− arr <- newAs ps len
2500− -- XXX is StreamK fold faster or StreamD fold?
2501− K.foldlM' spliceUnsafe (pure arr) as
2502− -- fromStreamDN len $ D.unfoldMany reader $ D.fromStreamK as
2503−
2504−-- XXX Need to compare this with fromChunks and fromChunkList and keep the
2505−-- fastest or simplest one if all are equally fast.
2506−
2507−-- | Convert an array stream to an array. Note that this requires peak memory
2508−-- that is double the size of the array stream.
2509−--
2510−-- Also see 'fromChunksRealloced'.
2511−--
2512−{-# INLINE fromChunksK #-}
2513−fromChunksK :: (Unbox a, MonadIO m) =>
2514− StreamK m (MutArray a) -> m (MutArray a)
2515−fromChunksK = fromChunkskAs Unpinned
2516−
2517−{-# DEPRECATED fromArrayStreamK "Please use fromChunksK instead." #-}
25182048{-# INLINE fromArrayStreamK #-}
25192049fromArrayStreamK :: (Unbox a, MonadIO m) =>
25202050 StreamK m (MutArray a) -> m (MutArray a)
2521−fromArrayStreamK = fromChunksK
2051+fromArrayStreamK as = do
2052+ len <- arrayStreamKLength as
2053+ fromStreamDN len $ D.unfoldMany reader $ D.fromStreamK as
25222054
25232055{-# INLINE fromStreamDAs #-}
25242056fromStreamDAs ::
25252057 (MonadIO m, Unbox a) => PinnedState -> D.Stream m a -> m (MutArray a)
2526−fromStreamDAs ps m =
2527− arrayStreamKFromStreamDAs Unpinned m >>= fromChunkskAs ps
2058+fromStreamDAs ps m = arrayStreamKFromStreamDAs ps m >>= fromArrayStreamK
25282059
2529−-- | Create an 'Array' from a stream. This is useful when we want to create a
2530−-- single array from a stream of unknown size. 'createOf' is at least twice
2531−-- as efficient when the size is already known.
2532−--
2533−-- Note that if the input stream is too large memory allocation for the array
2534−-- may fail. When the stream size is not known, `chunksOf` followed by
2535−-- processing of indvidual arrays in the resulting stream should be preferred.
2536−--
2537−-- /Pre-release/
2538−{-# INLINE fromStream #-}
2539−fromStream :: (MonadIO m, Unbox a) => Stream m a -> m (MutArray a)
2540−fromStream = fromStreamDAs Unpinned
2541−
2542−-- fromStream (Stream m) = P.fold create m
25432060-- CAUTION: a very large number (millions) of arrays can degrade performance
25442061-- due to GC overhead because we need to buffer the arrays before we flatten
25452062-- all the arrays.
25462063--
2547−-- XXX Compare if this is faster or "fold create".
2064+-- XXX Compare if this is faster or "fold write".
25482065--
25492066-- | We could take the approach of doubling the memory allocation on each
25502067-- overflow. This would result in more or less the same amount of copying as in
25512068-- the chunking approach. However, if we have to shrink in the end then it may
25522069-- result in an extra copy of the entire data.
25532070--
2554−-- >>> fromStreamD = StreamD.fold MutArray.create
2071+-- >>> fromStreamD = StreamD.fold MutArray.write
25552072--
25562073{-# INLINE fromStreamD #-}
2557−{-# DEPRECATED fromStreamD "Please use fromStream instead." #-}
25582074fromStreamD :: (MonadIO m, Unbox a) => D.Stream m a -> m (MutArray a)
2559−fromStreamD = fromStream
2075+fromStreamD = fromStreamDAs Unpinned
25602076
25612077-- | Create a 'MutArray' from a list. The list must be of finite size.
25622078--
@@ -2581,20 +2097,10 @@ fromListRev xs = fromListRevN (Prelude.length xs) xs
25812097-- Cloning
25822098-------------------------------------------------------------------------------
25832099
2584−-- Arrays are aligned on 64-bit boundaries. The fastest way to copy an array is
2585−-- to unsafeCast it to Word64, read it, write it to Word64 array and unsafeCast
2586−-- it again. We can use SIMD read/write as well.
2587−
25882100{-# INLINE cloneAs #-}
2589−cloneAs ::
2590− ( MonadIO m
2591−#ifdef DEVBUILD
2592− , Unbox a
2593−#endif
2594− )
2595− => PinnedState -> MutArray a -> m (MutArray a)
2101+cloneAs :: MonadIO m => PinnedState -> MutArray a -> m (MutArray a)
25962102cloneAs ps src =
2597− do
2103+ liftIO $ do
25982104 let startSrc = arrStart src
25992105 srcLen = arrEnd src - startSrc
26002106 newArrContents <-
@@ -2602,23 +2108,11 @@ cloneAs ps src =
26022108 return $ MutArray newArrContents 0 srcLen srcLen
26032109
26042110{-# INLINE clone #-}
2605−clone ::
2606− ( MonadIO m
2607−#ifdef DEVBUILD
2608− , Unbox a
2609−#endif
2610− )
2611− => MutArray a -> m (MutArray a)
2111+clone :: MonadIO m => MutArray a -> m (MutArray a)
26122112clone = cloneAs Unpinned
26132113
26142114{-# INLINE pinnedClone #-}
2615−pinnedClone ::
2616− ( MonadIO m
2617−#ifdef DEVBUILD
2618− , Unbox a
2619−#endif
2620− )
2621− => MutArray a -> m (MutArray a)
2115+pinnedClone :: MonadIO m => MutArray a -> m (MutArray a)
26222116pinnedClone = cloneAs Pinned
26232117
26242118-------------------------------------------------------------------------------
@@ -2633,16 +2127,17 @@ spliceCopy :: forall m a. MonadIO m =>
26332127 Unbox a =>
26342128#endif
26352129 MutArray a -> MutArray a -> m (MutArray a)
2636−spliceCopy arr1 arr2 = do
2130+spliceCopy arr1 arr2 = liftIO $ do
26372131 let start1 = arrStart arr1
26382132 start2 = arrStart arr2
26392133 len1 = arrEnd arr1 - start1
26402134 len2 = arrEnd arr2 - start2
2641− let len = len1 + len2
2135+ let newLen = len1 + len2
26422136 newArrContents <-
26432137 if Unboxed.isPinned (arrContents arr1)
2644− then liftIO $ Unboxed.pinnedNew len
2645− else liftIO $ Unboxed.new len
2138+ then Unboxed.pinnedNew newLen
2139+ else Unboxed.new newLen
2140+ let len = len1 + len2
26462141 putSliceUnsafe (arrContents arr1) start1 newArrContents 0 len1
26472142 putSliceUnsafe (arrContents arr2) start2 newArrContents len1 len2
26482143 return $ MutArray newArrContents 0 len len
@@ -2654,7 +2149,7 @@ spliceCopy arr1 arr2 = do
26542149spliceUnsafe :: MonadIO m =>
26552150 MutArray a -> MutArray a -> m (MutArray a)
26562151spliceUnsafe dst src =
2657− do
2152+ liftIO $ do
26582153 let startSrc = arrStart src
26592154 srcLen = arrEnd src - startSrc
26602155 endDst = arrEnd dst
@@ -2676,7 +2171,7 @@ spliceWith :: forall m a. (MonadIO m, Unbox a) =>
26762171 (Int -> Int -> Int) -> MutArray a -> MutArray a -> m (MutArray a)
26772172spliceWith sizer dst@(MutArray _ start end bound) src = do
26782173{-
2679− let f = appendWith (`sizer` byteLength src) (return dst)
2174+ let f = writeAppendWith (`sizer` byteLength src) (return dst)
26802175 in D.fold f (toStreamD src)
26812176-}
26822177 assert (end <= bound) (return ())
@@ -2692,7 +2187,7 @@ spliceWith sizer dst@(MutArray _ start end bound) src = do
26922187 $ "splice: newSize is less than the total size "
26932188 ++ "of arrays being appended. Please check the "
26942189 ++ "sizer function passed."
2695− realloc newSizeInBytes dst
2190+ liftIO $ realloc newSizeInBytes dst
26962191 else return dst
26972192 spliceUnsafe dst1 src
26982193
@@ -2729,24 +2224,14 @@ spliceExp = spliceWith (\l1 l2 -> max (l1 * 2) (l1 + l2))
27292224-- Splitting
27302225-------------------------------------------------------------------------------
27312226
2732−-- | Generate a stream of array slices using a predicate. The array element
2733−-- matching the predicate is dropped.
2734−--
2735−-- /Pre-release/
2736−{-# INLINE splitOn #-}
2737−splitOn :: (MonadIO m, Unbox a) =>
2738− (a -> Bool) -> MutArray a -> Stream m (MutArray a)
2739−splitOn predicate arr =
2740− fmap (\(i, len) -> getSliceUnsafe i len arr)
2741− $ D.indexOnSuffix predicate (read arr)
2742−
27432227-- | Drops the separator byte
27442228{-# INLINE breakOn #-}
27452229breakOn :: MonadIO m
27462230 => Word8 -> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
2747−breakOn sep arr@MutArray{..} = unsafeAsPtr arr $ \p -> liftIO $ do
2231+breakOn sep arr@MutArray{..} = asPtrUnsafe arr $ \p -> liftIO $ do
2232+ -- XXX Instead of using asPtrUnsafe (pinning memory) we can pass unlifted
2233+ -- Addr# to memchr and it should be safe (from ghc 8.4).
27482234 -- XXX We do not need memchr here, we can use a Haskell equivalent.
2749− -- Need efficient stream based primitives that work on Word64.
27502235 loc <- c_memchr p sep (fromIntegral $ byteLength arr)
27512236 let sepIndex = loc `minusPtr` p
27522237 return $
@@ -2767,41 +2252,32 @@ breakOn sep arr@MutArray{..} = unsafeAsPtr arr $ \p -> liftIO $ do
27672252 }
27682253 )
27692254
2770−-- | Like 'splitAt' but does not check whether the index is valid.
2771−--
2772−{-# INLINE unsafeSplitAt #-}
2773−unsafeSplitAt :: forall a. Unbox a =>
2774− Int -> MutArray a -> (MutArray a, MutArray a)
2775−unsafeSplitAt i MutArray{..} =
2776− let off = i * SIZE_OF(a)
2777− p = arrStart + off
2778− in ( MutArray
2779− { arrContents = arrContents
2780− , arrStart = arrStart
2781− , arrEnd = p
2782− , arrBound = p
2783− }
2784− , MutArray
2785− { arrContents = arrContents
2786− , arrStart = p
2787− , arrEnd = arrEnd
2788− , arrBound = arrBound
2789− }
2790− )
2791−
27922255-- | Create two slices of an array without copying the original array. The
27932256-- specified index @i@ is the first index of the second slice.
27942257--
2795−{-# INLINE splitAt #-}
27962258splitAt :: forall a. Unbox a => Int -> MutArray a -> (MutArray a, MutArray a)
2797−splitAt i arr =
2259+splitAt i arr@MutArray{..} =
27982260 let maxIndex = length arr - 1
27992261 in if i < 0
28002262 then error "sliceAt: negative array index"
28012263 else if i > maxIndex
28022264 then error $ "sliceAt: specified array index " ++ show i
28032265 ++ " is beyond the maximum index " ++ show maxIndex
2804− else unsafeSplitAt i arr
2266+ else let off = i * SIZE_OF(a)
2267+ p = arrStart + off
2268+ in ( MutArray
2269+ { arrContents = arrContents
2270+ , arrStart = arrStart
2271+ , arrEnd = p
2272+ , arrBound = p
2273+ }
2274+ , MutArray
2275+ { arrContents = arrContents
2276+ , arrStart = p
2277+ , arrEnd = arrEnd
2278+ , arrBound = arrBound
2279+ }
2280+ )
28052281
28062282-------------------------------------------------------------------------------
28072283-- Casting
@@ -2851,13 +2327,9 @@ cast arr =
28512327-- guarantees that unsafe calls will be performed in the calling thread. Making
28522328-- it safe to pass heap-allocated objects to unsafe functions.
28532329
2854−-- XXX Should we just name it asPtr, the unsafety is implicit for any pointer
2330+-- Should we just name it asPtr, the unsafety is implicit for any pointer
28552331-- operations. And we are safe from Haskell perspective because we will be
28562332-- pinning the memory.
2857−--
2858−-- XXX we cannot pass the length of the ptr here as in some cases it may not be
2859−-- available e.g. a null terminated C string. However, we can create another
2860−-- flavor of the API e.g. asPtrN.
28612333
28622334-- | Use a @MutArray a@ as @Ptr a@. This is useful when we want to pass an
28632335-- array as a pointer to some operating system call or to a "safe" FFI call.
@@ -2875,377 +2347,48 @@ cast arr =
28752347--
28762348-- /Pre-release/
28772349--
2878−{-# INLINE unsafePinnedAsPtr #-}
2879−unsafePinnedAsPtr :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
2880−unsafePinnedAsPtr arr f =
2881− Unboxed.unsafePinnedAsPtr
2882− (arrContents arr) (\ptr -> f (ptr `plusPtr` arrStart arr))
2883−
2884−{-# DEPRECATED asPtrUnsafe "Please use unsafePinnedAsPtr instead." #-}
28852350{-# INLINE asPtrUnsafe #-}
28862351asPtrUnsafe :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
2887−asPtrUnsafe = unsafePinnedAsPtr
2888−
2889−{-# INLINE unsafeAsPtr #-}
2890−unsafeAsPtr :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
2891−unsafeAsPtr arr f =
2892− Unboxed.unsafeAsPtr
2352+asPtrUnsafe arr f =
2353+ Unboxed.asPtrUnsafe
28932354 (arrContents arr) (\ptr -> f (ptr `plusPtr` arrStart arr))
28942355
28952356-------------------------------------------------------------------------------
28962357-- Equality
28972358-------------------------------------------------------------------------------
28982359
2899−-- | Byte compare two arrays. Compare the length of the arrays. If the length
2900−-- is equal, compare the lexicographical ordering of two underlying byte arrays
2901−-- otherwise return the result of length comparison.
2902−--
2903−-- /Unsafe/: Note that the 'Unbox' instance of sum types with constructors of
2904−-- different sizes may leave some memory uninitialized which can make byte
2905−-- comparison unreliable.
2360+-- | Compare the length of the arrays. If the length is equal, compare the
2361+-- lexicographical ordering of two underlying byte arrays otherwise return the
2362+-- result of length comparison.
29062363--
29072364-- /Pre-release/
2908−{-# INLINE byteCmp #-}
2909−byteCmp :: MonadIO m => MutArray a -> MutArray a -> m Ordering
2910−byteCmp arr1 arr2 = do
2911− let marr1 = getMutableByteArray# (arrContents arr1)
2912− marr2 = getMutableByteArray# (arrContents arr2)
2913− !(I# st1#) = arrStart arr1
2914− !(I# st2#) = arrStart arr2
2915− !(I# len#) = byteLength arr1
2916− case compare (byteLength arr1) (byteLength arr2) of
2917− EQ -> do
2918− r <- liftIO $ IO $ \s# ->
2919− let res =
2920− I#
2921− (compareByteArrays#
2922− (unsafeCoerce# marr1)
2923− st1#
2924− (unsafeCoerce# marr2)
2925− st2#
2926− len#)
2927− in (# s#, res #)
2928− return $ compare r 0
2929− x -> return x
2930−
29312365{-# INLINE cmp #-}
2932−{-# DEPRECATED cmp "Please use byteCmp instead." #-}
29332366cmp :: MonadIO m => MutArray a -> MutArray a -> m Ordering
2934−cmp = byteCmp
2367+cmp arr1 arr2 =
2368+ liftIO
2369+ $ do
2370+ let marr1 = getMutableByteArray# (arrContents arr1)
2371+ marr2 = getMutableByteArray# (arrContents arr2)
2372+ !(I# st1#) = arrStart arr1
2373+ !(I# st2#) = arrStart arr2
2374+ !(I# len#) = byteLength arr1
2375+ case compare (byteLength arr1) (byteLength arr2) of
2376+ EQ -> do
2377+ r <- liftIO $ IO $ \s# ->
2378+ let res =
2379+ I#
2380+ (compareByteArrays#
2381+ (unsafeCoerce# marr1)
2382+ st1#
2383+ (unsafeCoerce# marr2)
2384+ st2#
2385+ len#)
2386+ in (# s#, res #)
2387+ return $ compare r 0
2388+ x -> return x
29352389
2936−-- | Byte equality of two arrays.
2937−--
2938−-- >>> byteEq arr1 arr2 = (==) EQ $ MArray.byteCmp arr1 arr2
2939−--
2940−-- /Unsafe/: See 'byteCmp'.
2941−{-# INLINE byteEq #-}
2942−byteEq :: MonadIO m => MutArray a -> MutArray a -> m Bool
2943−byteEq arr1 arr2 = fmap (EQ ==) $ byteCmp arr1 arr2
2944−
2945−-------------------------------------------------------------------------------
2946−-- Compact
29472390-------------------------------------------------------------------------------
2948−
2949−-- Note: LE versions avoid an extra copy compared to GE. LE parser trades
2950−-- backtracking one array in lieu of avoiding a copy. However, LE and GE both
2951−-- can leave some memory unused. They can split the last array to fit it
2952−-- exactly in the space.
2953−
2954−{-# INLINE_NORMAL pCompactLeAs #-}
2955−pCompactLeAs ::
2956− forall m a. (MonadIO m, Unbox a)
2957− => PinnedState -> Int -> Parser (MutArray a) m (MutArray a)
2958−pCompactLeAs ps maxElems = Parser step initial extract
2959−
2960− where
2961−
2962− maxBytes = maxElems * SIZE_OF(a)
2963−
2964− functionName = "Streamly.Internal.Data.MutArray.pCompactLE"
2965−
2966− initial =
2967− return
2968− $ if maxElems <= 0
2969− then error
2970− $ functionName
2971− ++ ": the size of arrays ["
2972− ++ show maxElems ++ "] must be a natural number"
2973− else Parser.IPartial Nothing
2974−
2975− step Nothing arr =
2976− return
2977− $ let len = byteLength arr
2978− in if len >= maxBytes
2979− then Parser.Done 0 arr
2980− else Parser.Partial 0 (Just arr)
2981− -- XXX Split the last array to use the space more compactly.
2982− step (Just buf) arr =
2983− let len = byteLength buf + byteLength arr
2984− in if len > maxBytes
2985− then return $ Parser.Done 1 buf
2986− else do
2987− buf1 <-
2988− if byteCapacity buf < maxBytes
2989− then liftIO $ reallocExplicitAs
2990− ps (SIZE_OF(a)) maxBytes buf
2991− else return buf
2992− buf2 <- spliceUnsafe buf1 arr
2993− return $ Parser.Partial 0 (Just buf2)
2994−
2995− extract Nothing = return $ Parser.Done 0 nil
2996− extract (Just buf) = return $ Parser.Done 0 buf
2997−
2998−-- | Parser @pCompactLE maxElems@ coalesces adjacent arrays in the input stream
2999−-- only if the combined size would be less than or equal to @maxElems@
3000−-- elements. Note that it won't split an array if the original array is already
3001−-- larger than maxElems.
3002−--
3003−-- @maxElems@ must be greater than 0.
3004−--
3005−-- Generates unpinned arrays irrespective of the pinning status of input
3006−-- arrays.
3007−--
3008−-- /Internal/
3009−{-# INLINE pCompactLE #-}
3010−pCompactLE ::
3011− forall m a. (MonadIO m, Unbox a)
3012− => Int -> Parser (MutArray a) m (MutArray a)
3013−pCompactLE = pCompactLeAs Unpinned
3014−
3015−-- | Pinned version of 'pCompactLE'.
3016−{-# INLINE pPinnedCompactLE #-}
3017−pPinnedCompactLE ::
3018− forall m a. (MonadIO m, Unbox a)
3019− => Int -> Parser (MutArray a) m (MutArray a)
3020−pPinnedCompactLE = pCompactLeAs Pinned
3021−
3022−data SpliceState s arr
3023− = SpliceInitial s
3024− | SpliceBuffering s arr
3025− | SpliceYielding arr (SpliceState s arr)
3026− | SpliceFinish
3027−
3028−-- This mutates the first array (if it has space) to append values from the
3029−-- second one. This would work for immutable arrays as well because an
3030−-- immutable array never has additional space so a new array is allocated
3031−-- instead of mutating it.
3032−
3033−{-# INLINE_NORMAL compactLeAs #-}
3034−compactLeAs :: forall m a. (MonadIO m, Unbox a)
3035− => PinnedState -> Int -> D.Stream m (MutArray a) -> D.Stream m (MutArray a)
3036−compactLeAs ps maxElems (D.Stream step state) =
3037− D.Stream step' (SpliceInitial state)
3038−
3039− where
3040−
3041− maxBytes = maxElems * SIZE_OF(a)
3042−
3043− functionName = "Streamly.Internal.Data.MutArray.rCompactLE"
3044−
3045− {-# INLINE_LATE step' #-}
3046− step' gst (SpliceInitial st) = do
3047− when (maxElems <= 0) $
3048− -- XXX we can pass the module string from the higher level API
3049− error $ functionName ++ ": the size of arrays [" ++ show maxElems
3050− ++ "] must be a natural number"
3051− r <- step gst st
3052− case r of
3053− D.Yield arr s -> return $
3054− let len = byteLength arr
3055− in if len >= maxBytes
3056− then D.Skip (SpliceYielding arr (SpliceInitial s))
3057− else D.Skip (SpliceBuffering s arr)
3058− D.Skip s -> return $ D.Skip (SpliceInitial s)
3059− D.Stop -> return D.Stop
3060−
3061− -- XXX Split the last array to use the space more compactly.
3062− step' gst (SpliceBuffering st buf) = do
3063− r <- step gst st
3064− case r of
3065− D.Yield arr s -> do
3066− let len = byteLength buf + byteLength arr
3067− if len > maxBytes
3068− then return $
3069− D.Skip (SpliceYielding buf (SpliceBuffering s arr))
3070− else do
3071− buf1 <- if byteCapacity buf < maxBytes
3072− then liftIO $ reallocExplicitAs
3073− ps (SIZE_OF(a)) maxBytes buf
3074− else return buf
3075− buf2 <- spliceUnsafe buf1 arr
3076− return $ D.Skip (SpliceBuffering s buf2)
3077− D.Skip s -> return $ D.Skip (SpliceBuffering s buf)
3078− D.Stop -> return $ D.Skip (SpliceYielding buf SpliceFinish)
3079−
3080− step' _ SpliceFinish = return D.Stop
3081−
3082− step' _ (SpliceYielding arr next) = return $ D.Yield arr next
3083−
3084−
3085−{-# INLINE_NORMAL fCompactGeAs #-}
3086−fCompactGeAs ::
3087− forall m a. (MonadIO m, Unbox a)
3088− => PinnedState -> Int -> FL.Fold m (MutArray a) (MutArray a)
3089−fCompactGeAs ps minElems = Fold step initial extract extract
3090−
3091− where
3092−
3093− minBytes = minElems * SIZE_OF(a)
3094−
3095− functionName = "Streamly.Internal.Data.MutArray.fCompactGE"
3096−
3097− initial =
3098− return
3099− $ if minElems < 0
3100− then error
3101− $ functionName
3102− ++ ": the size of arrays ["
3103− ++ show minElems ++ "] must be a natural number"
3104− else FL.Partial Nothing
3105−
3106− step Nothing arr =
3107− return
3108− $ let len = byteLength arr
3109− in if len >= minBytes
3110− then FL.Done arr
3111− else FL.Partial (Just arr)
3112− -- XXX Buffer arrays as a list to avoid copy and reallocations
3113− step (Just buf) arr = do
3114− let len = byteLength buf + byteLength arr
3115− buf1 <-
3116− if byteCapacity buf < len
3117− then liftIO $ reallocExplicitAs
3118− ps (SIZE_OF(a)) (max minBytes len) buf
3119− else return buf
3120− buf2 <- spliceUnsafe buf1 arr
3121− if len >= minBytes
3122− then return $ FL.Done buf2
3123− else return $ FL.Partial (Just buf2)
3124−
3125− extract Nothing = return nil
3126− extract (Just buf) = return buf
3127−
3128−-- | Fold @fCompactGE minElems@ coalesces adjacent arrays in the input stream
3129−-- until the size becomes greater than or equal to @minElems@.
3130−--
3131−-- Generates unpinned arrays irrespective of the pinning status of input
3132−-- arrays.
3133−{-# INLINE fCompactGE #-}
3134−fCompactGE ::
3135− forall m a. (MonadIO m, Unbox a)
3136− => Int -> FL.Fold m (MutArray a) (MutArray a)
3137−fCompactGE = fCompactGeAs Unpinned
3138−
3139−-- | Pinned version of 'fCompactGE'.
3140−{-# INLINE fPinnedCompactGE #-}
3141−fPinnedCompactGE ::
3142− forall m a. (MonadIO m, Unbox a)
3143− => Int -> FL.Fold m (MutArray a) (MutArray a)
3144−fPinnedCompactGE = fCompactGeAs Pinned
3145−
3146−{-# INLINE_NORMAL lCompactGeAs #-}
3147−lCompactGeAs :: forall m a. (MonadIO m, Unbox a)
3148− => PinnedState -> Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
3149−-- The fold version turns out to be a little bit slower.
3150−-- lCompactGeAs ps n = FL.many (fCompactGeAs ps n)
3151−lCompactGeAs ps minElems (Fold step1 initial1 _ final1) =
3152− Fold step initial extract final
3153−
3154− where
3155−
3156− minBytes = minElems * SIZE_OF(a)
3157−
3158− functionName = "Streamly.Internal.Data.MutArray.lCompactGE"
3159−
3160− initial = do
3161− when (minElems <= 0) $
3162− -- XXX we can pass the module string from the higher level API
3163− error $ functionName ++ ": the size of arrays ["
3164− ++ show minElems ++ "] must be a natural number"
3165−
3166− r <- initial1
3167− return $ first (Tuple' Nothing) r
3168−
3169− {-# INLINE runInner #-}
3170− runInner len acc buf =
3171− if len >= minBytes
3172− then do
3173− r <- step1 acc buf
3174− case r of
3175− FL.Done _ -> return $ FL.Done ()
3176− FL.Partial s -> do
3177− _ <- final1 s
3178− res <- initial1
3179− return $ first (Tuple' Nothing) res
3180− else return $ FL.Partial $ Tuple' (Just buf) acc
3181−
3182− step (Tuple' Nothing r1) arr =
3183− runInner (byteLength arr) r1 arr
3184−
3185− -- XXX Buffer arrays as a list to avoid copy and reallocations
3186− step (Tuple' (Just buf) r1) arr = do
3187− let len = byteLength buf + byteLength arr
3188− buf1 <- if byteCapacity buf < len
3189− then liftIO $ reallocExplicitAs
3190− ps (SIZE_OF(a)) (max minBytes len) buf
3191− else return buf
3192− buf2 <- spliceUnsafe buf1 arr
3193− runInner len r1 buf2
3194−
3195− -- XXX Several folds do extract >=> final, therefore, we need to make final
3196− -- return "m b" rather than using extract post it if we want extract to be
3197− -- partial.
3198− --
3199− -- extract forces the pending buffer to be sent to the fold which is not
3200− -- what we want.
3201− extract _ = error "lCompactGE: not designed for scanning"
3202−
3203− final (Tuple' Nothing r1) = final1 r1
3204− final (Tuple' (Just buf) r1) = do
3205− r <- step1 r1 buf
3206− case r of
3207− FL.Partial rr -> final1 rr
3208− FL.Done _ -> return ()
3209−
3210−-- | Like 'compactGE' but for transforming folds instead of stream.
3211−--
3212−-- >>> lCompactGE n = Fold.many (MutArray.fCompactGE n)
3213−--
3214−-- Generates unpinned arrays irrespective of the pinning status of input
3215−-- arrays.
3216−{-# INLINE lCompactGE #-}
3217−lCompactGE :: forall m a. (MonadIO m, Unbox a)
3218− => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
3219−lCompactGE = lCompactGeAs Unpinned
3220−
3221−-- | Pinned version of 'lCompactGE'.
3222−{-# INLINE lPinnedCompactGE #-}
3223−lPinnedCompactGE :: forall m a. (MonadIO m, Unbox a)
3224− => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
3225−lPinnedCompactGE = lCompactGeAs Pinned
3226−
3227−-- | @compactGE n stream@ coalesces adjacent arrays in the @stream@ until
3228−-- the size becomes greater than or equal to @n@.
3229−--
3230−-- >>> compactGE n = Stream.foldMany (MutArray.fCompactGE n)
3231−--
3232−{-# INLINE compactGE #-}
3233−compactGE ::
3234− (MonadIO m, Unbox a)
3235− => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
3236−compactGE n = D.foldMany (fCompactGE n)
3237−
3238−-- | 'compactEQ n' coalesces adajacent arrays in the input stream to
3239−-- arrays of exact size @n@.
3240−--
3241−-- /Unimplemented/
3242−{-# INLINE compactEQ #-}
3243−compactEQ :: -- (MonadIO m, Unbox a) =>
3244− Int -> Stream m (MutArray a) -> Stream m (MutArray a)
3245−compactEQ _n = undefined -- D.parseManyD (pCompactEQ n)
3246−
3247−-------------------------------------------------------------------------------
3248−-- In-place mutation algorithms
2391+-- NFData
32492392-------------------------------------------------------------------------------
32502393
32512394-- | Strip elements which match with predicate from both ends.
core/src/Streamly/Internal/Data/MutByteArray/Type.hs+15−55
@@ -13,7 +13,7 @@ module Streamly.Internal.Data.MutByteArray.Type
1313 -- ** MutByteArray
1414 MutByteArray(..)
1515 , MutableByteArray
16− , getMutableByteArray# -- XXX getMutByteArray#
16+ , getMutableByteArray#
1717
1818 -- ** Pinning
1919 , PinnedState(..)
@@ -22,29 +22,23 @@ module Streamly.Internal.Data.MutByteArray.Type
2222 , unpin
2323
2424 -- ** Allocation
25− , empty
26− , newBytesAs -- XXX should be removed
25+ , nil
26+ , newBytesAs
2727 , new
2828 , pinnedNew
29− , pinnedNewAlignedBytes -- XXX should be removed
29+ , pinnedNewAlignedBytes
3030
3131 -- ** Access
32− , sizeOfMutableByteArray -- XXX length
32+ , sizeOfMutableByteArray
3333 , putSliceUnsafe
3434 , cloneSliceUnsafeAs
3535 , cloneSliceUnsafe
3636 , pinnedCloneSliceUnsafe
37− , unsafePinnedAsPtr
38− , unsafeAsPtr
39−
40− -- ** Deprecated
4137 , asPtrUnsafe
42− , nil
4338 ) where
4439
4540import Control.Monad.IO.Class (MonadIO(..))
4641#ifdef DEBUG
47−import Control.Monad (when)
4842import Debug.Trace (trace)
4943#endif
5044import GHC.Base (IO(..))
@@ -58,7 +52,7 @@ import GHC.Exts
5852
5953data PinnedState
6054 = Pinned
61− | Unpinned deriving (Show, Eq)
55+ | Unpinned
6256
6357-- XXX can use UnliftedNewtypes
6458
@@ -87,9 +81,6 @@ touch :: MutByteArray -> IO ()
8781touch (MutByteArray contents) =
8882 IO $ \s -> case touch# contents s of s' -> (# s', () #)
8983
90−-- XXX Some functions in this module are "IO" and others are "m", we need to
91−-- make it consistent.
92−
9384-- XXX We can provide another API for "unsafe" FFI calls passing an unlifted
9485-- pointer to the FFI call. For unsafe calls we do not need to pin the array.
9586-- We can pass an unlifted pointer to the FFI routine to avoid GC kicking in
@@ -118,9 +109,9 @@ touch (MutByteArray contents) =
118109--
119110-- /Pre-release/
120111--
121−{-# INLINE unsafePinnedAsPtr #-}
122−unsafePinnedAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
123−unsafePinnedAsPtr arr f = do
112+{-# INLINE asPtrUnsafe #-}
113+asPtrUnsafe :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
114+asPtrUnsafe arr f = do
124115 contents <- liftIO $ pin arr
125116 let !ptr = Ptr (byteArrayContents#
126117 (unsafeCoerce# (getMutableByteArray# contents)))
@@ -128,35 +119,14 @@ unsafePinnedAsPtr arr f = do
128119 liftIO $ touch contents
129120 return r
130121
131−{-# DEPRECATED asPtrUnsafe "Please use unsafePinnedAsPtr instead." #-}
132−{-# INLINE asPtrUnsafe #-}
133−asPtrUnsafe :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
134−asPtrUnsafe = unsafePinnedAsPtr
135−
136−-- | For use with unsafe FFI functions. Does not force pin the array memory.
137−{-# INLINE unsafeAsPtr #-}
138−unsafeAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
139−unsafeAsPtr arr f = do
140− let !ptr = Ptr (byteArrayContents#
141− (unsafeCoerce# (getMutableByteArray# arr)))
142− r <- f ptr
143− liftIO $ touch arr
144− return r
145−
146122--------------------------------------------------------------------------------
147123-- Creation
148124--------------------------------------------------------------------------------
149125
150−{-# NOINLINE empty #-}
151−empty :: MutByteArray
152−empty = unsafePerformIO $ new 0
153−
154−{-# DEPRECATED nil "Please use empty instead" #-}
126+{-# NOINLINE nil #-}
155127nil :: MutByteArray
156−nil = empty
128+nil = unsafePerformIO $ new 0
157129
158−-- XXX add "newRounded" to round up the large size to the next page boundary
159−-- and return the allocated size.
160130{-# INLINE new #-}
161131new :: Int -> IO MutByteArray
162132new nbytes | nbytes < 0 =
@@ -170,7 +140,7 @@ new (I# nbytes) = IO $ \s ->
170140{-# INLINE pinnedNew #-}
171141pinnedNew :: Int -> IO MutByteArray
172142pinnedNew nbytes | nbytes < 0 =
173− errorWithoutStackTrace "pinnedNew: size must be >= 0"
143+ errorWithoutStackTrace "pinnedNewByteArray: size must be >= 0"
174144pinnedNew (I# nbytes) = IO $ \s ->
175145 case newPinnedByteArray# nbytes s of
176146 (# s', mbarr# #) ->
@@ -196,12 +166,6 @@ newBytesAs Pinned = pinnedNew
196166-- Copying
197167-------------------------------------------------------------------------------
198168
199−-- Note: Array copy is more efficient than streaming copy.
200−-- CopyMutableByteArray# translates to genMemcpy in GHC/CmmToAsm/X86/CodeGen.hs
201−-- glibc memcpy copies bytes/words/pages - unrolls the loops:
202−-- https://github.com/bminor/glibc/blob/4290aed05135ae4c0272006442d147f2155e70d7/string/memcpy.c
203−-- https://github.com/bminor/glibc/blob/4290aed05135ae4c0272006442d147f2155e70d7/string/wordcopy.c
204−
205169-- | Put a sub range of a source array into a subrange of a destination array.
206170-- This is not safe as it does not check the bounds of neither the src array
207171-- nor the destination array.
@@ -217,13 +181,9 @@ putSliceUnsafe ::
217181putSliceUnsafe src srcStartBytes dst dstStartBytes lenBytes = liftIO $ do
218182#ifdef DEBUG
219183 srcLen <- sizeOfMutableByteArray src
220− dstLen <- sizeOfMutableByteArray dst
221− when (srcLen - srcStartBytes < lenBytes)
222− $ error $ "putSliceUnsafe: src overflow: start" ++ show srcStartBytes
223− ++ " end " ++ show srcLen ++ " len " ++ show lenBytes
224− when (dstLen - dstStartBytes < lenBytes)
225− $ error $ "putSliceUnsafe: dst overflow: start" ++ show dstStartBytes
226− ++ " end " ++ show dstLen ++ " len " ++ show lenBytes
184+ dstLen <- sizeOfMutableByteArray src
185+ when (srcLen - srcStartBytes < lenBytes) $ error "SRC: Insufficient length."
186+ when (dstLen - dstStartBytes < lenBytes) $ error "DST: Insufficient length."
227187#endif
228188 let !(I# srcStartBytes#) = srcStartBytes
229189 !(I# dstStartBytes#) = dstStartBytes
core/src/Streamly/Internal/Data/Serialize/TH.hs+15−28
@@ -7,11 +7,7 @@
77-- Maintainer : streamly@composewell.com
88-- Stability : experimental
99-- Portability : GHC
10−
11−-- XXX Instead of applying the product constructor in one go can we apply it
12−-- one at a time in case of too many arguments, compiler may not have to save
13−-- them in local vars.
14−
10+--
1511module Streamly.Internal.Data.Serialize.TH
1612 (
1713 -- Deriving
@@ -221,7 +217,6 @@ mkDeserializeExpr True False headTy tyOfTy =
221217mkDeserializeExpr False False headTy tyOfTy =
222218 case tyOfTy of
223219 -- Unit constructor
224− -- XXX Should we peek and check if the byte value is 0?
225220 UnitType cname ->
226221 [|pure ($(varE _initialOffset) + 1, $(conE cname))|]
227222 -- Product type
@@ -346,8 +341,7 @@ mkSerializeExpr True False tyOfTy =
346341mkSerializeExpr False False tyOfTy =
347342 case tyOfTy of
348343 -- Unit type
349− UnitType _ ->
350− [|serializeAt $(varE _initialOffset) $(varE _arr) (0 :: Word8)|]
344+ UnitType _ -> [|pure ($(varE _initialOffset) + 1)|]
351345 -- Product type
352346 (TheType (SimpleDataCon cname fields)) ->
353347 letE
@@ -401,7 +395,7 @@ mkSerializeDec (SerializeConfig {..}) headTy cons = do
401395 'serializeAt
402396 [ Clause
403397 (if isUnitType cons && not cfgConstructorTagAsString
404− then [VarP _initialOffset, VarP _arr, WildP]
398+ then [VarP _initialOffset, WildP, WildP]
405399 else [VarP _initialOffset, VarP _arr, VarP _val])
406400 (NormalB pokeMethod)
407401 []
@@ -452,36 +446,29 @@ deriveSerializeInternal conf headTy cons next = do
452446 let methods = concat [sizeDec, peekDec, pokeDec]
453447 next methods
454448
455−-- | @deriveSerializeWith config-modifier instance-dec@ generates a template
456−-- Haskell splice consisting of a declaration of a 'Serialize' instance.
457−-- @instance-dec@ is a template Haskell declaration splice consisting of a
458−-- standard Haskell instance declaration without the type class methods (e.g.
459−-- @[d|instance Serialize a => Serialize (Maybe a)|]@).
460−--
461−-- The type class methods for the given instance are generated according to the
462−-- supplied @config-modifier@ parameter. See 'SerializeConfig' for default
463−-- configuration settings.
449+-- | @deriveSerializeWith config instance-dec@ generates a template Haskell
450+-- splice consisting of a declaration of a 'Serialize' instance. @instance-dec@
451+-- is a template Haskell declaration splice consisting of a standard Haskell
452+-- instance declaration without the type class methods (e.g. @[d|instance
453+-- Serialize a => Serialize (Maybe a)|]@). The type class methods for the given
454+-- instance are generated according to the supplied @config@ parameter.
464455--
465456-- Usage:
466457--
467458-- @
468459-- \$(deriveSerializeWith
469−-- ( inlineSerializeAt (Just NoInline)
470−-- . inlineDeserializeAt (Just NoInline)
471−-- )
460+-- serializeConfig
472461-- [d|instance Serialize a => Serialize (Maybe a)|])
473462-- @
474−deriveSerializeWith ::
475− (SerializeConfig -> SerializeConfig) -> Q [Dec] -> Q [Dec]
476−deriveSerializeWith modifier mDecs = do
463+deriveSerializeWith :: SerializeConfig -> Q [Dec] -> Q [Dec]
464+deriveSerializeWith conf mDecs = do
477465 dec <- mDecs
478466 case dec of
479467 [InstanceD mo preds headTyWC []] -> do
480468 let headTy = unwrap dec headTyWC
481469 dt <- reifyDataType (getMainTypeName dec headTy)
482470 let cons = dtCons dt
483− deriveSerializeInternal
484− (modifier serializeConfig) headTy cons (next mo preds headTyWC)
471+ deriveSerializeInternal conf headTy cons (next mo preds headTyWC)
485472 _ -> errorMessage dec
486473
487474 where
@@ -518,7 +505,7 @@ deriveSerializeWith modifier mDecs = do
518505-- @[d|instance Serialize a => Serialize (Maybe a)|]@), generate an instance
519506-- declaration including all the type class method implementations.
520507--
521−-- >>> deriveSerialize = deriveSerializeWith id
508+-- >>> deriveSerialize = deriveSerializeWith serializeConfig
522509--
523510-- Usage:
524511--
@@ -527,4 +514,4 @@ deriveSerializeWith modifier mDecs = do
527514-- [d|instance Serialize a => Serialize (Maybe a)|])
528515-- @
529516deriveSerialize :: Q [Dec] -> Q [Dec]
530−deriveSerialize = deriveSerializeWith id
517+deriveSerialize = deriveSerializeWith serializeConfig
core/src/Streamly/Internal/Data/Serialize/TH/Bottom.hs+29−35
@@ -80,22 +80,11 @@ import Streamly.Internal.Data.Unbox.TH (DataCon(..))
8080-- no inline specific pragma let's GHC decide whether to put the code in
8181-- interface file or not.
8282
83−-- | Configuration to control how the 'Serialize' instance is generated. The
84−-- configuration is opaque and is modified by composing config modifier
85−-- functions, for example:
83+-- | Configuration to control how the 'Serialize' instance is generated. Use
84+-- 'serializeConfig' and config setter functions to generate desired Config. For
85+-- example:
8686--
87−-- >>> (inlineSerializeAt (Just NoInline)) . (inlineSerializeAt (Just Inlinable))
88−--
89−-- The default configuration settings are:
90−--
91−-- * 'inlineAddSizeTo' Nothing
92−-- * 'inlineSerializeAt' (Just Inline)
93−-- * 'inlineDeserializeAt' (Just Inline)
94−--
95−-- The following experimental options are also available:
96−--
97−-- * 'encodeConstrNames' False
98−-- * 'encodeRecordFields' False
87+-- >>> (inlineAddSizeTo (Just Inline)) . (inlineSerializeAt (Just Inlinable)) serializeConfig
9988--
10089data SerializeConfig =
10190 SerializeConfig
@@ -106,19 +95,19 @@ data SerializeConfig =
10695 , cfgRecordSyntaxWithHeader :: Bool
10796 }
10897
109−-- | How should we inline the 'addSizeTo' function? The default is 'Nothing'
110−-- which means left to the compiler. Forcing inline on @addSizeTo@ function
111−-- actually worsens some benchmarks and improves none.
98+-- | How should we inline the 'addSizeTo' function? The default in 'serializeConfig'
99+-- is 'Nothing' which means left to the compiler. Forcing inline on @addSizeTo@
100+-- function actually worsens some benchmarks and improves none.
112101inlineAddSizeTo :: Maybe Inline -> SerializeConfig -> SerializeConfig
113102inlineAddSizeTo v cfg = cfg {cfgInlineSize = v}
114103
115104-- XXX Should we make the default Inlinable instead?
116105
117−-- | How should we inline the 'serialize' function? The default 'Just Inline'.
118−-- However, aggressive inlining can bloat the code and increase in compilation
119−-- times when there are big functions and too many nesting levels so you can
120−-- change it accordingly. A 'Nothing' value leaves the decision to the
121−-- compiler.
106+-- | How should we inline the 'serialize' function? The default in
107+-- 'serializeConfig' is 'Just Inline'. However, aggressive inlining can bloat
108+-- the code and increase in compilation times when there are big functions and
109+-- too many nesting levels so you can change it accordingly. A 'Nothing' value
110+-- leaves the decision to the compiler.
122111inlineSerializeAt :: Maybe Inline -> SerializeConfig -> SerializeConfig
123112inlineSerializeAt v cfg = cfg {cfgInlineSerialize = v}
124113
@@ -132,26 +121,25 @@ inlineDeserializeAt v cfg = cfg {cfgInlineDeserialize = v}
132121-- | __Experimental__
133122--
134123-- In sum types, use Latin-1 encoded original constructor names rather than
135−-- binary values to identify constructors. This option is not applicable to
136−-- product types.
124+-- binary values to identify constructors. This option is not useful on a
125+-- product type.
137126--
138−-- This option enables the following behavior:
127+-- This option enables the following backward compatible behavior:
139128--
140129-- * __Reordering__: Order of the fields can be changed without affecting
141130-- serialization.
142131-- * __Addition__: If a field is added in the new version, the old version of
143132-- the data type can still be deserialized by the new version. The new value
144133-- would never occur in the old one.
145−-- * __Deletion__: If a field is deleted in the new version, deserialization
134+-- * __Deletion__: If a field is deleted in the new version and deserialization
146135-- of the old version will result in an error. TBD: We can possibly designate a
147−-- catch-all case to handle this scenario.
136+-- catch-all field to handle this case.
148137--
149138-- Note that if you change a type, change the semantics of a type, or delete a
150139-- field and add a new field with the same name, deserialization of old data
151140-- may result in silent unexpected behavior.
152141--
153142-- This option has to be the same on both encoding and decoding side.
154−--
155143-- The default is 'False'.
156144--
157145encodeConstrNames :: Bool -> SerializeConfig -> SerializeConfig
@@ -167,11 +155,11 @@ encodeConstrNames v cfg = cfg {cfgConstructorTagAsString = v}
167155-- | __Experimental__
168156--
169157-- In explicit record types, use Latin-1 encoded record field names rather than
170−-- binary values to identify the record fields. Note that this option is not
171−-- applicable to sum types. Also, it does not work on a product type which is
172−-- not a record, because there are no field names to begin with.
158+-- binary values to identify the record fields. Note that this option cannot be
159+-- used on a sum type. Also, it does not work on a product type which is not a
160+-- record, because there are no field names to begin with.
173161--
174−-- This option enables the following behavior:
162+-- This option enables the following backward compatible behavior:
175163--
176164-- * __Reordering__: Order of the fields can be changed without affecting
177165-- serialization.
@@ -179,10 +167,10 @@ encodeConstrNames v cfg = cfg {cfgConstructorTagAsString = v}
179167-- version of the data type can still be deserialized by the new version, the
180168-- field value in the older version is assumed to be 'Nothing'. If any other
181169-- type of field is added, deserialization of the older version results in an
182−-- error but only when that field is actually accessed in the deserialized
183−-- record.
170+-- error but only when that field is accessed in the deserialized record.
184171-- * __Deletion__: If a field is deleted in the new version and it is
185172-- encountered in a previously serialized version then the field is discarded.
173+-- TBD: We can possibly designate a catch-all field to handle this case.
186174--
187175-- This option has to be the same on both encoding and decoding side.
188176--
@@ -194,6 +182,12 @@ encodeConstrNames v cfg = cfg {cfgConstructorTagAsString = v}
194182encodeRecordFields :: Bool -> SerializeConfig -> SerializeConfig
195183encodeRecordFields v cfg = cfg {cfgRecordSyntaxWithHeader = v}
196184
185+-- | The default configuration settings are:
186+--
187+-- * 'inlineAddSizeTo' 'Nothing'
188+-- * 'inlineSerializeAt' (Just Inline)
189+-- * 'inlineDeserializeAt' (Just Inline)
190+--
197191serializeConfig :: SerializeConfig
198192serializeConfig =
199193 SerializeConfig
core/src/Streamly/Internal/Data/Serialize/Type.hs+9−10
@@ -151,17 +151,20 @@ class Serialize a where
151151-- Instances
152152--------------------------------------------------------------------------------
153153
154−-- _size is the length from array start to the last accessed byte.
154+-- XXX We do not need to pass the end of data offset, we can just check the
155+-- mutable array end here to avoid a crash, and when we return from deserialize
156+-- we can check if the offset returned is beyond the bound or not.
157+--
155158#ifdef DEBUG
156159{-# INLINE checkBounds #-}
157160checkBounds :: String -> Int -> MutByteArray -> IO ()
158−checkBounds _label _size _arr = do
159− sz <- MBA.sizeOfMutableByteArray _arr
160− if (_size > sz)
161+checkBounds _label _off _arr = do
162+ sz <- sizeOfMutableByteArray _arr
163+ if (_off > sz)
161164 then error
162165 $ _label
163166 ++ ": accessing array at offset = "
164− ++ show (_size - 1)
167+ ++ show (_off - 1)
165168 ++ " max valid offset = " ++ show (sz - 1)
166169 else return ()
167170#endif
@@ -271,11 +274,7 @@ instance forall a. Serialize a => Serialize [a] where
271274 pokeList (acc + 1) o1 xs
272275 pokeList 0 off1 val
273276
274−instance
275−#ifdef DEVBUILD
276− Unbox a =>
277−#endif
278− Serialize (Array a) where
277+instance Serialize (Array a) where
279278 {-# INLINE addSizeTo #-}
280279 addSizeTo i (Array {..}) = i + (arrEnd - arrStart) + 8
281280
core/src/Streamly/Internal/Data/Stream/Container.hs+48−56
@@ -11,17 +11,16 @@
1111
1212module Streamly.Internal.Data.Stream.Container
1313 (
14− -- * Deduplication
15− ordNub
14+ nub
1615
17− -- * Joins
18− , leftJoin
19− , outerJoin
16+ -- * Joins for unconstrained types
17+ , joinLeftGeneric
18+ , joinOuterGeneric
2019
21− -- * Ord Joins
22− , innerOrdJoin
23− , leftOrdJoin
24− , outerOrdJoin
20+ -- * Joins with Ord constraint
21+ , joinInner
22+ , joinLeft
23+ , joinOuter
2524 )
2625where
2726
@@ -48,15 +47,12 @@ import qualified Streamly.Internal.Data.Stream.Transformer as Stream
4847
4948#include "DocTestDataStream.hs"
5049
51−-- | @nub@ specialized to 'Ord' types for better performance. Returns a
52−-- subsequence of the stream removing any duplicate elements.
53−--
54−-- The memory used is proportional to the number of unique elements in the
55−-- stream. One way to limit the memory is to use @take@ on the resulting
56−-- stream to limit the unique elements in the stream.
57−{-# INLINE_NORMAL ordNub #-}
58−ordNub :: (Monad m, Ord a) => Stream m a -> Stream m a
59−ordNub (Stream step1 state1) = Stream step (Set.empty, state1)
50+-- | The memory used is proportional to the number of unique elements in the
51+-- stream. If we want to limit the memory we can just use "take" to limit the
52+-- uniq elements in the stream.
53+{-# INLINE_NORMAL nub #-}
54+nub :: (Monad m, Ord a) => Stream m a -> Stream m a
55+nub (Stream step1 state1) = Stream step (Set.empty, state1)
6056
6157 where
6258
@@ -82,8 +78,8 @@ toMap =
8278--
8379-- XXX An IntMap may be faster when the keys are Int.
8480-- XXX Use hashmap instead of map?
85−
86−-- | 'innerJoin' specialized to 'Ord' types for better performance.
81+--
82+-- | Like 'joinInner' but uses a 'Map' for efficiency.
8783--
8884-- If the input streams have duplicate keys, the behavior is undefined.
8985--
@@ -94,10 +90,10 @@ toMap =
9490-- Time: O(m + n)
9591--
9692-- /Pre-release/
97−{-# INLINE innerOrdJoin #-}
98−innerOrdJoin :: (Monad m, Ord k) =>
93+{-# INLINE joinInner #-}
94+joinInner :: (Monad m, Ord k) =>
9995 Stream m (k, a) -> Stream m (k, b) -> Stream m (k, a, b)
100−innerOrdJoin s1 s2 =
96+joinInner s1 s2 =
10197 Stream.concatEffect $ do
10298 km <- toMap s2
10399 pure $ Stream.mapMaybe (joinAB km) s1
@@ -110,33 +106,32 @@ innerOrdJoin s1 s2 =
110106 Nothing -> Nothing
111107
112108-- XXX We can do this concurrently.
113−-- XXX Check performance of StreamD vs StreamK
114109-- XXX If the second stream is sorted and passed as an Array or a seek capable
115110-- stream then we could use binary search if we have an Ord instance or
116111-- Ordering returning function. The time complexity would then become (m x log
117112-- n).
118113
119−-- | Like 'innerJoin' but emits @(a, Just b)@ whenever a and b are equal, for
120−-- those @a@'s that are not equal to any @b@ emits @(a, Nothing)@.
121−--
122−-- This is a generalization of 'innerJoin' to include all elements from the
123−-- left stream and not just those which have an equal in the right stream. This
124−-- is not a commutative operation, the order of the stream arguments matters.
114+-- XXX Check performance of StreamD vs StreamK
115+
116+-- | Like 'joinInner' but emit @(a, Just b)@, and additionally, for those @a@'s
117+-- that are not equal to any @b@ emit @(a, Nothing)@.
125118--
126−-- All the caveats mentioned in 'innerJoin' apply here as well. Right join is
127−-- not provided because it is just a flipped left join:
119+-- The second stream is evaluated multiple times. If the stream is a
120+-- consume-once stream then the caller should cache it in an 'Data.Array.Array'
121+-- before calling this function. Caching may also improve performance if the
122+-- stream is expensive to evaluate.
128123--
129−-- >>> rightJoin eq = flip (Stream.leftJoin eq)
124+-- >>> joinRightGeneric eq = flip (Stream.joinLeftGeneric eq)
130125--
131126-- Space: O(n) assuming the second stream is cached in memory.
132127--
133128-- Time: O(m x n)
134129--
135130-- /Unimplemented/
136−{-# INLINE leftJoin #-}
137−leftJoin :: Monad m =>
131+{-# INLINE joinLeftGeneric #-}
132+joinLeftGeneric :: Monad m =>
138133 (a -> b -> Bool) -> Stream m a -> Stream m b -> Stream m (a, Maybe b)
139−leftJoin eq s1 s2 = Stream.evalStateT (return False) $ unCross $ do
134+joinLeftGeneric eq s1 s2 = Stream.evalStateT (return False) $ unCross $ do
140135 a <- mkCross (Stream.liftInner s1)
141136 -- XXX should we use StreamD monad here?
142137 -- XXX Is there a better way to perform some action at the end of a loop
@@ -157,17 +152,19 @@ leftJoin eq s1 s2 = Stream.evalStateT (return False) $ unCross $ do
157152 else mkCross Stream.nil
158153 Nothing -> return (a, Nothing)
159154
160−-- | 'leftJoin' specialized to 'Ord' types for better performance.
155+-- XXX rename to joinLeftOrd?
156+
157+-- | A more efficient 'joinLeft' using a hashmap for efficiency.
161158--
162159-- Space: O(n)
163160--
164161-- Time: O(m + n)
165162--
166163-- /Pre-release/
167−{-# INLINE leftOrdJoin #-}
168−leftOrdJoin :: (Ord k, Monad m) =>
164+{-# INLINE joinLeft #-}
165+joinLeft :: (Ord k, Monad m) =>
169166 Stream m (k, a) -> Stream m (k, b) -> Stream m (k, a, Maybe b)
170−leftOrdJoin s1 s2 =
167+joinLeft s1 s2 =
171168 Stream.concatEffect $ do
172169 km <- toMap s2
173170 return $ fmap (joinAB km) s1
@@ -180,19 +177,14 @@ leftOrdJoin s1 s2 =
180177 Nothing -> (k, a, Nothing)
181178
182179-- XXX We can do this concurrently.
183−-- XXX Check performance of StreamD vs StreamK cross operation.
184180
185−-- | Like 'leftJoin' but emits a @(Just a, Just b)@. Like 'leftJoin', for those
181+-- XXX Check performance of StreamD vs StreamK
182+
183+-- | Like 'joinLeft' but emits a @(Just a, Just b)@. Like 'joinLeft', for those
186184-- @a@'s that are not equal to any @b@ emit @(Just a, Nothing)@, but
187185-- additionally, for those @b@'s that are not equal to any @a@ emit @(Nothing,
188186-- Just b)@.
189187--
190−-- This is a generalization of left join to include all the elements from the
191−-- right stream as well, in other words it is a combination of left and right
192−-- joins. This is a commutative operation. The order of stream arguments can be
193−-- changed without affecting results, except for the ordering of elements in
194−-- the resulting tuple.
195−--
196188-- For space efficiency use the smaller stream as the second stream.
197189--
198190-- Space: O(n)
@@ -200,15 +192,15 @@ leftOrdJoin s1 s2 =
200192-- Time: O(m x n)
201193--
202194-- /Pre-release/
203−{-# INLINE outerJoin #-}
204−outerJoin :: MonadIO m =>
195+{-# INLINE joinOuterGeneric #-}
196+joinOuterGeneric :: MonadIO m =>
205197 (a -> b -> Bool)
206198 -> Stream m a
207199 -> Stream m b
208200 -> Stream m (Maybe a, Maybe b)
209−outerJoin eq s1 s2 =
201+joinOuterGeneric eq s1 s =
210202 Stream.concatEffect $ do
211− inputArr <- Array.fromStream s2
203+ inputArr <- Array.fromStream s
212204 let len = Array.length inputArr
213205 foundArr <-
214206 Stream.fold
@@ -262,18 +254,18 @@ outerJoin eq s1 s2 =
262254-- a flag. At the end go through @Stream m b@ and find those that are not in that
263255-- hash to return (Nothing, b).
264256
265−-- | 'outerJoin' specialized to 'Ord' types for better performance.
257+-- | Like 'joinOuter' but uses a 'Map' for efficiency.
266258--
267259-- Space: O(m + n)
268260--
269261-- Time: O(m + n)
270262--
271263-- /Pre-release/
272−{-# INLINE outerOrdJoin #-}
273−outerOrdJoin ::
264+{-# INLINE joinOuter #-}
265+joinOuter ::
274266 (Ord k, MonadIO m) =>
275267 Stream m (k, a) -> Stream m (k, b) -> Stream m (k, Maybe a, Maybe b)
276−outerOrdJoin s1 s2 =
268+joinOuter s1 s2 =
277269 Stream.concatEffect $ do
278270 km1 <- kvFold s1
279271 km2 <- kvFold s2
core/src/Streamly/Internal/Data/Stream/Eliminate.hs+25−33
@@ -13,24 +13,36 @@
1313--
1414module Streamly.Internal.Data.Stream.Eliminate
1515 (
16− -- * Running a Parser
17− parse
16+ -- * Running a 'Fold'
17+ fold
18+
19+ -- -- * Running a 'Parser'
20+ , parse
1821 , parseD
1922 , parseBreak
2023 , parseBreakD
2124
22− -- * Deconstruction
25+ -- * Stream Deconstruction
2326 , uncons
2427
2528 -- * Right Folds
29+ , foldrM
30+ , foldr
31+ , foldrMx
2632 , foldr1
2733
34+ -- * Left Folds
35+ , foldlM'
36+ , foldl'
37+ , foldlMx'
38+ , foldlx'
39+
2840 -- * Specific Fold Functions
41+ , drain
2942 , mapM_ -- Map and Fold
3043 , null
3144 , head
3245 , headElse
33− , init
3446 , tail
3547 , last
3648 , elem
@@ -48,9 +60,16 @@ module Streamly.Internal.Data.Stream.Eliminate
4860 , the
4961
5062 -- * To containers
63+ , toList
5164 , toListRev
5265
5366 -- * Multi-Stream Folds
67+ -- ** Comparisons
68+ -- | These should probably be expressed using zipping operations.
69+ , eqBy
70+ , cmpBy
71+
72+ -- ** Substreams
5473 -- | These should probably be expressed using parsers.
5574 , isPrefixOf
5675 , isInfixOf
@@ -71,7 +90,7 @@ import Foreign.Storable (Storable)
7190import GHC.Exts (SpecConstrAnnotation(..))
7291import GHC.Types (SPEC(..))
7392import Streamly.Internal.Data.Parser (ParseError(..))
74−import Streamly.Internal.Data.SVar.Type (adaptState, defState)
93+import Streamly.Internal.Data.SVar.Type (defState)
7594import Streamly.Internal.Data.Unbox (Unbox)
7695
7796import Streamly.Internal.Data.Maybe.Strict (Maybe'(..))
@@ -86,7 +105,7 @@ import qualified Streamly.Internal.Data.Stream.Transform as StreamD
86105
87106import Prelude hiding
88107 ( Foldable(..), all, any, head, last, lookup, mapM, mapM_
89− , notElem, splitAt, init, tail, (!!))
108+ , notElem, splitAt, tail, (!!))
90109import Data.Foldable (length)
91110import Streamly.Internal.Data.Stream.Type
92111
@@ -372,35 +391,9 @@ head = foldrM (\x _ -> return (Just x)) (return Nothing)
372391headElse :: Monad m => a -> Stream m a -> m a
373392headElse a = foldrM (\x _ -> return x) (return a)
374393
375−{-# INLINE_NORMAL init #-}
376−init :: Monad m => Stream m a -> m (Maybe (Stream m a))
377−init stream = do
378− r <- uncons stream
379− case r of
380− Nothing -> return Nothing
381− Just (h, Stream step1 state1) ->
382− return $ Just $ Stream step (h, state1)
383−
384− where
385−
386− step gst (a, s1) = do
387− res <- step1 (adaptState gst) s1
388− return $
389− case res of
390− Yield x s -> Yield a (x, s)
391− Skip s -> Skip (a, s)
392− Stop -> Stop
393−
394−-- | Same as:
395−--
396−-- >>> tail = fmap (fmap snd) . Stream.uncons
397−--
398394-- Does not fuse, has the same performance as the StreamK version.
399−--
400395{-# INLINE_NORMAL tail #-}
401396tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
402−tail = fmap (fmap snd) . uncons
403−{-
404397tail (UnStream step state) = go SPEC state
405398 where
406399 go !_ st = do
@@ -409,7 +402,6 @@ tail (UnStream step state) = go SPEC state
409402 Yield _ s -> return (Just $ Stream step s)
410403 Skip s -> go SPEC s
411404 Stop -> return Nothing
412−-}
413405
414406-- XXX will it fuse? need custom impl?
415407{-# INLINE_NORMAL last #-}
core/src/Streamly/Internal/Data/Stream/Exception.hs+6−9
@@ -9,20 +9,17 @@
99
1010module Streamly.Internal.Data.Stream.Exception
1111 (
12− -- * Resources
13− before
14− , afterIO
15− , afterUnsafe
16− , finallyIO
17− , finallyUnsafe
18− , gbracket_
12+ gbracket_
1913 , gbracket
14+ , before
15+ , afterUnsafe
16+ , afterIO
2017 , bracketUnsafe
2118 , bracketIO3
2219 , bracketIO
23−
24− -- * Exceptions
2520 , onException
21+ , finallyUnsafe
22+ , finallyIO
2623 , ghandle
2724 , handle
2825 )
core/src/Streamly/Internal/Data/Stream/Generate.hs+12−2
@@ -16,13 +16,20 @@ module Streamly.Internal.Data.Stream.Generate
1616 (
1717 -- * Primitives
1818 nil
19+ , nilM
1920 , cons
21+ , consM
22+
23+ -- * From 'Unfold'
24+ , unfold
2025
2126 -- * Unfolding
2227 , unfoldr
2328 , unfoldrM
2429
2530 -- * From Values
31+ , fromPure
32+ , fromEffect
2633 , repeat
2734 , repeatM
2835 , replicate
@@ -88,6 +95,7 @@ module Streamly.Internal.Data.Stream.Generate
8895 -- * From Containers
8996 -- | Transform an input structure into a stream.
9097
98+ , fromList
9199 , fromListM
92100 , fromFoldable
93101 , fromFoldableM
@@ -96,6 +104,10 @@ module Streamly.Internal.Data.Stream.Generate
96104 , fromPtr
97105 , fromPtrN
98106 , fromByteStr#
107+
108+ -- * Conversions
109+ , fromStreamK
110+ , toStreamK
99111 )
100112where
101113
@@ -142,8 +154,6 @@ import Streamly.Internal.Data.Stream.Type
142154nil :: Applicative m => Stream m a
143155nil = Stream (\_ _ -> pure Stop) ()
144156
145−infixr 5 `cons`
146−
147157-- XXX implement in terms of consM?
148158-- cons x = consM (return x)
149159-- From an implementation perspective, StreamK.cons translates into a
core/src/Streamly/Internal/Data/Stream/Nesting.hs+146−19
@@ -55,6 +55,11 @@ module Streamly.Internal.Data.Stream.Nesting
5555 -- yields an element. A special case of unfoldRoundRobin.
5656 , roundRobin -- interleaveFair?/ParallelFair
5757
58+ -- *** Zipping
59+ -- | Zip corresponding elements of two streams.
60+ , zipWith
61+ , zipWithM
62+
5863 -- *** Merging
5964 -- | Interleave elements from two streams based on a condition.
6065 , mergeBy
@@ -71,10 +76,17 @@ module Streamly.Internal.Data.Stream.Nesting
7176 -- unfoldMany: Unfold m a b -> t m a -> t m b
7277 -- @
7378
79+ -- *** ConcatMap
80+ -- | Generate streams by mapping a stream generator on each element of an
81+ -- input stream, append the resulting streams and flatten.
82+ , concatMap
83+ , concatMapM
84+
7485 -- *** ConcatUnfold
7586 -- | Generate streams by using an unfold on each element of an input
7687 -- stream, append the resulting streams and flatten. A special case of
7788 -- gintercalate.
89+ , unfoldMany
7890 , ConcatUnfoldInterleaveState (..)
7991 , unfoldInterleave
8092 , unfoldRoundRobin
@@ -106,8 +118,11 @@ module Streamly.Internal.Data.Stream.Nesting
106118
107119 -- ** Folding
108120 -- | Apply folds on a stream.
121+ , foldMany
122+ , refoldMany
109123 , foldSequence
110124 , foldIterateM
125+ , refoldIterateM
111126
112127 -- ** Parsing
113128 -- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
@@ -124,6 +139,7 @@ module Streamly.Internal.Data.Stream.Nesting
124139
125140 -- ** Grouping
126141 -- | Group segments of a stream and fold. Special case of parsing.
142+ , groupsOf
127143 , groupsBy
128144 , groupsWhile
129145 , groupsRollingBy
@@ -131,8 +147,9 @@ module Streamly.Internal.Data.Stream.Nesting
131147 -- ** Splitting
132148 -- | A special case of parsing.
133149 , wordsBy
134− , splitOnSeq -- XXX splitOnSeg
135− , splitOnSuffixSeq -- XXX splitOnSegSuffix, splitOnTrailer
150+ , splitOnSeq
151+ , splitOnSuffixSeq
152+ , sliceOnSuffix
136153
137154 -- XXX Implement these as folds or parsers instead.
138155 , splitOnSuffixSeqAny
@@ -141,8 +158,9 @@ module Streamly.Internal.Data.Stream.Nesting
141158
142159 -- * Transform (Nested Containers)
143160 -- | Opposite to compact in ArrayStream
144− , splitInnerBy -- XXX innerSplitOn
145− , splitInnerBySuffix -- XXX innerSplitOnSuffix
161+ , splitInnerBy
162+ , splitInnerBySuffix
163+ , intersectBySorted
146164
147165 -- * Reduce By Streams
148166 , dropPrefix
@@ -164,9 +182,12 @@ import Fusion.Plugin.Types (Fuse(..))
164182import GHC.Types (SPEC(..))
165183
166184import Streamly.Internal.Data.Array.Type (Array(..))
185+import Streamly.Internal.Data.Fold.Step (Step(..))
167186import Streamly.Internal.Data.Fold.Type (Fold(..))
168187import Streamly.Internal.Data.Parser (ParseError(..))
188+import Streamly.Internal.Data.Refold.Type (Refold(..))
169189import Streamly.Internal.Data.SVar.Type (adaptState)
190+import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
170191import Streamly.Internal.Data.Unbox (Unbox, sizeOf)
171192import Streamly.Internal.Data.Unfold.Type (Unfold(..))
172193
@@ -592,6 +613,49 @@ mergeFstBy :: -- Monad m =>
592613mergeFstBy _f _m1 _m2 = undefined
593614 -- fromStreamK $ D.mergeFstBy f (toStreamD m1) (toStreamD m2)
594615
616+-------------------------------------------------------------------------------
617+-- Intersection of sorted streams
618+-------------------------------------------------------------------------------
619+
620+-- Assuming the streams are sorted in ascending order
621+{-# INLINE_NORMAL intersectBySorted #-}
622+intersectBySorted :: Monad m
623+ => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
624+intersectBySorted cmp (Stream stepa ta) (Stream stepb tb) =
625+ Stream step
626+ ( ta -- left stream state
627+ , tb -- right stream state
628+ , Nothing -- left value
629+ , Nothing -- right value
630+ )
631+
632+ where
633+
634+ {-# INLINE_LATE step #-}
635+ -- step 1, fetch the first value
636+ step gst (sa, sb, Nothing, b) = do
637+ r <- stepa gst sa
638+ return $ case r of
639+ Yield a sa' -> Skip (sa', sb, Just a, b) -- step 2/3
640+ Skip sa' -> Skip (sa', sb, Nothing, b)
641+ Stop -> Stop
642+
643+ -- step 2, fetch the second value
644+ step gst (sa, sb, a@(Just _), Nothing) = do
645+ r <- stepb gst sb
646+ return $ case r of
647+ Yield b sb' -> Skip (sa, sb', a, Just b) -- step 3
648+ Skip sb' -> Skip (sa, sb', a, Nothing)
649+ Stop -> Stop
650+
651+ -- step 3, compare the two values
652+ step _ (sa, sb, Just a, Just b) = do
653+ let res = cmp a b
654+ return $ case res of
655+ GT -> Skip (sa, sb, Just a, Nothing) -- step 2
656+ LT -> Skip (sa, sb, Nothing, Just b) -- step 1
657+ EQ -> Yield a (sa, sb, Nothing, Just b) -- step 1
658+
595659------------------------------------------------------------------------------
596660-- Combine N Streams - unfoldMany
597661------------------------------------------------------------------------------
@@ -1230,6 +1294,77 @@ foldIterateM func seed0 (Stream step state) =
12301294 stepOuter _ (FIterYield a next) = return $ Yield a next
12311295 stepOuter _ FIterStop = return Stop
12321296
1297+{-# ANN type CIterState Fuse #-}
1298+data CIterState s f fs b
1299+ = CIterInit s f
1300+ | CIterConsume s fs
1301+ | CIterYield b (CIterState s f fs b)
1302+ | CIterStop
1303+
1304+-- | Like 'foldIterateM' but using the 'Refold' type instead. This could be
1305+-- much more efficient due to stream fusion.
1306+--
1307+-- /Internal/
1308+{-# INLINE_NORMAL refoldIterateM #-}
1309+refoldIterateM ::
1310+ Monad m => Refold m b a b -> m b -> Stream m a -> Stream m b
1311+refoldIterateM (Refold fstep finject fextract) initial (Stream step state) =
1312+ Stream stepOuter (CIterInit state initial)
1313+
1314+ where
1315+
1316+ {-# INLINE iterStep #-}
1317+ iterStep st action = do
1318+ res <- action
1319+ return
1320+ $ Skip
1321+ $ case res of
1322+ FL.Partial fs -> CIterConsume st fs
1323+ FL.Done fb -> CIterYield fb $ CIterInit st (return fb)
1324+
1325+ {-# INLINE_LATE stepOuter #-}
1326+ stepOuter _ (CIterInit st action) = do
1327+ iterStep st (action >>= finject)
1328+ stepOuter gst (CIterConsume st fs) = do
1329+ r <- step (adaptState gst) st
1330+ case r of
1331+ Yield x s -> iterStep s (fstep fs x)
1332+ Skip s -> return $ Skip $ CIterConsume s fs
1333+ Stop -> do
1334+ b <- fextract fs
1335+ return $ Skip $ CIterYield b CIterStop
1336+ stepOuter _ (CIterYield a next) = return $ Yield a next
1337+ stepOuter _ CIterStop = return Stop
1338+
1339+-- "n" elements at the end are dropped by the fold.
1340+{-# INLINE sliceBy #-}
1341+sliceBy :: Monad m => Fold m a Int -> Int -> Refold m (Int, Int) a (Int, Int)
1342+sliceBy (Fold step1 initial1 extract1 _final) n = Refold step inject extract
1343+
1344+ where
1345+
1346+ inject (i, len) = do
1347+ r <- initial1
1348+ return $ case r of
1349+ Partial s -> Partial $ Tuple' (i + len + n) s
1350+ Done l -> Done (i, l)
1351+
1352+ step (Tuple' i s) x = do
1353+ r <- step1 s x
1354+ return $ case r of
1355+ Partial s1 -> Partial $ Tuple' i s1
1356+ Done len -> Done (i, len)
1357+
1358+ extract (Tuple' i s) = (i,) <$> extract1 s
1359+
1360+{-# INLINE sliceOnSuffix #-}
1361+sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
1362+sliceOnSuffix predicate =
1363+ -- Scan the stream with the given refold
1364+ refoldIterateM
1365+ (sliceBy (FL.takeEndBy_ predicate FL.length) 1)
1366+ (return (-1, 0))
1367+
12331368------------------------------------------------------------------------------
12341369-- Parsing
12351370------------------------------------------------------------------------------
@@ -2930,13 +3065,12 @@ splitInnerBy splitter joiner (Stream step1 state1) =
29303065-- | Performs infix separator style splitting.
29313066{-# INLINE_NORMAL splitInnerBySuffix #-}
29323067splitInnerBySuffix
2933− :: Monad m
2934− => (f a -> Bool) -- isEmpty?
2935− -> (f a -> m (f a, Maybe (f a))) -- splitter
3068+ :: (Monad m, Eq (f a), Monoid (f a))
3069+ => (f a -> m (f a, Maybe (f a))) -- splitter
29363070 -> (f a -> f a -> m (f a)) -- joiner
29373071 -> Stream m (f a)
29383072 -> Stream m (f a)
2939−splitInnerBySuffix isEmpty splitter joiner (Stream step1 state1) =
3073+splitInnerBySuffix splitter joiner (Stream step1 state1) =
29403074 Stream step (SplitInitial state1)
29413075
29423076 where
@@ -2963,11 +3097,10 @@ splitInnerBySuffix isEmpty splitter joiner (Stream step1 state1) =
29633097 Nothing -> Skip (SplitBuffering s buf')
29643098 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
29653099 Skip s -> return $ Skip (SplitBuffering s buf)
2966− Stop ->
2967− return $
2968− if isEmpty buf
2969− then Stop
2970− else Skip (SplitYielding buf SplitFinishing)
3100+ Stop -> return $
3101+ if buf == mempty
3102+ then Stop
3103+ else Skip (SplitYielding buf SplitFinishing)
29713104
29723105 step _ (SplitSplitting st buf) = do
29733106 (x1, mx2) <- splitter buf
@@ -2986,8 +3119,6 @@ splitInnerBySuffix isEmpty splitter joiner (Stream step1 state1) =
29863119--
29873120-- Space: @O(1)@
29883121--
2989−-- See also stripPrefix.
2990−--
29913122-- /Unimplemented/
29923123{-# INLINE dropPrefix #-}
29933124dropPrefix ::
@@ -3000,8 +3131,6 @@ dropPrefix = error "Not implemented yet!"
30003131--
30013132-- Space: @O(n)@ where n is the length of the infix.
30023133--
3003−-- See also stripInfix.
3004−--
30053134-- /Unimplemented/
30063135{-# INLINE dropInfix #-}
30073136dropInfix ::
@@ -3014,8 +3143,6 @@ dropInfix = error "Not implemented yet!"
30143143--
30153144-- Space: @O(n)@ where n is the length of the suffix.
30163145--
3017−-- See also stripSuffix.
3018−--
30193146-- /Unimplemented/
30203147{-# INLINE dropSuffix #-}
30213148dropSuffix ::
core/src/Streamly/Internal/Data/Stream/Top.hs+115−243
@@ -8,73 +8,38 @@
88-- Portability : GHC
99--
1010-- Top level module that can depend on all other lower level Stream modules.
11−--
12−-- Design notes:
13−--
14−-- The order of arguments in the join operations should ideally be opposite. It
15−-- should be such that the infinite stream is the last one. The transformation
16−-- should be on the last argument, so if you curry the functions with all other
17−-- arguments we get a @Stream -> Stream@ function. The first stream argument
18−-- may be considered as a config or modifier for the operation.
19−--
20−-- Benefit of changing the order is that we get a more intuitive Stream ->
21−-- Stream transformation after currying all other arguments. The inner loop
22−-- streams become arguments for the transformation, more like local modifiers
23−-- for the global outer stream as the last argument. Thus we can continue using
24−-- transformations on the outer stream in a composed pipeline. Otherwise we can
25−-- use flip to flip the order.
26−--
27−-- The fact that the inner stream can be used in the loop multiple times also
28−-- tells that this is not the real effectful stream, it is more like a pure
29−-- stream or an array. In fact we may consider using an Identity streams as
30−-- inner streams in which case these functions will not look nice.
31−--
32−-- Downsides:
33−--
34−-- * Maybe less intuitive to think about, because we usually think the first
35−-- stream as the outer loop and second as the inner.
36−-- * Zip and merge operations will continue using the opposite order.
37−-- * Need to change the order of cross, crossWith operations as well
38−-- * It will be inconsistent with Data.List. The functions cannot be used as
39−-- intuitive operators.
40−--
41−-- The choice is similar to concatMap vs bind. concatMap is pipeline
42−-- composition friendly but bind is user intuition friendly. Another option is
43−-- to have other functions with a different argument order e.g. flippedCross
44−-- instead of cross.
45−--
46−-- If we change the order we have to make sure that we have a consistent
47−-- convention for set-like and the cross join operations.
4811
4912module Streamly.Internal.Data.Stream.Top
5013 (
51− -- * Sampling
14+ -- * Transformation
15+ -- ** Sampling
5216 -- | Value agnostic filtering.
5317 strideFromThen
5418
55− -- * Straight Joins
56− -- | These are set-like operations but not exactly set operations because
57− -- streams are not necessarily sets, they may have duplicated elements.
58− -- These operations are generic i.e. they work on streams of unconstrained
59− -- types, therefore, they have quadratic performance characterstics. For
60− -- better performance using Set or Map structures see the
61− -- Streamly.Internal.Data.Stream.Container module.
62− , intersectBy
63− , deleteFirstsBy
64− , unionBy
65−
66− -- Set like operations on sorted streams
67− , sortedIntersectBy
68− , sortedDeleteFirstsBy
69− , sortedUnionBy
70−
71− -- * Cross Joins
72− , innerJoin
73−
74− -- Joins on sorted stream
75− , innerSortedJoin
76− , leftSortedJoin
77− , outerSortedJoin
19+ -- * Nesting
20+ -- ** Set like operations
21+ -- | These are not exactly set operations because streams are not
22+ -- necessarily sets, they may have duplicated elements. These operations
23+ -- are generic i.e. they work on streams of unconstrained types, therefore,
24+ -- they have quadratic performance characterstics. For better performance
25+ -- using Set structures see the Streamly.Internal.Data.Stream.Container
26+ -- module.
27+ , filterInStreamGenericBy
28+ , deleteInStreamGenericBy
29+ , unionWithStreamGenericBy
30+
31+ -- ** Set like operations on sorted streams
32+ , filterInStreamAscBy
33+ , deleteInStreamAscBy
34+ , unionWithStreamAscBy
35+
36+ -- ** Join operations
37+ , joinInnerGeneric
38+
39+ -- * Joins on sorted stream
40+ , joinInnerAscBy
41+ , joinLeftAscBy
42+ , joinOuterAscBy
7843 )
7944where
8045
@@ -83,7 +48,7 @@ where
8348import Control.Monad.IO.Class (MonadIO(..))
8449import Data.IORef (newIORef, readIORef, modifyIORef')
8550import Streamly.Internal.Data.Fold.Type (Fold)
86−import Streamly.Internal.Data.Stream.Type (Stream(..), Step(..), cross)
51+import Streamly.Internal.Data.Stream.Type (Stream, cross)
8752
8853import qualified Data.List as List
8954import qualified Streamly.Internal.Data.Fold as Fold
@@ -145,40 +110,29 @@ strideFromThen offset stride =
145110-- binary search if we have an Ord instance or Ordering returning function. The
146111-- time complexity would then become (m x log n).
147112
148−-- | Like 'cross' but emits only those tuples where @a == b@ using the supplied
149−-- equality predicate. This is essentially a @cross intersection@ of two
150−-- streams.
113+-- | Like 'cross' but emits only those tuples where @a == b@ using the
114+-- supplied equality predicate.
151115--
152116-- Definition:
153117--
154−-- >>> innerJoin eq s1 s2 = Stream.filter (\(a, b) -> a `eq` b) $ Stream.cross s1 s2
155−--
156−-- The second (inner) stream must be finite. Moreover, it must be either pure
157−-- or capable of multiple evaluations. If not then the caller should cache it
158−-- in an 'Data.Array.Array', if the type does not have an 'Unbox' instance then
159−-- use the Generic 'Data.Array.Generic.Array'. Convert the array to stream
160−-- before calling this function. Caching may also improve performance if the
161−-- stream is expensive to evaluate.
118+-- >>> joinInnerGeneric eq s1 s2 = Stream.filter (\(a, b) -> a `eq` b) $ Stream.cross s1 s2
162119--
163−-- If you care about performance this function should be your last choice among
164−-- all inner joins. 'Streamly.Internal.Data.Unfold.innerJoin' is a much faster
165−-- fused alternative. 'innerSortedJoin' is a faster alternative when streams
166−-- are sorted. 'innerOrdJoin' is an order of magnitude faster alternative when
167−-- the type has an 'Ord' instance.
120+-- You should almost always prefer @joinInnerOrd@ over 'joinInnerGeneric' if
121+-- possible. @joinInnerOrd@ is an order of magnitude faster but may take more
122+-- space for caching the second stream.
168123--
169−-- Note: Conceptually, this is a commutative operation. Result includes all the
170−-- elements from the left and the right stream. The order of streams can be
171−-- changed without affecting results, except for the ordering within the tuple.
124+-- See 'Streamly.Internal.Data.Unfold.joinInnerGeneric' for a much faster fused
125+-- alternative.
172126--
173127-- Time: O(m x n)
174128--
175129-- /Pre-release/
176−{-# INLINE innerJoin #-}
177−innerJoin :: Monad m =>
130+{-# INLINE joinInnerGeneric #-}
131+joinInnerGeneric :: Monad m =>
178132 (a -> b -> Bool) -> Stream m a -> Stream m b -> Stream m (a, b)
179−innerJoin eq s1 s2 = Stream.filter (\(a, b) -> a `eq` b) $ cross s1 s2
133+joinInnerGeneric eq s1 s2 = Stream.filter (\(a, b) -> a `eq` b) $ cross s1 s2
180134{-
181−innerJoin eq s1 s2 = do
135+joinInnerGeneric eq s1 s2 = do
182136 -- ConcatMap works faster than bind
183137 Stream.concatMap (\a ->
184138 Stream.concatMap (\b ->
@@ -189,44 +143,44 @@ innerJoin eq s1 s2 = do
189143 ) s1
190144-}
191145
192−-- | A more efficient 'innerJoin' for sorted streams.
146+-- | A more efficient 'joinInner' for sorted streams.
193147--
194148-- Space: O(1)
195149--
196150-- Time: O(m + n)
197151--
198152-- /Unimplemented/
199−{-# INLINE innerSortedJoin #-}
200−innerSortedJoin ::
153+{-# INLINE joinInnerAscBy #-}
154+joinInnerAscBy ::
201155 (a -> b -> Ordering) -> Stream m a -> Stream m b -> Stream m (a, b)
202−innerSortedJoin = undefined
156+joinInnerAscBy = undefined
203157
204−-- | A more efficient 'leftJoin' for sorted streams.
158+-- | A more efficient 'joinLeft' for sorted streams.
205159--
206160-- Space: O(1)
207161--
208162-- Time: O(m + n)
209163--
210164-- /Unimplemented/
211−{-# INLINE leftSortedJoin #-}
212−leftSortedJoin :: -- Monad m =>
165+{-# INLINE joinLeftAscBy #-}
166+joinLeftAscBy :: -- Monad m =>
213167 (a -> b -> Ordering) -> Stream m a -> Stream m b -> Stream m (a, Maybe b)
214−leftSortedJoin _eq _s1 _s2 = undefined
168+joinLeftAscBy _eq _s1 _s2 = undefined
215169
216−-- | A more efficient 'outerJoin' for sorted streams.
170+-- | A more efficient 'joinOuter' for sorted streams.
217171--
218172-- Space: O(1)
219173--
220174-- Time: O(m + n)
221175--
222176-- /Unimplemented/
223−{-# INLINE outerSortedJoin #-}
224−outerSortedJoin :: -- Monad m =>
177+{-# INLINE joinOuterAscBy #-}
178+joinOuterAscBy :: -- Monad m =>
225179 (a -> b -> Ordering)
226180 -> Stream m a
227181 -> Stream m b
228182 -> Stream m (Maybe a, Maybe b)
229−outerSortedJoin _eq _s1 _s2 = undefined
183+joinOuterAscBy _eq _s1 _s2 = undefined
230184
231185------------------------------------------------------------------------------
232186-- Set operations (special joins)
@@ -236,8 +190,8 @@ outerSortedJoin _eq _s1 _s2 = undefined
236190-- the best would be to use an Array with linear search. If the second stream
237191-- is sorted we can also use a binary search, using Ord constraint.
238192
239−-- | Keep only those elements in the first stream that are present in the
240−-- second stream too. The second stream is folded to a container using the
193+-- | Keep only those elements in the second stream that are present in the
194+-- first stream too. The first stream is folded to a container using the
241195-- supplied fold and then the elements in the container are looked up using the
242196-- supplied lookup function.
243197--
@@ -252,30 +206,23 @@ filterStreamWith :: Monad m =>
252206filterStreamWith fld member s1 s2 =
253207 Stream.concatEffect
254208 $ do
255− xs <- Stream.fold fld s2
256− return $ Stream.filter (`member` xs) s1
257−
258−-- XXX instead of folding the second stream to a list we could use it directly.
259−-- If the user wants they can generate the stream from an array and also call
260−-- uniq or nub on it. We can provide a convenience Stream -> Stream to cache
261−-- a finite stream in an array and serve it from the cache. The user can decide
262−-- what is best based on the context. They can also choose to use a boxed or
263−-- unboxed array for caching. To force caching we can make the second stream
264−-- monad type Identity. But that may be less flexible. One option is to use
265−-- cachedIntersectBy etc for automatic caching.
209+ xs <- Stream.fold fld s1
210+ return $ Stream.filter (`member` xs) s2
266211
267−-- | 'intersectBy' returns a subsequence of the first stream which intersects
268−-- with the second stream. Note that this is not a commutative operation unlike
269−-- a set intersection, because of duplicate elements in the stream the order of
270−-- the streams matters. This is similar to 'Data.List.intersectBy'. Note that
271−-- intersectBy is a special case of 'innerJoin'.
212+-- | 'filterInStreamGenericBy' retains only those elements in the second stream that
213+-- are present in the first stream.
272214--
273−-- >>> f s1 s2 = Stream.fold Fold.toList $ Stream.intersectBy (==) (Stream.fromList s1) (Stream.fromList s2)
274−-- >>> f [1,3,4,4,5]) [2,3,4,5,5]
275−-- [3,4,4,5]
215+-- >>> Stream.fold Fold.toList $ Stream.filterInStreamGenericBy (==) (Stream.fromList [1,2,2,4]) (Stream.fromList [2,1,1,3])
216+-- [2,1,1]
276217--
277−-- First stream can be infinite, the second stream must be finite and must be
278−-- capable of multiple evaluations.
218+-- >>> Stream.fold Fold.toList $ Stream.filterInStreamGenericBy (==) (Stream.fromList [2,1,1,3]) (Stream.fromList [1,2,2,4])
219+-- [1,2,2]
220+--
221+-- Similar to the list intersectBy operation but with the stream argument order
222+-- flipped.
223+--
224+-- The first stream must be finite and must not block. Second stream is
225+-- processed only after the first stream is fully realized.
279226--
280227-- Space: O(n) where @n@ is the number of elements in the second stream.
281228--
@@ -283,87 +230,46 @@ filterStreamWith fld member s1 s2 =
283230-- @n@ is the number of elements in the second stream.
284231--
285232-- /Pre-release/
286−{-# INLINE intersectBy #-}
287−intersectBy :: Monad m =>
233+{-# INLINE filterInStreamGenericBy #-}
234+filterInStreamGenericBy :: Monad m =>
288235 (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
289−intersectBy eq =
236+filterInStreamGenericBy eq =
290237 -- XXX Use an (unboxed) array instead.
291238 filterStreamWith
292239 (Fold.scanMaybe (Fold.uniqBy eq) Fold.toListRev)
293240 (List.any . eq)
294241
295−-------------------------------------------------------------------------------
296−-- Intersection of sorted streams
297−-------------------------------------------------------------------------------
298−
299−-- XXX The sort order is not important as long both the streams have the same
300−-- sort order. We need to move only in one direction in each stream.
301−-- XXX Fix the argument order to use the same behavior as intersectBy.
302−
303−-- | Like 'intersectBy' but assumes that the input streams are sorted in
242+-- | Like 'filterInStreamGenericBy' but assumes that the input streams are sorted in
304243-- ascending order. To use it on streams sorted in descending order pass an
305244-- inverted comparison function returning GT for less than and LT for greater
306245-- than.
307246--
308−-- Both streams can be infinite.
309−--
310247-- Space: O(1)
311248--
312249-- Time: O(m+n)
313250--
314251-- /Pre-release/
315−{-# INLINE_NORMAL sortedIntersectBy #-}
316−sortedIntersectBy :: Monad m =>
252+{-# INLINE filterInStreamAscBy #-}
253+filterInStreamAscBy :: Monad m =>
317254 (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
318−sortedIntersectBy cmp (Stream stepa ta) (Stream stepb tb) =
319− Stream step
320− ( ta -- left stream state
321− , tb -- right stream state
322− , Nothing -- left value
323− , Nothing -- right value
324− )
325−
326− where
255+filterInStreamAscBy eq s1 s2 = Stream.intersectBySorted eq s2 s1
327256
328− {-# INLINE_LATE step #-}
329− -- step 1, fetch the first value
330− step gst (sa, sb, Nothing, b) = do
331− r <- stepa gst sa
332− return $ case r of
333− Yield a sa' -> Skip (sa', sb, Just a, b) -- step 2/3
334− Skip sa' -> Skip (sa', sb, Nothing, b)
335− Stop -> Stop
336−
337− -- step 2, fetch the second value
338− step gst (sa, sb, a@(Just _), Nothing) = do
339− r <- stepb gst sb
340− return $ case r of
341− Yield b sb' -> Skip (sa, sb', a, Just b) -- step 3
342− Skip sb' -> Skip (sa, sb', a, Nothing)
343− Stop -> Stop
344−
345− -- step 3, compare the two values
346− step _ (sa, sb, Just a, Just b) = do
347− let res = cmp a b
348− return $ case res of
349− GT -> Skip (sa, sb, Just a, Nothing) -- step 2
350− LT -> Skip (sa, sb, Nothing, Just b) -- step 1
351− EQ -> Yield a (sa, sb, Nothing, Just b) -- step 1
352−
353−-- | Returns a subsequence of the first stream, deleting first occurrences of
354−-- those elements that are present in the second stream. Note that this is not
355−-- a commutative operation. This is similar to the 'Data.List.deleteFirstsBy'.
257+-- | Delete all elements of the first stream from the seconds stream. If an
258+-- element occurs multiple times in the first stream as many occurrences of it
259+-- are deleted from the second stream.
356260--
357−-- >>> f xs ys = Stream.fold Fold.toList $ Stream.deleteFirstsBy (==) (Stream.fromList xs) (Stream.fromList ys)
358−-- >>> f [1,2,2,3,3,5] [1,2,2,3,4]
359−-- [2,3,5]
261+-- >>> Stream.fold Fold.toList $ Stream.deleteInStreamGenericBy (==) (Stream.fromList [1,2,3]) (Stream.fromList [1,2,2])
262+-- [2]
360263--
361−-- The following holds:
264+-- The following laws hold:
362265--
363−-- > deleteFirstsBy (==) (Stream.nub s2 `append` s1) s2 === s1
364−-- > deleteFirstsBy (==) (Stream.nub s2 `interleave` s1) s2 === s1
266+-- > deleteInStreamGenericBy (==) s1 (s1 `append` s2) === s2
267+-- > deleteInStreamGenericBy (==) s1 (s1 `interleave` s2) === s2
365268--
366−-- First stream can be infinite, second stream must be finite.
269+-- Same as the list 'Data.List.//' operation but with argument order flipped.
270+--
271+-- The first stream must be finite and must not block. Second stream is
272+-- processed only after the first stream is fully realized.
367273--
368274-- Space: O(m) where @m@ is the number of elements in the first stream.
369275--
@@ -371,83 +277,58 @@ sortedIntersectBy cmp (Stream stepa ta) (Stream stepb tb) =
371277-- @n@ is the number of elements in the second stream.
372278--
373279-- /Pre-release/
374−{-# INLINE deleteFirstsBy #-}
375−deleteFirstsBy :: Monad m =>
280+{-# INLINE deleteInStreamGenericBy #-}
281+deleteInStreamGenericBy :: Monad m =>
376282 (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
377−deleteFirstsBy eq s2 s1 =
378− -- XXX s2 can be a sorted mutable array and we can use binary
379− -- search to find. Mark the element deleted, count the deletions
380− -- and reconsolidate the array when a min number of elements is
381− -- deleted.
382−
383− -- XXX Use StreamK or list as second argument instead of Stream to avoid
384− -- concatEffect?
385− Stream.concatEffect $ do
386− xs <- Stream.toList s1
387− -- It reverses the list but that is fine.
388− let del x =
389− List.foldl' (\(ys,res) y ->
390− if x `eq` y
391− then (ys, True)
392− else (x:ys, res)) ([], False)
393− g (ys,_) x =
394− let (ys1, deleted) = del x ys
395− in if deleted
396− then (ys1, Nothing)
397− else (ys1, Just x)
398− in return
399− $ Stream.catMaybes
400− $ fmap snd
401− $ Stream.postscanl' g (xs, Nothing) s2
283+deleteInStreamGenericBy eq s1 s2 =
284+ Stream.concatEffect
285+ $ do
286+ -- This may work well if s1 is small
287+ -- If s1 is big we can go through s1, deleting elements from s2 and
288+ -- not emitting an element if it was successfully deleted from s2.
289+ -- we will need a deleteBy that can return whether the element was
290+ -- deleted or not.
291+ xs <- Stream.fold Fold.toList s2
292+ let f = Fold.foldl' (flip (List.deleteBy eq)) xs
293+ fmap Stream.fromList $ Stream.fold f s1
402294
403−-- | A more efficient 'deleteFirstsBy' for streams sorted in ascending order.
404−--
405−-- Both streams can be infinite.
295+-- | A more efficient 'deleteInStreamGenericBy' for streams sorted in ascending order.
406296--
407297-- Space: O(1)
408298--
409299-- /Unimplemented/
410−{-# INLINE sortedDeleteFirstsBy #-}
411−sortedDeleteFirstsBy :: -- (Monad m) =>
300+{-# INLINE deleteInStreamAscBy #-}
301+deleteInStreamAscBy :: -- (Monad m) =>
412302 (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
413−sortedDeleteFirstsBy _eq _s1 _s2 = undefined
303+deleteInStreamAscBy _eq _s1 _s2 = undefined
414304
415305-- XXX Remove the MonadIO constraint. We can just cache one stream and then
416306-- implement using differenceEqBy.
417307
418−-- | Returns the first stream appended with those unique elements from the
419−-- second stream that are not already present in the first stream. Note that
420−-- this is not a commutative operation unlike a set union, argument order
421−-- matters. The behavior is similar to the 'Data.List.unionBy'.
308+-- | This essentially appends to the second stream all the occurrences of
309+-- elements in the first stream that are not already present in the second
310+-- stream.
422311--
423312-- Equivalent to the following except that @s2@ is evaluated only once:
424313--
425−-- >>> unionBy eq s1 s2 = s1 `Stream.append` Stream.deleteFirstsBy eq s1 (Stream.nub s2)
314+-- >>> unionWithStreamGenericBy eq s1 s2 = s2 `Stream.append` (Stream.deleteInStreamGenericBy eq s2 s1)
426315--
427316-- Example:
428317--
429−-- >>> f s1 s2 = Stream.fold Fold.toList $ Stream.unionBy (==) (Stream.fromList s1) (Stream.fromList s2)
430−-- >>> f [1,2,2,4] [1,1,2,3,3]
318+-- >>> Stream.fold Fold.toList $ Stream.unionWithStreamGenericBy (==) (Stream.fromList [1,1,2,3]) (Stream.fromList [1,2,2,4])
431319-- [1,2,2,4,3]
432320--
433−-- First stream can be infinite, but second stream must be finite. Note that if
434−-- the first stream is infinite the union means just the first stream. Thus
435−-- union is useful only when both streams are finite. See 'sortedUnionBy' where
436−-- union can work on infinite streams if they are sorted.
437−--
438321-- Space: O(n)
439322--
440323-- Time: O(m x n)
441324--
442325-- /Pre-release/
443−{-# INLINE unionBy #-}
444−unionBy :: MonadIO m =>
326+{-# INLINE unionWithStreamGenericBy #-}
327+unionWithStreamGenericBy :: MonadIO m =>
445328 (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
446−unionBy eq s2 s1 =
329+unionWithStreamGenericBy eq s1 s2 =
447330 Stream.concatEffect
448331 $ do
449− -- XXX use a rewrite rule such that if a list converted to stream
450− -- is passed to unionBy then this becomes an identity operation.
451332 xs <- Stream.fold Fold.toList s1
452333 -- XXX we can use postscanlMAfter' instead of IORef
453334 ref <- liftIO $ newIORef $! List.nubBy eq xs
@@ -460,21 +341,12 @@ unionBy eq s2 s1 =
460341 return $ Stream.fromList xs1
461342 return $ Stream.mapM f s2 `Stream.append` s3
462343
463−-- | A more efficient 'unionBy' for sorted streams.
464−--
465−-- Note that the behavior is different from 'unionBy'. In 'unionBy' we append
466−-- the unique elements from second stream only after exhausting the first one
467−-- whereas in sorted streams we can determine unique elements early even when
468−-- we are going through the first stream. Thus the result is an interleaving of
469−-- the two streams, merging those elements from the second stream that are not
470−-- present in the first.
344+-- | A more efficient 'unionWithStreamGenericBy' for sorted streams.
471345--
472346-- Space: O(1)
473347--
474−-- Both streams can be infinite.
475−--
476348-- /Unimplemented/
477−{-# INLINE sortedUnionBy #-}
478−sortedUnionBy :: -- (Monad m) =>
349+{-# INLINE unionWithStreamAscBy #-}
350+unionWithStreamAscBy :: -- (Monad m) =>
479351 (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
480−sortedUnionBy _eq _s1 _s2 = undefined
352+unionWithStreamAscBy _eq _s1 _s2 = undefined
core/src/Streamly/Internal/Data/Stream/Transform.hs+27−53
@@ -21,6 +21,8 @@ module Streamly.Internal.Data.Stream.Transform
2121
2222 -- * Mapping
2323 -- | Stateless one-to-one maps.
24+ , map
25+ , mapM
2426 , sequence
2527
2628 -- * Mapping Effects
@@ -73,7 +75,7 @@ module Streamly.Internal.Data.Stream.Transform
7375 , scanMaybe
7476 , filter
7577 , filterM
76− , deleteBy -- deleteOnceBy?
78+ , deleteBy
7779 , uniqBy
7880 , uniq
7981 , prune
@@ -81,8 +83,9 @@ module Streamly.Internal.Data.Stream.Transform
8183
8284 -- * Trimming
8385 -- | Produce a subset of the stream trimmed at ends.
84− , initNonEmpty
85− , tailNonEmpty
86+ , take
87+ , takeWhile
88+ , takeWhileM
8689 , takeWhileLast
8790 , takeWhileAround
8891 , drop
@@ -129,6 +132,7 @@ module Streamly.Internal.Data.Stream.Transform
129132 -- * Searching
130133 , findIndices
131134 , elemIndices
135+ , slicesBy
132136
133137 -- * Rolling map
134138 -- | Map using the previous element.
@@ -1070,55 +1074,6 @@ repeated = undefined
10701074-- Trimming
10711075------------------------------------------------------------------------------
10721076
1073−-- | init for non-empty streams, fails for empty stream case.
1074−--
1075−{-# INLINE initNonEmpty #-}
1076−initNonEmpty :: Monad m => Stream m a -> Stream m a
1077−initNonEmpty (Stream step1 state1) = Stream step (Nothing, state1)
1078−
1079− where
1080−
1081− step gst (Nothing, s1) = do
1082− r <- step1 (adaptState gst) s1
1083− return $
1084− case r of
1085− Yield x s -> Skip (Just x, s)
1086− Skip s -> Skip (Nothing, s)
1087− Stop -> error "initNonEmpty: empty Stream"
1088−
1089− step gst (Just a, s1) = do
1090− r <- step1 (adaptState gst) s1
1091− return $
1092− case r of
1093− Yield x s -> Yield a (Just x, s)
1094− Skip s -> Skip (Just a, s)
1095− Stop -> Stop
1096−
1097−-- | tail for non-empty streams, fails for empty stream case.
1098−--
1099−-- See also 'tail' for a non-partial version of this function..
1100−{-# INLINE tailNonEmpty #-}
1101−tailNonEmpty :: Monad m => Stream m a -> Stream m a
1102−tailNonEmpty (Stream step1 state1) = Stream step (Nothing, state1)
1103−
1104− where
1105−
1106− step gst (Nothing, s1) = do
1107− r <- step1 (adaptState gst) s1
1108− return $
1109− case r of
1110− Yield x s -> Skip (Just x, s)
1111− Skip s -> Skip (Nothing, s)
1112− Stop -> error "tailNonEmpty: empty Stream"
1113−
1114− step gst (Just a, s1) = do
1115− r <- step1 (adaptState gst) s1
1116− return $
1117− case r of
1118− Yield x s -> Yield x (Just x, s)
1119− Skip s -> Skip (Just a, s)
1120− Stop -> Stop
1121−
11221077-- | Take all consecutive elements at the end of the stream for which the
11231078-- predicate is true.
11241079--
@@ -1582,7 +1537,7 @@ reverse m = Stream step Nothing
15821537{-# INLINE reverseUnbox #-}
15831538reverseUnbox :: (MonadIO m, Unbox a) => Stream m a -> Stream m a
15841539reverseUnbox =
1585− A.concatRev -- unfoldMany A.readerRev
1540+ A.flattenArraysRev -- unfoldMany A.readRev
15861541 . fromStreamK
15871542 . K.reverse
15881543 . toStreamK
@@ -1754,6 +1709,25 @@ findIndices p (Stream step state) = Stream step' (state, 0)
17541709elemIndices :: (Monad m, Eq a) => a -> Stream m a -> Stream m Int
17551710elemIndices a = findIndices (== a)
17561711
1712+{-# INLINE_NORMAL slicesBy #-}
1713+slicesBy :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
1714+slicesBy p (Stream step1 state1) = Stream step (Just (state1, 0, 0))
1715+
1716+ where
1717+
1718+ {-# INLINE_LATE step #-}
1719+ step gst (Just (st, i, len)) = i `seq` len `seq` do
1720+ r <- step1 (adaptState gst) st
1721+ return
1722+ $ case r of
1723+ Yield x s ->
1724+ if p x
1725+ then Yield (i, len + 1) (Just (s, i + len + 1, 0))
1726+ else Skip (Just (s, i, len + 1))
1727+ Skip s -> Skip (Just (s, i, len))
1728+ Stop -> if len == 0 then Stop else Yield (i, len) Nothing
1729+ step _ Nothing = return Stop
1730+
17571731------------------------------------------------------------------------------
17581732-- Rolling map
17591733------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Stream/Transformer.hs+1−2
@@ -11,11 +11,10 @@
1111
1212module Streamly.Internal.Data.Stream.Transformer
1313 (
14− -- * Fold to Transformer Monad
1514 foldlT
1615 , foldrT
1716
18− -- * Inner Monad Operations
17+ -- * Transform Inner Monad
1918 , liftInner
2019 , runReaderT
2120 , usingReaderT
core/src/Streamly/Internal/Data/Stream/Type.hs+3−132
@@ -1,11 +1,5 @@
11{-# LANGUAGE CPP #-}
2−{-# LANGUAGE PatternSynonyms #-}
3−{-# LANGUAGE TypeFamilies #-}
4−-- Must come after TypeFamilies, otherwise it is re-enabled.
5−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
6−{-# LANGUAGE NoMonoLocalBinds #-}
72{-# LANGUAGE UndecidableInstances #-}
8−{-# LANGUAGE ViewPatterns #-}
93
104-- |
115-- Module : Streamly.Internal.Data.Stream.Type
@@ -22,18 +16,18 @@
2216
2317module Streamly.Internal.Data.Stream.Type
2418 (
25− -- * Type
19+ -- * The stream type
2620 Step (..)
2721 -- XXX UnStream is exported to avoid a performance issue in some
2822 -- combinators if we use the pattern synonym "Stream".
2923 , Stream (Stream, UnStream)
3024
31− -- * CrossStream
25+ -- * CrossStream type wrapper
3226 , CrossStream
3327 , unCross
3428 , mkCross
3529
36− -- * To StreamK
30+ -- * Conversion to StreamK
3731 , fromStreamK
3832 , toStreamK
3933
@@ -91,7 +85,6 @@ module Streamly.Internal.Data.Stream.Type
9185
9286 -- * Combining Two Streams
9387 -- ** Zipping
94− -- | Zip corresponding elements of two streams.
9588 , zipWithM
9689 , zipWith
9790
@@ -107,8 +100,6 @@ module Streamly.Internal.Data.Stream.Type
107100 , unfoldMany
108101
109102 -- * Concat
110− -- | Generate streams by mapping a stream generator on each element of an
111− -- input stream, append the resulting streams and flatten.
112103 , concatEffect
113104 , concatMap
114105 , concatMapM
@@ -132,22 +123,14 @@ module Streamly.Internal.Data.Stream.Type
132123 , foldManyPost
133124 , groupsOf
134125 , refoldMany
135− , refoldIterateM
136126
137127 -- * Fold Iterate
138128 , reduceIterateBfs
139129 , foldIterateBfs
140130
141− -- * Splitting
142− , indexOnSuffix
143−
144131 -- * Multi-stream folds
145− -- | These should probably be expressed using zipping operations.
146132 , eqBy
147133 , cmpBy
148−
149− -- * Deprecated
150− , sliceOnSuffix
151134 )
152135where
153136
@@ -179,7 +162,6 @@ import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
179162import Streamly.Internal.Data.Refold.Type (Refold(..))
180163import Streamly.Internal.Data.Stream.Step (Step (..))
181164import Streamly.Internal.Data.SVar.Type (State, adaptState, defState)
182−import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
183165import Streamly.Internal.Data.Unfold.Type (Unfold(..))
184166
185167import qualified Streamly.Internal.Data.Fold.Type as FL hiding (foldr)
@@ -230,9 +212,6 @@ pattern Stream step state <- (unShare -> UnStream step state)
230212nilM :: Applicative m => m b -> Stream m a
231213nilM m = Stream (\_ _ -> m $> Stop) ()
232214
233−
234−infixr 5 `consM`
235−
236215-- | Like 'cons' but fuses an effect instead of a pure value.
237216{-# INLINE_NORMAL consM #-}
238217consM :: Applicative m => m a -> Stream m a -> Stream m a
@@ -572,12 +551,8 @@ foldAdd f =
572551-- >>> Stream.foldrM step (return False) s
573552-- True
574553--
575−-- >>> import Control.Monad (join)
576−-- >>> foldrM f z = join $ Stream.foldr f z
577−--
578554{-# INLINE_NORMAL foldrM #-}
579555foldrM :: Monad m => (a -> m b -> m b) -> m b -> Stream m a -> m b
580−-- foldrM f z = join . Streamly.Internal.Data.Stream.StreamD.Type.foldr f z
581556foldrM f z (Stream step state) = go SPEC state
582557 where
583558 {-# INLINE_LATE go #-}
@@ -1996,110 +1971,6 @@ refoldMany (Refold fstep inject extract) action (Stream step state) =
19961971 step' _ (FoldManyYield b next) = return $ Yield b next
19971972 step' _ FoldManyDone = return Stop
19981973
1999−{-# ANN type CIterState Fuse #-}
2000−data CIterState s f fs b
2001− = CIterInit s f
2002− | CIterConsume s fs
2003− | CIterYield b (CIterState s f fs b)
2004− | CIterStop
2005−
2006−-- | Like 'foldIterateM' but using the 'Refold' type instead. This could be
2007−-- much more efficient due to stream fusion.
2008−--
2009−-- /Internal/
2010−{-# INLINE_NORMAL refoldIterateM #-}
2011−refoldIterateM ::
2012− Monad m => Refold m b a b -> m b -> Stream m a -> Stream m b
2013−refoldIterateM (Refold fstep finject fextract) initial (Stream step state) =
2014− Stream stepOuter (CIterInit state initial)
2015−
2016− where
2017−
2018− {-# INLINE iterStep #-}
2019− iterStep st action = do
2020− res <- action
2021− return
2022− $ Skip
2023− $ case res of
2024− FL.Partial fs -> CIterConsume st fs
2025− FL.Done fb -> CIterYield fb $ CIterInit st (return fb)
2026−
2027− {-# INLINE_LATE stepOuter #-}
2028− stepOuter _ (CIterInit st action) = do
2029− iterStep st (action >>= finject)
2030− stepOuter gst (CIterConsume st fs) = do
2031− r <- step (adaptState gst) st
2032− case r of
2033− Yield x s -> iterStep s (fstep fs x)
2034− Skip s -> return $ Skip $ CIterConsume s fs
2035− Stop -> do
2036− b <- fextract fs
2037− return $ Skip $ CIterYield b CIterStop
2038− stepOuter _ (CIterYield a next) = return $ Yield a next
2039− stepOuter _ CIterStop = return Stop
2040−
2041−-- | The refold @indexerBy f n@ takes an (index, len) tuple as initial input,
2042−-- and returns @(index + len + n, b)@ as output where @b@ is the output of the
2043−-- fold.
2044−{-# INLINE indexerBy #-}
2045−indexerBy :: Monad m =>
2046− Fold m a Int -> Int -> Refold m (Int, Int) a (Int, Int)
2047−indexerBy (Fold step1 initial1 extract1 _final) n =
2048− Refold step inject extract
2049−
2050− where
2051−
2052− inject (i, len) = do
2053− r <- initial1
2054− return $ case r of
2055− FL.Partial s -> FL.Partial $ Tuple' (i + len + n) s
2056− FL.Done l -> FL.Done (i, l)
2057−
2058− step (Tuple' i s) x = do
2059− r <- step1 s x
2060− return $ case r of
2061− FL.Partial s1 -> FL.Partial $ Tuple' i s1
2062− FL.Done len -> FL.Done (i, len)
2063−
2064− extract (Tuple' i s) = (i,) <$> extract1 s
2065−
2066−-- | Like 'splitOnSuffix' but generates a stream of (index, len) tuples marking
2067−-- the places where the predicate matches in the stream.
2068−--
2069−-- /Pre-release/
2070−{-# INLINE indexOnSuffix #-}
2071−indexOnSuffix :: Monad m =>
2072− (a -> Bool) -> Stream m a -> Stream m (Int, Int)
2073−indexOnSuffix predicate =
2074− -- Scan the stream with the given refold
2075− refoldIterateM
2076− (indexerBy (FL.takeEndBy_ predicate FL.length) 1)
2077− (return (-1, 0))
2078−
2079−-- Alternate implementation
2080−{-# INLINE_NORMAL _indexOnSuffix #-}
2081−_indexOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
2082−_indexOnSuffix p (Stream step1 state1) = Stream step (Just (state1, 0, 0))
2083−
2084− where
2085−
2086− {-# INLINE_LATE step #-}
2087− step gst (Just (st, i, len)) = i `seq` len `seq` do
2088− r <- step1 (adaptState gst) st
2089− return
2090− $ case r of
2091− Yield x s ->
2092− if p x
2093− then Yield (i, len + 1) (Just (s, i + len + 1, 0))
2094− else Skip (Just (s, i, len + 1))
2095− Skip s -> Skip (Just (s, i, len))
2096− Stop -> if len == 0 then Stop else Yield (i, len) Nothing
2097− step _ Nothing = return Stop
2098−
2099−{-# DEPRECATED sliceOnSuffix "Please use indexOnSuffix instead." #-}
2100−sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
2101−sliceOnSuffix = indexOnSuffix
2102−
21031974------------------------------------------------------------------------------
21041975-- Stream with a cross product style monad instance
21051976------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/StreamK.hs+28−19
@@ -16,15 +16,16 @@ module Streamly.Internal.Data.StreamK
1616 --
1717 -- $setup
1818
19+ -- * The stream type
1920 module Streamly.Internal.Data.StreamK.Type
20− -- * Transformer
2121 , module Streamly.Internal.Data.StreamK.Transformer
2222
23− -- * From containers
23+ , StreamK(..)
2424 , fromList
2525 , fromStream
26+ , toStream
2627
27− -- * Specialized Generation
28+ -- ** Specialized Generation
2829 , repeatM
2930 , replicate
3031 , replicateM
@@ -36,6 +37,8 @@ module Streamly.Internal.Data.StreamK
3637 -- * Elimination
3738 -- ** General Folds
3839 , foldr1
40+ , foldlM'
41+ , foldlMx'
3942 , fold
4043 , foldBreak
4144 , foldEither
@@ -66,13 +69,13 @@ module Streamly.Internal.Data.StreamK
6669 , find
6770 , (!!)
6871
69− -- ** To Containers
70− , toList
71− , toStream
72−
7372 -- ** Map and Fold
7473 , mapM_
7574
75+ -- ** Conversions
76+ , toList
77+ , hoist
78+
7679 -- * Transformation
7780 -- ** By folding (scans)
7881 , scanl'
@@ -99,7 +102,6 @@ module Streamly.Internal.Data.StreamK
99102
100103 -- ** Reordering
101104 , sortBy
102− , sortOn
103105
104106 -- ** Map and Filter
105107 , mapMaybe
@@ -115,9 +117,6 @@ module Streamly.Internal.Data.StreamK
115117 -- ** Transformation comprehensions
116118 , the
117119
118− -- ** Transforming Inner Monad
119− , hoist
120−
121120 -- * Exceptions
122121 , handle
123122
@@ -134,7 +133,6 @@ import Control.Exception (mask_, Exception)
134133import Control.Monad (void, join)
135134import Control.Monad.Catch (MonadCatch)
136135import Control.Monad.IO.Class (MonadIO(..))
137−import Data.Ord (comparing)
138136import Data.Proxy (Proxy(..))
139137import GHC.Types (SPEC(..))
140138import Streamly.Internal.Data.Array.Type (Array(..))
@@ -308,6 +306,19 @@ foldr1 step m = do
308306 yieldk a r = fmap (step p) (go a r)
309307 in foldStream defState yieldk single stp m1
310308
309+-- XXX replace the recursive "go" with explicit continuations.
310+-- | Like 'foldx', but with a monadic step function.
311+{-# INLINABLE foldlMx' #-}
312+foldlMx' :: Monad m
313+ => (x -> a -> m x) -> m x -> (x -> m b) -> StreamK m a -> m b
314+foldlMx' step begin done = go begin
315+ where
316+ go !acc m1 =
317+ let stop = acc >>= done
318+ single a = acc >>= \b -> step b a >>= done
319+ yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
320+ in foldStream defState yieldk single stop m1
321+
311322-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
312323-- expression strictly at each step. The behavior is similar to 'foldl''. A
313324-- 'Fold' can terminate early without consuming the full stream. See the
@@ -459,6 +470,11 @@ foldConcat
459470 Stream.Skip s -> go1 SPEC fs s
460471 Stream.Stop -> return $ Left fs
461472
473+-- | Like 'foldl'' but with a monadic step function.
474+{-# INLINE foldlM' #-}
475+foldlM' :: Monad m => (b -> a -> m b) -> m b -> StreamK m a -> m b
476+foldlM' step begin = foldlMx' step begin return
477+
462478------------------------------------------------------------------------------
463479-- Specialized folds
464480------------------------------------------------------------------------------
@@ -1721,10 +1737,3 @@ sortBy cmp =
17211737 . Stream.catRights -- its a non-failing backtracking parser
17221738 . Stream.parseMany (fmap (either id id) p)
17231739 . Stream.fromStreamK
1724−
1725−{-# INLINE sortOn #-}
1726−sortOn :: (Monad m, Ord b) => (a -> b) -> StreamK m a -> StreamK m a
1727−sortOn f =
1728− fmap snd
1729− . sortBy (comparing fst)
1730− . fmap (\x -> let y = f x in y `seq` (y, x))
core/src/Streamly/Internal/Data/StreamK/Type.hs+11−80
@@ -1,8 +1,4 @@
11{-# LANGUAGE CPP #-}
2−{-# LANGUAGE TypeFamilies #-}
3−-- Must come after TypeFamilies, otherwise it is re-enabled.
4−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
5−{-# LANGUAGE NoMonoLocalBinds #-}
62{-# LANGUAGE UndecidableInstances #-}
73-- |
84-- Module : Streamly.Internal.Data.StreamK.Type
@@ -88,8 +84,6 @@ module Streamly.Internal.Data.StreamK.Type
8884 -- ** Strict Left Folds
8985 , Streamly.Internal.Data.StreamK.Type.foldl'
9086 , foldlx'
91− , foldlMx'
92− , foldlM'
9387
9488 -- ** Lazy Right Folds
9589 , Streamly.Internal.Data.StreamK.Type.foldr
@@ -97,11 +91,8 @@ module Streamly.Internal.Data.StreamK.Type
9791 -- ** Specific Folds
9892 , drain
9993 , null
100− , headNonEmpty
10194 , tail
102− , tailNonEmpty
10395 , init
104− , initNonEmpty
10596
10697 -- * Mapping
10798 , map
@@ -826,24 +817,6 @@ foldlx' step begin done m = get $ go m begin
826817foldl' :: Monad m => (b -> a -> b) -> b -> StreamK m a -> m b
827818foldl' step begin = foldlx' step begin id
828819
829−-- XXX replace the recursive "go" with explicit continuations.
830−-- | Like 'foldx', but with a monadic step function.
831−{-# INLINABLE foldlMx' #-}
832−foldlMx' :: Monad m
833− => (x -> a -> m x) -> m x -> (x -> m b) -> StreamK m a -> m b
834−foldlMx' step begin done = go begin
835− where
836− go !acc m1 =
837− let stop = acc >>= done
838− single a = acc >>= \b -> step b a >>= done
839− yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
840− in foldStream defState yieldk single stop m1
841−
842−-- | Like 'foldl'' but with a monadic step function.
843−{-# INLINE foldlM' #-}
844−foldlM' :: Monad m => (b -> a -> m b) -> m b -> StreamK m a -> m b
845−foldlM' step begin = foldlMx' step begin return
846−
847820------------------------------------------------------------------------------
848821-- Specialized folds
849822------------------------------------------------------------------------------
@@ -1814,42 +1787,14 @@ iterateMWith cns step = go
18141787 !next <- s
18151788 foldStreamShared st stp sng yld (return next `cns` go (step next))
18161789
1817−-- | head for non-empty streams, fails for empty stream case.
1818−--
1819−{-# INLINE headNonEmpty #-}
1820−headNonEmpty :: Monad m => StreamK m a -> m a
1821−headNonEmpty = foldrM (\x _ -> return x) (error "headNonEmpty: empty stream")
1822−
1823−-- | init for non-empty streams, fails for empty stream case.
1824−--
1825−-- See also 'init' for a non-partial version of this function..
1826−{-# INLINE initNonEmpty #-}
1827−initNonEmpty :: Stream m a -> Stream m a
1828−initNonEmpty = go0
1829−
1830− where
1831−
1832− go0 m = mkStream $ \st yld sng stp ->
1833− let stop = error "initNonEmpty: Empty Stream."
1834− single _ = stp
1835− yieldk a r = foldStream st yld sng stp (go1 a r)
1836− in foldStream st yieldk single stop m
1837−
1838− go1 a r = mkStream $ \st yld sng stp ->
1839− let stop = stp
1840− single _ = sng a
1841− yieldk a1 r1 = yld a (go1 a1 r1)
1842− in foldStream st yieldk single stop r
1790+{-# INLINE headPartial #-}
1791+headPartial :: Monad m => StreamK m a -> m a
1792+headPartial = foldrM (\x _ -> return x) (error "head of nil")
18431793
1844−-- | tail for non-empty streams, fails for empty stream case.
1845−--
1846−-- See also 'tail' for a non-partial version of this function..
1847−--
1848−-- Note: this is same as "drop 1" with error on empty stream.
1849−{-# INLINE tailNonEmpty #-}
1850−tailNonEmpty :: StreamK m a -> StreamK m a
1851−tailNonEmpty m = mkStream $ \st yld sng stp ->
1852− let stop = error "tailNonEmpty: empty stream"
1794+{-# INLINE tailPartial #-}
1795+tailPartial :: StreamK m a -> StreamK m a
1796+tailPartial m = mkStream $ \st yld sng stp ->
1797+ let stop = error "tail of nil"
18531798 single _ = stp
18541799 yieldk _ r = foldStream st yld sng stp r
18551800 in foldStream st yieldk single stop m
@@ -1914,10 +1859,10 @@ mfix f = mkStream $ \st yld sng stp ->
19141859 where
19151860
19161861 -- fix the head element of the stream
1917− xs = fix (f . headNonEmpty)
1862+ xs = fix (f . headPartial)
19181863
19191864 -- now fix the tail recursively
1920− ys = mfix (tailNonEmpty . f)
1865+ ys = mfix (tailPartial . f)
19211866
19221867-------------------------------------------------------------------------------
19231868-- Conversions
@@ -1948,15 +1893,6 @@ uncons m =
19481893 yieldk a r = pure (Just (a, r))
19491894 in foldStream defState yieldk single stop m
19501895
1951−-- Note that this is not a StreamK -> StreamK because then we cannot handle the
1952−-- empty stream case without making this a partial function.
1953−--
1954−-- See tailNonEmpty as well above.
1955−
1956−-- | Same as:
1957−--
1958−-- >>> tail = fmap (fmap snd) StreamK.uncons
1959−--
19601896{-# INLINE tail #-}
19611897tail :: Applicative m => StreamK m a -> m (Maybe (StreamK m a))
19621898tail =
@@ -1965,14 +1901,9 @@ tail =
19651901 yieldk _ r = pure $ Just r
19661902 in foldStream defState yieldk single stop
19671903
1968−-- Note that this is not a StreamK -> StreamK because then we cannot handle the
1969−-- empty stream case without making this a partial function.
1904+-- | Extract all but the last element of the stream, if any.
19701905--
1971−-- XXX How do we implement unsnoc? Make StreamK a monad and return the
1972−-- remaining stream as a result value in the monad?
1973−
1974−-- | Extract all but the last element of the stream, if any. This will end up
1975−-- evaluating the last element as well to find out that it is last.
1906+-- Note: This will end up buffering the entire stream.
19761907--
19771908-- /Pre-release/
19781909{-# INLINE init #-}
core/src/Streamly/Internal/Data/Time/Units.hs+4
@@ -1,3 +1,7 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE PolyKinds #-}
3+{-# LANGUAGE UnboxedTuples #-}
4+
15-- |
26-- Module : Streamly.Internal.Data.Time.Units
37-- Copyright : (c) 2019 Composewell Technologies
core/src/Streamly/Internal/Data/Unbox.hs+39−75
@@ -1,8 +1,5 @@
11{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−-- Must come after TypeFamilies, otherwise it is re-enabled.
4−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
5−{-# LANGUAGE NoMonoLocalBinds #-}
2+{-# LANGUAGE DefaultSignatures #-}
63{-# LANGUAGE UnboxedTuples #-}
74{-# LANGUAGE UndecidableInstances #-}
85
@@ -50,6 +47,9 @@ import Data.Functor.Const (Const(..))
5047import Data.Functor.Identity (Identity(..))
5148import Data.Kind (Type)
5249import Data.Proxy (Proxy (..))
50+#ifdef DEBUG
51+import Debug.Trace (trace)
52+#endif
5353import Foreign.Ptr (IntPtr(..), WordPtr(..))
5454import GHC.Base (IO(..))
5555import GHC.Fingerprint.Type (Fingerprint(..))
@@ -68,9 +68,6 @@ import GHC.TypeLits
6868import Prelude hiding (read)
6969
7070import Streamly.Internal.Data.MutByteArray.Type (MutByteArray(..))
71−#ifdef DEBUG
72−import Streamly.Internal.Data.MutByteArray.Type (sizeOfMutableByteArray)
73−#endif
7471
7572--------------------------------------------------------------------------------
7673-- The Unbox type class
@@ -269,66 +266,43 @@ class Unbox a where
269266{-# DEPRECATED peekByteIndex "Use peekAt." #-}
270267{-# DEPRECATED pokeByteIndex "Use pokeAt." #-}
271268
272−-- _size is the length from array start to the last accessed byte.
273−{-# INLINE checkBounds #-}
274−checkBounds :: String -> Int -> MutByteArray -> IO ()
275−checkBounds _label _size _arr = do
276−#ifdef DEBUG
277− sz <- sizeOfMutableByteArray _arr
278− if (_size > sz)
279− then error
280− $ _label
281− ++ ": accessing array at offset = "
282− ++ show (_size - 1)
283− ++ " max valid offset = " ++ show (sz - 1)
284− else return ()
285−#else
286− return ()
287−#endif
269+-- XXX Add asserts to check bounds
288270
289271#define DERIVE_UNBOXED(_type, _constructor, _readArray, _writeArray, _sizeOf) \
290−instance Unbox _type where { \
291−; {-# INLINE peekAt #-} \
292−; peekAt off@(I# n) arr@(MutByteArray mbarr) = \
293− checkBounds "peek" (off + sizeOf (Proxy :: Proxy _type)) arr \
294− >> (IO $ \s -> \
295− case _readArray mbarr n s of \
296− { (# s1, i #) -> (# s1, _constructor i #) }) \
297−; {-# INLINE pokeAt #-} \
298−; pokeAt off@(I# n) arr@(MutByteArray mbarr) (_constructor val) = \
299− checkBounds "poke" (off + sizeOf (Proxy :: Proxy _type)) arr \
300− >> (IO $ \s -> (# _writeArray mbarr n val s, () #)) \
301−; {-# INLINE sizeOf #-} \
302−; sizeOf _ = _sizeOf \
272+instance Unbox _type where { \
273+; {-# INLINE peekAt #-} \
274+; peekAt (I# n) (MutByteArray mbarr) = IO $ \s -> \
275+ case _readArray mbarr n s of \
276+ { (# s1, i #) -> (# s1, _constructor i #) } \
277+; {-# INLINE pokeAt #-} \
278+; pokeAt (I# n) (MutByteArray mbarr) (_constructor val) = \
279+ IO $ \s -> (# _writeArray mbarr n val s, () #) \
280+; {-# INLINE sizeOf #-} \
281+; sizeOf _ = _sizeOf \
303282}
304283
305284#define DERIVE_WRAPPED_UNBOX(_constraint, _type, _constructor, _innerType) \
306285instance _constraint Unbox _type where \
307−; {-# INLINE peekAt #-} \
308−; peekAt i arr = \
309− checkBounds "peek" (i + sizeOf (Proxy :: Proxy _type)) arr \
310− >> _constructor <$> peekAt i arr \
311−; {-# INLINE pokeAt #-} \
312−; pokeAt i arr (_constructor a) = \
313− checkBounds "poke" (i + sizeOf (Proxy :: Proxy _type)) arr \
314− >> pokeAt i arr a \
286+; {-# INLINE peekAt #-} \
287+; peekAt i arr = _constructor <$> peekAt i arr \
288+; {-# INLINE pokeAt #-} \
289+; pokeAt i arr (_constructor a) = pokeAt i arr a \
315290; {-# INLINE sizeOf #-} \
316291; sizeOf _ = SIZE_OF(_innerType)
317292
318−#define DERIVE_BINARY_UNBOX(_constraint, _type, _constructor, _innerType) \
319−instance _constraint Unbox _type where { \
320−; {-# INLINE peekAt #-} \
321−; peekAt i arr = \
322− checkBounds "peek" (i + sizeOf (Proxy :: Proxy _type)) arr >> \
323− peekAt i arr >>= \
324− (\p1 -> peekAt (i + SIZE_OF(_innerType)) arr <&> _constructor p1) \
325−; {-# INLINE pokeAt #-} \
326−; pokeAt i arr (_constructor p1 p2) = \
327− checkBounds "poke" (i + sizeOf (Proxy :: Proxy _type)) arr >> \
328− pokeAt i arr p1 >> \
329− pokeAt (i + SIZE_OF(_innerType)) arr p2 \
330−; {-# INLINE sizeOf #-} \
331−; sizeOf _ = 2 * SIZE_OF(_innerType) \
293+#define DERIVE_BINARY_UNBOX(_constraint, _type, _constructor, _innerType) \
294+instance _constraint Unbox _type where { \
295+; {-# INLINE peekAt #-} \
296+; peekAt i arr = \
297+ peekAt i arr >>= \
298+ (\p1 -> peekAt (i + SIZE_OF(_innerType)) arr \
299+ <&> _constructor p1) \
300+; {-# INLINE pokeAt #-} \
301+; pokeAt i arr (_constructor p1 p2) = \
302+ pokeAt i arr p1 >> \
303+ pokeAt (i + SIZE_OF(_innerType)) arr p2 \
304+; {-# INLINE sizeOf #-} \
305+; sizeOf _ = 2 * SIZE_OF(_innerType) \
332306}
333307
334308-------------------------------------------------------------------------------
@@ -449,12 +423,10 @@ DERIVE_BINARY_UNBOX(,Fingerprint,Fingerprint,Word64)
449423instance Unbox () where
450424
451425 {-# INLINE peekAt #-}
452− peekAt i arr =
453− checkBounds "peek ()" (i + sizeOf (Proxy :: Proxy ())) arr >> return ()
426+ peekAt _ _ = return ()
454427
455428 {-# INLINE pokeAt #-}
456− pokeAt i arr _ =
457− checkBounds "poke ()" (i + sizeOf (Proxy :: Proxy ())) arr >> return ()
429+ pokeAt _ _ _ = return ()
458430
459431 {-# INLINE sizeOf #-}
460432 sizeOf _ = 1
@@ -463,16 +435,10 @@ instance Unbox () where
463435instance Unbox IoSubSystem where
464436
465437 {-# INLINE peekAt #-}
466− peekAt i arr =
467− checkBounds
468− "peek IoSubSystem" (i + sizeOf (Proxy :: Proxy IoSubSystem)) arr
469− >> toEnum <$> peekAt i arr
438+ peekAt i arr = toEnum <$> peekAt i arr
470439
471440 {-# INLINE pokeAt #-}
472− pokeAt i arr a =
473− checkBounds
474− "poke IoSubSystem" (i + sizeOf (Proxy :: Proxy IoSubSystem)) arr
475− >> pokeAt i arr (fromEnum a)
441+ pokeAt i arr a = pokeAt i arr (fromEnum a)
476442
477443 {-# INLINE sizeOf #-}
478444 sizeOf _ = sizeOf (Proxy :: Proxy Int)
@@ -482,16 +448,14 @@ instance Unbox Bool where
482448
483449 {-# INLINE peekAt #-}
484450 peekAt i arr = do
485− checkBounds "peek Bool" (i + sizeOf (Proxy :: Proxy Bool)) arr
486451 res <- peekAt i arr
487452 return $ res /= (0 :: Int8)
488453
489454 {-# INLINE pokeAt #-}
490455 pokeAt i arr a =
491− checkBounds "poke Bool" (i + sizeOf (Proxy :: Proxy Bool)) arr
492− >> if a
493− then pokeAt i arr (1 :: Int8)
494− else pokeAt i arr (0 :: Int8)
456+ if a
457+ then pokeAt i arr (1 :: Int8)
458+ else pokeAt i arr (0 :: Int8)
495459
496460 {-# INLINE sizeOf #-}
497461 sizeOf _ = 1
core/src/Streamly/Internal/Data/Unbox/TH.hs+1−4
@@ -241,7 +241,6 @@ mkSizeOfExpr headTy constructors =
241241mkPeekExprOne :: Int -> DataCon -> Q Exp
242242mkPeekExprOne tagSize (DataCon cname _ _ fields) =
243243 case fields of
244− -- XXX Should we peek and check if the byte value is 0?
245244 [] -> [|pure $(conE cname)|]
246245 _ ->
247246 letE
@@ -337,9 +336,7 @@ mkPokeExpr headTy cons =
337336 [|error
338337 ("Attempting to poke type with no constructors (" ++
339338 $(lift (pprint headTy)) ++ ")")|]
340− -- XXX We don't gaurentee encoded equivalilty for Unbox. Does it still
341− -- make sense to encode a default value for unit constructor?
342− [(DataCon _ _ _ [])] -> [|pure ()|] -- mkPokeExprTag ''Word8 0
339+ [(DataCon _ _ _ [])] -> [|pure ()|]
343340 [(DataCon cname _ _ fields)] ->
344341 caseE
345342 (varE _val)
core/src/Streamly/Internal/Data/Unfold.hs+4−6
@@ -82,7 +82,7 @@ module Streamly.Internal.Data.Unfold
8282 , dropWhileM
8383
8484 -- ** Cross product
85− , innerJoin
85+ , joinInnerGeneric
8686
8787 -- ** Resource Management
8888 -- | 'bracket' is the most general resource management operation, all other
@@ -677,12 +677,10 @@ dropWhileM f (Unfold step inject) = Unfold step' inject'
677677dropWhile :: Monad m => (b -> Bool) -> Unfold m a b -> Unfold m a b
678678dropWhile f = dropWhileM (return . f)
679679
680−-- | Cross intersection of two unfolds. See
681−-- 'Streamly.Internal.Data.Stream.innerJoin' for more details.
682−{-# INLINE_NORMAL innerJoin #-}
683−innerJoin :: Monad m =>
680+{-# INLINE_NORMAL joinInnerGeneric #-}
681+joinInnerGeneric :: Monad m =>
684682 (b -> c -> Bool) -> Unfold m a b -> Unfold m a c -> Unfold m a (b, c)
685−innerJoin eq s1 s2 = filter (\(a, b) -> a `eq` b) $ cross s1 s2
683+joinInnerGeneric eq s1 s2 = filter (\(a, b) -> a `eq` b) $ cross s1 s2
686684
687685------------------------------------------------------------------------------
688686-- Exceptions
core/src/Streamly/Internal/FileSystem/File.hs+9−4
@@ -103,14 +103,15 @@ import qualified Control.Monad.Catch as MC
103103import qualified System.IO as SIO
104104
105105import Streamly.Data.Fold (groupsOf, drain)
106−import Streamly.Internal.Data.Array.Type (Array(..))
106+import Streamly.Internal.Data.Array.Type (Array(..), pinnedWriteNUnsafe)
107107import Streamly.Internal.Data.Fold.Type (Fold(..))
108108import Streamly.Data.Stream (Stream)
109+import Streamly.Internal.Data.Unbox (Unbox)
109110import Streamly.Internal.Data.Unfold.Type (Unfold(..))
110111-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
111112import Streamly.Internal.System.IO (defaultChunkSize)
112113
113−import qualified Streamly.Internal.Data.Array as A
114+import qualified Streamly.Data.Array as A
114115import qualified Streamly.Data.Stream as S
115116import qualified Streamly.Data.Unfold as UF
116117import qualified Streamly.Internal.Data.Array.Type as IA (pinnedChunksOf)
@@ -338,6 +339,10 @@ readWithBufferOf = readerWith
338339reader :: (MonadIO m, MonadCatch m) => Unfold m FilePath Word8
339340reader = UF.many A.reader (usingFile FH.chunkReader)
340341
342+{-# INLINE concatChunks #-}
343+concatChunks :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
344+concatChunks = S.unfoldMany A.reader
345+
341346-- | Generate a stream of bytes from a file specified by path. The stream ends
342347-- when EOF is encountered. File is locked using multiple reader and single
343348-- writer locking mode.
@@ -346,7 +351,7 @@ reader = UF.many A.reader (usingFile FH.chunkReader)
346351--
347352{-# INLINE read #-}
348353read :: (MonadIO m, MonadCatch m) => FilePath -> Stream m Word8
349−read file = A.concat $ withFile file ReadMode FH.readChunks
354+read file = concatChunks $ withFile file ReadMode FH.readChunks
350355
351356{-# DEPRECATED toBytes "Please use 'read' instead" #-}
352357{-# INLINE toBytes #-}
@@ -462,7 +467,7 @@ writeChunks path = Fold step initial extract final
462467writeWith :: (MonadIO m, MonadCatch m)
463468 => Int -> FilePath -> Fold m Word8 ()
464469writeWith n path =
465− groupsOf n (A.unsafePinnedCreateOf n) (writeChunks path)
470+ groupsOf n (pinnedWriteNUnsafe n) (writeChunks path)
466471
467472{-# DEPRECATED writeWithBufferOf "Please use 'writeWith' instead" #-}
468473{-# INLINE writeWithBufferOf #-}
core/src/Streamly/Internal/FileSystem/Handle.hs+28−21
@@ -40,8 +40,8 @@ module Streamly.Internal.FileSystem.Handle
4040
4141 -- * Streams
4242 , read
43− , readWith -- readConcatChunksOf
44− , readChunksWith -- readChunksOf
43+ , readWith
44+ , readChunksWith
4545 , readChunks
4646
4747 -- * Unfolds
@@ -59,10 +59,10 @@ module Streamly.Internal.FileSystem.Handle
5959 -- , writeUtf8ByLines
6060 -- , writeByFrames
6161 -- , writeLines
62− , writeWith -- writeChunksOf
62+ , writeWith
6363 , writeChunks
64− , writeChunksWith -- writeCompactChunksOf
65− , writeMaybesWith -- writeCompactJustsOf
64+ , writeChunksWith
65+ , writeMaybesWith
6666
6767 -- * Refolds
6868 , writer
@@ -131,13 +131,16 @@ import Streamly.Internal.Data.Fold (Fold)
131131import Streamly.Internal.Data.Refold.Type (Refold(..))
132132import Streamly.Internal.Data.Unfold.Type (Unfold(..))
133133import Streamly.Internal.Data.Array.Type
134− (Array(..), unsafeFreezeWithShrink, byteLength)
134+ (Array(..), pinnedWriteNUnsafe, unsafeFreezeWithShrink, byteLength)
135135import Streamly.Internal.Data.Stream.Type (Stream)
136+import Streamly.Internal.Data.Array.Stream (lpackArraysChunksOf)
136137-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
137138import Streamly.Internal.System.IO (defaultChunkSize)
138139
139140import qualified Streamly.Data.Fold as FL
140−import qualified Streamly.Internal.Data.Array as A
141+import qualified Streamly.Data.Array as A
142+import qualified Streamly.Internal.Data.Array.Type as A
143+import qualified Streamly.Internal.Data.Array.Stream as AS
141144import qualified Streamly.Internal.Data.MutArray.Type as MArray
142145import qualified Streamly.Internal.Data.Refold.Type as Refold
143146import qualified Streamly.Internal.Data.Fold.Type as FL(refoldMany)
@@ -166,8 +169,6 @@ import qualified Streamly.Internal.Data.StreamK.Type as K (mkStream)
166169-- Array IO (Input)
167170-------------------------------------------------------------------------------
168171
169−-- XXX add an API that compacts the arrays to an exact size.
170−
171172-- | Read a 'ByteArray' consisting of one or more bytes from a file handle. If
172173-- no data is available on the handle it blocks until at least one byte becomes
173174-- available. If any data is available then it immediately returns that data
@@ -177,9 +178,9 @@ import qualified Streamly.Internal.Data.StreamK.Type as K (mkStream)
177178{-# INLINABLE getChunk #-}
178179getChunk :: MonadIO m => Int -> Handle -> m (Array Word8)
179180getChunk size h = liftIO $ do
180− arr :: MArray.MutArray Word8 <- MArray.pinnedEmptyOf size
181+ arr <- MArray.pinnedNewBytes size
181182 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
182− MArray.unsafePinnedAsPtr arr $ \p -> do
183+ MArray.asPtrUnsafe arr $ \p -> do
183184 n <- hGetBufSome h p size
184185 -- XXX shrink only if the diff is significant
185186 return $
@@ -337,6 +338,10 @@ readerWith = UF.many A.reader chunkReaderWith
337338readWithBufferOf :: MonadIO m => Unfold m (Int, Handle) Word8
338339readWithBufferOf = readerWith
339340
341+{-# INLINE concatChunks #-}
342+concatChunks :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
343+concatChunks = S.unfoldMany A.reader
344+
340345-- | @readWith bufsize handle@ reads a byte stream from a file
341346-- handle, reads are performed in chunks of up to @bufsize@.
342347--
@@ -345,7 +350,7 @@ readWithBufferOf = readerWith
345350-- /Pre-release/
346351{-# INLINE readWith #-}
347352readWith :: MonadIO m => Int -> Handle -> Stream m Word8
348−readWith size h = A.concat $ readChunksWith size h
353+readWith size h = concatChunks $ readChunksWith size h
349354
350355-- | Unfolds a file handle into a byte stream. IO requests to the device are
351356-- performed in sizes of
@@ -364,7 +369,7 @@ reader = UF.many A.reader chunkReader
364369-- /Pre-release/
365370{-# INLINE read #-}
366371read :: MonadIO m => Handle -> Stream m Word8
367−read = A.concat . readChunks
372+read = concatChunks . readChunks
368373
369374-------------------------------------------------------------------------------
370375-- Writing
@@ -379,12 +384,12 @@ read = A.concat . readChunks
379384{-# INLINABLE putChunk #-}
380385putChunk :: MonadIO m => Handle -> Array a -> m ()
381386putChunk _ arr | byteLength arr == 0 = return ()
382−putChunk h arr = A.unsafePinnedAsPtr arr $ \ptr ->
387+putChunk h arr = A.asPtrUnsafe arr $ \ptr ->
383388 liftIO $ hPutBuf h ptr aLen
384389
385390 where
386391
387− -- XXX We should have the length passed by unsafePinnedAsPtr itself.
392+ -- XXX We should have the length passed by asPtrUnsafe itself.
388393 aLen = A.byteLength arr
389394
390395-------------------------------------------------------------------------------
@@ -416,7 +421,7 @@ putChunks h = S.fold (FL.drainMapM (putChunk h))
416421{-# INLINE putChunksWith #-}
417422putChunksWith :: (MonadIO m, Unbox a)
418423 => Int -> Handle -> Stream m (Array a) -> m ()
419−putChunksWith n h xs = putChunks h $ A.compactLE n xs
424+putChunksWith n h xs = putChunks h $ AS.compact n xs
420425
421426-- > putBytesWith n h m = Handle.putChunks h $ A.pinnedChunksOf n m
422427
@@ -456,6 +461,8 @@ writeChunks h = FL.drainMapM (putChunk h)
456461chunkWriter :: MonadIO m => Refold m Handle (Array a) ()
457462chunkWriter = Refold.drainBy putChunk
458463
464+-- XXX lpackArraysChunksOf should be written idiomatically
465+
459466-- | @writeChunksWith bufsize handle@ writes a stream of arrays
460467-- to @handle@ after coalescing the adjacent arrays in chunks of @bufsize@.
461468-- We never split an array, if a single array is bigger than the specified size
@@ -465,7 +472,7 @@ chunkWriter = Refold.drainBy putChunk
465472{-# INLINE writeChunksWith #-}
466473writeChunksWith :: (MonadIO m, Unbox a)
467474 => Int -> Handle -> Fold m (Array a) ()
468−writeChunksWith n h = A.lCompactGE n (writeChunks h)
475+writeChunksWith n h = lpackArraysChunksOf n (writeChunks h)
469476
470477-- | Same as 'writeChunksWith'
471478--
@@ -489,11 +496,11 @@ writeChunksWithBufferOf = writeChunksWith
489496-- Bytes in the input stream are collected into a buffer until we have a chunk
490497-- of @reqSize@ and then written to the IO device.
491498--
492−-- >>> writeWith n h = Fold.groupsOf n (Array.unsafeCreateOf n) (Handle.writeChunks h)
499+-- >>> writeWith n h = Fold.groupsOf n (Array.writeNUnsafe n) (Handle.writeChunks h)
493500--
494501{-# INLINE writeWith #-}
495502writeWith :: MonadIO m => Int -> Handle -> Fold m Word8 ()
496−writeWith n h = FL.groupsOf n (A.unsafePinnedCreateOf n) (writeChunks h)
503+writeWith n h = FL.groupsOf n (pinnedWriteNUnsafe n) (writeChunks h)
497504
498505-- | Same as 'writeWith'
499506--
@@ -511,7 +518,7 @@ writeWithBufferOf = writeWith
511518writeMaybesWith :: (MonadIO m )
512519 => Int -> Handle -> Fold m (Maybe Word8) ()
513520writeMaybesWith n h =
514− let writeNJusts = FL.lmap fromJust $ A.pinnedCreateOf n
521+ let writeNJusts = FL.lmap fromJust $ A.pinnedWriteN n
515522 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
516523 in FL.many writeOnNothing (writeChunks h)
517524
@@ -521,7 +528,7 @@ writeMaybesWith n h =
521528{-# INLINE writerWith #-}
522529writerWith :: MonadIO m => Int -> Refold m Handle Word8 ()
523530writerWith n =
524− FL.refoldMany (FL.take n $ A.unsafePinnedCreateOf n) chunkWriter
531+ FL.refoldMany (FL.take n $ pinnedWriteNUnsafe n) chunkWriter
525532
526533-- | Write a byte stream to a file handle. Accumulates the input in chunks of
527534-- up to 'Streamly.Internal.Data.Array.Type.defaultChunkSize' before writing
core/src/Streamly/Internal/FileSystem/Path.hsdeleted−515
@@ -1,515 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−
3−-- |
4−-- Module : Streamly.Internal.FileSystem.Path
5−-- Copyright : (c) 2023 Composewell Technologies
6−-- License : BSD3
7−-- Maintainer : streamly@composewell.com
8−-- Portability : GHC
9−--
10−-- Well typed and flexible file systems paths, preserving the OS and filesystem
11−-- encoding.
12−--
13−-- You can choose the level of type safety you want. 'Path' is the basic path
14−-- type which can represent a file, directory, absolute or relative path with
15−-- no restrictions. Depending on how much type safety you want you can choose
16−-- appropriate type wrappers to wrap 'Path'. @File Path@ mandates the path to
17−-- be a file whereas @Abs (File Path)@ mandates it to be an absolute path
18−-- representing a file.
19−--
20−-- You can upgrade or downgrade the safety. Whenever a less restrictive path
21−-- type is converted to a more restrctive path type the conversion involves
22−-- checks and it may fail. However, a more restrictive path type can be freely
23−-- converted to a less restrictive one.
24−--
25−-- See the @streamly-filepath@ package for interworking with the 'OsPath' type.
26−-- The 'Path' type can be converted to and from 'OsPath' type at zero cost
27−-- since the underlying representation of both is the same.
28−
29−-- Conventions: A trailing separator on a path indicates that it is a directory.
30−-- However, the absence of a trailing separator does not convey any
31−-- information, it could either be a directory or a file.
32−
33−-- You may also find the 'str' quasiquoter from "Streamly.Unicode.String" to be
34−-- useful in creating paths.
35−--
36−module Streamly.Internal.FileSystem.Path
37− (
38− -- * Path Types
39− Path (..)
40− , File
41− , Dir
42− , Abs
43− , Rel
44−
45− -- * Conversions
46− , IsPath (..)
47− , adaptPath
48−
49− -- * Construction
50− , fromChunk
51− , fromChunkUnsafe
52− , fromString
53− , fromChars
54−
55− -- * Statically Verified Literals
56− -- quasiquoters
57− , path
58− , abs
59− , rel
60− , dir
61− , file
62− , absdir
63− , reldir
64− , absfile
65− , relfile
66−
67− -- * Statically Verified Strings
68− -- TH macros
69− , mkPath
70− , mkAbs
71− , mkRel
72− , mkDir
73− , mkFile
74− , mkAbsDir
75− , mkRelDir
76− , mkAbsFile
77− , mkRelFile
78−
79− -- * Elimination
80− , toChunk
81− , toString
82− , toChars
83−
84− -- * Operations
85− -- Do we need to export the separator functions? They are not essential if
86− -- operations to split and combine paths are provided. If someone wants to
87− -- work on paths at low level then they know what they are.
88− , primarySeparator
89− , isSeparator
90− , extendPath
91− , extendDir
92− )
93−where
94−
95−import Control.Exception (Exception)
96−import Control.Monad.Catch (MonadThrow(..))
97−import Data.Char (chr)
98−import Data.Functor.Identity (Identity(..))
99−import Data.Word (Word8)
100−#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
101−import Data.Word (Word16)
102−#endif
103−import Language.Haskell.TH (Q, Exp)
104−import Language.Haskell.TH.Quote (QuasiQuoter)
105−import Streamly.Internal.Data.Array (Array)
106−import Streamly.Internal.Data.Stream (Stream)
107−import System.IO.Unsafe (unsafePerformIO)
108−
109−import qualified Streamly.Internal.Data.Array as Array
110−import qualified Streamly.Internal.Data.Fold as Fold
111−import qualified Streamly.Internal.Data.MutArray as MutArray
112−import qualified Streamly.Internal.Data.Stream as Stream
113−import qualified Streamly.Internal.Unicode.Stream as Unicode
114−
115−import Prelude hiding (abs)
116−
117−#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
118−#define WORD_TYPE Word16
119−#define SEPARATOR 92
120−#else
121−#define WORD_TYPE Word8
122−#define SEPARATOR 47
123−#endif
124−
125−------------------------------------------------------------------------------
126−-- Exceptions
127−------------------------------------------------------------------------------
128−
129−-- | Exceptions thrown by path operations.
130−data PathException =
131− InvalidPath String
132− | InvalidAbsPath String
133− | InvalidRelPath String
134− | InvalidFilePath String
135− | InvalidDirPath String
136− deriving (Show,Eq)
137−
138−instance Exception PathException
139−
140−-- XXX Path must not contain null char on Posix. System calls consider the path
141−-- as null terminated.
142−-- XXX Maintain the Array with null termination because Unix system calls
143−-- require a null terminated string, also they return null terminated strings
144−-- as paths. Implementation of path append will have to handle the null
145−-- termination. Or we can choose to always copy the array when using it in
146−-- system calls.
147−
148−-- XXX The eq instance needs to make sure that the paths are equivalent. If we
149−-- normalize the paths we can do a byte comparison. However, on windows paths
150−-- are case insensitive but the case is preserved, therefore, we cannot
151−-- normalize and need to do case insensitive comparison.
152−
153−------------------------------------------------------------------------------
154−-- Types
155−------------------------------------------------------------------------------
156−
157−-- | A type representing file system paths for directories or files.
158−newtype Path = Path (Array WORD_TYPE) -- deriving Eq
159−
160−-- Show instance prints raw bytes without any decoding for rountdtripping.
161−-- Should we print this as a string instead, may be useful for ascii chars but
162−-- utf8 encoded chars may be unprintable. Better use toString if you want to
163−-- pretty print the path.
164−{-
165−instance Show Path where
166− show (Path x) = show x
167−-}
168−
169−-- XXX Do we need a type for file or dir Name as names cannot have the
170−-- separator char and there may be other restrictions on names? For example,
171−-- length restriction. A file name cannot be "." or "..". We can use the types
172−-- "File Name" and "Dir Name" to represent names. Also, file systems may put
173−-- limits on names. Can have an IsName type class with members Name, (File
174−-- Name), (Dir Name).
175−
176−-- | A type representing a file path.
177−newtype File a = File a
178−
179−-- | A type representing a directory path.
180−newtype Dir a = Dir a
181−
182−-- | A type representing absolute paths.
183−newtype Abs a = Abs a
184−
185−-- | A type representing relative paths.
186−newtype Rel a = Rel a
187−
188−------------------------------------------------------------------------------
189−-- Conversions
190−------------------------------------------------------------------------------
191−
192−-- | A member of 'IsPath' knows how to convert to and from the 'Path' type.
193−class IsPath a where
194− -- | Like 'fromPath' but does not check the properties of 'Path'. Provides
195− -- performance and simplicity when we know that the properties of the path
196− -- are already verified, for example, when we get the path from the file
197− -- system or the OS APIs.
198− fromPathUnsafe :: Path -> a
199−
200− -- | Convert a raw 'Path' to other forms of well-typed paths. It may fail
201− -- if the path does not satisfy the properties of the target type.
202− --
203− -- Path components may have limits.
204− -- Total path length may have a limit.
205− fromPath :: MonadThrow m => Path -> m a
206−
207− -- | Convert a well-typed path to a raw 'Path'. Never fails.
208− toPath :: a -> Path
209−
210−instance IsPath Path where
211− fromPathUnsafe = id
212− fromPath = pure
213− toPath = id
214−
215−instance IsPath (File Path) where
216− fromPathUnsafe p = File p
217− fromPath p = pure (File p)
218− toPath (File p) = p
219−
220−instance IsPath (Dir Path) where
221− fromPathUnsafe p = Dir p
222− fromPath p = pure (Dir p)
223− toPath (Dir p) = p
224−
225−instance IsPath (Abs Path) where
226− fromPathUnsafe p = Abs p
227− fromPath p = pure (Abs p)
228− toPath (Abs p) = p
229−
230−instance IsPath (Rel Path) where
231− fromPathUnsafe p = Rel p
232− fromPath p = pure (Rel p)
233− toPath (Rel p) = p
234−
235−instance IsPath (Abs (File Path)) where
236− fromPathUnsafe p = Abs (File p)
237− fromPath p = pure (Abs (File p))
238− toPath (Abs (File p)) = p
239−
240−instance IsPath (Abs (Dir Path)) where
241− fromPathUnsafe p = Abs (Dir p)
242− fromPath p = pure (Abs (Dir p))
243− toPath (Abs (Dir p)) = p
244−
245−instance IsPath (Rel (File Path)) where
246− fromPathUnsafe p = Rel (File p)
247− fromPath p = pure (Rel (File p))
248− toPath (Rel (File p)) = p
249−
250−instance IsPath (Rel (Dir Path)) where
251− fromPathUnsafe p = Rel (Dir p)
252− fromPath p = pure (Rel (Dir p))
253− toPath (Rel (Dir p)) = p
254−
255−-- XXX Use rewrite rules to eliminate intermediate conversions for better
256−-- efficiency.
257−
258−-- | Convert a path type to another path type. This operation may fail with a
259−-- 'PathException' when converting a less restrictive path type to a more
260−-- restrictive one.
261−adaptPath :: (MonadThrow m, IsPath a, IsPath b) => a -> m b
262−adaptPath p = fromPath $ toPath p
263−
264−------------------------------------------------------------------------------
265−-- Construction
266−------------------------------------------------------------------------------
267−
268−-- A chunk is essentially an untyped Array i.e. Array Word8. We can either use
269−-- the term ByteArray for that or just Chunk. The latter is shorter and we have
270−-- been using it consistently in streamly.
271−
272−-- | /Unsafe/: On Posix, a path cannot contain null characters. On Windows, the
273−-- array passed must be a multiple of 2 bytes as the underlying representation
274−-- uses 'Word16'.
275−{-# INLINE fromChunkUnsafe #-}
276−fromChunkUnsafe :: Array Word8 -> Path
277−fromChunkUnsafe arr = Path (Array.castUnsafe arr)
278−
279−-- | On Posix it may fail if the byte array contains null characters. On
280−-- Windows the array passed must be a multiple of 2 bytes as the underlying
281−-- representation uses 'Word16'.
282−--
283−-- Throws 'InvalidPath'.
284−fromChunk :: MonadThrow m => Array Word8 -> m Path
285−fromChunk arr =
286− case Array.cast arr of
287− Nothing ->
288− -- XXX Windows only message.
289− throwM
290− $ InvalidPath
291− $ "Encoded path length " ++ show (Array.byteLength arr)
292− ++ " is not a multiple of 16-bit."
293− Just x -> pure (Path x)
294−
295−-- | Convert 'Path' to an array of bytes.
296−toChunk :: Path -> Array Word8
297−toChunk (Path arr) = Array.asBytes arr
298−
299−-- | Encode a Unicode char stream to 'Path' using strict UTF-8 encoding on
300−-- Posix. On Posix it may fail if the stream contains null characters.
301−-- TBD: Use UTF16LE on Windows.
302−fromChars :: MonadThrow m => Stream Identity Char -> m Path
303−fromChars s =
304− let n = runIdentity $ Stream.fold Fold.length s
305−#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
306− in pure $ Path (Array.fromPureStreamN n (Unicode.encodeUtf16le' s))
307−#else
308− in pure $ Path (Array.fromPureStreamN n (Unicode.encodeUtf8' s))
309−#endif
310−
311−-- | Decode the path to a stream of Unicode chars using strict UTF-8 decoding
312−-- on Posix.
313−-- TBD: Use UTF16LE on Windows.
314−toChars :: Monad m => Path -> Stream m Char
315−toChars (Path arr) =
316−#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
317− Unicode.decodeUtf16le' $ Array.read arr
318−#else
319− Unicode.decodeUtf8' $ Array.read arr
320−#endif
321−
322−-- | Encode a Unicode string to 'Path' using strict UTF-8 encoding on Posix.
323−-- On Posix it may fail if the stream contains null characters.
324−-- TBD: Use UTF16LE on Windows.
325−fromString :: MonadThrow m => [Char] -> m Path
326−fromString = fromChars . Stream.fromList
327−
328−-- | Decode the path to a Unicode string using strict UTF-8 decoding on Posix.
329−-- TBD: Use UTF16LE on Windows.
330−toString :: Path -> [Char]
331−toString = runIdentity . Stream.toList . toChars
332−
333−------------------------------------------------------------------------------
334−-- Statically Verified Literals
335−------------------------------------------------------------------------------
336−
337−-- XXX Build these on top of the str quasiquoter so that we get the
338−-- interpolation for free.
339−
340−-- | Generates a 'Path' type from an interpolated string literal.
341−--
342−-- /Unimplemented/
343−path :: QuasiQuoter
344−path = undefined
345−
346−-- | Generates an @Abs Path@ type from an interpolated string literal.
347−--
348−-- /Unimplemented/
349−abs :: QuasiQuoter
350−abs = undefined
351−
352−-- | Generates an @Rel Path@ type from an interpolated string literal.
353−--
354−-- /Unimplemented/
355−rel :: QuasiQuoter
356−rel = undefined
357−
358−-- | Generates an @Dir Path@ type from an interpolated string literal.
359−--
360−-- /Unimplemented/
361−dir :: QuasiQuoter
362−dir = undefined
363−
364−-- | Generates an @File Path@ type from an interpolated string literal.
365−--
366−-- /Unimplemented/
367−file :: QuasiQuoter
368−file = undefined
369−
370−-- | Generates an @Abs (Dir Path)@ type from an interpolated string literal.
371−--
372−-- /Unimplemented/
373−absdir :: QuasiQuoter
374−absdir = undefined
375−
376−-- | Generates an @Rel (Dir Path)@ type from an interpolated string literal.
377−--
378−-- /Unimplemented/
379−reldir :: QuasiQuoter
380−reldir = undefined
381−
382−-- | Generates an @Abs (File Path)@ type from an interpolated string literal.
383−--
384−-- /Unimplemented/
385−absfile :: QuasiQuoter
386−absfile = undefined
387−
388−-- | Generates an @Rel (File Path)@ type from an interpolated string literal.
389−--
390−-- /Unimplemented/
391−relfile :: QuasiQuoter
392−relfile = undefined
393−
394−------------------------------------------------------------------------------
395−-- Statically Verified Strings
396−------------------------------------------------------------------------------
397−
398−-- | Generates a 'Path' type.
399−--
400−-- /Unimplemented/
401−mkPath :: String -> Q Exp
402−mkPath = undefined
403−
404−-- | Generates an @Abs Path@ type.
405−--
406−-- /Unimplemented/
407−mkAbs :: String -> Q Exp
408−mkAbs = undefined
409−
410−-- | Generates an @Rel Path@ type.
411−--
412−-- /Unimplemented/
413−mkRel :: String -> Q Exp
414−mkRel = undefined
415−
416−-- | Generates an @Dir Path@ type.
417−--
418−-- /Unimplemented/
419−mkDir :: String -> Q Exp
420−mkDir = undefined
421−
422−-- | Generates an @File Path@ type.
423−--
424−-- /Unimplemented/
425−mkFile :: String -> Q Exp
426−mkFile = undefined
427−
428−-- | Generates an @Abs (Dir Path)@ type.
429−--
430−-- /Unimplemented/
431−mkAbsDir :: String -> Q Exp
432−mkAbsDir = undefined
433−
434−-- | Generates an @Rel (Dir Path)@ type.
435−--
436−-- /Unimplemented/
437−mkRelDir :: String -> Q Exp
438−mkRelDir = undefined
439−
440−-- | Generates an @Abs (File Path)@ type.
441−--
442−-- /Unimplemented/
443−mkAbsFile :: String -> Q Exp
444−mkAbsFile = undefined
445−
446−-- | Generates an @Rel (File Path)@ type.
447−--
448−-- /Unimplemented/
449−mkRelFile :: String -> Q Exp
450−mkRelFile = undefined
451−
452−------------------------------------------------------------------------------
453−-- Operations
454−------------------------------------------------------------------------------
455−
456−separatorWord :: WORD_TYPE
457−separatorWord = SEPARATOR
458−
459−-- Portable definition for exporting.
460−
461−-- | Primary path separator character, @/@ on Posix and @\\@ on Windows.
462−-- Windows supports @/@ too as a separator. Please use 'isSeparator' for
463−-- testing if a char is a separator char.
464−primarySeparator :: Char
465−primarySeparator = chr (SEPARATOR)
466−
467−-- | On Posix only @/@ is a path separator but in windows it could be either
468−-- @/@ or @\\@.
469−isSeparator :: Char -> Bool
470−#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
471−isSeparator c = (c == '/') || (c == '\\')
472−#else
473−isSeparator = (== '/')
474−#endif
475−
476−-- If we append an absolute path it may fail with an error if the 'Path'
477−-- implementation stores absolute path information (a leading separator char).
478−-- However, the implementation may choose to store the path as a list of
479−-- components in which case we cannot distinguish an absolute path from
480−-- relative.
481−
482−-- | Like 'extendDir' but for the less restrictive 'Path' type which will always
483−-- create a syntactically valid 'Path' type but it may not be semantically valid
484−-- because we may append an absolute path or we may append to a file path.
485−-- The onus lies on the user to ensure that the first path is not a file and
486−-- the second path is not absolute.
487−extendPath :: Path -> Path -> Path
488−extendPath (Path a) (Path b) =
489− let len = Array.byteLength a + 1 + Array.byteLength b
490− -- XXX Check the leading separator or drive identifier. However,
491− -- checking the drive letter may add an additional overhead (can it be
492− -- arbitrarily long?), if it is significant we may want to have a
493− -- separate combinePathChecked API for that.
494− --
495− -- Also, do not add a separator char if the first path has a trailing
496− -- separator.
497− newArr = unsafePerformIO $ do
498− arr <- MutArray.new len
499− arr1 <- MutArray.spliceUnsafe arr (Array.unsafeThaw a)
500− arr2 <- MutArray.snocUnsafe arr1 separatorWord
501− arr3 <- MutArray.spliceUnsafe arr2 (Array.unsafeThaw b)
502− return (Array.unsafeFreeze arr3)
503− in Path newArr
504−
505−-- The only safety we need for paths is: (1) The first path can only be a Dir
506−-- type path, and (2) second path can only be a Rel path.
507−-- Can this be coerced to create unsafe versions?
508−
509−-- | Extend a directory path by appending a relative path to it. This is the
510−-- equivalent to the @</>@ operator from the @filepath@ package.
511−{-# INLINE extendDir #-}
512−extendDir :: (IsPath (a (Dir Path)), IsPath b, IsPath (a b)) =>
513− (a (Dir Path)) -> Rel b -> a b
514−extendDir a (Rel b) =
515− fromPathUnsafe $ extendPath (toPath a) (toPath b)
core/src/Streamly/Internal/Unicode/Parser.hs−3
@@ -300,9 +300,6 @@ data ScientificParseState
300300 | SPExponentWithSign !Multiplier !Number !DecimalPlaces !PowerMultiplier
301301 | SPAfterExponent !Multiplier !Number !DecimalPlaces !PowerMultiplier !Power
302302
303−-- XXX See https://hackage.haskell.org/package/integer-conversion for large
304−-- integers.
305−
306303-- | A generic parser for scientific notation of numbers. Returns (mantissa,
307304-- exponent) tuple. The result can be mapped to 'Double' or any other number
308305-- representation e.g. @Scientific@.
core/src/Streamly/Internal/Unicode/Stream.hs+3−30
@@ -28,7 +28,6 @@ module Streamly.Internal.Unicode.Stream
2828 , decodeUtf8
2929 , decodeUtf8'
3030 , decodeUtf8_
31− , decodeUtf16le'
3231
3332 -- ** Resumable UTF-8 Decoding
3433 , DecodeError(..)
@@ -56,7 +55,6 @@ module Streamly.Internal.Unicode.Stream
5655 , encodeUtf8'
5756 , encodeUtf8_
5857 , encodeStrings
59− , encodeUtf16le'
6058 {-
6159 -- * Operations on character strings
6260 , strip -- (dropAround isSpace)
@@ -99,7 +97,7 @@ import Data.Char (chr, ord)
9997#if MIN_VERSION_base(4,17,0)
10098import Data.Char (generalCategory, GeneralCategory(Space))
10199#endif
102−import Data.Word (Word8, Word16)
100+import Data.Word (Word8)
103101import Foreign.Marshal.Alloc (mallocBytes)
104102import Foreign.Storable (Storable(..))
105103#ifndef __GHCJS__
@@ -111,7 +109,7 @@ import GHC.IO.Encoding.Failure (isSurrogate)
111109import GHC.Ptr (Ptr (..), plusPtr)
112110import System.IO.Unsafe (unsafePerformIO)
113111import Streamly.Internal.Data.Array.Type (Array(..))
114−import Streamly.Internal.Data.MutByteArray.Type (MutByteArray)
112+import Streamly.Internal.Data.MutArray.Type (MutByteArray)
115113import Streamly.Internal.Data.Fold (Fold)
116114import Streamly.Internal.Data.Parser (Parser)
117115import Streamly.Internal.Data.Stream (Stream)
@@ -678,19 +676,6 @@ decodeUtf8_ = decodeUtf8D_
678676decodeUtf8Lax :: Monad m => Stream m Word8 -> Stream m Char
679677decodeUtf8Lax = decodeUtf8
680678
681−-------------------------------------------------------------------------------
682−-- Decoding Utf16
683−-------------------------------------------------------------------------------
684−
685−-- | Decode a UTF-16 little endian encoded bytestream to a stream of Unicode
686−-- characters. The function throws an error if an invalid codepoint is
687−-- encountered.
688−--
689−-- /Unimplemented/
690−{-# INLINE decodeUtf16le' #-}
691−decodeUtf16le' :: Stream m Word16 -> Stream m Char
692−decodeUtf16le' = undefined
693−
694679-------------------------------------------------------------------------------
695680-- Decoding Array Streams
696681-------------------------------------------------------------------------------
@@ -961,18 +946,6 @@ encodeUtf8_ = encodeUtf8D_
961946encodeUtf8Lax :: Monad m => Stream m Char -> Stream m Word8
962947encodeUtf8Lax = encodeUtf8
963948
964−-------------------------------------------------------------------------------
965−-- Encoding to Utf16
966−-------------------------------------------------------------------------------
967−
968−-- | Encode a stream of Unicode characters to a UTF-16 little endian encoded
969−-- bytestream.
970−--
971−-- /Unimplemented/
972−{-# INLINE encodeUtf16le' #-}
973−encodeUtf16le' :: Stream m Char -> Stream m Word16
974−encodeUtf16le' = undefined
975−
976949-------------------------------------------------------------------------------
977950-- Decoding string literals
978951-------------------------------------------------------------------------------
@@ -1057,7 +1030,7 @@ stripHead = Stream.dropWhile isSpace
10571030-- >>> Stream.fold Fold.toList $ Unicode.lines Fold.toList (Stream.fromList "lines\nthis\nstring\n\n\n")
10581031-- ["lines","this","string","",""]
10591032--
1060−-- >>> lines f = Stream.foldMany (Fold.takeEndBy_ (== '\n') f)
1033+-- > lines = Stream.splitOnSuffix (== '\n')
10611034--
10621035-- /Pre-release/
10631036{-# INLINE lines #-}
core/src/Streamly/Internal/Unicode/String.hs+7−7
@@ -39,14 +39,14 @@ module Streamly.Internal.Unicode.String
3939 --
4040 -- $setup
4141
42− str
42+ str
4343 ) where
4444
4545
4646import Control.Applicative (Alternative(..))
4747import Control.Exception (displayException)
4848import Data.Functor.Identity (runIdentity)
49−import Streamly.Internal.Data.Parser (Parser, ParseError)
49+import Streamly.Internal.Data.Parser (Parser)
5050
5151import Language.Haskell.TH
5252import Language.Haskell.TH.Quote
@@ -106,12 +106,9 @@ strSegmentExp (StrVar name) = do
106106strExp :: [StrSegment] -> Q Exp
107107strExp xs = appE [| concat |] $ listE $ map strSegmentExp xs
108108
109−parseStr :: String -> Either ParseError [StrSegment]
110−parseStr = runIdentity . Stream.parse strParser . Stream.fromList
111−
112109expandVars :: String -> Q Exp
113−expandVars input =
114− case parseStr input of
110+expandVars ln =
111+ case runIdentity $ Stream.parse strParser (Stream.fromList ln) of
115112 Left e ->
116113 fail $ "str QuasiQuoter parse error: " ++ displayException e
117114 Right x ->
@@ -144,6 +141,9 @@ expandVars input =
144141-- :}
145142-- "hello world!"
146143--
144+-- Bugs: because of a bug in parsers, a lone # at the end of input gets
145+-- removed.
146+--
147147str :: QuasiQuoter
148148str =
149149 QuasiQuoter
core/streamly-core.cabal+16−62
@@ -1,13 +1,8 @@
11cabal-version: 2.2
22name: streamly-core
3−version: 0.2.2
4−synopsis: Streaming, parsers, arrays, serialization and more
3+version: 0.2.0
4+synopsis: Streaming, parsers, arrays and more
55description:
6− For upgrading to streamly-0.9.0+ please read the
7− <https://github.com/composewell/streamly/blob/streamly-0.10.0/docs/User/Project/Upgrading-0.8-to-0.9.md Streamly-0.9.0 upgrade guide>.
8− .
9− Streamly is a standard library for Haskell that focuses on C-like
10− performance, modular combinators, and streaming data flow model.
116 Streamly consists of two packages: "streamly-core" and "streamly".
127 <https://hackage.haskell.org/package/streamly-core streamly-core>
138 provides basic features, and depends only on GHC boot libraries (see
@@ -17,41 +12,8 @@ description:
1712 and networking. For documentation, visit the
1813 <https://streamly.composewell.com Streamly website>.
1914 .
20− The streamly-core package provides the following functionality:
21− .
22− * Streams as composable producers of a sequence of values.
23− * Streams provide all the functionality provided by Haskell lists but
24− in an effectful, streaming fashion with better performance.
25− * Streams provide ListT and logic programming functionality as well.
26− * Folds as composable stream consumers that reduce the streams to a
27− single value or reduce segments of streams to transform the stream.
28− * Parsers as more powerful, composable stream consumers supporting
29− standard parser combinators with backtracking but in a streaming
30− fashion.
31− * Arrays with streaming interfaces providing high performance,
32− modularity, and concise interface as all streaming operations can be
33− performed on arrays.
34− * Arrays can be immutable or mutable, unboxed or boxed, pinned or
35− unpinned.
36− * Arrays generalize the functionality provided by @bytestring@ and
37− @text@ packages.
38− * Interoperability with @bytestring@ and @text@ is
39− provided via separate packages.
40− * Arrays and folds provide natural builder functionality so there are no
41− separate builder modules.
42− * High performance binary serialization with configurable JSON like features.
43− * Streaming combinators for unicode text processing, providing
44− functionality equivalent to the @text@ package.
45− * String interpolation for convenient construction of strings.
46− * Streaming console IO (stdin/stdout) operations.
47− * Streaming file and directory IO operations.
48− .
49− This package covers some or all of the functionality covered
50− by @streaming, pipes, conduit, list-t, logic-t, foldl, attoparsec,
51− array, primitive, vector, vector-algorithms, binary, cereal, store,
52− bytestring, text, stringsearch, interpolate@. Streamly provides a
53− consistent, concise, modular and performant interface for all this
54− functionality.
15+ This package provides streams, arrays, parsers, unicode text, file
16+ IO, and console IO functionality.
5517 .
5618 Note: The dependencies "heaps" and "monad-control" are included in
5719 the package solely for backward compatibility, and will be removed in
@@ -115,8 +77,6 @@ extra-doc-files:
11577 Changelog.md
11678 docs/*.md
11779 docs/ApiChangelogs/0.1.0.txt
118− docs/ApiChangelogs/0.1.0-0.2.0.txt
119− docs/ApiChangelogs/0.2.0-0.2.2.txt
12080
12181source-repository head
12282 type: git
@@ -218,6 +178,8 @@ common compile-options
218178common default-extensions
219179 default-extensions:
220180 BangPatterns
181+ CApiFFI
182+ CPP
221183 ConstraintKinds
222184 DeriveDataTypeable
223185 DeriveGeneric
@@ -228,29 +190,24 @@ common default-extensions
228190 GeneralizedNewtypeDeriving
229191 InstanceSigs
230192 KindSignatures
193+ LambdaCase
194+ MagicHash
231195 MultiParamTypeClasses
196+ PatternSynonyms
232197 RankNTypes
198+ RecordWildCards
233199 ScopedTypeVariables
234200 StandaloneDeriving
235201 TupleSections
236202 TypeApplications
203+ TypeFamilies
237204 TypeOperators
205+ ViewPatterns
238206
239− -- Not GHC2021
240− CApiFFI
241− CPP
242− DefaultSignatures
243− LambdaCase
244− MagicHash
245− RecordWildCards
246−
247− -- TypeFamilies is required by IsList, IsMap type classes and
248− -- Unbox generic deriving code.
249− -- TypeFamilies
250207 -- MonoLocalBinds, enabled by TypeFamilies, causes performance
251208 -- regressions. Disable it. This must come after TypeFamilies,
252209 -- otherwise TypeFamilies will enable it again.
253− -- NoMonoLocalBinds
210+ NoMonoLocalBinds
254211
255212 -- UndecidableInstances -- Does not show any perf impact
256213 -- UnboxedTuples -- interferes with (#.)
@@ -264,7 +221,6 @@ common optimization-options
264221
265222 -- For this to be effective it must come after the -O2 option
266223 if flag(dev) || flag(debug) || !flag(opt)
267− cpp-options: -DDEBUG
268224 ghc-options: -fno-ignore-asserts
269225
270226common threading-options
@@ -376,7 +332,6 @@ library
376332 , Streamly.Internal.Unicode.Array
377333
378334 -- Filesystem/IO
379− , Streamly.Internal.FileSystem.Path
380335 , Streamly.Internal.FileSystem.Handle
381336 , Streamly.Internal.FileSystem.File
382337 , Streamly.Internal.FileSystem.Dir
@@ -485,10 +440,9 @@ library
485440 , Streamly.Internal.Data.Time.Clock.Type
486441
487442 if flag(dev)
488− exposed-modules:
443+ other-modules:
489444 Streamly.Internal.Data.StreamK.Alt
490− -- XXX Compilation needs to be fixed
491− -- , Streamly.Internal.Data.List
445+ , Streamly.Internal.Data.List
492446
493447 build-depends:
494448 -- streamly-base
@@ -507,7 +461,7 @@ library
507461 , base >= 4.12 && < 4.20
508462 , exceptions >= 0.8.0 && < 0.11
509463 , transformers >= 0.5.5 && < 0.7
510− , filepath >= 1.4.2 && < 1.6
464+ , filepath >= 1.4.2 && < 1.5
511465
512466 -- streamly-unicode-core
513467 , template-haskell >= 2.14 && < 2.22
docs/Developer/optimization-guidelines.md−12
@@ -191,18 +191,6 @@ the stages of a loop, it is often not useful to inline the whole loop
191191itself, in fact we may have to occasionally use a `NOINLINE` so that the
192192compiler does not inline it.
193193
194−We need to be careful about NOINLINE on polymorphic functions. When
195−NOINLINE is used, the function cannot be specialized causing huge
196−performance degradation. To avoid that we can either make the
197−function monomorphic or sometimes using `NOINLINE [0]` can do the
198−trick. `NOINLINE [0]` blocks inlining in earlier phases but lets it
199−specialize in the last phase, inlining in the last phase is left to
200−the compiler. `INLINE [0]` may sound the same as `NOINLINE [0]`,
201−however, it behaves differently because we ask the compiler to INLINE
202−it compulsorily and it may not give us the desired results. The
203−Data.Fold.writeLastN benchmark is one such case where `NOINLINE [0]`
204−provides much better performance than `INLINE [0]`.
205−
206194### NoSpecConstr
207195
208196It is not always useful to specialize function calls for all constructors, some
docs/Developer/paths.rst+2−25
@@ -140,35 +140,12 @@ know exactly how the file system stores the path. Otherwise if we display
140140it differently, the user may use the displayed result to find the file
141141and may not find it.
142142
143−OS Specific Path Encodings
144−--------------------------
145−
146−In general, the OS does not have to look inside the path components
147−other than the ability to recognize the separator char to parse the
148−path into components and to construct it from components. However, in
149−some cases the OS may may have to look inside the path e.g. "." or ".."
150−special paths on Unix.
151−
152−On Unix a path component is just a blob of bytes. The user can encode
153−and decode this blob of bytes as they desire. All they need to care
154−about is that the path separator byte is respected. However, the the
155−path component blobs may be changed by the underlying filesystem
156−e.g. apple HFS may normalize the path before storing, therefore, the
157−representation may change when it is returned back to the user.
158−
159−On modern Windows systems a path component is UTF16-LE
160−encoded. Theoretically, from the OS perspective, it does not have to
161−look inside the path components other than determining whether a 16-bit
162−unit represents the separator character, therefore, users can use any
163−encoding as long as it encodes to 16-bit multiples and the separator is
164−preserved as equivalent to the UTF16-LE representation.
165−
166143Type Safety Requirements
167144------------------------
168145
169146* Safety against using an absolute path where a relative path is to be
170− used and vice-versa.
171−
147+ used and vice-versa.
148+
172149 * Validations for absolute or relative path when constructing a path.
173150 * We cannot append an absolute path to another path
174151* Safety against using a file name where a directory name is to be used and
docs/User/Project/ApiChangelogs/0.9.0-0.10.0.txtdeleted−424
@@ -1,424 +0,0 @@
1−---------------------------------
2−API Annotations
3−---------------------------------
4−
5−[A] : Added
6−[R] : Removed
7−[C] : Changed
8−[O] : Old definition
9−[N] : New definition
10−[D] : Deprecated
11−
12−---------------------------------
13−API diff
14−---------------------------------
15−
16−[C] Streamly.Network.Socket
17− [A] readWith :: MonadIO m => Int -> Socket -> Stream m Word8
18− [A] readChunksWith :: MonadIO m => Int -> Socket -> Stream m (Array Word8)
19−[C] Streamly.Network.Inet.TCP
20− [D] acceptorOnPortLocal :: MonadIO m => Unfold m PortNumber Socket
21− [D] acceptorOnPort :: MonadIO m => Unfold m PortNumber Socket
22− [A] acceptorLocal :: MonadIO m => Unfold m PortNumber Socket
23− [A] acceptor :: MonadIO m => Unfold m PortNumber Socket
24− [A] acceptOnAddrWith :: MonadIO m => [(SocketOption, Int)] -> (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Socket
25− [A] acceptLocal :: MonadIO m => PortNumber -> Stream m Socket
26− [A] accept :: MonadIO m => PortNumber -> Stream m Socket
27−[C] Streamly.Data.Stream.Prelude
28− [D] tapCount :: MonadAsync m => (a -> Bool) -> (Stream m Int -> m b) -> Stream m a -> Stream m a
29− [A] parTapCount :: MonadAsync m => (a -> Bool) -> (Stream m Int -> m b) -> Stream m a -> Stream m a
30−[A] Streamly.Data.Fold.Prelude
31− [A] Config
32− [A] toHashMapIO :: (MonadIO m, Hashable k, Ord k) => (a -> k) -> Fold m a b -> Fold m a (HashMap k b)
33− [A] parEval :: MonadAsync m => (Config -> Config) -> Fold m a b -> Fold m a b
34− [A] maxBuffer :: Int -> Config -> Config
35− [A] inspect :: Bool -> Config -> Config
36− [A] boundThreads :: Bool -> Config -> Config
37−
38−---------------------------------
39−Internal API diff
40−---------------------------------
41−
42−[C] Streamly.Internal.Network.Inet.TCP
43− [A] acceptorWith :: MonadIO m => [(SocketOption, Int)] -> Unfold m PortNumber Socket
44− [R] acceptorOnPortWith :: MonadIO m => [(SocketOption, Int)] -> Unfold m PortNumber Socket
45− [D] acceptorOnPortLocal :: MonadIO m => Unfold m PortNumber Socket
46− [D] acceptorOnPort :: MonadIO m => Unfold m PortNumber Socket
47− [A] acceptorLocal :: MonadIO m => Unfold m PortNumber Socket
48− [A] acceptor :: MonadIO m => Unfold m PortNumber Socket
49− [R] acceptOnPortLocal :: MonadIO m => PortNumber -> Stream m Socket
50− [R] acceptOnPort :: MonadIO m => PortNumber -> Stream m Socket
51− [A] acceptLocal :: MonadIO m => PortNumber -> Stream m Socket
52− [A] accept :: MonadIO m => PortNumber -> Stream m Socket
53−[R] Streamly.Internal.Data.Unfold.SVar
54−[A] Streamly.Internal.Data.Unfold.Prelude
55− [A] gbracket :: MonadRunInIO m => (a -> m c) -> (c -> m d) -> Unfold m (c, e) b -> (forall s. m s -> m (Either e s)) -> Unfold m c b -> Unfold m a b
56− [A] fromSVar :: MonadAsync m => Unfold m (SVar t m a) a
57− [A] fromProducer :: MonadAsync m => Unfold m (SVar t m a) a
58− [A] finally :: (MonadAsync m, MonadCatch m) => (a -> m c) -> Unfold m a b -> Unfold m a b
59− [A] bracket :: (MonadAsync m, MonadCatch m) => (a -> m c) -> (c -> m d) -> Unfold m c b -> Unfold m a b
60− [A] after :: MonadRunInIO m => (a -> m c) -> Unfold m a b -> Unfold m a b
61−[R] Streamly.Internal.Data.Unfold.Exception
62−[R] Streamly.Internal.Data.Stream.Zip.Concurrent
63−[D] Streamly.Internal.Data.Stream.Zip
64− [C] GHC.Base.Functor
65− [A] instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Zip.ZipConcurrent m)
66− [C] GHC.Base.Applicative
67− [A] instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Zip.ZipConcurrent m)
68− [A] ZipConcurrent
69− [A] [getZipConcurrent] :: ZipConcurrent m a -> Stream m a
70− [A] ZipConcurrent :: Stream m a -> ZipConcurrent m a
71−[R] Streamly.Internal.Data.Stream.Time
72−[R] Streamly.Internal.Data.Stream.SVar.Generate
73−[R] Streamly.Internal.Data.Stream.SVar.Eliminate
74−[A] Streamly.Internal.Data.Stream.Prelude
75− [A] StopWhen
76− [A] FirstStops :: StopWhen
77− [A] AnyStops :: StopWhen
78− [A] AllStop :: StopWhen
79− [A] Rate
80− [A] [rateLow] :: Rate -> Double
81− [A] [rateHigh] :: Rate -> Double
82− [A] [rateGoal] :: Rate -> Double
83− [A] [rateBuffer] :: Rate -> Int
84− [A] Rate :: Double -> Double -> Double -> Int -> Rate
85− [A] Config
86− [A] Channel
87− [A] [yieldRateInfo] :: Channel m a -> Maybe YieldRateInfo
88− [A] [workerThreads] :: Channel m a -> IORef (Set ThreadId)
89− [A] [workerStopMVar] :: Channel m a -> MVar ()
90− [A] [workerCount] :: Channel m a -> IORef Int
91− [A] [workLoop] :: Channel m a -> Maybe WorkerInfo -> m ()
92− [A] [svarStats] :: Channel m a -> SVarStats
93− [A] [svarRef] :: Channel m a -> Maybe (IORef ())
94− [A] [svarMrun] :: Channel m a -> RunInIO m
95− [A] [svarInspectMode] :: Channel m a -> Bool
96− [A] [svarCreator] :: Channel m a -> ThreadId
97− [A] [remainingWork] :: Channel m a -> Maybe (IORef Count)
98− [A] [readOutputQ] :: Channel m a -> m [ChildEvent a]
99− [A] [postProcess] :: Channel m a -> m Bool
100− [A] [outputQueue] :: Channel m a -> IORef ([ChildEvent a], Int)
101− [A] [outputDoorBell] :: Channel m a -> MVar ()
102− [A] [maxWorkerLimit] :: Channel m a -> Limit
103− [A] [maxBufferLimit] :: Channel m a -> Limit
104− [A] [isWorkDone] :: Channel m a -> IO Bool
105− [A] [isQueueDone] :: Channel m a -> IO Bool
106− [A] [enqueue] :: Channel m a -> Bool -> (RunInIO m, StreamK m a) -> IO ()
107− [A] [eagerDispatch] :: Channel m a -> m ()
108− [A] [doorBellOnWorkQ] :: Channel m a -> IORef Bool
109− [A] [accountThread] :: Channel m a -> ThreadId -> m ()
110− [A] Channel :: RunInIO m -> IORef ([ChildEvent a], Int) -> MVar () -> m [ChildEvent a] -> m Bool -> Limit -> Limit -> Maybe (IORef Count) -> Maybe YieldRateInfo -> (Bool -> (RunInIO m, StreamK m a) -> IO ()) -> m () -> IO Bool -> IO Bool -> IORef Bool -> (Maybe WorkerInfo -> m ()) -> IORef (Set ThreadId) -> IORef Int -> (ThreadId -> m ()) -> MVar () -> Maybe (IORef ()) -> SVarStats -> Bool -> ThreadId -> Channel m a
111− [A] type MonadAsync m = (MonadIO m, MonadBaseControl IO m, MonadThrow m)
112− [A] yield :: Channel m a -> Maybe WorkerInfo -> a -> IO Bool
113− [A] withChannelK :: MonadAsync m => (Config -> Config) -> StreamK m a -> (Channel m b -> StreamK m a -> StreamK m b) -> StreamK m b
114− [A] withChannel :: MonadAsync m => (Config -> Config) -> Stream m a -> (Channel m b -> Stream m a -> Stream m b) -> Stream m b
115− [A] toChannelK :: MonadRunInIO m => Channel m a -> StreamK m a -> m ()
116− [A] toChannel :: MonadRunInIO m => Channel m a -> Stream m a -> m ()
117− [A] ticksRate :: MonadAsync m => Rate -> Stream m ()
118− [A] ticks :: MonadIO m => Double -> Stream m ()
119− [A] takeLastInterval :: Double -> Stream m a -> Stream m a
120− [A] takeInterval :: MonadAsync m => Double -> Stream m a -> Stream m a
121− [A] stopWhen :: StopWhen -> Config -> Config
122− [A] stopChannel :: MonadIO m => Channel m a -> m ()
123− [A] stop :: Channel m a -> Maybe WorkerInfo -> IO ()
124− [A] startChannel :: MonadRunInIO m => Channel m a -> m ()
125− [A] sendWorkerWait :: MonadIO m => Bool -> (Channel m a -> IO ()) -> (Channel m a -> m Bool) -> Channel m a -> m ()
126− [A] sendWorkerDelayPaced :: Channel m a -> IO ()
127− [A] sendWorkerDelay :: Channel m a -> IO ()
128− [A] sampleIntervalStart :: MonadAsync m => Double -> Stream m a -> Stream m a
129− [A] sampleIntervalEnd :: MonadAsync m => Double -> Stream m a -> Stream m a
130− [A] sampleBurstStart :: MonadAsync m => Double -> Stream m a -> Stream m a
131− [A] sampleBurstEnd :: MonadAsync m => Double -> Stream m a -> Stream m a
132− [A] sampleBurst :: MonadAsync m => Bool -> Double -> Stream m a -> Stream m a
133− [A] retryD :: forall e m a. (Exception e, Ord e, MonadCatch m) => Map e Int -> (e -> Stream m a) -> Stream m a -> Stream m a
134− [A] retry :: (MonadCatch m, Exception e, Ord e) => Map e Int -> (e -> Stream m a) -> Stream m a -> Stream m a
135− [A] readOutputQPaced :: MonadRunInIO m => Channel m a -> m [ChildEvent a]
136− [A] readOutputQBounded :: MonadRunInIO m => Bool -> Channel m a -> m [ChildEvent a]
137− [A] rate :: Maybe Rate -> Config -> Config
138− [A] pushWorker :: MonadRunInIO m => Count -> Channel m a -> m ()
139− [A] postProcessPaced :: MonadRunInIO m => Channel m a -> m Bool
140− [A] postProcessBounded :: MonadRunInIO m => Channel m a -> m Bool
141− [A] periodic :: MonadIO m => m a -> Double -> Stream m a
142− [A] parZipWithM :: MonadAsync m => (Config -> Config) -> (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
143− [A] parZipWith :: MonadAsync m => (Config -> Config) -> (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
144− [A] parTwo :: MonadAsync m => (Config -> Config) -> Stream m a -> Stream m a -> Stream m a
145− [A] parTapCount :: MonadAsync m => (a -> Bool) -> (Stream m Int -> m b) -> Stream m a -> Stream m a
146− [A] parSequence :: MonadAsync m => (Config -> Config) -> Stream m (m a) -> Stream m a
147− [A] parReplicateM :: MonadAsync m => (Config -> Config) -> Int -> m a -> Stream m a
148− [A] parRepeatM :: MonadAsync m => (Config -> Config) -> m a -> Stream m a
149− [A] parMergeByM :: MonadAsync m => (Config -> Config) -> (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
150− [A] parMergeBy :: MonadAsync m => (Config -> Config) -> (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
151− [A] parMapM :: MonadAsync m => (Config -> Config) -> (a -> m b) -> Stream m a -> Stream m b
152− [A] parListOrdered :: MonadAsync m => [Stream m a] -> Stream m a
153− [A] parListLazy :: MonadAsync m => [Stream m a] -> Stream m a
154− [A] parListInterleaved :: MonadAsync m => [Stream m a] -> Stream m a
155− [A] parListEagerMin :: MonadAsync m => [Stream m a] -> Stream m a
156− [A] parListEagerFst :: MonadAsync m => [Stream m a] -> Stream m a
157− [A] parListEager :: MonadAsync m => [Stream m a] -> Stream m a
158− [A] parList :: MonadAsync m => (Config -> Config) -> [Stream m a] -> Stream m a
159− [A] parEval :: MonadAsync m => (Config -> Config) -> Stream m a -> Stream m a
160− [A] parConcatMap :: MonadAsync m => (Config -> Config) -> (a -> Stream m b) -> Stream m a -> Stream m b
161− [A] parConcatIterate :: MonadAsync m => (Config -> Config) -> (a -> Stream m a) -> Stream m a -> Stream m a
162− [A] parConcat :: MonadAsync m => (Config -> Config) -> Stream m (Stream m a) -> Stream m a
163− [A] parApply :: MonadAsync m => (Config -> Config) -> Stream m (a -> b) -> Stream m a -> Stream m b
164− [A] ordered :: Bool -> Config -> Config
165− [A] newInterleaveChannel :: MonadAsync m => (Config -> Config) -> m (Channel m a)
166− [A] newChannel :: MonadAsync m => (Config -> Config) -> m (Channel m a)
167− [A] newAppendChannel :: MonadRunInIO m => (Config -> Config) -> m (Channel m a)
168− [A] minRate :: Double -> Config -> Config
169− [A] maxThreads :: Int -> Config -> Config
170− [A] maxRate :: Double -> Config -> Config
171− [A] maxBuffer :: Int -> Config -> Config
172− [A] intervalsOf :: MonadAsync m => Double -> Fold m a b -> Stream m a -> Stream m b
173− [A] interleaved :: Bool -> Config -> Config
174− [A] interject :: MonadAsync m => m a -> Double -> Stream m a -> Stream m a
175− [A] inspect :: Bool -> Config -> Config
176− [A] groupsOfTimeout :: MonadAsync m => Int -> Double -> Fold m a b -> Stream m a -> Stream m b
177− [A] getStopWhen :: Config -> StopWhen
178− [A] fromChannelK :: MonadAsync m => Channel m a -> StreamK m a
179− [A] fromChannel :: MonadAsync m => Channel m a -> Stream m a
180− [A] fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> Stream m a
181− [A] finally :: (MonadAsync m, MonadCatch m) => m b -> Stream m a -> Stream m a
182− [A] eager :: Bool -> Config -> Config
183− [A] dumpSVar :: Channel m a -> IO String
184− [A] dropLastInterval :: Int -> Stream m a -> Stream m a
185− [A] dropInterval :: MonadAsync m => Double -> Stream m a -> Stream m a
186− [A] dispatchWorkerPaced :: MonadRunInIO m => Channel m a -> m Bool
187− [A] dispatchWorker :: MonadRunInIO m => Count -> Channel m a -> m Bool
188− [A] defaultConfig :: Config
189− [A] constRate :: Double -> Config -> Config
190− [A] classifySessionsOf :: (MonadAsync m, Ord k) => (Int -> m Bool) -> Double -> Fold m a b -> Stream m (AbsTime, (k, a)) -> Stream m (k, b)
191− [A] classifySessionsByGeneric :: forall m f a b. (MonadAsync m, IsMap f) => Proxy (f :: Type -> Type) -> Double -> Bool -> (Int -> m Bool) -> Double -> Fold m a b -> Stream m (AbsTime, (Key f, a)) -> Stream m (Key f, b)
192− [A] classifySessionsBy :: (MonadAsync m, Ord k) => Double -> Bool -> (Int -> m Bool) -> Double -> Fold m a b -> Stream m (AbsTime, (k, a)) -> Stream m (k, b)
193− [A] classifyKeepAliveSessions :: (MonadAsync m, Ord k) => (Int -> m Bool) -> Double -> Fold m a b -> Stream m (AbsTime, (k, a)) -> Stream m (k, b)
194− [A] bufferOldestN :: Int -> Stream m a -> Stream m a
195− [A] bufferLatestN :: Int -> Stream m a -> Stream m a
196− [A] bufferLatest :: Stream m a -> Stream m (Maybe a)
197− [A] bracket3D :: (MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> m d) -> (b -> m e) -> (b -> Stream m a) -> Stream m a
198− [A] bracket3 :: (MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> m d) -> (b -> m e) -> (b -> Stream m a) -> Stream m a
199− [A] bracket :: (MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
200− [A] avgRate :: Double -> Config -> Config
201− [A] afterD :: MonadRunInIO m => m b -> Stream m a -> Stream m a
202− [A] after :: (MonadIO m, MonadBaseControl IO m) => m b -> Stream m a -> Stream m a
203−[R] Streamly.Internal.Data.Stream.Exception.Lifted
204−[R] Streamly.Internal.Data.Stream.Concurrent.Channel.Type
205−[R] Streamly.Internal.Data.Stream.Concurrent.Channel.Operations
206−[R] Streamly.Internal.Data.Stream.Concurrent.Channel.Interleave
207−[R] Streamly.Internal.Data.Stream.Concurrent.Channel.Dispatcher
208−[R] Streamly.Internal.Data.Stream.Concurrent.Channel.Consumer
209−[R] Streamly.Internal.Data.Stream.Concurrent.Channel.Append
210−[R] Streamly.Internal.Data.Stream.Concurrent.Channel
211−[R] Streamly.Internal.Data.Stream.Concurrent
212−[R] Streamly.Internal.Data.Stream.Channel.Worker
213−[R] Streamly.Internal.Data.Stream.Channel.Types
214−[R] Streamly.Internal.Data.Stream.Channel.Dispatcher
215−[R] Streamly.Internal.Data.SVar.Worker
216−[R] Streamly.Internal.Data.SVar.Pull
217−[R] Streamly.Internal.Data.SVar.Dispatch
218−[D] Streamly.Internal.Data.SVar
219− [A] Work
220− [A] PartialWorker :: Count -> Work
221− [A] ManyWorkers :: Int -> Count -> Work
222− [A] BlockWait :: NanoSecond64 -> Work
223− [A] workerUpdateLatency :: YieldRateInfo -> WorkerInfo -> IO ()
224− [A] workerRateControl :: SVar t m a -> YieldRateInfo -> WorkerInfo -> IO Bool
225− [A] withDiagMVar :: SVar t m a -> String -> IO () -> IO ()
226− [A] updateYieldCount :: WorkerInfo -> IO Count
227− [A] sendYield :: SVar t m a -> Maybe WorkerInfo -> ChildEvent a -> IO Bool
228− [A] sendWorkerWait :: MonadAsync m => (SVar t m a -> IO ()) -> (SVar t m a -> m Bool) -> SVar t m a -> m ()
229− [A] sendWorkerDelayPaced :: SVar t m a -> IO ()
230− [A] sendWorkerDelay :: SVar t m a -> IO ()
231− [A] sendToProducer :: SVar t m a -> ChildEvent a -> IO Int
232− [A] sendStopToProducer :: MonadIO m => SVar t m a -> m ()
233− [A] sendStop :: SVar t m a -> Maybe WorkerInfo -> IO ()
234− [A] sendFirstWorker :: MonadAsync m => SVar t m a -> t m a -> m (SVar t m a)
235− [A] send :: SVar t m a -> ChildEvent a -> IO Int
236− [A] ringDoorBell :: SVar t m a -> IO ()
237− [A] resetBufferLimit :: SVar t m a -> IO ()
238− [A] recordMaxWorkers :: MonadIO m => SVar t m a -> m ()
239− [A] readOutputQRaw :: SVar t m a -> IO ([ChildEvent a], Int)
240− [A] readOutputQPaced :: MonadAsync m => SVar t m a -> m [ChildEvent a]
241− [A] readOutputQBounded :: MonadAsync m => SVar t m a -> m [ChildEvent a]
242− [A] readOutputQBasic :: IORef ([ChildEvent a], Int) -> IO ([ChildEvent a], Int)
243− [A] pushWorkerPar :: MonadAsync m => SVar t m a -> (Maybe WorkerInfo -> m ()) -> m ()
244− [A] pushWorker :: MonadAsync m => Count -> SVar t m a -> m ()
245− [A] printSVar :: SVar t m a -> String -> IO ()
246− [A] postProcessPaced :: MonadAsync m => SVar t m a -> m Bool
247− [A] postProcessBounded :: MonadAsync m => SVar t m a -> m Bool
248− [A] modifyThread :: MonadIO m => SVar t m a -> ThreadId -> m ()
249− [A] minThreadDelay :: NanoSecond64
250− [A] isBeyondMaxRate :: SVar t m a -> YieldRateInfo -> IO Bool
251− [A] incrementYieldLimit :: SVar t m a -> IO ()
252− [A] incrementBufferLimit :: SVar t m a -> IO ()
253− [A] handleFoldException :: SVar t m a -> SomeException -> IO ()
254− [A] handleChildException :: SVar t m a -> SomeException -> IO ()
255− [A] estimateWorkers :: Limit -> Count -> Count -> NanoSecond64 -> NanoSecond64 -> NanoSecond64 -> LatencyRange -> Work
256− [A] dumpSVar :: SVar t m a -> IO String
257− [A] dispatchWorkerPaced :: MonadAsync m => SVar t m a -> m Bool
258− [A] dispatchWorker :: MonadAsync m => Count -> SVar t m a -> m Bool
259− [A] delThread :: MonadIO m => SVar t m a -> ThreadId -> m ()
260− [A] decrementYieldLimit :: SVar t m a -> IO Bool
261− [A] decrementBufferLimit :: SVar t m a -> IO ()
262− [A] collectLatency :: SVar t m a -> YieldRateInfo -> Bool -> IO (Count, AbsTime, NanoSecond64)
263− [A] cleanupSVarFromWorker :: SVar t m a -> IO ()
264− [A] cleanupSVar :: SVar t m a -> IO ()
265− [A] allThreadsDone :: MonadIO m => SVar t m a -> m Bool
266−[C] Streamly.Internal.Data.IsMap.HashMap
267− [C] Streamly.Internal.Data.IsMap.IsMap
268− [C] (Data.HashMap.Internal.HashMap k)
269− [O] instance (Data.Hashable.Class.Hashable k, GHC.Classes.Eq k) => Streamly.Internal.Data.IsMap.IsMap (Data.HashMap.Internal.HashMap k)
270− [N] instance Data.Hashable.Class.Hashable k => Streamly.Internal.Data.IsMap.IsMap (Data.HashMap.Internal.HashMap k)
271−[C] Streamly.Internal.Data.IOFinalizer.Lifted
272− [C] IOFinalizer
273−[R] Streamly.Internal.Data.Fold.SVar
274−[A] Streamly.Internal.Data.Fold.Prelude
275− [A] Config
276− [A] Channel
277− [A] [svarStats] :: Channel m a b -> SVarStats
278− [A] [svarRef] :: Channel m a b -> Maybe (IORef ())
279− [A] [svarInspectMode] :: Channel m a b -> Bool
280− [A] [svarCreator] :: Channel m a b -> ThreadId
281− [A] [readOutputQ] :: Channel m a b -> m [ChildEvent a]
282− [A] [outputQueue] :: Channel m a b -> IORef ([ChildEvent a], Int)
283− [A] [outputQueueFromConsumer] :: Channel m a b -> IORef ([ChildEvent b], Int)
284− [A] [outputDoorBell] :: Channel m a b -> MVar ()
285− [A] [outputDoorBellFromConsumer] :: Channel m a b -> MVar ()
286− [A] [maxBufferLimit] :: Channel m a b -> Limit
287− [A] [bufferSpaceDoorBell] :: Channel m a b -> MVar ()
288− [A] Channel :: IORef ([ChildEvent a], Int) -> Limit -> MVar () -> m [ChildEvent a] -> IORef ([ChildEvent b], Int) -> MVar () -> MVar () -> Maybe (IORef ()) -> SVarStats -> Bool -> ThreadId -> Channel m a b
289− [A] writeLimited :: MonadIO m => SVar t m a -> Maybe WorkerInfo -> Fold m a ()
290− [A] write :: MonadIO m => SVar t m a -> Maybe WorkerInfo -> Fold m a ()
291− [A] takeInterval :: MonadAsync m => Double -> Fold m a b -> Fold m a b
292− [A] sendToWorker :: MonadAsync m => Channel m a b -> a -> m (Maybe b)
293− [A] parEval :: MonadAsync m => (Config -> Config) -> Fold m a b -> Fold m a b
294− [A] newChannel :: MonadRunInIO m => (Config -> Config) -> Fold m a b -> m (Channel m a b)
295− [A] maxBuffer :: Int -> Config -> Config
296− [A] intervalsOf :: MonadAsync m => Double -> Fold m a b -> Fold m b c -> Fold m a c
297− [A] inspect :: Bool -> Config -> Config
298− [A] dumpSVar :: Channel m a b -> IO String
299− [A] checkFoldStatus :: MonadAsync m => Channel m a b -> m (Maybe b)
300− [A] boundThreads :: Bool -> Config -> Config
301−[R] Streamly.Internal.Data.Fold.Concurrent.Channel.Type
302−[R] Streamly.Internal.Data.Fold.Concurrent.Channel
303−[R] Streamly.Internal.Data.Fold.Concurrent
304−[R] Streamly.Internal.Data.Fold.Async
305−[A] Streamly.Internal.Data.Channel
306− [A] YieldRateInfo
307− [A] [workerPollingInterval] :: YieldRateInfo -> IORef Count
308− [A] [workerPendingLatency] :: YieldRateInfo -> IORef (Count, Count, NanoSecond64)
309− [A] [workerMeasuredLatency] :: YieldRateInfo -> IORef NanoSecond64
310− [A] [workerCollectedLatency] :: YieldRateInfo -> IORef (Count, Count, NanoSecond64)
311− [A] [workerBootstrapLatency] :: YieldRateInfo -> Maybe NanoSecond64
312− [A] [svarRateBuffer] :: YieldRateInfo -> Int
313− [A] [svarLatencyTarget] :: YieldRateInfo -> NanoSecond64
314− [A] [svarLatencyRange] :: YieldRateInfo -> LatencyRange
315− [A] [svarGainedLostYields] :: YieldRateInfo -> IORef Count
316− [A] [svarAllTimeLatency] :: YieldRateInfo -> IORef (Count, AbsTime)
317− [A] YieldRateInfo :: NanoSecond64 -> LatencyRange -> Int -> IORef Count -> IORef (Count, AbsTime) -> Maybe NanoSecond64 -> IORef Count -> IORef (Count, Count, NanoSecond64) -> IORef (Count, Count, NanoSecond64) -> IORef NanoSecond64 -> YieldRateInfo
318− [A] WorkerInfo
319− [A] [workerYieldMax] :: WorkerInfo -> Count
320− [A] [workerYieldCount] :: WorkerInfo -> IORef Count
321− [A] [workerLatencyStart] :: WorkerInfo -> IORef (Count, AbsTime)
322− [A] WorkerInfo :: Count -> IORef Count -> IORef (Count, AbsTime) -> WorkerInfo
323− [A] Work
324− [A] PartialWorker :: Count -> Work
325− [A] ManyWorkers :: Int -> Count -> Work
326− [A] BlockWait :: NanoSecond64 -> Work
327− [A] ThreadAbort
328− [A] ThreadAbort :: ThreadAbort
329− [A] StopWhen
330− [A] FirstStops :: StopWhen
331− [A] AnyStops :: StopWhen
332− [A] AllStop :: StopWhen
333− [A] SVarStats
334− [A] [totalDispatches] :: SVarStats -> IORef Int
335− [A] [svarStopTime] :: SVarStats -> IORef (Maybe AbsTime)
336− [A] [minWorkerLatency] :: SVarStats -> IORef NanoSecond64
337− [A] [maxWorkers] :: SVarStats -> IORef Int
338− [A] [maxWorkerLatency] :: SVarStats -> IORef NanoSecond64
339− [A] [maxWorkQSize] :: SVarStats -> IORef Int
340− [A] [maxOutQSize] :: SVarStats -> IORef Int
341− [A] [maxHeapSize] :: SVarStats -> IORef Int
342− [A] [avgWorkerLatency] :: SVarStats -> IORef (Count, NanoSecond64)
343− [A] SVarStats :: IORef Int -> IORef Int -> IORef Int -> IORef Int -> IORef Int -> IORef (Count, NanoSecond64) -> IORef NanoSecond64 -> IORef NanoSecond64 -> IORef (Maybe AbsTime) -> SVarStats
344− [A] Rate
345− [A] [rateLow] :: Rate -> Double
346− [A] [rateHigh] :: Rate -> Double
347− [A] [rateGoal] :: Rate -> Double
348− [A] [rateBuffer] :: Rate -> Int
349− [A] Rate :: Double -> Double -> Double -> Int -> Rate
350− [A] Limit
351− [A] Unlimited :: Limit
352− [A] Limited :: Word -> Limit
353− [A] LatencyRange
354− [A] [minLatency] :: LatencyRange -> NanoSecond64
355− [A] [maxLatency] :: LatencyRange -> NanoSecond64
356− [A] LatencyRange :: NanoSecond64 -> NanoSecond64 -> LatencyRange
357− [A] Config
358− [A] ChildEvent
359− [A] ChildYield :: a -> ChildEvent a
360− [A] ChildStopChannel :: ChildEvent a
361− [A] ChildStop :: ThreadId -> Maybe SomeException -> ChildEvent a
362− [A] Count
363− [A] Count :: Int64 -> Count
364− [A] workerRateControl :: Limit -> IORef Int -> YieldRateInfo -> WorkerInfo -> IO Bool
365− [A] withDiagMVar :: Bool -> IO String -> String -> IO () -> IO ()
366− [A] stopWhen :: StopWhen -> Config -> Config
367− [A] setStreamLatency :: Int -> Config -> Config
368− [A] sendYield :: Limit -> Limit -> IORef Int -> Maybe WorkerInfo -> Maybe YieldRateInfo -> IORef ([ChildEvent a], Int) -> MVar () -> ChildEvent a -> IO Bool
369− [A] sendWithDoorBell :: IORef ([ChildEvent a], Int) -> MVar () -> ChildEvent a -> IO Int
370− [A] sendStop :: IORef Int -> Maybe WorkerInfo -> Maybe YieldRateInfo -> IORef ([ChildEvent a], Int) -> MVar () -> IO ()
371− [A] ringDoorBell :: IORef Bool -> MVar () -> IO ()
372− [A] recordMaxWorkers :: MonadIO m => IORef Int -> SVarStats -> m ()
373− [A] readOutputQRaw :: IORef ([ChildEvent a], Int) -> Maybe SVarStats -> IO ([ChildEvent a], Int)
374− [A] readOutputQBasic :: IORef ([ChildEvent a], Int) -> IO ([ChildEvent a], Int)
375− [A] rate :: Maybe Rate -> Config -> Config
376− [A] printSVar :: IO String -> String -> IO ()
377− [A] ordered :: Bool -> Config -> Config
378− [A] newSVarStats :: IO SVarStats
379− [A] newRateInfo :: Config -> IO (Maybe YieldRateInfo)
380− [A] modifyThread :: MonadIO m => IORef (Set ThreadId) -> MVar () -> ThreadId -> m ()
381− [A] minThreadDelay :: NanoSecond64
382− [A] minRate :: Double -> Config -> Config
383− [A] maxYields :: Maybe Int64 -> Config -> Config
384− [A] maxThreads :: Int -> Config -> Config
385− [A] maxRate :: Double -> Config -> Config
386− [A] maxBuffer :: Int -> Config -> Config
387− [A] magicMaxBuffer :: Word
388− [A] isBeyondMaxRate :: Limit -> IORef Int -> YieldRateInfo -> IO Bool
389− [A] interleaved :: Bool -> Config -> Config
390− [A] inspect :: Bool -> Config -> Config
391− [A] incrementYieldLimit :: Maybe (IORef Count) -> IO ()
392− [A] handleChildException :: IORef ([ChildEvent a], Int) -> MVar () -> SomeException -> IO ()
393− [A] getYieldLimit :: Config -> Maybe Count
394− [A] getStreamRate :: Config -> Maybe Rate
395− [A] getStreamLatency :: Config -> Maybe NanoSecond64
396− [A] getStopWhen :: Config -> StopWhen
397− [A] getOrdered :: Config -> Bool
398− [A] getMaxThreads :: Config -> Limit
399− [A] getMaxBuffer :: Config -> Limit
400− [A] getInterleaved :: Config -> Bool
401− [A] getInspectMode :: Config -> Bool
402− [A] getEagerDispatch :: Config -> Bool
403− [A] getBound :: Config -> Bool
404− [A] estimateWorkers :: Limit -> Count -> Count -> NanoSecond64 -> NanoSecond64 -> NanoSecond64 -> LatencyRange -> Work
405− [A] eager :: Bool -> Config -> Config
406− [A] dumpWorkerCount :: Show a => IORef a -> IO String
407− [A] dumpSVarStats :: Bool -> Maybe YieldRateInfo -> SVarStats -> IO String
408− [A] dumpRunningThreads :: Show a => IORef a -> IO String
409− [A] dumpOutputQ :: (Foldable t, Show a1) => IORef (t a2, a1) -> IO String
410− [A] dumpNeedDoorBell :: Show a => IORef a -> IO String
411− [A] dumpDoorBell :: Show a => MVar a -> IO String
412− [A] dumpCreator :: Show a => a -> String
413− [A] delThread :: MonadIO m => IORef (Set ThreadId) -> ThreadId -> m ()
414− [A] defaultConfig :: Config
415− [A] decrementYieldLimit :: Maybe (IORef Count) -> IO Bool
416− [A] constRate :: Double -> Config -> Config
417− [A] collectLatency :: Bool -> SVarStats -> YieldRateInfo -> Bool -> IO (Count, AbsTime, NanoSecond64)
418− [A] cleanupSVar :: IORef (Set ThreadId) -> IO ()
419− [A] boundThreads :: Bool -> Config -> Config
420− [A] avgRate :: Double -> Config -> Config
421− [A] allThreadsDone :: MonadIO m => IORef (Set ThreadId) -> m Bool
422− [A] addThread :: MonadIO m => IORef (Set ThreadId) -> ThreadId -> m ()
423−[C] Streamly.Internal.Control.ForkLifted
424− [A] doForkWith :: MonadRunInIO m => Bool -> m () -> RunInIO m -> (SomeException -> IO ()) -> m ThreadId
docs/User/Project/Changelog.md+10−23
@@ -2,17 +2,11 @@
22
33<!-- See rendered changelog at https://streamly.composewell.com -->
44
5−## 0.10.1 (Jan 2024)
6−
7−* Fix TH macros in `Streamly.Data.Stream.MkType` for GHC 9.6 and above.
8−
95## 0.10.0 (Nov 2023)
106
11−See
12−[0.9.0-0.10.0 API Changelog](https://github.com/composewell/streamly/blob/streamly-0.10.0/docs/User/Project/ApiChangelogs/0.9.0-0.10.0.txt)
13−for a full list of API changes in this release. Only a few significant
14−changes are mentioned here. For changes to the core functionality
15−please see the changelog of the `streamly-core` package.
7+This changelog lists only the changes of the higher level `streamly`
8+package. For changes to the core functionality please see the changelog
9+in the `streamly-core` package.
1610
1711### Breaking Changes
1812
@@ -21,21 +15,15 @@ please see the changelog of the `streamly-core` package.
2115 breaking change in `transformers` 0.6. You can replace `lift` with
2216 `fromEffect` when using these as top level monads in a monad stack.
2317
24−### Enhancements
25−
26−* __Concurrent Folds__: `Streamly.Data.Fold.Prelude` module added with
27− concurrent fold APIs and a container fold API to fold a key value
28− stream to a HashMap.
29−
3018## 0.9.0 (Mar 2023)
3119
3220Also see the following:
3321
34−* [streamly-0.9.0 Upgrade Guide](https://github.com/composewell/streamly/blob/streamly-0.10.0/docs/User/Project/Upgrading-0.8-to-0.9.md) or
22+* [streamly-0.9.0 Upgrade Guide](/docs/User/ProjectRelated/Upgrading.md) or
3523 https://hackage.haskell.org/package/streamly-0.9.0/docs/docs/User/ProjectRelated/Upgrading.md
36−* [streamly-0.9.0 API Changelog](https://github.com/composewell/streamly/blob/streamly-0.10.0/docs/User/Project/ApiChangelogs/0.8.3-0.9.0.txt) or
24+* [streamly-0.9.0 API Changelog](/docs/User/ProjectRelated/ApiChangelogs/0.8.3-0.9.0.txt) or
3725 https://hackage.haskell.org/package/streamly-0.9.0/docs/docs/User/ProjectRelated/ApiChangelogs/0.8.3-0.9.0.txt
38−* [streamly-core-0.1.0 API Changelog](https://github.com/composewell/streamly/blob/streamly-0.10.0/core/docs/ApiChangelogs/0.1.0.txt) or
26+* [streamly-core-0.1.0 API Changelog](/core/docs/ApiChangelogs/0.1.0.txt) or
3927 https://hackage.haskell.org/package/streamly-core-0.1.0/docs/docs/ApiChangelogs/0.1.0.txt
4028
4129### Package split
@@ -82,9 +70,8 @@ added which provide a CPS based stream implementation. `Stream` and
8270`StreamK` types can be easily interconverted.
8371
8472The old code can be adapted to use the new modules with some changes.
85−See the
86−[streamly-0.9.0 Upgrade Guide](https://github.com/composewell/streamly/blob/streamly-0.10.0/docs/User/Project/Upgrading-0.8-to-0.9.md)
87−for more details on how to adapt your existing code to the new release.
73+See the [upgrade guide](/docs/User/ProjectRelated/Upgrading.md) for more
74+details on how to adapt your existing code to the new release.
8875
8976### Enhancements
9077
@@ -165,7 +152,7 @@ See ApiChangelogs/0.8.3.txt for new APIs introduced.
165152
166153## 0.8.0 (Jun 2021)
167154
168−See [API Changelog](/docs/User/Project/ApiChangelogs/0.8.3.txt) for a complete list of signature
155+See [API Changelog](/docs/User/ProjectRelated/ApiChangelogs/0.8.3.txt) for a complete list of signature
169156changes and new APIs introduced.
170157
171158### Breaking changes
@@ -204,7 +191,7 @@ changes and new APIs introduced.
204191
205192### Enhancements
206193
207−* See [API Changelog](/docs/User/Project/ApiChangelogs/0.8.3.txt) for a complete list of new
194+* See [API Changelog](/docs/User/ProjectRelated/ApiChangelogs/0.8.3.txt) for a complete list of new
208195 modules and APIs introduced.
209196* The Fold type is now more powerful, the new termination behavior allows
210197 to express basic parsing of streams using folds.
docs/User/Project/README.md+2−9
@@ -1,15 +1,8 @@
11# [Streamly][]: Idiomatic Haskell with C-Like Performance
22
33[![Gitter chat](https://badges.gitter.im/composewell/gitter.svg)](https://gitter.im/composewell/streamly)
4−[![Hackage](https://img.shields.io/hackage/v/streamly-core.svg?style=flat)](https://hackage.haskell.org/package/streamly-core)
54[![Hackage](https://img.shields.io/hackage/v/streamly.svg?style=flat)](https://hackage.haskell.org/package/streamly)
65
7−## Upgrading to 0.9.0+
8−
9−Please read the [Streamly 0.9.0 Upgrade Guide](/docs/User/Project/Upgrading-0.8-to-0.9.md).
10−
11−## Overview
12−
136Streamly is a powerful Haskell library that provides developers with
147the essential building blocks to create safe, scalable, modular, and
158high-performance software. With Streamly, developers can enjoy the
@@ -24,8 +17,8 @@ comprising:
2417* Fearless, declarative concurrency for seamless parallel execution.
2518* A collection of ecosystem libraries for fast and efficient development.
2619
27−Check out the [Streamly Getting Started
28−Guide](/docs/User/Tutorials/getting-started.md) and [Quick
20+Check out the [Streamly Setup and Usage
21+Guide](/docs/User/Tutorials/setup-and-usage.md) and [Quick
2922Overview](/docs/User/Tutorials/quick-overview.md) for an introduction
3023to the library. For more detailed documentation, visit the [Haskell
3124Streamly website][Streamly].
docs/User/Project/Upgrading-0.8-to-0.9.md → docs/User/Project/Upgrading.mdrenamed+9−87
@@ -1,9 +1,9 @@
11# Upgrading to streamly 0.9.0
22
3−Also see the detailed changelog describing all the changes in the release:
3+Also see:
44
5−* [0.9.0 API Changelog](/docs/User/Project/ApiChangelogs/0.8.3-0.9.0.txt) or
6−* [0.9.0 API Changelog](https://hackage.haskell.org/package/streamly-0.9.0/docs/docs/User/ProjectRelated/ApiChangelogs/0.8.3-0.9.0.txt)
5+* [0.9.0 API Changelog](/docs/User/ProjectRelated/ApiChangelogs/0.8.3-0.9.0.txt) or
6+ https://hackage.haskell.org/package/streamly-0.9.0/docs/docs/User/ProjectRelated/ApiChangelogs/0.8.3-0.9.0.txt
77
88`Streamly.Prelude` module has been deprecated, equivalent
99functionality is covered by the `Streamly.Data.Stream`,
@@ -46,14 +46,13 @@ Assume the following imports in the code snippets below:
4646
4747## Dependencies in cabal file
4848
49−If you allow streamly < 0.9 in version bounds in your package then you
50−may not be able to build if any of the following is true:
49+If you allow streamly < 0.9 in version bounds then you may not be able
50+to build if you:
5151
52−* there is a dependency on `streamly-core` (module name conflicts)
53−* there is a dependency on `streamly-bytestring` >= 0.2 (type conflict)
52+* also depend on the new `streamly-core` package (module name conflicts)
53+* depend on `streamly-bytestring` >= 0.2 (type conflict)
5454
55−You can define and use a build flag in your package to allow older
56−streamly versions:
55+You can use a build flag to allow older streamly versions:
5756
5857```
5958flag old-streamly
@@ -104,82 +103,6 @@ ZipSerialM or WSerialT) with custom Applicative or Monadic properties.
104103But in general, try to avoid specific types and use explicit functions
105104from the stream module.
106105
107−Here are the TH macro based recipes to define types equivalent to all the older
108−types:
109−
110−```
111−{-# LANGUAGE StandaloneDeriving #-}
112−{-# LANGUAGE TemplateHaskell #-}
113−{-# LANGUAGE TypeFamilies #-}
114−{-# LANGUAGE UndecidableInstances #-}
115−
116−import Streamly.Data.Stream.MkType
117−import qualified Streamly.Data.Stream.Prelude as Stream
118−import qualified Streamly.Internal.Data.StreamK as StreamK
119−import Language.Haskell.TH
120−```
121−
122−`SerialT`: Use `CrossStreamK` from `Streamly.Internal.Data.StreamK` equivalent
123−Monad and other instances.
124−
125−For `WSerialT`, create a newtype wrapper using the following monad bind
126−operation:
127−
128−```
129−bind = StreamK.bindWith StreamK.interleave
130−```
131−
132−`WSerialT` requires `StreamK`, therefore you can not generate the code directly
133−using TH macros. However, you can print the code generated by the TH macro.
134−Then you can tweak that code, replacing `Stream` type with `StreamK`.
135−
136−```
137−expr <- runQ (mkCrossType "WSerialT" "bind" True)
138−putStrLn $ pprint expr
139−```
140−
141−For `AsyncT`:
142−
143−```
144−bind = flip (Stream.parConcatMap id)
145−$(mkCrossType "AsyncT" "bind" True)
146−```
147−
148−For `WAsyncT`:
149−
150−```
151−bind = flip (Stream.parConcatMap (Stream.interleaved True))
152−$(mkCrossType "WAsyncT" "bind" True)
153−```
154−
155−For `AheadT`:
156−
157−```
158−bind = flip (Stream.parConcatMap (Stream.ordered True))
159−$(mkCrossType "AheadT" "bind" True)
160−```
161−
162−For `ParallelT`:
163−
164−```
165−bind = flip (Stream.parConcatMap (Stream.eager True))
166−$(mkCrossType "ParallelT" "bind" True)
167−```
168−
169−For `ZipSerialM`:
170−
171−```
172−apply = Stream.zipWith ($)
173−$(mkZipType "ZipSerialM" "apply" False)
174−```
175−
176−For `ZipAsync`:
177−
178−```
179−apply = Stream.parApply id
180−$(mkZipType "ZipAsync" "apply" False)
181−```
182−
183106`adapt` is not needed anymore.
184107
185108```haskell docspec
@@ -305,8 +228,7 @@ combinators are prefixed with `par`.
305228Parallel combinators take a concurrency config argument to specify the
306229concurrency control parameters. The following combinators have the same
307230meaning as before except that they are used to set the config parameters
308−instead of being applied on the stream:
309−
231+instead of being applied on the stream.
310232* `rate`
311233* `maxRate`
312234* `constRate`
docs/User/Tutorials/quick-overview.md+14−10
@@ -44,6 +44,8 @@ The meaning of these types are:
4444 `a` in the IO Monad.
4545* A `Fold IO a b` is a representation of a function that converts a stream of
4646 type `a` to a final accumulator of type `b` in the IO Monad.
47+* An `Unfold IO a b` is a representation of a function that converts a seed
48+ value of type `a` into a stream of values of type `b` in the IO Monad.
4749
4850## The Examples
4951
@@ -217,7 +219,7 @@ import qualified Streamly.Unicode.Stream as Unicode
217219
218220countArray :: Array Word8 -> IO Counts
219221countArray arr =
220− Array.read arr -- Stream IO Word8
222+ Stream.unfold Array.reader arr -- Stream IO Word8
221223 & Unicode.decodeLatin1 -- Stream IO Char
222224 & Stream.fold (Fold.foldl' count (Counts 0 0 0 True)) -- IO Counts
223225```
@@ -333,9 +335,9 @@ fetch w = threadDelay 1000000 >> return (w,w)
333335-- connection is closed.
334336lookupWords :: Socket -> IO ()
335337lookupWords sk =
336− Socket.read sk -- Stream IO Word8
338+ Stream.unfold Socket.reader sk -- Stream IO Word8
337339 & Unicode.decodeLatin1 -- Stream IO Char
338− & Stream.wordsBy isSpace Fold.toList -- Stream IO String
340+ & Stream.parseMany word -- Stream IO String
339341 & Stream.parMapM cfg fetch -- Stream IO (String, String)
340342 & fmap show -- Stream IO String
341343 & Stream.intersperse "\n" -- Stream IO String
@@ -344,6 +346,7 @@ lookupWords sk =
344346
345347 where
346348
349+ word = Parser.wordBy isSpace Fold.toList
347350 cfg = Stream.ordered True
348351
349352serve :: Socket -> IO ()
@@ -354,9 +357,9 @@ serve sk = finally (lookupWords sk) (close sk)
354357-- "nc" as a client to try it out.
355358main :: IO ()
356359main =
357− TCP.accept 8091 -- Stream IO Socket
358− & Stream.parMapM id serve -- Stream IO ()
359− & Stream.fold Fold.drain -- IO ()
360+ Stream.unfold TCP.acceptorOnPort 8091 -- Stream IO Socket
361+ & Stream.parMapM id serve -- Stream IO ()
362+ & Stream.fold Fold.drain -- IO ()
360363```
361364
362365### Merging Incoming Streams
@@ -376,6 +379,7 @@ including the imports that we have omitted below.
376379import Streamly.Data.Stream (Stream)
377380import System.IO (IOMode(AppendMode), Handle, withFile)
378381
382+import qualified Streamly.Data.Unfold as Unfold
379383import qualified Streamly.Network.Socket as Socket
380384import qualified Streamly.FileSystem.Handle as Handle
381385
@@ -384,9 +388,9 @@ import qualified Streamly.FileSystem.Handle as Handle
384388-- buffering for safety.
385389readLines :: Socket -> Stream IO (Array Char)
386390readLines sk =
387− Socket.read sk -- Stream IO Word8
388− & Unicode.decodeLatin1 -- Stream IO Char
389− & Stream.foldMany line -- Stream IO (Array Char)
391+ Stream.unfold Socket.reader sk -- Stream IO Word8
392+ & Unicode.decodeLatin1 -- Stream IO Char
393+ & Stream.foldMany line -- Stream IO (Array Char)
390394
391395 where
392396
@@ -401,7 +405,7 @@ recv sk = Stream.finallyIO (close sk) (readLines sk)
401405-- streams at line boundaries and writes the merged stream to a file.
402406server :: Handle -> IO ()
403407server file =
404− TCP.accept 8090 -- Stream IO Socket
408+ Stream.unfold TCP.acceptorOnPort 8090 -- Stream IO Socket
405409 & Stream.parConcatMap (Stream.eager True) recv -- Stream IO (Array Char)
406410 & Stream.unfoldMany Array.reader -- Stream IO Char
407411 & Unicode.encodeLatin1 -- Stream IO Word8
src/Streamly/Data/Fold/Prelude.hs+13−31
@@ -6,27 +6,8 @@
66-- Stability : released
77-- Portability : GHC
88--
9−-- All Fold related combinators including the streamly-core
10−-- "Streamly.Data.Fold" module, concurrency, unordered container operations.
11−--
129module Streamly.Data.Fold.Prelude
13− (
14− -- * "Streamly.Data.Fold"
15− -- | All "Streamly.Data.Fold" combinators are re-exported via this
16− -- module. For more pre-release combinators also see
17− -- "Streamly.Internal.Data.Fold" module.
18− module Streamly.Data.Fold
19− -- * Concurrent Operations
20− -- ** Configuration
21− , Config
22− , maxBuffer
23− , boundThreads
24− , inspect
25−
26− -- ** Combinators
27− , parEval
28−
29− -- * Container Related
10+ ( module Streamly.Data.Fold
3011 , toHashMapIO
3112 )
3213where
@@ -36,26 +17,27 @@ import Data.HashMap.Strict (HashMap)
3617import Data.Hashable (Hashable)
3718import Streamly.Data.Fold
3819import Streamly.Internal.Data.Fold (toContainerIO)
39−import Streamly.Internal.Data.Fold.Concurrent
4020import Streamly.Internal.Data.IsMap.HashMap ()
4121
4222-- | Split the input stream based on a hashable component of the key field and
4323-- fold each split using the given fold. Useful for map/reduce, bucketizing
4424-- the input in different bins or for generating histograms.
4525--
26+-- Example:
27+--
4628-- >>> import Data.HashMap.Strict (HashMap, fromList)
4729-- >>> import qualified Streamly.Data.Fold.Prelude as Fold
4830-- >>> import qualified Streamly.Data.Stream as Stream
49−--
50−-- Consider a stream of key value pairs:
51−--
52−-- >>> input = Stream.fromList [("k1",1),("k1",1.1),("k2",2), ("k2",2.2)]
53−--
54−-- Classify each key to a different hash bin and fold the bins:
55−--
56−-- >>> classify = Fold.toHashMapIO fst (Fold.lmap snd Fold.toList)
57−-- >>> Stream.fold classify input :: IO (HashMap String [Double])
58−-- fromList [("k2",[2.0,2.2]),("k1",[1.0,1.1])]
31+-- >>> import Streamly.Data.Fold.Prelude (toHashMapIO)
32+-- >>> :{
33+-- do
34+-- let input = Stream.fromList [("ONE",1),("ONE",1.1),("TWO",2), ("TWO",2.2)]
35+-- classify = toHashMapIO fst (Fold.lmap snd Fold.toList)
36+-- x <- Stream.fold classify input :: IO (HashMap String [Double])
37+-- let y = fromList [("ONE",[1.0,1.1]),("TWO",[2.0,2.2])]
38+-- return (x == y)
39+-- :}
40+-- True
5941--
6042-- /Pre-release/
6143--
src/Streamly/Data/Stream/Concurrent.hsnew file+194
@@ -0,0 +1,194 @@
1+-- |
2+-- Module : Streamly.Data.Stream.Concurrent
3+-- Copyright : (c) 2022 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : released
7+-- Portability : GHC
8+--
9+-- This module provides concurrent streaming abstractions.
10+--
11+-- == Programming Tips
12+--
13+-- The names in this module do not conflict with other stream modules,
14+-- therefore, you can import it in the same namespace:
15+--
16+-- >>> import qualified Streamly.Data.Stream.Concurrent as Stream
17+
18+module Streamly.Data.Stream.Concurrent
19+ (
20+ -- * Concurrency
21+ -- $concurrency
22+ MonadAsync
23+
24+ -- ** Configuration
25+ , Config
26+
27+ -- *** Limits
28+ , maxThreads
29+ , maxBuffer
30+
31+ -- *** Rate Control
32+ , Rate(..)
33+ , rate
34+ , avgRate
35+ , minRate
36+ , maxRate
37+ , constRate
38+
39+ -- *** Stop behavior
40+ , StopWhen (..)
41+ , stopWhen
42+
43+ -- *** Scheduling behavior
44+ , eager
45+ , ordered
46+ , interleaved
47+
48+ -- *** Diagnostics
49+ , inspect
50+
51+ -- ** Combinators
52+ -- | Stream combinators using a concurrent channel.
53+
54+ -- *** Evaluate
55+ -- | Evaluates a serial stream asynchronously using a concurency channel.
56+
57+ , parEval
58+
59+ -- *** Generate
60+ -- | Uses a concurrency channel to evaluate multiple actions concurrently.
61+ , parRepeatM
62+ , parReplicateM
63+ , fromCallback
64+
65+ -- *** Map
66+ -- | Uses a concurrency channel to evaluate multiple mapped actions
67+ -- concurrently.
68+
69+ , parMapM
70+ , parSequence
71+
72+ -- *** Combine two
73+ -- | Use a channel for each pair.
74+ , parZipWithM
75+ , parZipWith
76+ , parMergeByM
77+ , parMergeBy
78+
79+ -- *** List of streams
80+ -- | Shares a single channel across many streams.
81+
82+ , parList
83+ -- , zipWithM
84+ -- , zipWith
85+
86+ -- *** Stream of streams
87+ -- **** Apply
88+
89+ , parApply
90+
91+ -- **** Concat
92+ -- | Shares a single channel across many streams.
93+
94+ , parConcat
95+ , parConcatMap
96+
97+ -- **** ConcatIterate
98+ , parConcatIterate
99+
100+ -- *** Observation
101+ , parTapCount
102+
103+ -- ** Deprecated
104+ , tapCount
105+ )
106+where
107+
108+import Streamly.Internal.Data.Stream.Concurrent
109+import Prelude hiding (mapM, sequence, concat, concatMap, zipWith)
110+
111+-- $concurrency
112+--
113+-- == Concurrency Channels
114+--
115+-- At a lower level, concurrency is implemented using channels that support
116+-- concurrent evaluation of streams. We create a channel, and add one or more
117+-- streams to it. The channel evaluates multiple streams concurrently and then
118+-- generates a single output stream from the results. How the streams are
119+-- combined depends on the configuration of the channel.
120+--
121+-- == Concurrency Primitives
122+--
123+-- There are only a few fundamental abstractions for concurrency, 'parEval',
124+-- 'parConcatMap', and 'parConcatIterate', all concurrency combinators can be
125+-- expressed in terms of these.
126+--
127+-- 'parEval', evaluates a single stream asynchronously, a worker thread runs
128+-- the stream and buffers the results, and the consumer of the stream runs in
129+-- another thread consuming it from the buffer, thus decoupling the production
130+-- and consumption of the stream. This can be used to run different stages of a
131+-- pipeline concurrently.
132+--
133+-- 'parConcatMap' is used to evaluate multiple streams concurrently and combine
134+-- the results. A stream generator function is mapped to the input stream and
135+-- all the generated streams are then evaluated concurrently, and the results
136+-- are combined.
137+--
138+-- 'parConcatIterate' is like 'parConcatMap' but iterates a stream generator
139+-- function recursively over the stream. This can be used to traverse trees or
140+-- graphs.
141+--
142+-- == Concurrency Configuration
143+--
144+-- Concurrent combinators take a 'Config' argument which controls the
145+-- concurrent behavior. For example, maximum number of threads to be used
146+-- ('maxThreads') or the maxmimum size of the buffer ('maxBuffer'), or how the
147+-- streams are scheduled with respect to each other ('interleaved'), or how the
148+-- results are consumed ('ordered').
149+--
150+-- Configuration is specified as @Config -> Config@ modifier functions that can
151+-- be composed together using function composition. For example, to specify the
152+-- maximum threads we can use @parConcatMap (maxThreads 10)@ if we also want to
153+-- specify the maximum buffer we can compose the two options @parConcatMap
154+-- (maxThreads 10 . maxBuffer 100)@. To use default configuration use 'id' as
155+-- the config modifier e.g. @parConcatMap id@.
156+--
157+-- See the @Configuration@ section and individual configuration options'
158+-- documentation for the default behavior and default values of configuration
159+-- parameters.
160+--
161+-- == Scheduling behavior
162+--
163+-- The most important configuration option is to control whether the output of
164+-- the concurrent execution is consumed in the same order as the corresponding
165+-- actions in the input stream or as soon as they arrive. The default is the
166+-- latter, however, we can enforce the original order by using the 'ordered'
167+-- option.
168+--
169+-- Another important option controls whether the number of worker threads are
170+-- automatically increased and decreased based on the consumption rate or
171+-- threads are started as aggresively as possible until the 'maxThreads' or
172+-- 'maxBuffer' limits are hit. The default is the former. However, the 'eager'
173+-- option can be enabled to use the latter behavior. When 'eager' is on, even
174+-- if the stream consumer thread blocks it does not make any impact on the
175+-- scheduling of the available tasks.
176+--
177+-- == Concurrent Combinators
178+--
179+-- Using the few fundamental concurrency primitives we can implement all the
180+-- usual streaming combinators with concurrent behavior. Combinators like
181+-- 'unfoldrM', 'iterateM' that are inherently serial can be evaluated
182+-- concurrently with respect to the consumer pipeline using 'parEval'.
183+-- Combinators like 'zipWithM', 'mergeByM' can also use 'parEval' on the input
184+-- streams to evaluate them concurrently before combining.
185+--
186+-- Combinators like 'repeatM', 'replicateM', 'fromListM', 'sequence', 'mapM' in
187+-- which all actions are independent of each other can be made concurrent using
188+-- the 'parConcatMap' operation.
189+--
190+-- A concurrent 'repeatM' repeats an action using multiple concurrent
191+-- executions of the action. Similarly, a concurrent 'mapM' performs the mapped
192+-- action in independent threads.
193+--
194+-- Some common concurrent combinators are provided in this module.
src/Streamly/Data/Stream/Exception.hsnew file+25
@@ -0,0 +1,25 @@
1+-- |
2+-- Module : Streamly.Data.Stream.Exception
3+-- Copyright : (c) 2022 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : released
7+-- Portability : GHC
8+--
9+-- This module is designed such that it does not conflict with
10+-- "Streamly.Data.Stream" module.
11+--
12+-- >>> import qualified Streamly.Data.Stream.Exception as Stream
13+--
14+module Streamly.Data.Stream.Exception
15+ (
16+ -- * Lifted Exceptions
17+ after
18+ , bracket
19+ -- , bracket3
20+ , finally
21+ )
22+where
23+
24+import Streamly.Internal.Data.Stream.Exception.Lifted
25+ ( bracket, finally, after )
src/Streamly/Data/Stream/MkType.hs+10−41
@@ -7,8 +7,7 @@
77-- Portability : GHC
88--
99-- Template Haskell macros to create custom newtype wrappers for the 'Stream'
10−-- type. See the examples below to create the standard stream types that were
11−-- available in streamly versions before 0.9.0.
10+-- type, deriving all the usual instances.
1211--
1312-- To use this module, the following extensions must be enabled:
1413--
@@ -24,61 +23,31 @@
2423-- >>> import Streamly.Data.Stream.MkType
2524-- >>> import qualified Streamly.Data.Stream.Prelude as Stream
2625--
27−-- For 'Streamly.Prelude.AsyncT' monad type with a concurrent cross product
28−-- bind:
26+-- Example, create an applicative type with zipping apply:
2927--
3028-- >>> :{
31−-- bind = flip (Stream.parConcatMap id)
32−-- $(mkCrossType "AsyncT" "bind" True)
33−-- :}
34−--
35−-- For 'Streamly.Prelude.WAsyncT' monad type with a concurrent interleaved
36−-- bind:
37−--
38−-- >>> :{
39−-- bind = flip (Stream.parConcatMap (Stream.interleaved True))
40−-- $(mkCrossType "WAsyncT" "bind" True)
29+-- zipApply = Stream.zipWith ($)
30+-- $(mkZipType "ZipStream" "zipApply" False)
4131-- :}
4232--
43−-- For 'Streamly.Prelude.AheadT' monad type with a concurrent ordered
44−-- cross product bind:
33+-- Example, create an applicative type with concurrent zipping apply:
4534--
4635-- >>> :{
47−-- bind = flip (Stream.parConcatMap (Stream.ordered True))
48−-- $(mkCrossType "AheadT" "bind" True)
36+-- parApply = Stream.parApply id
37+-- $(mkZipType "ParZipStream" "parApply" True)
4938-- :}
5039--
51−-- For 'Streamly.Prelude.ParallelT' monad type with an eager concurrent cross
52−-- product bind:
40+-- Example, create a monad type with an eager concurrent cross product bind:
5341--
5442-- >>> :{
5543-- parBind = flip (Stream.parConcatMap (Stream.eager True))
56−-- $(mkCrossType "ParallelT" "parBind" True)
57−-- :}
58−--
59−-- For 'Streamly.Prelude.ZipSerialM' serial zipping applicative type:
60−--
61−-- >>> :{
62−-- zipApply = Stream.zipWith ($)
63−-- $(mkZipType "ZipSerialM" "zipApply" False)
64−-- :}
65−--
66−-- For 'Streamly.Prelude.ZipAsync' concurrent zipping applicative type:
67−--
68−-- >>> :{
69−-- parApply = Stream.parApply id
70−-- $(mkZipType "ZipAsync" "parApply" True)
44+-- $(mkCrossType "ParEagerStream" "parBind" True)
7145-- :}
7246--
7347-- Instead of using these macros directly you could use the generated code as
7448-- well. Use these macros in ghci to generate the required code and paste it in
7549-- your package, you can customize the code as desired. See the docs of the
76−-- macros below for examples about how to view the generated code. For example:
77−--
78−-- >>> bind = flip (Stream.parConcatMap id)
79−-- >>> expr <- runQ (mkCrossType "AsyncT" "bind" True)
80−--
81−-- >> putStrLn $ pprint expr
50+-- macros below for examples about how to view the generated code.
8251--
8352module Streamly.Data.Stream.MkType
8453 (
src/Streamly/Data/Stream/Prelude.hs+15−217
@@ -6,227 +6,25 @@
66-- Stability : experimental
77-- Portability : GHC
88--
9−-- For upgrading to streamly-0.9.0+ please read the
10−-- <https://github.com/composewell/streamly/blob/streamly-0.10.0/docs/User/Project/Upgrading-0.8-to-0.9.md Streamly-0.9.0 upgrade guide>.
11−-- Also, see the "Streamly.Data.Stream.MkType" module for direct replacement of
12−-- stream types that have been removed in 0.9.0.
9+-- This module re-exports the "Streamly.Data.Stream" module from the
10+-- "streamly-core" package and additionally provides concurrency, time and
11+-- lifted exception operations as well in a single module.
1312--
14−-- All Stream related combinators including the streamly-core
15−-- "Streamly.Data.Stream" module, concurrency, time and lifted
16−-- exception operations. For more pre-release operations also see
17−-- "Streamly.Internal.Data.Stream.Prelude" module.
13+-- Also see the following modules for more pre-release operations:
14+--
15+-- * "Streamly.Internal.Data.Stream.Concurrent"
16+-- * "Streamly.Internal.Data.Stream.Time"
17+-- * "Streamly.Internal.Data.Stream.Exception.Lifted"
1818--
1919module Streamly.Data.Stream.Prelude
20− (
21− -- * "Streamly.Data.Stream"
22− -- | All "Streamly.Data.Stream" combinators are re-exported via this
23− -- module. For more pre-release combinators also see
24− -- "Streamly.Internal.Data.Stream" module.
25− module Streamly.Data.Stream
26−
27− -- * Concurrent Operations
28− -- $concurrency
29−
30− -- ** Types
31− , MonadAsync
32−
33− -- ** Configuration
34− , Config
35−
36− -- *** Limits
37− , maxThreads
38− , maxBuffer
39−
40− -- *** Rate Control
41− , Rate(..)
42− , rate
43− , avgRate
44− , minRate
45− , maxRate
46− , constRate
47−
48− -- *** Stop behavior
49− , StopWhen (..)
50− , stopWhen
51−
52− -- *** Scheduling behavior
53− , eager
54− , ordered
55− , interleaved
56−
57− -- *** Diagnostics
58− , inspect
59−
60− -- ** Combinators
61− -- | Stream combinators using a concurrent channel.
62−
63− -- *** Evaluate
64− -- | Evaluate a stream as a whole concurrently with respect to the consumer
65− -- of the stream.
66−
67− , parEval
68−
69− -- *** Generate
70− -- | Generate a stream by evaluating multiple actions concurrently.
71− , parRepeatM
72− , parReplicateM
73− , fromCallback
74−
75− -- *** Map
76− -- | Map actions on a stream such that the mapped actions are evaluated
77− -- concurrently with each other.
78−
79− , parMapM
80− , parSequence
81−
82− -- *** Combine two
83− -- | Combine two streams such that each stream as a whole is evaluated
84− -- concurrently with respect to the other stream as well as the consumer of
85− -- the resulting stream.
86− , parZipWithM
87− , parZipWith
88− , parMergeByM
89− , parMergeBy
90−
91− -- *** List of streams
92− -- | Shares a single channel across many streams.
93−
94− , parList
95− -- , zipWithM
96− -- , zipWith
97−
98− -- *** Stream of streams
99− -- **** Apply
100−
101− , parApply
102−
103− -- **** Concat
104− -- | Shares a single channel across many streams.
105−
106− , parConcat
107− , parConcatMap
108−
109− -- **** ConcatIterate
110− , parConcatIterate
111−
112− -- *** Observation
113− , parTapCount
114−
115− -- * Time Related
116−
117− -- ** Timers
118− , interject
119−
120− -- ** Trimming
121− , takeInterval
122− , dropInterval
123−
124− -- ** Chunking
125− , intervalsOf
126−
127− -- ** Sampling
128− , sampleIntervalEnd
129− , sampleIntervalStart
130− , sampleBurstEnd
131− , sampleBurstStart
132−
133− -- * Lifted Exceptions
134− , after
135− , bracket
136− -- , bracket3
137− , finally
138−
139− -- ** Deprecated
140− , tapCount
20+ ( module Streamly.Data.Stream
21+ , module Streamly.Data.Stream.Concurrent
22+ , module Streamly.Data.Stream.Time
23+ , module Streamly.Data.Stream.Exception
14124 )
14225where
14326
14427import Streamly.Data.Stream
145−import Streamly.Internal.Data.Stream.Prelude
146−
147−-- $concurrency
148−--
149−-- == Channels
150−--
151−-- At a lower level, concurrency is implemented using channels that support
152−-- concurrent evaluation of streams. We create a channel, and add one or more
153−-- streams to it. The channel evaluates multiple streams concurrently and then
154−-- generates a single output stream from the results. How the streams are
155−-- combined depends on the configuration of the channel.
156−--
157−-- == Primitives
158−--
159−-- There are only a few fundamental abstractions for concurrency, 'parEval',
160−-- 'parConcatMap', and 'parConcatIterate', all concurrency combinators can be
161−-- expressed in terms of these.
162−--
163−-- 'parEval' evaluates a stream as a whole asynchronously with respect to
164−-- the consumer of the stream. A worker thread evaluates multiple elements of
165−-- the stream ahead of time and buffers the results; the consumer of the stream
166−-- runs in another thread consuming the elements from the buffer, thus
167−-- decoupling the production and consumption of the stream. 'parEval' can be
168−-- used to run different stages of a pipeline concurrently.
169−--
170−-- 'parConcatMap' is used to evaluate multiple actions in a stream concurrently
171−-- with respect to each other or to evaluate multiple streams concurrently and
172−-- combine the results. A stream generator function is mapped to the input
173−-- stream and all the generated streams are then evaluated concurrently, and
174−-- the results are combined.
175−--
176−-- 'parConcatIterate' is like 'parConcatMap' but iterates a stream generator
177−-- function recursively over the stream. This can be used to traverse trees or
178−-- graphs.
179−--
180−-- == Configuration
181−--
182−-- Concurrent combinators take a 'Config' argument which controls the
183−-- concurrent behavior. For example, maximum number of threads to be used
184−-- ('maxThreads') or the maxmimum size of the buffer ('maxBuffer'), or how the
185−-- streams are scheduled with respect to each other ('interleaved'), or how the
186−-- results are consumed ('ordered').
187−--
188−-- Configuration is specified as @Config -> Config@ modifier functions that can
189−-- be composed together using function composition. For example, to specify the
190−-- maximum threads we can use @parConcatMap (maxThreads 10)@ if we also want to
191−-- specify the maximum buffer we can compose the two options @parConcatMap
192−-- (maxThreads 10 . maxBuffer 100)@. To use default configuration use 'id' as
193−-- the config modifier e.g. @parConcatMap id@.
194−--
195−-- See the @Configuration@ section and individual configuration options'
196−-- documentation for the default behavior and default values of configuration
197−-- parameters.
198−--
199−-- == Scheduling
200−--
201−-- The most important configuration option is to control whether the output of
202−-- the concurrent execution is consumed in the same order as the corresponding
203−-- actions in the input stream or as soon as they arrive. The default is the
204−-- latter, however, we can enforce the original order by using the 'ordered'
205−-- option.
206−--
207−-- Another important option controls whether the number of worker threads are
208−-- automatically increased and decreased based on the consumption rate or
209−-- threads are started as aggresively as possible until the 'maxThreads' or
210−-- 'maxBuffer' limits are hit. The default is the former. However, the 'eager'
211−-- option can be enabled to use the latter behavior. When 'eager' is on, even
212−-- if the stream consumer thread blocks it does not make any impact on the
213−-- scheduling of the available tasks.
214−--
215−-- == Combinators
216−--
217−-- Using the few fundamental concurrency primitives we can implement all the
218−-- usual streaming combinators with concurrent behavior. Combinators like
219−-- 'unfoldrM', 'iterateM' that are inherently serial can be evaluated
220−-- concurrently with respect to the consumer pipeline using 'parEval'.
221−-- Combinators like 'zipWithM', 'mergeByM' can also use 'parEval' on the input
222−-- streams to evaluate them concurrently before combining.
223−--
224−-- Combinators like 'repeatM', 'replicateM', 'fromListM', 'sequence', 'mapM' in
225−-- which all actions are independent of each other can be made concurrent using
226−-- the 'parConcatMap' operation.
227−--
228−-- A concurrent 'repeatM' repeats an action using multiple concurrent
229−-- executions of the action. Similarly, a concurrent 'mapM' performs the mapped
230−-- action in independent threads.
231−--
232−-- Some common concurrent combinators are provided in this module.
28+import Streamly.Data.Stream.Concurrent
29+import Streamly.Data.Stream.Exception
30+import Streamly.Data.Stream.Time
src/Streamly/Data/Stream/Time.hsnew file+37
@@ -0,0 +1,37 @@
1+-- |
2+-- Module : Streamly.Data.Stream.Time
3+-- Copyright : (c) 2022 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : released
7+-- Portability : GHC
8+--
9+-- This module provides time related streaming abstractions.
10+--
11+-- The names in this module do not conflict with other stream modules,
12+-- therefore, you can import it in the same namespace:
13+--
14+-- >>> import qualified Streamly.Data.Stream.Time as Stream
15+--
16+module Streamly.Data.Stream.Time
17+ (
18+ -- * Time
19+ -- ** Timers
20+ interject
21+
22+ -- ** Trimming
23+ , takeInterval
24+ , dropInterval
25+
26+ -- ** Chunking
27+ , intervalsOf
28+
29+ -- ** Sampling
30+ , sampleIntervalEnd
31+ , sampleIntervalStart
32+ , sampleBurstEnd
33+ , sampleBurstStart
34+ )
35+where
36+
37+import Streamly.Internal.Data.Stream.Time
src/Streamly/Internal/Data/Channel.hsdeleted−19
@@ -1,19 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Channel
3−-- Copyright : (c) 2017 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−
9−module Streamly.Internal.Data.Channel
10− (
11− module Streamly.Internal.Data.Channel.Dispatcher
12− , module Streamly.Internal.Data.Channel.Types
13− , module Streamly.Internal.Data.Channel.Worker
14− )
15−where
16−
17−import Streamly.Internal.Data.Channel.Dispatcher
18−import Streamly.Internal.Data.Channel.Types
19−import Streamly.Internal.Data.Channel.Worker
src/Streamly/Internal/Data/Fold/Concurrent.hs+44−1
@@ -50,8 +50,51 @@
5050
5151module Streamly.Internal.Data.Fold.Concurrent
5252 (
53− module Streamly.Internal.Data.Fold.Concurrent.Channel
53+ -- * Configuration
54+ Config
55+ , maxBuffer
56+ , bound
57+ , inspect
58+
59+ -- * Combinators
60+ -- | Stream combinators using Async channel
61+
62+ , parEval
5463 )
5564where
5665
66+-- import Streamly.Internal.Control.Concurrent (MonadAsync)
67+-- import Streamly.Internal.Data.Fold (Fold)
68+
5769import Streamly.Internal.Data.Fold.Concurrent.Channel
70+
71+-- $setup
72+--
73+-- Imports for example snippets in this module.
74+--
75+-- >>> :m
76+-- >>> :set -XFlexibleContexts
77+-- >>> import Control.Concurrent (threadDelay)
78+-- >>> import qualified Streamly.Data.Array as Array
79+-- >>> import qualified Streamly.Data.Fold as Fold
80+-- >>> import qualified Streamly.Data.Parser as Parser
81+-- >>> import qualified Streamly.Data.Stream as Stream
82+-- >>> import qualified Streamly.Internal.Data.Fold.Concurrent as Fold
83+-- >>> import Prelude hiding (concatMap, concat)
84+-- >>> :{
85+-- delay n = do
86+-- threadDelay (n * 1000000) -- sleep for n seconds
87+-- putStrLn (show n ++ " sec") -- print "n sec"
88+-- return n -- IO Int
89+-- :}
90+
91+{-
92+-- | Evaluate a stream asynchronously using a channel and serve the consumer
93+-- from the evaluation buffer.
94+--
95+-- >>> eval = Fold.parEval id
96+--
97+{-# INLINE eval #-}
98+eval :: MonadAsync m => Fold m a b -> Fold m a b
99+eval = parEval id
100+-}
src/Streamly/Internal/Data/Fold/Concurrent/Channel.hs+6−4
@@ -8,11 +8,13 @@
88
99module Streamly.Internal.Data.Fold.Concurrent.Channel
1010 (
11− module Streamly.Internal.Data.Fold.Concurrent.Channel.Type
11+ -- * Channel
12+ Channel
1213
1314 -- * Configuration
15+ , Config
1416 , maxBuffer
15− , boundThreads
17+ , bound
1618 , inspect
1719
1820 -- * Fold operations
@@ -26,11 +28,11 @@ import Control.Monad.IO.Class (MonadIO(liftIO))
2628import Data.IORef (writeIORef)
2729import Streamly.Internal.Control.Concurrent (MonadAsync)
2830import Streamly.Internal.Data.Fold (Fold(..), Step (..))
29−import Streamly.Internal.Data.Channel.Worker (sendWithDoorBell)
31+import Streamly.Internal.Data.Stream.Channel.Worker (sendWithDoorBell)
3032import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
3133
3234import Streamly.Internal.Data.Fold.Concurrent.Channel.Type
33−import Streamly.Internal.Data.Channel.Types
35+import Streamly.Internal.Data.Stream.Channel.Types
3436
3537-------------------------------------------------------------------------------
3638-- Evaluating a Fold
src/Streamly/Internal/Data/Fold/Concurrent/Channel/Type.hs+3−3
@@ -30,13 +30,13 @@ import Streamly.Internal.Control.Concurrent
3030 (MonadAsync, MonadRunInIO, askRunInIO)
3131import Streamly.Internal.Control.ForkLifted (doForkWith)
3232import Streamly.Internal.Data.Fold (Fold(..))
33−import Streamly.Internal.Data.Channel.Dispatcher (dumpSVarStats)
34−import Streamly.Internal.Data.Channel.Worker (sendWithDoorBell)
33+import Streamly.Internal.Data.Stream.Channel.Dispatcher (dumpSVarStats)
34+import Streamly.Internal.Data.Stream.Channel.Worker (sendWithDoorBell)
3535
3636import qualified Streamly.Internal.Data.Fold as Fold
3737import qualified Streamly.Internal.Data.Stream as D
3838
39−import Streamly.Internal.Data.Channel.Types
39+import Streamly.Internal.Data.Stream.Channel.Types
4040
4141data Channel m a b = Channel
4242 {
src/Streamly/Internal/Data/Fold/Prelude.hsdeleted−19
@@ -1,19 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Fold.Prelude
3−-- Copyright : (c) 2022 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−module Streamly.Internal.Data.Fold.Prelude
10− (
11− module Streamly.Internal.Data.Fold.Async
12− , module Streamly.Internal.Data.Fold.Concurrent
13− , module Streamly.Internal.Data.Fold.SVar
14− )
15−where
16−
17−import Streamly.Internal.Data.Fold.Async
18−import Streamly.Internal.Data.Fold.Concurrent
19−import Streamly.Internal.Data.Fold.SVar
src/Streamly/Internal/Data/Fold/SVar.hs−1
@@ -1,4 +1,3 @@
1−{-# OPTIONS_GHC -Wno-deprecations #-}
21-- |
32-- Module : Streamly.Internal.Data.Fold.SVar
43-- Copyright : (c) 2017 Composewell Technologies
src/Streamly/Internal/Data/IsMap/HashMap.hs−5
@@ -1,8 +1,3 @@
1−{-# LANGUAGE TypeFamilies #-}
2−-- Must come after TypeFamilies, otherwise it is re-enabled.
3−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
4−{-# LANGUAGE NoMonoLocalBinds #-}
5−
61{-# OPTIONS_GHC -Wno-orphans #-}
72
83-- |
src/Streamly/Internal/Data/SVar.hs−1
@@ -8,7 +8,6 @@
88--
99--
1010module Streamly.Internal.Data.SVar
11− {-# DEPRECATED "SVar is replaced by Channel." #-}
1211 (
1312 module Streamly.Internal.Data.SVar.Type
1413 , module Streamly.Internal.Data.SVar.Worker
src/Streamly/Internal/Data/SmallArray.hs+1−1
@@ -106,7 +106,7 @@ foldr f z arr = runIdentity $ D.foldr f z $ toStreamD arr
106106-- of elements use an 'Array' from either "Streamly.Data.Array.Generic" or "Streamly.Data.Array.Foreign".
107107{-# INLINE_NORMAL writeN #-}
108108writeN :: MonadIO m => Int -> Fold m a (SmallArray a)
109−writeN len = FL.Fold step initial extract extract
109+writeN len = FL.Fold step initial extract
110110
111111 where
112112
src/Streamly/Internal/Data/Channel/Dispatcher.hs → src/Streamly/Internal/Data/Stream/Channel/Dispatcher.hsrenamed+3−3
@@ -1,5 +1,5 @@
11-- |
2−-- Module : Streamly.Internal.Data.Channel.Dispatcher
2+-- Module : Streamly.Internal.Data.Stream.Channel.Dispatcher
33-- Copyright : (c) 2017 Composewell Technologies
44-- License : BSD-3-Clause
55-- Maintainer : streamly@composewell.com
@@ -7,7 +7,7 @@
77-- Portability : GHC
88--
99--
10−module Streamly.Internal.Data.Channel.Dispatcher
10+module Streamly.Internal.Data.Stream.Channel.Dispatcher
1111 (
1212 -- * Latency collection
1313 minThreadDelay
@@ -40,7 +40,7 @@ import Streamly.Internal.Data.Time.Units
4040
4141import qualified Data.Set as S
4242
43−import Streamly.Internal.Data.Channel.Types
43+import Streamly.Internal.Data.Stream.Channel.Types
4444
4545-------------------------------------------------------------------------------
4646-- Worker latency data processing
src/Streamly/Internal/Data/Channel/Types.hs → src/Streamly/Internal/Data/Stream/Channel/Types.hsrenamed+37−12
@@ -1,5 +1,5 @@
11-- |
2−-- Module : Streamly.Internal.Data.Channel.Types
2+-- Module : Streamly.Internal.Data.Stream.Channel.Types
33-- Copyright : (c) 2017 Composewell Technologies
44-- License : BSD-3-Clause
55-- Maintainer : streamly@composewell.com
@@ -31,7 +31,7 @@
3131-- consumer is not pulling fast enough. The number of workers may even get
3232-- reduced depending on the consuming pace.
3333--
34−module Streamly.Internal.Data.Channel.Types
34+module Streamly.Internal.Data.Stream.Channel.Types
3535 (
3636 -- * Types
3737 Count (..)
@@ -76,7 +76,7 @@ module Streamly.Internal.Data.Channel.Types
7676 , stopWhen
7777 , ordered
7878 , interleaved
79− , boundThreads
79+ , bound
8080
8181 , rate
8282 , avgRate
@@ -111,6 +111,8 @@ module Streamly.Internal.Data.Channel.Types
111111
112112 , withDiagMVar
113113 , printSVar
114+
115+ , concatMapDivK
114116 )
115117where
116118
@@ -125,11 +127,13 @@ import Data.IORef (IORef, newIORef, readIORef, writeIORef)
125127import Data.Set (Set)
126128import Streamly.Internal.Data.Atomics
127129 (atomicModifyIORefCAS, atomicModifyIORefCAS_, storeLoadBarrier)
130+import Streamly.Internal.Data.SVar.Type (adaptState)
128131import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
129132import Streamly.Internal.Data.Time.Units (AbsTime, NanoSecond64(..))
130133import System.IO (hPutStrLn, stderr)
131134
132135import qualified Data.Set as Set
136+import qualified Streamly.Internal.Data.StreamK as K
133137
134138------------------------------------------------------------------------------
135139-- Common types
@@ -495,10 +499,10 @@ getInspectMode = _inspect
495499
496500-- | By default, processing of output from the worker threads is given priority
497501-- over dispatching new workers. More workers are dispatched only when there is
498−-- no output to process. When 'eager' is set to 'True', workers are dispatched
499−-- aggresively as long as there is more work to do irrespective of whether
500−-- there is output pending to be processed by the stream consumer. However,
501−-- dispatching may stop if 'maxThreads' or 'maxBuffer' is reached.
502+-- no output to process. With 'eager' on workers are dispatched aggresively as
503+-- long as there is more work to do irrespective of whether there is output
504+-- pending to be processed. However, dispatching may stop if 'maxThreads' or
505+-- 'maxBuffer' is reached.
502506--
503507-- /Note:/ This option has no effect when rate has been specified.
504508--
@@ -542,14 +546,13 @@ interleaved flag st = st { _interleaved = flag }
542546getInterleaved :: Config -> Bool
543547getInterleaved = _interleaved
544548
545−-- TODO: Make it consistently take effect everywhere.
546−
547549-- | Spawn bound threads (i.e., spawn threads using 'forkOS' instead of
548550-- 'forkIO'). The default value is 'False'.
549551--
550−-- Currently, this only takes effect only for concurrent folds.
551−boundThreads :: Bool -> Config -> Config
552−boundThreads flag st = st { _bound = flag }
552+-- Currently, this only takes effect for concurrent folds. TODO: Make it
553+-- consistently take effect everywhere.
554+bound :: Bool -> Config -> Config
555+bound flag st = st { _bound = flag }
553556
554557getBound :: Config -> Bool
555558getBound = _bound
@@ -815,3 +818,25 @@ cleanupSVar workerSet = do
815818 Prelude.mapM_ (`throwTo` ThreadAbort)
816819 -- (Prelude.filter (/= self) $ Set.toList workers)
817820 (Set.toList workers)
821+
822+-------------------------------------------------------------------------------
823+-- Evaluator
824+-------------------------------------------------------------------------------
825+
826+-- | @concatMapDivK useTail useHead stream@, divides the stream in head and
827+-- tail, maps a stream generator on the head and maps an action on the tail of
828+-- a stream. Returns the stream generated by the head.
829+--
830+-- Used for concurrent evaluation of streams using a Channel.
831+{-# INLINE concatMapDivK #-}
832+concatMapDivK :: Monad m =>
833+ (K.StreamK m a -> m ())
834+ -> (a -> K.StreamK m b)
835+ -> K.StreamK m a
836+ -> K.StreamK m b
837+concatMapDivK useTail useHead stream =
838+ K.mkStream $ \st yld sng stp -> do
839+ let foldShared = K.foldStreamShared st yld sng stp
840+ single a = foldShared $ useHead a
841+ yieldk a r = useTail r >> single a
842+ in K.foldStreamShared (adaptState st) yieldk single stp stream
src/Streamly/Internal/Data/Channel/Worker.hs → src/Streamly/Internal/Data/Stream/Channel/Worker.hsrenamed+3−3
@@ -1,5 +1,5 @@
11-- |
2−-- Module : Streamly.Internal.Data.Channel.Worker
2+-- Module : Streamly.Internal.Data.Stream.Concurrent.Channel.Worker
33-- Copyright : (c) 2017 Composewell Technologies
44-- License : BSD-3-Clause
55-- Maintainer : streamly@composewell.com
@@ -8,7 +8,7 @@
88--
99-- Collecting results from child workers in a streamed fashion
1010
11−module Streamly.Internal.Data.Channel.Worker
11+module Streamly.Internal.Data.Stream.Channel.Worker
1212 (
1313 Work (..)
1414 , estimateWorkers
@@ -34,7 +34,7 @@ import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
3434import Streamly.Internal.Data.Time.Units
3535 (AbsTime, NanoSecond64(..), diffAbsTime64, fromRelTime64)
3636
37−import Streamly.Internal.Data.Channel.Types
37+import Streamly.Internal.Data.Stream.Channel.Types
3838
3939-------------------------------------------------------------------------------
4040-- Yield control
src/Streamly/Internal/Data/Stream/Concurrent.hs+35−47
@@ -21,10 +21,26 @@ module Streamly.Internal.Data.Stream.Concurrent
2121 -- * Imports
2222 -- $setup
2323
24− module Streamly.Internal.Data.Stream.Concurrent.Channel
25−
2624 -- * Types
27− , MonadAsync
25+ MonadAsync
26+
27+ -- * Configuration
28+ , Config
29+ , maxThreads
30+ , maxBuffer
31+ , eager
32+ , StopWhen (..)
33+ , stopWhen
34+ , ordered
35+ , interleaved
36+ -- maxYields
37+ , Rate(..)
38+ , rate
39+ , avgRate
40+ , minRate
41+ , maxRate
42+ , constRate
43+ , inspect
2844
2945 -- * Combinators
3046 -- | Stream combinators using a concurrent channel
@@ -88,11 +104,13 @@ import Control.Monad (void, when)
88104import Control.Monad.IO.Class (MonadIO(liftIO))
89105import Streamly.Internal.Control.Concurrent (MonadAsync, askRunInIO)
90106import Streamly.Internal.Control.ForkLifted (forkManaged)
91−import Streamly.Internal.Data.Channel.Dispatcher (modifyThread)
92−import Streamly.Internal.Data.Channel.Types (ChildEvent(..))
93−import Streamly.Internal.Data.Channel.Worker (sendWithDoorBell)
107+import Streamly.Internal.Data.Stream.Channel.Dispatcher (modifyThread)
108+import Streamly.Internal.Data.Stream.Channel.Types
109+ ( ChildEvent(..)
110+ , concatMapDivK
111+ )
112+import Streamly.Internal.Data.Stream.Channel.Worker (sendWithDoorBell)
94113import Streamly.Internal.Data.Stream (Stream, Step(..))
95−import Streamly.Internal.Data.SVar.Type (adaptState)
96114
97115import qualified Streamly.Internal.Data.MutArray as Unboxed
98116import qualified Streamly.Internal.Data.Stream as Stream
@@ -147,23 +165,15 @@ parEvalD modifier m = D.Stream step Nothing
147165 D.Stop -> D.Stop
148166-}
149167
150−-- | 'parEval' evaluates a stream as a whole asynchronously with respect to
151−-- the consumer of the stream. A worker thread evaluates multiple elements of
152−-- the stream ahead of time and buffers the results; the consumer of the stream
153−-- runs in another thread consuming the elements from the buffer, thus
154−-- decoupling the production and consumption of the stream. 'parEval' can be
155−-- used to run different stages of a pipeline concurrently.
156−--
157−-- It is important to note that 'parEval' does not evaluate individual actions
158−-- in the stream concurrently with respect to each other, it merely evaluates
159−-- the stream serially but in a different thread than the consumer thread,
160−-- thus the consumer and producer can run concurrently. See 'parMapM' and
161−-- 'parSequence' to evaluate actions in the stream concurrently.
168+-- | Evaluate a stream asynchronously. In a serial stream, each element of the
169+-- stream is generated as it is demanded by the consumer. `parEval` evaluates
170+-- multiple elements of the stream ahead of time and serves the results from a
171+-- buffer.
162172--
163−-- The evaluation requires only one thread as only one stream needs to be
164−-- evaluated. Therefore, the concurrency options that are relevant to multiple
165−-- streams do not apply here e.g. maxThreads, eager, interleaved, ordered,
166−-- stopWhen options do not have any effect on 'parEval'.
173+-- Note that the evaluation requires only one thread as only one stream needs
174+-- to be evaluated. Therefore, the concurrency options that are relevant to
175+-- multiple streams won't apply here e.g. maxThreads, eager, interleaved,
176+-- ordered, stopWhen options won't have any effect.
167177--
168178-- Useful idioms:
169179--
@@ -265,28 +275,6 @@ parTwo modifier stream1 stream2 =
265275 $ appendWithK
266276 modifier (Stream.toStreamK stream1) (Stream.toStreamK stream2)
267277
268−-------------------------------------------------------------------------------
269−-- Evaluator
270−-------------------------------------------------------------------------------
271−
272−-- | @concatMapDivK useTail useHead stream@, divides the stream in head and
273−-- tail, maps a stream generator on the head and maps an action on the tail of
274−-- a stream. Returns the stream generated by the head.
275−--
276−-- Used for concurrent evaluation of streams using a Channel.
277−{-# INLINE concatMapDivK #-}
278−concatMapDivK :: Monad m =>
279− (K.StreamK m a -> m ())
280− -> (a -> K.StreamK m b)
281− -> K.StreamK m a
282− -> K.StreamK m b
283−concatMapDivK useTail useHead stream =
284− K.mkStream $ \st yld sng stp -> do
285− let foldShared = K.foldStreamShared st yld sng stp
286− single a = foldShared $ useHead a
287− yieldk a r = useTail r >> single a
288− in K.foldStreamShared (adaptState st) yieldk single stp stream
289−
290278-------------------------------------------------------------------------------
291279-- concat streams
292280-------------------------------------------------------------------------------
@@ -654,8 +642,8 @@ parConcatIterate modifier f input =
654642
655643 where
656644
657− iterateStream channel =
658− parConcatMapChanKGeneric modifier channel (generate channel)
645+ iterateStream channel stream =
646+ parConcatMapChanKGeneric modifier channel (generate channel) stream
659647
660648 generate channel x =
661649 -- XXX The channel q should be FIFO for DFS, otherwise it is BFS
src/Streamly/Internal/Data/Stream/Concurrent/Channel.hs+14−17
@@ -8,18 +8,15 @@
88
99module Streamly.Internal.Data.Stream.Concurrent.Channel
1010 (
11− module Streamly.Internal.Data.Stream.Concurrent.Channel.Type
12− , module Streamly.Internal.Data.Stream.Concurrent.Channel.Operations
13− , module Streamly.Internal.Data.Stream.Concurrent.Channel.Append
14− , module Streamly.Internal.Data.Stream.Concurrent.Channel.Interleave
15− , module Streamly.Internal.Data.Stream.Concurrent.Channel.Dispatcher
16− , module Streamly.Internal.Data.Stream.Concurrent.Channel.Consumer
17−
1811 -- * Channel
19− , Channel (..)
12+ Channel (..)
2013 , newChannel
2114 , withChannel
2215 , withChannelK
16+ , fromChannel
17+ , toChannel
18+ , toChannelK
19+ , stopChannel
2320 -- quiesceChannel -- wait for running tasks but do not schedule any more.
2421
2522 -- * Configuration
@@ -55,17 +52,17 @@ where
5552
5653import Streamly.Internal.Control.Concurrent (MonadAsync)
5754import Streamly.Internal.Data.Stream (Stream)
55+import Streamly.Internal.Data.Stream.Concurrent.Channel.Operations
56+ (fromChannel, fromChannelK, toChannel, toChannelK)
5857
58+import qualified Streamly.Internal.Data.Stream.Concurrent.Channel.Append
59+ as Append
60+import qualified Streamly.Internal.Data.Stream.Concurrent.Channel.Interleave
61+ as Interleave
5962import qualified Streamly.Internal.Data.StreamK as K
6063
61−import Streamly.Internal.Data.Channel.Types
62−
6364import Streamly.Internal.Data.Stream.Concurrent.Channel.Type
64−import Streamly.Internal.Data.Stream.Concurrent.Channel.Operations
65−import Streamly.Internal.Data.Stream.Concurrent.Channel.Append
66−import Streamly.Internal.Data.Stream.Concurrent.Channel.Interleave
67−import Streamly.Internal.Data.Stream.Concurrent.Channel.Dispatcher
68−import Streamly.Internal.Data.Stream.Concurrent.Channel.Consumer
65+import Streamly.Internal.Data.Stream.Channel.Types
6966
7067-- | Create a new concurrent stream evaluation channel. The monad
7168-- state used to run the stream actions is captured from the call site of
@@ -76,8 +73,8 @@ newChannel :: MonadAsync m =>
7673newChannel modifier =
7774 let cfg = modifier defaultConfig
7875 in if getInterleaved cfg
79− then newInterleaveChannel modifier
80− else newAppendChannel modifier
76+ then Interleave.newChannel modifier
77+ else Append.newChannel modifier
8178
8279-- | Allocate a channel and evaluate the stream using the channel and the
8380-- supplied evaluator function. The evaluator is run in a worker thread.
src/Streamly/Internal/Data/Stream/Concurrent/Channel/Append.hs+10−10
@@ -7,7 +7,7 @@
77-- Portability : GHC
88--
99-- The functions in this module are separated from the combinators using
10−-- these because of a GHC issue. We need to have newAppendChannel specialized but
10+-- these because of a GHC issue. We need to have newChannel specialized but
1111-- not inlined. If we keep it in the same module as its users we cannot achieve
1212-- that and the code becomes bloated. But if it is in a separate module we can
1313-- use INLINABLE and SPECIALIZE on it which makes it specialized but it is not
@@ -15,7 +15,7 @@
1515
1616module Streamly.Internal.Data.Stream.Concurrent.Channel.Append
1717 (
18− newAppendChannel
18+ newChannel
1919 )
2020where
2121
@@ -32,7 +32,7 @@ import Streamly.Internal.Control.Concurrent
3232 (MonadRunInIO, RunInIO(..), askRunInIO, restoreM)
3333import Streamly.Internal.Data.Atomics
3434 (atomicModifyIORefCAS, atomicModifyIORefCAS_)
35−import Streamly.Internal.Data.Channel.Dispatcher (modifyThread)
35+import Streamly.Internal.Data.Stream.Channel.Dispatcher (modifyThread)
3636
3737import qualified Data.Heap as H
3838import qualified Data.Set as Set
@@ -41,8 +41,8 @@ import qualified Streamly.Internal.Data.StreamK as K
4141import Streamly.Internal.Data.Stream.Concurrent.Channel.Consumer
4242import Streamly.Internal.Data.Stream.Concurrent.Channel.Dispatcher
4343import Streamly.Internal.Data.Stream.Concurrent.Channel.Type
44−import Streamly.Internal.Data.Channel.Types
45−import Streamly.Internal.Data.Channel.Worker
44+import Streamly.Internal.Data.Stream.Channel.Types
45+import Streamly.Internal.Data.Stream.Channel.Worker
4646
4747------------------------------------------------------------------------------
4848-- Concurrent streams with first-come-first serve results
@@ -1037,10 +1037,10 @@ getLifoSVar mrun cfg = do
10371037
10381038-- | Create a new async style concurrent stream evaluation channel. The monad
10391039-- state used to run the stream actions is taken from the call site of
1040−-- newAppendChannel.
1041−{-# INLINABLE newAppendChannel #-}
1042−{-# SPECIALIZE newAppendChannel :: (Config -> Config) -> IO (Channel IO a) #-}
1043−newAppendChannel :: MonadRunInIO m => (Config -> Config) -> m (Channel m a)
1044−newAppendChannel modifier = do
1040+-- newChannel.
1041+{-# INLINABLE newChannel #-}
1042+{-# SPECIALIZE newChannel :: (Config -> Config) -> IO (Channel IO a) #-}
1043+newChannel :: MonadRunInIO m => (Config -> Config) -> m (Channel m a)
1044+newChannel modifier = do
10451045 mrun <- askRunInIO
10461046 liftIO $ getLifoSVar mrun (modifier defaultConfig)
src/Streamly/Internal/Data/Stream/Concurrent/Channel/Consumer.hs+2−2
@@ -25,8 +25,8 @@ import Streamly.Internal.Control.Concurrent (MonadRunInIO)
2525
2626import Streamly.Internal.Data.Stream.Concurrent.Channel.Dispatcher
2727import Streamly.Internal.Data.Stream.Concurrent.Channel.Type
28−import Streamly.Internal.Data.Channel.Dispatcher
29−import Streamly.Internal.Data.Channel.Types
28+import Streamly.Internal.Data.Stream.Channel.Dispatcher
29+import Streamly.Internal.Data.Stream.Channel.Types
3030
3131-------------------------------------------------------------------------------
3232-- Reading from the workers' output queue/buffer
src/Streamly/Internal/Data/Stream/Concurrent/Channel/Dispatcher.hs+3−3
@@ -34,9 +34,9 @@ import Streamly.Internal.Data.Time.Units
3434 (MicroSecond64(..), diffAbsTime64, fromRelTime64, toRelTime64)
3535
3636import Streamly.Internal.Data.Stream.Concurrent.Channel.Type
37−import Streamly.Internal.Data.Channel.Dispatcher
38−import Streamly.Internal.Data.Channel.Types
39−import Streamly.Internal.Data.Channel.Worker
37+import Streamly.Internal.Data.Stream.Channel.Dispatcher
38+import Streamly.Internal.Data.Stream.Channel.Types
39+import Streamly.Internal.Data.Stream.Channel.Worker
4040
4141-------------------------------------------------------------------------------
4242-- Dispatching workers
src/Streamly/Internal/Data/Stream/Concurrent/Channel/Interleave.hs+8−8
@@ -8,7 +8,7 @@
88
99module Streamly.Internal.Data.Stream.Concurrent.Channel.Interleave
1010 (
11− newInterleaveChannel
11+ newChannel
1212 )
1313where
1414
@@ -21,14 +21,14 @@ import Data.Concurrent.Queue.MichaelScott (LinkedQueue, newQ, nullQ, tryPopR, pu
2121import Data.IORef (newIORef, readIORef)
2222import Streamly.Internal.Control.Concurrent
2323 (MonadRunInIO, MonadAsync, RunInIO(..), askRunInIO, restoreM)
24−import Streamly.Internal.Data.Channel.Dispatcher (delThread)
24+import Streamly.Internal.Data.Stream.Channel.Dispatcher (delThread)
2525
2626import qualified Data.Set as Set
2727import qualified Streamly.Internal.Data.StreamK as K
2828
2929import Streamly.Internal.Data.Stream.Concurrent.Channel.Consumer
3030import Streamly.Internal.Data.Stream.Concurrent.Channel.Type
31−import Streamly.Internal.Data.Channel.Types
31+import Streamly.Internal.Data.Stream.Channel.Types
3232
3333------------------------------------------------------------------------------
3434-- Creating a channel
@@ -242,11 +242,11 @@ getFifoSVar mrun cfg = do
242242--
243243-- | Create a new async style concurrent stream evaluation channel. The monad
244244-- state used to run the stream actions is taken from the call site of
245−-- newInterleaveChannel.
246−{-# INLINABLE newInterleaveChannel #-}
247−{-# SPECIALIZE newInterleaveChannel :: (Config -> Config) -> IO (Channel IO a) #-}
248−newInterleaveChannel :: MonadAsync m =>
245+-- newChannel.
246+{-# INLINABLE newChannel #-}
247+{-# SPECIALIZE newChannel :: (Config -> Config) -> IO (Channel IO a) #-}
248+newChannel :: MonadAsync m =>
249249 (Config -> Config) -> m (Channel m a)
250−newInterleaveChannel modifier = do
250+newChannel modifier = do
251251 mrun <- askRunInIO
252252 liftIO $ getFifoSVar mrun (modifier defaultConfig)
src/Streamly/Internal/Data/Stream/Concurrent/Channel/Operations.hs+1−1
@@ -44,7 +44,7 @@ import qualified Streamly.Internal.Data.StreamK as K
4444
4545import Streamly.Internal.Data.Stream.Concurrent.Channel.Dispatcher
4646import Streamly.Internal.Data.Stream.Concurrent.Channel.Type
47−import Streamly.Internal.Data.Channel.Types hiding (inspect)
47+import Streamly.Internal.Data.Stream.Channel.Types hiding (inspect)
4848
4949import Prelude hiding (map, concat, concatMap)
5050
src/Streamly/Internal/Data/Stream/Concurrent/Channel/Type.hs+3−3
@@ -25,12 +25,12 @@ import Data.List (intersperse)
2525import Data.Set (Set)
2626import Streamly.Internal.Control.Concurrent (RunInIO)
2727import Streamly.Internal.Data.Atomics (atomicModifyIORefCAS_)
28−import Streamly.Internal.Data.Channel.Dispatcher (dumpSVarStats)
29−import Streamly.Internal.Data.Channel.Worker
28+import Streamly.Internal.Data.Stream.Channel.Dispatcher (dumpSVarStats)
29+import Streamly.Internal.Data.Stream.Channel.Worker
3030 (sendYield, sendStop, sendWithDoorBell)
3131import Streamly.Internal.Data.StreamK (StreamK)
3232
33−import Streamly.Internal.Data.Channel.Types
33+import Streamly.Internal.Data.Stream.Channel.Types
3434
3535-- IMPORTANT NOTE: we cannot update the SVar after generating it as we have
3636-- references to the original SVar stored in several functions which will keep
src/Streamly/Internal/Data/Stream/Lifted.hs → src/Streamly/Internal/Data/Stream/Exception/Lifted.hsrenamed+2−2
@@ -1,12 +1,12 @@
11-- |
2−-- Module : Streamly.Internal.Data.Stream.Lifted
2+-- Module : Streamly.Internal.Data.Stream.Exception.Lifted
33-- Copyright : (c) 2019 Composewell Technologies
44-- License : BSD-3-Clause
55-- Maintainer : streamly@composewell.com
66-- Stability : experimental
77-- Portability : GHC
88
9−module Streamly.Internal.Data.Stream.Lifted
9+module Streamly.Internal.Data.Stream.Exception.Lifted
1010 (
1111 after
1212 , bracket
src/Streamly/Internal/Data/Stream/IsStream.hs−6
@@ -22,9 +22,6 @@ module Streamly.Internal.Data.Stream.IsStream {-# DEPRECATED "Please use \"Stre
2222 , module Streamly.Internal.Data.Stream.IsStream.Exception
2323 , module Streamly.Internal.Data.Stream.IsStream.Lift
2424 , module Streamly.Internal.Data.Stream.IsStream.Top
25− , module Streamly.Internal.Data.Stream.IsStream.Combinators
26− , module Streamly.Internal.Data.Stream.IsStream.Common
27− , module Streamly.Internal.Data.Stream.IsStream.Enumeration
2825 , fromStream
2926 , toStream
3027 )
@@ -41,9 +38,6 @@ import Streamly.Internal.Data.Stream.IsStream.Transform
4138import Streamly.Internal.Data.Stream.IsStream.Type
4239 hiding (cmpBy, drain, eqBy, foldl', fold, toList, toStream
4340 , fromEffect, fromPure, repeat, fromStream)
44−import Streamly.Internal.Data.Stream.IsStream.Combinators
45−import Streamly.Internal.Data.Stream.IsStream.Common
46−import Streamly.Internal.Data.Stream.IsStream.Enumeration
4741
4842import qualified Streamly.Internal.Data.Stream as D
4943
src/Streamly/Internal/Data/Stream/IsStream/Common.hs+1−1
@@ -529,7 +529,7 @@ reverse' :: (IsStream t, MonadIO m, Unbox a) => t m a -> t m a
529529-- reverse' s = fromStreamD $ D.reverse' $ toStreamD s
530530reverse' =
531531 fromStreamD
532− . A.concatRev -- unfoldMany A.readerRev
532+ . A.flattenArraysRev -- unfoldMany A.readRev
533533 . D.fromStreamK
534534 . K.reverse
535535 . D.toStreamK
src/Streamly/Internal/Data/Stream/IsStream/Exception.hs+1−1
@@ -42,7 +42,7 @@ import qualified Streamly.Internal.Data.Stream as D
4242 , handle
4343 )
4444
45−import qualified Streamly.Internal.Data.Stream.Lifted as D
45+import qualified Streamly.Internal.Data.Stream.Exception.Lifted as D
4646 ( afterD
4747 , bracket3D
4848 , retryD
src/Streamly/Internal/Data/Stream/IsStream/Expand.hs−5
@@ -1,8 +1,3 @@
1−{-# LANGUAGE TypeFamilies #-}
2−-- Must come after TypeFamilies, otherwise it is re-enabled.
3−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
4−{-# LANGUAGE NoMonoLocalBinds #-}
5−
61{-# OPTIONS_GHC -Wno-deprecations #-}
72
83-- |
src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs+1−1
@@ -1624,4 +1624,4 @@ splitInnerBySuffix
16241624 -> t m (f a)
16251625 -> t m (f a)
16261626splitInnerBySuffix splitter joiner xs =
1627− fromStreamD $ D.splitInnerBySuffix (== mempty) splitter joiner $ toStreamD xs
1627+ fromStreamD $ D.splitInnerBySuffix splitter joiner $ toStreamD xs
src/Streamly/Internal/Data/Stream/IsStream/Top.hs+1−1
@@ -649,7 +649,7 @@ intersectBySorted :: (IsStream t, Monad m) =>
649649 (a -> a -> Ordering) -> t m a -> t m a -> t m a
650650intersectBySorted eq s1 =
651651 IsStream.fromStreamD
652− . StreamD.sortedIntersectBy eq (IsStream.toStreamD s1)
652+ . StreamD.intersectBySorted eq (IsStream.toStreamD s1)
653653 . IsStream.toStreamD
654654
655655-- Roughly joinLeft s1 s2 = s1 `difference` s2 + s1 `intersection` s2
src/Streamly/Internal/Data/Stream/MkType.hs+34−33
@@ -334,14 +334,10 @@ monadthrowInstance _Type =
334334 [ clause
335335 []
336336 (normalB
337− (infixE
338− (Just (conE _Type))
339− (varE _dotOp)
340− (Just
341− (infixE
342− (Just (varE (mkName "Stream.fromEffect")))
343− (varE _dotOp)
344− (Just (varE _throwM))))))
337+ (infixE
338+ (Just (varE _lift))
339+ (varE _dotOp)
340+ (Just (varE _throwM))))
345341 []
346342 ]
347343 ]
@@ -508,7 +504,7 @@ flattenDec (ma:mas) = do
508504-- >>> expr <- runQ (mkZipType "ZipStream" "zipApply" False)
509505-- >>> putStrLn $ pprint expr
510506-- newtype ZipStream m a
511−-- = ZipStream (Stream.Stream m a)
507+-- = ZipStream (Stream.Stream m a)
512508-- deriving Foldable
513509-- mkZipStream :: Stream.Stream m a -> ZipStream m a
514510-- mkZipStream = ZipStream
@@ -520,17 +516,19 @@ flattenDec (ma:mas) = do
520516-- deriving instance GHC.Classes.Eq a => Eq (ZipStream Identity a)
521517-- deriving instance GHC.Classes.Ord a => Ord (ZipStream Identity a)
522518-- instance Show a => Show (ZipStream Identity a)
523−-- where {{-# INLINE show #-}; show (ZipStream strm) = show strm}
519+-- where {-# INLINE show #-}
520+-- show (ZipStream strm) = show strm
524521-- instance Read a => Read (ZipStream Identity a)
525−-- where {{-# INLINE readPrec #-}; readPrec = fmap ZipStream readPrec}
522+-- where {-# INLINE readPrec #-}
523+-- readPrec = fmap ZipStream readPrec
526524-- instance Monad m => Functor (ZipStream m)
527−-- where {{-# INLINE fmap #-};
528−-- fmap f (ZipStream strm) = ZipStream (fmap f strm)}
525+-- where {-# INLINE fmap #-}
526+-- fmap f (ZipStream strm) = ZipStream (fmap f strm)
529527-- instance Monad m => Applicative (ZipStream m)
530−-- where {{-# INLINE pure #-};
531−-- pure = ZipStream . Stream.repeat;
532−-- {-# INLINE (<*>) #-};
533−-- (<*>) (ZipStream strm1) (ZipStream strm2) = ZipStream (zipApply strm1 strm2)}
528+-- where {-# INLINE pure #-}
529+-- pure = ZipStream . Stream.repeat
530+-- {-# INLINE (<*>) #-}
531+-- (<*>) (ZipStream strm1) (ZipStream strm2) = ZipStream (zipApply strm1 strm2)
534532mkZipType
535533 :: String -- ^ Name of the type
536534 -> String -- ^ Function to use for (\<*\>)
@@ -579,25 +577,27 @@ mkZipType dtNameStr apOpStr isConcurrent =
579577-- unParallel :: Parallel m a -> Stream.Stream m a
580578-- unParallel (Parallel strm) = strm
581579-- instance Monad m => Functor (Parallel m)
582−-- where {{-# INLINE fmap #-};
583−-- fmap f (Parallel strm) = Parallel (fmap f strm)}
580+-- where {-# INLINE fmap #-}
581+-- fmap f (Parallel strm) = Parallel (fmap f strm)
584582-- instance Stream.MonadAsync m => Monad (Parallel m)
585−-- where {{-# INLINE (>>=) #-};
586−-- (>>=) (Parallel strm1) f = let f1 a = unParallel (f a)
587−-- in Parallel (parBind strm1 f1)}
583+-- where {-# INLINE (>>=) #-}
584+-- (>>=) (Parallel strm1) f = let f1 a = unParallel (f a)
585+-- in Parallel (parBind strm1 f1)
588586-- instance Stream.MonadAsync m => Applicative (Parallel m)
589−-- where {{-# INLINE pure #-};
590−-- pure = Parallel . Stream.fromPure;
591−-- {-# INLINE (<*>) #-};
592−-- (<*>) = ap}
587+-- where {-# INLINE pure #-}
588+-- pure = Parallel . Stream.fromPure
589+-- {-# INLINE (<*>) #-}
590+-- (<*>) = ap
593591-- instance (Monad (Parallel m), MonadIO m) => MonadIO (Parallel m)
594−-- where {{-# INLINE liftIO #-};
595−-- liftIO = Parallel . (Stream.fromEffect . liftIO)}
592+-- where {-# INLINE liftIO #-}
593+-- liftIO = Parallel . (Stream.fromEffect . liftIO)
594+-- instance MonadTrans Parallel
595+-- where {-# INLINE lift #-}
596+-- lift = Parallel . Stream.fromEffect
596597-- instance (Monad (Parallel m),
597598-- MonadThrow m) => MonadThrow (Parallel m)
598−-- where {{-# INLINE throwM #-};
599−-- throwM = Parallel . (Stream.fromEffect . throwM)}
600−
599+-- where {-# INLINE throwM #-}
600+-- throwM = lift . throwM
601601mkCrossType
602602 :: String -- ^ Name of the type
603603 -> String -- ^ Function to use for (>>=)
@@ -617,7 +617,7 @@ mkCrossType dtNameStr bindOpStr isConcurrent =
617617 , readInstance _Type
618618 ]
619619 else []
620− , sequence $
620+ , sequence
621621 [ functorInstance _Type
622622 , mkStreamMonad dtNameStr classConstraints bindOpStr
623623 , mkStreamApplicative
@@ -627,9 +627,10 @@ mkCrossType dtNameStr bindOpStr isConcurrent =
627627 "Stream.fromPure"
628628 "ap"
629629 , monadioInstance _Type
630+ , monadtransInstance _Type
630631 , monadthrowInstance _Type
631632 -- , monadreaderInstance _Type
632− ] ++ [monadtransInstance _Type | not isConcurrent]
633+ ]
633634 ]
634635
635636 where
src/Streamly/Internal/Data/Stream/Prelude.hsdeleted−19
@@ -1,19 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Prelude
3−-- Copyright : (c) 2022 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−module Streamly.Internal.Data.Stream.Prelude
10− (
11− module Streamly.Internal.Data.Stream.Concurrent
12− , module Streamly.Internal.Data.Stream.Time
13− , module Streamly.Internal.Data.Stream.Lifted
14− )
15−where
16−
17−import Streamly.Internal.Data.Stream.Concurrent
18−import Streamly.Internal.Data.Stream.Time
19−import Streamly.Internal.Data.Stream.Lifted
src/Streamly/Internal/Data/Stream/SVar.hsdeleted−18
@@ -1,18 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.SVar
3−-- Copyright : (c) 2022 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−module Streamly.Internal.Data.Stream.SVar
10− {-# DEPRECATED "This module will be removed in future." #-}
11− (
12− module Streamly.Internal.Data.Stream.SVar.Eliminate
13− , module Streamly.Internal.Data.Stream.SVar.Generate
14− )
15−where
16−
17−import Streamly.Internal.Data.Stream.SVar.Eliminate
18−import Streamly.Internal.Data.Stream.SVar.Generate
src/Streamly/Internal/Data/Stream/Serial.hs−5
@@ -1,9 +1,4 @@
1−{-# LANGUAGE TypeFamilies #-}
2−-- Must come after TypeFamilies, otherwise it is re-enabled.
3−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
4−{-# LANGUAGE NoMonoLocalBinds #-}
51{-# LANGUAGE UndecidableInstances #-}
6−
72{-# OPTIONS_GHC -Wno-deprecations #-}
83{-# OPTIONS_GHC -Wno-redundant-constraints #-}
94
src/Streamly/Internal/Data/Stream/Zip.hs−37
@@ -1,9 +1,4 @@
1−{-# LANGUAGE TypeFamilies #-}
2−-- Must come after TypeFamilies, otherwise it is re-enabled.
3−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
4−{-# LANGUAGE NoMonoLocalBinds #-}
51{-# LANGUAGE UndecidableInstances #-}
6−
72{-# OPTIONS_GHC -Wno-deprecations #-}
83
94-- |
@@ -18,11 +13,8 @@
1813-- To run examples in this module:
1914--
2015-- >>> import qualified Streamly.Prelude as Stream
21−-- >>> import qualified Streamly.Internal.Data.Stream as D
22−-- >>> import qualified Streamly.Data.Fold as Fold
2316--
2417module Streamly.Internal.Data.Stream.Zip
25− {-# DEPRECATED "Use \"Streamly.Data.Stream.MkType\" instead." #-}
2618 (
2719 ZipSerialM (..)
2820 , ZipSerial
@@ -30,8 +22,6 @@ module Streamly.Internal.Data.Stream.Zip
3022 , zipWithK
3123 , zipWithMK
3224
33− , ZipConcurrent (..)
34−
3525 -- * Deprecated
3626 , ZipStream
3727 )
@@ -59,7 +49,6 @@ import Streamly.Internal.BaseCompat ((#.))
5949import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
6050import Streamly.Internal.Data.Stream.Serial (SerialT(..))
6151import Streamly.Internal.Data.StreamK (Stream)
62−import Streamly.Internal.Data.Stream.Concurrent (MonadAsync, parZipWith)
6352
6453import qualified Streamly.Internal.Data.Stream.Common as P
6554import qualified Streamly.Internal.Data.StreamK as K
@@ -72,8 +61,6 @@ import Prelude hiding (map, repeat, zipWith)
7261
7362-- $setup
7463-- >>> import qualified Streamly.Prelude as Stream
75−-- >>> import qualified Streamly.Internal.Data.Stream as D
76−-- >>> import qualified Streamly.Data.Fold as Fold
7764-- >>> import Control.Concurrent (threadDelay)
7865-- >>> :{
7966-- delay n = do
@@ -148,27 +135,3 @@ instance Monad m => Applicative (ZipSerialM m) where
148135
149136FOLDABLE_INSTANCE(ZipSerialM)
150137TRAVERSABLE_INSTANCE(ZipSerialM)
151−
152−-------------------------------------------------------------------------------
153−-- ZipConcurrent
154−-------------------------------------------------------------------------------
155−
156−newtype ZipConcurrent m a = ZipConcurrent {getZipConcurrent :: D.Stream m a}
157− deriving (Functor)
158−
159−-- | An IO stream whose applicative instance zips streams concurrently. Note
160−-- that it uses the default concurrency options.
161−--
162−-- >>> s = ZipConcurrent $ D.fromList [1, 2, 3]
163−-- >>> x = (,,) <$> s <*> s <*> s
164−-- >>> D.fold Fold.toList (getZipConcurrent x)
165−-- [(1,1,1),(2,2,2),(3,3,3)]
166−--
167−-- @since 0.9.0
168−
169−instance MonadAsync m => Applicative (ZipConcurrent m) where
170− pure = ZipConcurrent . D.repeat
171−
172− {-# INLINE (<*>) #-}
173− ZipConcurrent m1 <*> ZipConcurrent m2 =
174− ZipConcurrent $ parZipWith id id m1 m2
src/Streamly/Internal/Data/Stream/Zip/Concurrent.hsnew file+50
@@ -0,0 +1,50 @@
1+{-# LANGUAGE UndecidableInstances #-}
2+-- |
3+-- Module : Streamly.Internal.Data.Stream.Concurrent
4+-- Copyright : (c) 2017 Composewell Technologies
5+-- License : BSD-3-Clause
6+-- Maintainer : streamly@composewell.com
7+-- Stability : experimental
8+-- Portability : GHC
9+--
10+-- To run examples in this module:
11+--
12+-- >>> import qualified Streamly.Internal.Data.Stream as Stream
13+-- >>> import qualified Streamly.Data.Fold as Fold
14+--
15+module Streamly.Internal.Data.Stream.Zip.Concurrent
16+ (
17+ ZipConcurrent (..)
18+ )
19+where
20+
21+import Streamly.Internal.Data.Stream (Stream)
22+import Streamly.Internal.Data.Stream.Concurrent (MonadAsync, parZipWith)
23+
24+import qualified Streamly.Internal.Data.Stream as Stream (repeat)
25+import Prelude hiding (map, repeat, zipWith)
26+
27+-- $setup
28+-- >>> import qualified Streamly.Internal.Data.Stream as Stream
29+-- >>> import qualified Streamly.Data.Fold as Fold
30+--
31+
32+newtype ZipConcurrent m a = ZipConcurrent {getZipConcurrent :: Stream m a}
33+ deriving (Functor)
34+
35+-- | An IO stream whose applicative instance zips streams concurrently. Note
36+-- that it uses the default concurrency options.
37+--
38+-- >>> s = ZipConcurrent $ Stream.fromList [1, 2, 3]
39+-- >>> x = (,,) <$> s <*> s <*> s
40+-- >>> Stream.fold Fold.toList (getZipConcurrent x)
41+-- [(1,1,1),(2,2,2),(3,3,3)]
42+--
43+-- @since 0.9.0
44+
45+instance MonadAsync m => Applicative (ZipConcurrent m) where
46+ pure = ZipConcurrent . Stream.repeat
47+
48+ {-# INLINE (<*>) #-}
49+ ZipConcurrent m1 <*> ZipConcurrent m2 =
50+ ZipConcurrent $ parZipWith id id m1 m2
src/Streamly/Internal/Data/Stream/ZipAsync.hs+1−2
@@ -13,8 +13,7 @@
1313--
1414-- >>> import qualified Streamly.Prelude as Stream
1515--
16−module Streamly.Internal.Data.Stream.ZipAsync
17− {-# DEPRECATED "Use \"Streamly.Data.Stream.MkType\" instead." #-}
16+module Streamly.Internal.Data.Stream.ZipAsync {-# DEPRECATED "Please use \"Streamly.Internal.Data.Stream.Zip.Concurrent\" instead." #-}
1817 ( ZipAsyncM(..)
1918 , ZipAsync
2019 , consMZipAsync
src/Streamly/Internal/Data/Unfold/Prelude.hsdeleted−17
@@ -1,17 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Unfold.Prelude
3−-- Copyright : (c) 2022 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−module Streamly.Internal.Data.Unfold.Prelude
10− (
11− module Streamly.Internal.Data.Unfold.Exception
12− , module Streamly.Internal.Data.Unfold.SVar
13− )
14−where
15−
16−import Streamly.Internal.Data.Unfold.Exception
17−import Streamly.Internal.Data.Unfold.SVar
src/Streamly/Internal/Data/Unfold/SVar.hs−1
@@ -1,4 +1,3 @@
1−{-# OPTIONS_GHC -Wno-deprecations #-}
21-- |
32-- Module : Streamly.Internal.Data.Unfold.SVar
43-- Copyright : (c) 2019 Composewell Technologies
src/Streamly/Internal/FileSystem/Event.hs−3
@@ -20,9 +20,6 @@
2020-- * "Streamly.Internal.FileSystem.Event.Linux"
2121-- * "Streamly.Internal.FileSystem.Event.Windows"
2222
23−-- XXX Need to ensure that the signatures of the exported APIs are same on all
24−-- platforms.
25−
2623module Streamly.Internal.FileSystem.Event
2724 (
2825 -- * Creating a Watch
src/Streamly/Internal/FileSystem/Event/Darwin.hs+1−1
@@ -451,7 +451,7 @@ openWatch Config{..} paths = do
451451
452452 withPathName :: Array Word8 -> (PathName -> IO a) -> IO a
453453 withPathName arr act = do
454− A.unsafePinnedAsPtr arr $ \ptr ->
454+ A.asPtrUnsafe arr $ \ptr ->
455455 let pname = PathName (castPtr ptr) (fromIntegral (A.length arr))
456456 in act pname
457457
src/Streamly/Internal/FileSystem/Event/Linux.hs+2−2
@@ -188,7 +188,7 @@ import qualified Streamly.FileSystem.Handle as FH
188188import qualified Streamly.Unicode.Stream as U
189189
190190import qualified Streamly.Internal.Data.Array as A
191− ( fromStream, asCStringUnsafe, unsafePinnedAsPtr
191+ ( fromStream, asCStringUnsafe, asPtrUnsafe
192192 , getSliceUnsafe, read
193193 )
194194import qualified Streamly.Internal.FileSystem.Dir as Dir (readDirs)
@@ -809,7 +809,7 @@ readOneEvent :: Config -> Watch -> Parser Word8 IO Event
809809readOneEvent cfg wt@(Watch _ wdMap) = do
810810 let headerLen = sizeOf (undefined :: CInt) + 12
811811 arr <- PR.takeEQ headerLen (A.writeN headerLen)
812− (ewd, eflags, cookie, pathLen) <- PR.fromEffect $ A.unsafePinnedAsPtr arr readHeader
812+ (ewd, eflags, cookie, pathLen) <- PR.fromEffect $ A.asPtrUnsafe arr readHeader
813813 -- XXX need the "initial" in parsers to return a step type so that "take 0"
814814 -- can return without an input. otherwise if pathLen is 0 we will keep
815815 -- waiting to read one more char before we return this event.
src/Streamly/Internal/FileSystem/Event/Windows.hs+2−2
@@ -119,13 +119,13 @@ import System.Win32.Types (BOOL, DWORD, HANDLE, LPVOID, LPDWORD, failIfFalse_)
119119
120120import Streamly.Data.Array (Array)
121121import Streamly.Data.Stream (Stream)
122−import Streamly.Data.Stream.Prelude (eager)
122+import Streamly.Data.Stream.Concurrent (eager)
123123
124124import qualified Data.List.NonEmpty as NonEmpty
125125import qualified Streamly.Data.Array as A (fromList)
126126import qualified Streamly.Data.Fold as Fold
127127import qualified Streamly.Data.Stream as S
128−import qualified Streamly.Data.Stream.Prelude as S
128+import qualified Streamly.Data.Stream.Concurrent as S
129129import qualified Streamly.Unicode.Stream as U
130130import qualified Streamly.Internal.Unicode.Utf8 as UTF8 (pack, toArray)
131131import qualified Streamly.Internal.Data.Array as A (read)
src/Streamly/Internal/FileSystem/FD.hs+8−7
@@ -120,6 +120,7 @@ import Control.Monad.IO.Class (MonadIO(..))
120120import Data.Word (Word8)
121121-- import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
122122import Foreign.Ptr (castPtr)
123+import Streamly.Internal.Data.Unbox (Unbox)
123124-- import System.IO (Handle, hGetBufSome, hPutBuf)
124125import System.IO (IOMode)
125126import Prelude hiding (read)
@@ -127,10 +128,10 @@ import Prelude hiding (read)
127128import qualified GHC.IO.FD as FD
128129import qualified GHC.IO.Device as RawIO
129130
130−import Streamly.Data.Array (Array, Unbox)
131+import Streamly.Data.Array (Array)
131132import Streamly.Data.Stream (Stream)
132133
133−import Streamly.Internal.Data.Array (byteLength, unsafeFreeze, unsafePinnedAsPtr)
134+import Streamly.Internal.Data.Array (byteLength, unsafeFreeze, asPtrUnsafe)
134135import Streamly.Internal.System.IO (defaultChunkSize)
135136
136137#if !defined(mingw32_HOST_OS)
@@ -147,8 +148,8 @@ import qualified Streamly.Internal.System.IOVec.Type as RawIO
147148import qualified Streamly.Data.Array as A
148149import qualified Streamly.Data.Fold as FL
149150import qualified Streamly.Internal.Data.MutArray as MArray
150− (MutArray(..), unsafePinnedAsPtr, pinnedNewBytes)
151−import qualified Streamly.Internal.Data.Array.Stream as AS
151+ (MutArray(..), asPtrUnsafe, pinnedNewBytes)
152+import qualified Streamly.Internal.Data.Stream.Chunked as AS
152153import qualified Streamly.Internal.Data.Stream as S
153154import qualified Streamly.Internal.Data.Stream as D
154155 (Stream(..), Step(..))
@@ -220,7 +221,7 @@ readArrayUpto :: Int -> Handle -> IO (Array Word8)
220221readArrayUpto size (Handle fd) = do
221222 arr <- MArray.pinnedNewBytes size
222223 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
223− MArray.unsafePinnedAsPtr arr $ \p -> do
224+ MArray.asPtrUnsafe arr $ \p -> do
224225 -- n <- hGetBufSome h p size
225226#if MIN_VERSION_base(4,15,0)
226227 n <- RawIO.read fd p 0 size
@@ -244,7 +245,7 @@ readArrayUpto size (Handle fd) = do
244245writeArray :: Unbox a => Handle -> Array a -> IO ()
245246writeArray _ arr | A.length arr == 0 = return ()
246247writeArray (Handle fd) arr =
247− unsafePinnedAsPtr arr $ \p ->
248+ asPtrUnsafe arr $ \p ->
248249 -- RawIO.writeAll fd (castPtr p) aLen
249250#if MIN_VERSION_base(4,15,0)
250251 RawIO.write fd (castPtr p) 0 aLen
@@ -270,7 +271,7 @@ writeArray (Handle fd) arr =
270271writeIOVec :: Handle -> Array RawIO.IOVec -> IO ()
271272writeIOVec _ iov | A.length iov == 0 = return ()
272273writeIOVec (Handle fd) iov =
273− unsafePinnedAsPtr iov $ \p ->
274+ asPtrUnsafe iov $ \p ->
274275 RawIO.writevAll fd p (A.length iov)
275276-}
276277#endif
src/Streamly/Internal/Network/Inet/TCP.hs+4−4
@@ -116,6 +116,7 @@ import Prelude hiding (read)
116116import Streamly.Internal.Control.Concurrent (MonadAsync)
117117import Streamly.Internal.Control.ForkLifted (fork)
118118import Streamly.Data.Array (Array)
119+import Streamly.Internal.Data.Array (pinnedWriteNUnsafe)
119120import Streamly.Internal.Data.Fold ( Fold(..) )
120121import Streamly.Data.Stream (Stream)
121122import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
@@ -131,12 +132,11 @@ import qualified Streamly.Data.Array as A
131132import qualified Streamly.Data.Fold as FL
132133import qualified Streamly.Data.Stream as S
133134import qualified Streamly.Data.Unfold as UF
134−import qualified Streamly.Internal.Data.Array as A
135− (pinnedChunksOf, unsafePinnedCreateOf)
135+import qualified Streamly.Internal.Data.Array as A (pinnedChunksOf)
136136import qualified Streamly.Internal.Data.Unfold as UF (bracketIO)
137137import qualified Streamly.Internal.Data.Fold as FL (Step(..), reduce)
138138
139−import qualified Streamly.Internal.Data.Stream.Lifted as S (bracket)
139+import qualified Streamly.Internal.Data.Stream.Exception.Lifted as S (bracket)
140140import qualified Streamly.Internal.Network.Socket as ISK
141141
142142-- $setup
@@ -435,7 +435,7 @@ writeWithBufferOf
435435 -> PortNumber
436436 -> Fold m Word8 ()
437437writeWithBufferOf n addr port =
438− FL.groupsOf n (A.unsafePinnedCreateOf n) (writeChunks addr port)
438+ FL.groupsOf n (pinnedWriteNUnsafe n) (writeChunks addr port)
439439
440440-- | Write a stream to the supplied IPv4 host address and port number.
441441--
src/Streamly/Internal/Network/Socket.hs+13−16
@@ -11,7 +11,7 @@
1111--
1212module Streamly.Internal.Network.Socket
1313 (
14− SockSpec (..)
14+ SockSpec (..)
1515 -- * Use a socket
1616 , forSocketM
1717 , withSocket
@@ -87,6 +87,7 @@ import Prelude hiding (read)
8787import qualified Network.Socket as Net
8888
8989import Streamly.Internal.Data.Array (Array(..))
90+import Streamly.Internal.Data.Array.Stream (lpackArraysChunksOf)
9091import Streamly.Data.Fold (Fold)
9192import Streamly.Data.Stream (Stream)
9293import Streamly.Internal.Data.Unfold (Unfold(..))
@@ -98,11 +99,12 @@ import qualified Streamly.Data.Fold as FL
9899import qualified Streamly.Data.Stream as S
99100import qualified Streamly.Data.Unfold as UF
100101import qualified Streamly.Internal.Data.Array as A
101− ( unsafeFreeze, unsafePinnedAsPtr, byteLength, pinnedChunksOf,
102− pinnedCreateOf, unsafePinnedCreateOf, lCompactGE )
102+ ( unsafeFreeze, asPtrUnsafe, byteLength, pinnedChunksOf,
103+ pinnedWriteN, pinnedWriteNUnsafe )
103104import qualified Streamly.Internal.Data.MutArray as MArray
104− (MutArray(..), unsafePinnedAsPtr, pinnedEmptyOf)
105+ (MutArray(..), asPtrUnsafe, pinnedNewBytes)
105106import qualified Streamly.Internal.Data.Stream as S (fromStreamK, Stream(..), Step(..))
107+import qualified Streamly.Internal.Data.Unfold as UF (map)
106108import qualified Streamly.Internal.Data.StreamK as K (mkStream)
107109
108110-- $setup
@@ -138,9 +140,6 @@ withSocket sk f = S.finallyIO (Net.close sk) (f sk)
138140-- XXX Protocol specific socket options should be separated from socket level
139141-- options.
140142--
141−-- NOTE: the socket config is specified as a record and not by composing
142−-- functions because all the fields are mandatory except the sockOpts field.
143−
144143-- | Specify the socket protocol details.
145144data SockSpec = SockSpec
146145 {
@@ -184,7 +183,7 @@ listenTuples = Unfold step inject
184183--
185184{-# INLINE acceptor #-}
186185acceptor :: MonadIO m => Unfold m (Int, SockSpec, SockAddr) Socket
187−acceptor = fmap fst listenTuples
186+acceptor = UF.map fst listenTuples
188187
189188{-# INLINE connectCommon #-}
190189connectCommon :: SockSpec -> Maybe SockAddr -> SockAddr -> IO Socket
@@ -252,8 +251,6 @@ accept tcpListenQ spec addr =
252251-- Array IO (Input)
253252-------------------------------------------------------------------------------
254253
255−-- XXX add an API that compacts the arrays to an exact size.
256−
257254{-# INLINABLE readArrayUptoWith #-}
258255readArrayUptoWith
259256 :: (h -> Ptr Word8 -> Int -> IO Int)
@@ -261,9 +258,9 @@ readArrayUptoWith
261258 -> h
262259 -> IO (Array Word8)
263260readArrayUptoWith f size h = do
264− arr <- MArray.pinnedEmptyOf size
261+ arr <- MArray.pinnedNewBytes size
265262 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
266− MArray.unsafePinnedAsPtr arr $ \p -> do
263+ MArray.asPtrUnsafe arr $ \p -> do
267264 n <- f h p size
268265 let v = A.unsafeFreeze
269266 $ arr { MArray.arrEnd = n, MArray.arrBound = size }
@@ -311,7 +308,7 @@ writeArrayWith :: Unbox a
311308 -> Array a
312309 -> IO ()
313310writeArrayWith _ _ arr | A.length arr == 0 = return ()
314−writeArrayWith f h arr = A.unsafePinnedAsPtr arr $ \ptr -> f h (castPtr ptr) aLen
311+writeArrayWith f h arr = A.asPtrUnsafe arr $ \ptr -> f h (castPtr ptr) aLen
315312
316313 where
317314
@@ -474,7 +471,7 @@ writeChunks h = FL.drainMapM (liftIO . putChunk h)
474471{-# INLINE writeChunksWith #-}
475472writeChunksWith :: (MonadIO m, Unbox a)
476473 => Int -> Socket -> Fold m (Array a) ()
477−writeChunksWith n h = A.lCompactGE n (writeChunks h)
474+writeChunksWith n h = lpackArraysChunksOf n (writeChunks h)
478475
479476-- | Same as 'writeChunksWith'
480477--
@@ -505,7 +502,7 @@ putBytesWith n h m = putChunks h $ A.pinnedChunksOf n m
505502--
506503{-# INLINE writeWith #-}
507504writeWith :: MonadIO m => Int -> Socket -> Fold m Word8 ()
508−writeWith n h = FL.groupsOf n (A.unsafePinnedCreateOf n) (writeChunks h)
505+writeWith n h = FL.groupsOf n (A.pinnedWriteNUnsafe n) (writeChunks h)
509506
510507-- | Same as 'writeWith'
511508--
@@ -523,7 +520,7 @@ writeWithBufferOf = writeWith
523520writeMaybesWith :: (MonadIO m )
524521 => Int -> Socket -> Fold m (Maybe Word8) ()
525522writeMaybesWith n h =
526− let writeNJusts = FL.lmap fromJust $ A.pinnedCreateOf n
523+ let writeNJusts = FL.lmap fromJust $ A.pinnedWriteN n
527524 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
528525 in FL.many writeOnNothing (writeChunks h)
529526
src/Streamly/Internal/Unicode/Char.hs+3−3
@@ -227,13 +227,13 @@ partialComposeD (Stream step state) = Stream step' (ComposeNone state)
227227 Stop -> Skip $ YieldList rbuf ComposeStop
228228
229229 {-# INLINE initHangul #-}
230− initHangul c = ComposeJamo (Hangul c)
230+ initHangul c st = ComposeJamo (Hangul c) st
231231
232232 {-# INLINE initJamo #-}
233− initJamo c = ComposeJamo (Jamo c)
233+ initJamo c st = ComposeJamo (Jamo c) st
234234
235235 {-# INLINE initReg #-}
236− initReg !c = ComposeReg 0 [c]
236+ initReg !c st = ComposeReg 0 [c] st
237237
238238 {-# INLINE composeNone #-}
239239 composeNone ch st
src/Streamly/Network/Inet/TCP.hs−28
@@ -11,34 +11,6 @@
1111--
1212-- >>> import qualified Streamly.Network.Inet.TCP as TCP
1313--
14−-- = Examples
15−--
16−-- Following is a short example of a concurrent echo server.
17−--
18−-- >>> import Control.Monad.Catch (finally)
19−-- >>> import Data.Function ((&))
20−-- >>> import Network.Socket (Socket)
21−-- >>>
22−-- >>> import qualified Network.Socket as Net
23−-- >>> import qualified Streamly.Data.Fold as Fold
24−-- >>> import qualified Streamly.Data.Stream.Prelude as Stream
25−-- >>> import qualified Streamly.Network.Inet.TCP as TCP
26−-- >>> import qualified Streamly.Network.Socket as Socket
27−-- >>>
28−-- >>> :{
29−-- main :: IO ()
30−-- main =
31−-- TCP.accept 8091 -- Stream IO Socket
32−-- & Stream.parMapM id (handleExceptions echo) -- Stream IO ()
33−-- & Stream.fold Fold.drain -- IO ()
34−-- where
35−-- echo :: Socket -> IO ()
36−-- echo sk =
37−-- Socket.readChunksWith 32768 sk -- Stream IO (Array Word8)
38−-- & Stream.fold (Socket.writeChunks sk) -- IO ()
39−-- handleExceptions :: (Socket -> IO ()) -> Socket -> IO ()
40−-- handleExceptions f sk = finally (f sk) (Net.close sk)
41−-- :}
4214
4315module Streamly.Network.Inet.TCP
4416 (
src/Streamly/Network/Socket.hs+4−3
@@ -10,13 +10,13 @@
1010-- This module provides socket based streaming APIs to to receive connections
1111-- from remote hosts, and to read and write from and to network sockets.
1212--
13−-- For basic socket types and non-streaming operations please consult the @Network.Socket@
13+-- For basic socket types and operations please consult the @Network.Socket@
1414-- module of the <http://hackage.haskell.org/package/network network> package.
1515--
1616-- = Examples
1717--
18−-- To write a server, use the 'accept' stream to start listening for
19−-- connections from clients. 'accept' generates a stream of connected
18+-- To write a server, use the 'acceptor' unfold to start listening for
19+-- connections from clients. 'acceptor' generates a stream of connected
2020-- sockets. We can map an effectful action on this socket stream to handle the
2121-- connections. The action would typically use socket reading and writing
2222-- operations to communicate with the remote host. We can read/write a stream
@@ -33,6 +33,7 @@
3333-- >>> import Streamly.Network.Socket (SockSpec(..))
3434-- >>>
3535-- >>> import qualified Streamly.Data.Fold as Fold
36+-- >>> import qualified Streamly.Data.Stream as Stream
3637-- >>> import qualified Streamly.Data.Stream.Prelude as Stream
3738-- >>> import qualified Streamly.Network.Socket as Socket
3839-- >>>
streamly.cabal+51−68
@@ -1,14 +1,9 @@
11cabal-version: 2.2
22name: streamly
3−version: 0.10.1
3+version: 0.10.0
44synopsis: Streaming, dataflow programming and declarative concurrency
55description:
6− For upgrading to streamly-0.9.0+ please read the
7− <https://github.com/composewell/streamly/blob/streamly-0.10.0/docs/User/Project/Upgrading-0.8-to-0.9.md Streamly-0.9.0 upgrade guide>.
8− .
9− Streamly is a standard library for Haskell that focuses on C-like
10− performance, modular combinators, and streaming data flow model.
11− Streamly consists of two packages, the
6+ Streamly comprises two packages, the
127 <https://hackage.haskell.org/package/streamly-core streamly-core> package
138 provides functionality that depends only on boot libraries, and
149 the <https://hackage.haskell.org/package/streamly streamly> package
@@ -20,10 +15,10 @@ description:
2015 high-performance, concurrent, scalable applications in Haskell. Stream
2116 fusion optimizations in streamly enable exceptional modularity with
2217 high performance comparable to C. Streamly complements the Haskell
23− <https://hackage.haskell.org/package/base base> package, supplying
24− additional functionality to quickly build general-purpose applications
18+ <https://hackage.haskell.org/package/base base> package, supplying the
19+ missing functionality to quickly build general-purpose applications
2520 in Haskell. For high-level functionality built over streamly like
26− streaming OS processes, shell programming, GNU coreutils,
21+ streaming system processes, shell programming, GNU coreutils,
2722 statistics, and compression libraries please see the
2823 <https://streamly.composewell.com/ecosystem.html streamly ecosystem packages>.
2924 .
@@ -33,7 +28,6 @@ description:
3328 * API close to standard Haskell lists (<https://github.com/composewell/streamly-examples Examples>)
3429 * Declarative concurrency with automatic scaling
3530 * Filesystem, fsnotify, network, and Unicode support included
36− * Fast binary serialization (with optional JSON like features)
3731 * More functionality is provided via many (<https://streamly.composewell.com/ecosystem.html ecosystem packages>)
3832 .
3933 Unified and powerful abstractions:
@@ -42,7 +36,6 @@ description:
4236 * Unifies @Data.List@, @list-t@, and @logict@ with streaming
4337 * Unifies concurrency with standard streaming abstractions
4438 * Unifies reactive, time-domain programming with streaming
45− * Unifies binary serialization and unboxed arrays
4639 * Interworks with other streaming libraries
4740
4841homepage: https://streamly.composewell.com
@@ -174,11 +167,9 @@ extra-doc-files:
174167 docs/User/Explanatory/*.md
175168 docs/User/Explanatory/streaming-pradigms.rst
176169 docs/User/Project/*.md
177− docs/User/Project/Upgrading-0.8-to-0.9.md
178170 docs/User/Project/*.link
179− docs/User/Project/ApiChangelogs/0.8.3.txt
180171 docs/User/Project/ApiChangelogs/0.8.3-0.9.0.txt
181− docs/User/Project/ApiChangelogs/0.9.0-0.10.0.txt
172+ docs/User/Project/ApiChangelogs/0.8.3.txt
182173 test/README.md
183174 docs/Developer/Tests.md
184175
@@ -294,6 +285,8 @@ common compile-options
294285common default-extensions
295286 default-extensions:
296287 BangPatterns
288+ CApiFFI
289+ CPP
297290 ConstraintKinds
298291 DeriveDataTypeable
299292 DeriveGeneric
@@ -304,25 +297,23 @@ common default-extensions
304297 GeneralizedNewtypeDeriving
305298 InstanceSigs
306299 KindSignatures
300+ LambdaCase
301+ MagicHash
307302 MultiParamTypeClasses
303+ PatternSynonyms
308304 RankNTypes
305+ RecordWildCards
309306 ScopedTypeVariables
310307 TupleSections
311308 TypeApplications
309+ TypeFamilies
312310 TypeOperators
311+ ViewPatterns
313312
314− -- Not GHC2021
315− CApiFFI
316− CPP
317− LambdaCase
318− MagicHash
319− RecordWildCards
320−
321− -- TypeFamilies -- required by IsHashMap type class
322313 -- MonoLocalBinds, enabled by TypeFamilies, causes performance
323314 -- regressions. Disable it. This must come after TypeFamilies,
324315 -- otherwise TypeFamilies will enable it again.
325− -- NoMonoLocalBinds
316+ NoMonoLocalBinds
326317
327318 -- UndecidableInstances -- Does not show any perf impact
328319 -- UnboxedTuples -- interferes with (#.)
@@ -337,7 +328,6 @@ common optimization-options
337328 -- For this to be effective it must come after the -O2 option
338329 if flag(dev) || flag(debug) || !flag(opt)
339330 ghc-options: -fno-ignore-asserts
340− cpp-options: -DDEBUG
341331
342332common threading-options
343333 ghc-options: -threaded
@@ -373,7 +363,6 @@ library
373363 -- graphmod | dot -Tps > deps.ps
374364 Streamly.Internal.Data.IsMap.HashMap
375365 , Streamly.Internal.Data.Cont
376− , Streamly.Internal.Data.Channel
377366 , Streamly.Internal.Data.Stream.MkType
378367
379368 -- streamly-concurrent
@@ -381,10 +370,26 @@ library
381370 , Streamly.Internal.Control.ForkLifted
382371 , Streamly.Internal.Data.Atomics
383372 , Streamly.Internal.Data.IOFinalizer.Lifted
384−
385− , Streamly.Internal.Data.Stream.Prelude
386− , Streamly.Internal.Data.Unfold.Prelude
387− , Streamly.Internal.Data.Fold.Prelude
373+ , Streamly.Internal.Data.Stream.Channel.Types
374+ , Streamly.Internal.Data.Stream.Channel.Dispatcher
375+ , Streamly.Internal.Data.Stream.Channel.Worker
376+
377+ , Streamly.Internal.Data.Unfold.Exception
378+ , Streamly.Internal.Data.Fold.Concurrent.Channel.Type
379+ , Streamly.Internal.Data.Fold.Concurrent.Channel
380+ , Streamly.Internal.Data.Fold.Concurrent
381+
382+ , Streamly.Internal.Data.Stream.Concurrent.Channel.Type
383+ , Streamly.Internal.Data.Stream.Concurrent.Channel.Dispatcher
384+ , Streamly.Internal.Data.Stream.Concurrent.Channel.Consumer
385+ , Streamly.Internal.Data.Stream.Concurrent.Channel.Append
386+ , Streamly.Internal.Data.Stream.Concurrent.Channel.Interleave
387+ , Streamly.Internal.Data.Stream.Concurrent.Channel.Operations
388+ , Streamly.Internal.Data.Stream.Concurrent.Channel
389+ , Streamly.Internal.Data.Stream.Concurrent
390+ , Streamly.Internal.Data.Stream.Zip.Concurrent
391+ , Streamly.Internal.Data.Stream.Time
392+ , Streamly.Internal.Data.Stream.Exception.Lifted
388393
389394 -- streamly-unicode (depends on unicode-data)
390395 , Streamly.Internal.Unicode.Utf8
@@ -410,7 +415,12 @@ library
410415
411416 -- Deprecated Internal modules
412417 , Streamly.Internal.Data.SVar
413− , Streamly.Internal.Data.Stream.SVar
418+
419+ , Streamly.Internal.Data.Unfold.SVar
420+ , Streamly.Internal.Data.Fold.SVar
421+ , Streamly.Internal.Data.Fold.Async
422+ , Streamly.Internal.Data.Stream.SVar.Generate
423+ , Streamly.Internal.Data.Stream.SVar.Eliminate
414424
415425 , Streamly.Internal.Data.Stream.Serial
416426 , Streamly.Internal.Data.Stream.Zip
@@ -420,6 +430,9 @@ library
420430 , Streamly.Internal.Data.Stream.ZipAsync
421431
422432 , Streamly.Internal.Data.Stream.IsStream
433+ , Streamly.Internal.Data.Stream.IsStream.Combinators
434+ , Streamly.Internal.Data.Stream.IsStream.Common
435+ , Streamly.Internal.Data.Stream.IsStream.Enumeration
423436
424437 if !impl(ghcjs) && flag(dev)
425438 other-modules:
@@ -429,11 +442,9 @@ library
429442 , Streamly.Internal.FileSystem.FD
430443
431444 if flag(dev)
432− exposed-modules: Streamly.Internal.Data.SmallArray
433− -- Exposed modules show up on hackage irrespective of the flag, so keep
434− -- it hidden.
435445 other-modules: Streamly.Data.SmallArray
436− , Streamly.Internal.Data.SmallArray.Type
446+ , Streamly.Internal.Data.SmallArray
447+ , Streamly.Internal.Data.SmallArray.Type
437448
438449 if os(windows)
439450 exposed-modules: Streamly.Internal.FileSystem.Event.Windows
@@ -450,30 +461,10 @@ library
450461 exposed-modules: Streamly.Internal.FileSystem.Event
451462
452463 other-modules:
453− Streamly.Internal.Data.Channel.Types
454− , Streamly.Internal.Data.Channel.Dispatcher
455− , Streamly.Internal.Data.Channel.Worker
456−
457− , Streamly.Internal.Data.Stream.Concurrent.Channel.Type
458− , Streamly.Internal.Data.Stream.Concurrent.Channel.Dispatcher
459− , Streamly.Internal.Data.Stream.Concurrent.Channel.Consumer
460− , Streamly.Internal.Data.Stream.Concurrent.Channel.Append
461− , Streamly.Internal.Data.Stream.Concurrent.Channel.Interleave
462− , Streamly.Internal.Data.Stream.Concurrent.Channel.Operations
463− , Streamly.Internal.Data.Stream.Concurrent.Channel
464− , Streamly.Internal.Data.Stream.Concurrent
465− , Streamly.Internal.Data.Stream.Time
466− , Streamly.Internal.Data.Stream.Lifted
467−
468− , Streamly.Internal.Data.Fold.Async
469− , Streamly.Internal.Data.Fold.Concurrent.Channel.Type
470− , Streamly.Internal.Data.Fold.Concurrent.Channel
471− , Streamly.Internal.Data.Fold.Concurrent
472−
473− , Streamly.Internal.Data.Unfold.Exception
474− , Streamly.Internal.Data.Unfold.SVar
475−
476− -- Deprecated
464+ Streamly.Data.Stream.Exception
465+ , Streamly.Data.Stream.Concurrent
466+ , Streamly.Data.Stream.Time
467+
477468 , Streamly.Internal.Data.Stream.Common
478469 , Streamly.Internal.Data.Stream.IsStream.Type
479470 , Streamly.Internal.Data.Stream.IsStream.Generate
@@ -484,14 +475,6 @@ library
484475 , Streamly.Internal.Data.Stream.IsStream.Exception
485476 , Streamly.Internal.Data.Stream.IsStream.Lift
486477 , Streamly.Internal.Data.Stream.IsStream.Top
487− , Streamly.Internal.Data.Stream.IsStream.Combinators
488− , Streamly.Internal.Data.Stream.IsStream.Common
489− , Streamly.Internal.Data.Stream.IsStream.Enumeration
490−
491− , Streamly.Internal.Data.Stream.SVar.Generate
492− , Streamly.Internal.Data.Stream.SVar.Eliminate
493−
494− , Streamly.Internal.Data.Fold.SVar
495478
496479 , Streamly.Internal.Data.SVar.Worker
497480 , Streamly.Internal.Data.SVar.Dispatch
@@ -513,7 +496,7 @@ library
513496 , template-haskell >= 2.14 && < 2.22
514497
515498 -- The core streamly package
516− , streamly-core == 0.2.2
499+ , streamly-core == 0.2.0
517500
518501 , hashable >= 1.3 && < 1.5
519502 , unordered-containers >= 0.2 && < 0.3
targets/Targets.hs+1−4
@@ -187,13 +187,10 @@ targets =
187187 , ("Data.Fold.Window", [ "parser_grp", "infinite_grp" ])
188188 , ("Data.Parser", [ "parser_grp", "infinite_grp" ])
189189
190− , ("Data.Unbox", ["noTest"])
191− , ("Data.Unbox.TH", ["noBench"])
192− , ("Data.Unbox.Derive.Generic", ["noBench"])
190+ , ("Data.Unbox", [])
193191 , ("Data.Unbox.Derive.TH", [])
194192 , ("Data.Serialize", [])
195193 , ("Data.Serialize.Derive.TH", ["noBench"])
196− , ("Data.Serialize.ENABLE_constructorTagAsString", ["noBench"])
197194 , ("Data.Unfold", ["infinite_grp"])
198195 , ("FileSystem.Handle", [])
199196 , ("Unicode.Stream", [])
test/Streamly/Test/Data/Array.hs+2−2
@@ -185,7 +185,7 @@ testUnsafeIndxedFromList inp =
185185testAsPtrUnsafeMA :: IO ()
186186testAsPtrUnsafeMA = do
187187 arr <- MA.fromList ([0 .. 99] :: [Int])
188− MA.unsafePinnedAsPtr arr (getList (0 :: Int)) `shouldReturn` [0 .. 99]
188+ MA.asPtrUnsafe arr (getList (0 :: Int)) `shouldReturn` [0 .. 99]
189189
190190 where
191191
@@ -229,7 +229,7 @@ main =
229229 prop "read . write === id" testFoldUnfold
230230 prop "fromList" testFromList
231231 prop "foldMany with writeNUnsafe concats to original"
232− (foldManyWith (\n -> Fold.take n (A.unsafeCreateOf n)))
232+ (foldManyWith (\n -> Fold.take n (A.writeNUnsafe n)))
233233 describe "unsafeSlice" $ do
234234 it "partial" $ unsafeSlice 2 4 [1..10]
235235 it "none" $ unsafeSlice 10 0 [1..10]
test/Streamly/Test/Data/Fold.hs+6−7
@@ -2,8 +2,7 @@
22
33module Main (main) where
44
5−import Data.List (sort, sortBy)
6−import Data.Ord (comparing, Down(..))
5+import Data.List (sort)
76import Data.Semigroup (Sum(..), getSum)
87import Streamly.Test.Common (checkListEqual, listEquals)
98import Test.QuickCheck
@@ -413,7 +412,7 @@ partitionByM =
413412 where
414413
415414 action ls = do
416− let f x = if odd x then return (Left x) else return (Right x)
415+ let f = \x -> if odd x then return (Left x) else return (Right x)
417416 v1 <-
418417 run
419418 $ Stream.fold (Fold.partitionByM f Fold.length Fold.length)
@@ -430,7 +429,7 @@ partitionByFstM =
430429 where
431430
432431 action _ = do
433− let f x = if odd x then return (Left x) else return (Right x)
432+ let f = \x -> if odd x then return (Left x) else return (Right x)
434433 v1 <-
435434 run
436435 $ Stream.fold
@@ -448,7 +447,7 @@ partitionByMinM1 =
448447 where
449448
450449 action _ = do
451− let f x = if odd x then return (Left x) else return (Right x)
450+ let f = \x -> if odd x then return (Left x) else return (Right x)
452451 v1 <-
453452 run
454453 $ Stream.fold
@@ -466,7 +465,7 @@ partitionByMinM2 =
466465 where
467466
468467 action _ = do
469− let f x = if odd x then return (Left x) else return (Right x)
468+ let f = \x -> if odd x then return (Left x) else return (Right x)
470469 v1 <-
471470 run
472471 $ Stream.fold
@@ -691,7 +690,7 @@ topBy isTop = forAll (listOf (chooseInt (-50, 100))) $ \ls0 ->
691690 if isTop
692691 then do
693692 lst <- Stream.fold (Fold.top n) (Stream.fromList ls) >>= MArray.toList
694− assert ((Prelude.take n . sortBy (comparing Down)) ls == lst)
693+ assert ((Prelude.take n . Prelude.reverse . sort) ls == lst)
695694 else do
696695 lst <- Stream.fold (Fold.bottom n) (Stream.fromList ls) >>= MArray.toList
697696 assert ((Prelude.take n . sort) ls == lst)
test/Streamly/Test/Data/Parser.hs+4−6
@@ -198,8 +198,8 @@ takeBetweenPass =
198198 $ Prelude.take lpl ls
199199 Left _ -> property False
200200
201−_takeBetween :: Property
202−_takeBetween =
201+takeBetween :: Property
202+takeBetween =
203203 forAll (chooseInt (min_value, max_value)) $ \m ->
204204 forAll (chooseInt (min_value, max_value)) $ \n ->
205205 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
@@ -1318,10 +1318,8 @@ main =
13181318 describe "test for sequence parser" $ do
13191319 prop "P.takeBetween = Prelude.take when len >= m and len <= n"
13201320 takeBetweenPass
1321− -- XXX This test fails
1322− -- XXX cabal run test:Data.Parser -- --match "/Data.Parser/test for sequence parser/P.takeBetween = Prelude.take when len >= m and len <= n and failotherwise fail/" --seed 1563586298
1323− -- prop ("P.takeBetween = Prelude.take when len >= m and len <= n and fail"
1324− -- ++ "otherwise fail") Main._takeBetween
1321+ prop ("P.takeBetween = Prelude.take when len >= m and len <= n and fail"
1322+ ++ "otherwise fail") Main.takeBetween
13251323 prop "P.take = Prelude.take" Main.take
13261324 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
13271325 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise"
test/Streamly/Test/Data/Serialize.hs+3−34
@@ -21,8 +21,6 @@ module Streamly.Test.Data.Serialize (main) where
2121-- Imports
2222--------------------------------------------------------------------------------
2323
24−import Data.Foldable (forM_)
25−import Data.Word (Word8)
2624import System.Random (randomRIO)
2725import Streamly.Internal.Data.MutByteArray (MutByteArray)
2826import GHC.Generics (Generic)
@@ -47,10 +45,10 @@ import Test.Hspec as H
4745
4846#ifdef ENABLE_constructorTagAsString
4947#define CONF_NAME "ENABLE_constructorTagAsString"
50−#define CONF (Serialize.encodeConstrNames True)
48+#define CONF (Serialize.encodeConstrNames True Serialize.serializeConfig)
5149#else
5250#define CONF_NAME "DEFAULT"
53−#define CONF id
51+#define CONF Serialize.serializeConfig
5452#endif
5553
5654--------------------------------------------------------------------------------
@@ -109,19 +107,9 @@ $(Serialize.deriveSerializeWith
109107 CONF
110108 [d|instance Serialize a => Serialize (BinTree a)|])
111109
112−-- XXX This may not terminate, or could become really large.
113110instance Arbitrary a => Arbitrary (BinTree a) where
114111 arbitrary = oneof [Leaf <$> arbitrary, Tree <$> arbitrary <*> arbitrary]
115112
116−-- Make a balanced tree of given level
117−mkBinTree :: (Arbitrary a) => Int -> IO (BinTree a)
118−mkBinTree = go (generate arbitrary)
119−
120− where
121−
122− go r 0 = Leaf <$> r
123− go r n = Tree <$> go r (n - 1) <*> go r (n - 1)
124−
125113--------------------------------------------------------------------------------
126114-- Record syntax type
127115--------------------------------------------------------------------------------
@@ -182,18 +170,8 @@ poke val = do
182170 serStartOff = randomOff
183171 serEndOff = randomOff + sz
184172 arr <- Serialize.new arrSize
185− arr2 <- Serialize.new arrSize
186− -- Re-initialize the array with random value
187− forM_ [0..(arrSize - 1)] $ \i -> Serialize.pokeAt i arr2 (8 :: Word8)
188173
189174 off1 <- Serialize.serializeAt serStartOff arr val
190− off2 <- Serialize.serializeAt 0 arr2 val
191−
192− let slice1 = Array.Array arr serStartOff off1 :: Array.Array Word8
193− slice2 = Array.Array arr2 0 off2 :: Array.Array Word8
194− -- The serialized representation should be the same
195− slice1 `shouldBe` slice2
196−
197175 off1 `shouldBe` serEndOff
198176 pure (arr, serStartOff, serEndOff)
199177
@@ -217,10 +195,6 @@ roundtrip
217195 -> IO ()
218196roundtrip val = do
219197
220− -- For debugging large size generated by arbitrary
221− -- let sz = Serialize.addSizeTo 0 val
222− -- putStrLn $ "Size is: " ++ show sz
223−
224198 val `shouldBe` Array.deserialize (Array.pinnedSerialize val)
225199
226200 res <- poke val
@@ -284,12 +258,7 @@ testCases = do
284258 $ \(x :: [CustomDatatype]) -> roundtrip x
285259
286260 limitQC
287− $ prop "BinTree"
288− $ forAll (elements [1..15])
289− (\(x :: Int) -> do
290− (r :: BinTree Int) <- mkBinTree x
291− roundtrip r
292− )
261+ $ prop "BinTree" $ \(x :: BinTree Int) -> roundtrip x
293262
294263 where
295264
test/Streamly/Test/Data/Serialize/CompatV0.hs+2−2
@@ -29,7 +29,7 @@ instance Arbitrary a => Arbitrary (Rec a) where
2929 arbitrary = Rec <$> arbitrary <*> arbitrary <*> arbitrary
3030
3131$(Serialize.deriveSerializeWith
32− (Serialize.encodeRecordFields True)
32+ (Serialize.encodeRecordFields True Serialize.serializeConfig)
3333 [d|instance Serialize a => Serialize (Rec a)|])
3434
3535data River
@@ -42,5 +42,5 @@ instance Arbitrary River where
4242 arbitrary = elements [Ganga, Yamuna, Godavari]
4343
4444$(Serialize.deriveSerializeWith
45− (Serialize.encodeConstrNames True)
45+ (Serialize.encodeConstrNames True Serialize.serializeConfig)
4646 [d|instance Serialize River|])
test/Streamly/Test/Data/Serialize/CompatV1.hs+2−2
@@ -30,7 +30,7 @@ instance Arbitrary a => Arbitrary (Rec a) where
3030 arbitrary = Rec <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
3131
3232$(Serialize.deriveSerializeWith
33− (Serialize.encodeRecordFields True)
33+ (Serialize.encodeRecordFields True Serialize.serializeConfig)
3434 [d|instance Serialize a => Serialize (Rec a)|])
3535
3636data River
@@ -44,5 +44,5 @@ instance Arbitrary River where
4444 arbitrary = elements [Ganga, Yamuna, Godavari]
4545
4646$(Serialize.deriveSerializeWith
47− (Serialize.encodeConstrNames True)
47+ (Serialize.encodeConstrNames True Serialize.serializeConfig)
4848 [d|instance Serialize River|])
test/Streamly/Test/Data/Serialize/TH.hs+2−2
@@ -26,7 +26,7 @@ import Test.QuickCheck.Gen (oneof)
2626genDatatype :: String -> Int -> Q [Dec]
2727genDatatype tyName numCons =
2828 sequence
29− [ dataD
29+ ([ dataD
3030 (pure [])
3131 (mkName tyName)
3232 []
@@ -49,7 +49,7 @@ genDatatype tyName numCons =
4949 []
5050 ]
5151 ]
52− ]
52+ ])
5353
5454 where
5555
test/Streamly/Test/Data/Stream/Concurrent.hs+1−1
@@ -26,7 +26,7 @@ import Test.Hspec as H
2626import qualified Streamly.Data.Fold as Fold ( toList )
2727import qualified Streamly.Data.Stream as Stream
2828 ( replicate, fromEffect, fromPure, fromList, fold, take, nil )
29−import qualified Streamly.Internal.Data.Stream.Prelude as Async
29+import qualified Streamly.Internal.Data.Stream.Concurrent as Async
3030
3131import Streamly.Test.Common (listEquals)
3232
test/Streamly/Test/Data/Unbox.hs−19
@@ -20,12 +20,6 @@ module Streamly.Test.Data.Unbox (main) where
2020-- Imports
2121--------------------------------------------------------------------------------
2222
23−#ifdef USE_SERIALIZE
24−import Data.Foldable (forM_)
25−import Data.Word (Word8)
26−import qualified Streamly.Internal.Data.Array as Array
27−#endif
28−
2923import Data.Complex (Complex ((:+)))
3024import Data.Functor.Const (Const (..))
3125import Data.Functor.Identity (Identity (..))
@@ -207,19 +201,6 @@ testSerialization val = do
207201#endif
208202 arr <- MBA.new len
209203 nextOff <- POKE(0, arr, val)
210−#ifdef USE_SERIALIZE
211− arr2 <- MBA.new len
212− -- Re-initialize the array with random value
213− forM_ [0..(len - 1)] $ \i -> POKE(i, arr2, (8 :: Word8))
214− _ <- POKE(0, arr2, val)
215− let slice1 = Array.Array arr 0 len :: Array.Array Word8
216− slice2 = Array.Array arr2 0 len :: Array.Array Word8
217− -- The serialized representation should be the same
218− slice1 `shouldBe` slice2
219− -- The serialized representation is not the same for "Unbox" as the Array
220− -- might not be fully utilized in case of "Unbox". This is because different
221− -- constructors might have different lengths.
222−#endif
223204 (nextOff1, val1) <- PEEK(0, arr, len)
224205 val1 `shouldBe` val
225206 nextOff1 `shouldBe` len
test/Streamly/Test/FileSystem/Event/Common.hs+1−1
@@ -67,7 +67,7 @@ import System.IO.Temp (withSystemTempDirectory)
6767import qualified Data.List.NonEmpty as NonEmpty
6868import qualified Streamly.Internal.Data.Array as Array
6969import qualified Streamly.Internal.Data.Stream as Stream
70−import qualified Streamly.Internal.Data.Stream.Prelude as Stream
70+import qualified Streamly.Internal.Data.Stream.Concurrent as Stream
7171import qualified Streamly.Unicode.Stream as Unicode
7272
7373#if defined(FILESYSTEM_EVENT_LINUX)
test/Streamly/Test/FileSystem/Handle.hs+2−2
@@ -75,7 +75,7 @@ readFromHandle =
7575
7676readWithBufferFromHandle :: IO (Stream IO Char)
7777readWithBufferFromHandle =
78− let f1 h = (1024, h)
78+ let f1 = (\h -> (1024, h))
7979 f2 = Unicode.decodeUtf8 . Stream.unfold Handle.readerWith . f1
8080 in executor f2
8181
@@ -88,7 +88,7 @@ readChunksFromHandle =
8888
8989readChunksWithBuffer :: IO (Stream IO Char)
9090readChunksWithBuffer =
91− let f1 h = (1024, h)
91+ let f1 = (\h -> (1024, h))
9292 f2 =
9393 Unicode.decodeUtf8
9494 . Stream.concatMap Array.read
test/Streamly/Test/Prelude/Serial.hs+2−2
@@ -478,7 +478,7 @@ testTakeInterval :: IO Bool
478478testTakeInterval = do
479479 r <-
480480 S.fold (FL.tee FL.head FL.last)
481− $ S.takeInterval (fromIntegral takeDropTime * 10**(-9))
481+ $ S.takeInterval (toRelTime64 takeDropTime)
482482 $ S.repeatM (threadDelay 1000 >> getTime Monotonic)
483483 checkTakeDropTime r
484484
@@ -487,7 +487,7 @@ testDropInterval = do
487487 t0 <- getTime Monotonic
488488 mt1 <-
489489 S.fold FL.head
490− $ S.dropInterval (fromIntegral takeDropTime * 10**(-9))
490+ $ S.dropInterval (toRelTime64 takeDropTime)
491491 $ S.repeatM (threadDelay 1000 >> getTime Monotonic)
492492 checkTakeDropTime (Just t0, mt1)
493493#endif
test/Streamly/Test/Unicode/Char.hs+1−1
@@ -54,7 +54,7 @@ checkEqual opName op (mc1, mc2) = do
5454checkOp :: String -> NormalizationMode -> [(Text, Text)] -> IO Bool
5555checkOp name op pairs = do
5656 res <- mapM (checkEqual name (normalize op)) pairs
57− return $ and res
57+ return $ all (== True) res
5858
5959checkNFC :: (Text, Text, Text, Text, Text) -> IO Bool
6060checkNFC (c1, c2, c3, c4, c5) =
test/lib/Streamly/Test/Prelude/Common.hs+1−1
@@ -138,7 +138,7 @@ import Streamly.Prelude (avgRate, rate, maxBuffer, maxThreads)
138138import qualified Streamly.Prelude as S
139139import qualified Streamly.Data.Fold as FL
140140import qualified Streamly.Internal.Data.Stream.IsStream as S
141−import qualified Streamly.Internal.Data.Stream.IsStream as IS
141+import qualified Streamly.Internal.Data.Stream.IsStream.Common as IS
142142import qualified Streamly.Internal.Data.Unfold as UF
143143
144144import qualified Data.Map.Strict as Map
test/streamly-tests.cabal+7−8
@@ -216,14 +216,13 @@ common always-optimized
216216-- Test suites in sorted order
217217-------------------------------------------------------------------------------
218218
219−-- The Streamly.Data.List needs to be fixed to enable this
220−-- test-suite Data.List
221−-- import: test-options
222−-- type: exitcode-stdio-1.0
223−-- main-is: Streamly/Test/Data/List.hs
224−-- cpp-options: -DUSE_STREAMLY_LIST
225−-- if !flag(dev)
226−-- buildable: False
219+test-suite Data.List
220+ import: test-options
221+ type: exitcode-stdio-1.0
222+ main-is: Streamly/Test/Data/List.hs
223+ cpp-options: -DUSE_STREAMLY_LIST
224+ if !flag(dev)
225+ buildable: False
227226
228227test-suite Data.List.Base
229228 import: test-options