on 2ac457f help sign in
configure+9−9
since splitsnapshots
unifiedsplit
@@ -1,6 +1,6 @@
1#! /bin/sh
1#! /bin/sh
2# Guess values for system-dependent variables and create Makefiles.
2# 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.
4#
4#
5# Report bugs to <streamly@composewell.com>.
5# Report bugs to <streamly@composewell.com>.
6#
6#
@@ -610,8 +610,8 @@ MAKEFLAGS=
610# Identity of this package.
610# Identity of this package.
611PACKAGE_NAME='streamly'
611PACKAGE_NAME='streamly'
612PACKAGE_TARNAME='streamly'
612PACKAGE_TARNAME='streamly'
613−PACKAGE_VERSION='0.10.1'
613+PACKAGE_VERSION='0.10.0'
614−PACKAGE_STRING='streamly 0.10.1'
614+PACKAGE_STRING='streamly 0.10.0'
615PACKAGE_BUGREPORT='streamly@composewell.com'
615PACKAGE_BUGREPORT='streamly@composewell.com'
616PACKAGE_URL='https://streamly.composewell.com'
616PACKAGE_URL='https://streamly.composewell.com'
617
617
@@ -1224,7 +1224,7 @@ if test "$ac_init_help" = "long"; then
1224 # Omit some internal or obsolete options to make the list less imposing.
1224 # Omit some internal or obsolete options to make the list less imposing.
1225 # This message is too long to be a string in the A/UX 3.1 sh.
1225 # This message is too long to be a string in the A/UX 3.1 sh.
1226 cat <<_ACEOF
1226 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.
1228
1228
1229Usage: $0 [OPTION]... [VAR=VALUE]...
1229Usage: $0 [OPTION]... [VAR=VALUE]...
1230
1230
@@ -1286,7 +1286,7 @@ fi
1286
1286
1287if test -n "$ac_init_help"; then
1287if test -n "$ac_init_help"; then
1288 case $ac_init_help in
1288 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:";;
1290 esac
1290 esac
1291 cat <<\_ACEOF
1291 cat <<\_ACEOF
1292
1292
@@ -1372,7 +1372,7 @@ fi
1372test -n "$ac_init_help" && exit $ac_status
1372test -n "$ac_init_help" && exit $ac_status
1373if $ac_init_version; then
1373if $ac_init_version; then
1374 cat <<\_ACEOF
1374 cat <<\_ACEOF
1375−streamly configure 0.10.1
1375+streamly configure 0.10.0
1376generated by GNU Autoconf 2.71
1376generated by GNU Autoconf 2.71
1377
1377
1378Copyright (C) 2021 Free Software Foundation, Inc.
1378Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1500,7 +1500,7 @@ cat >config.log <<_ACEOF
1500This file contains any messages produced by compilers while
1500This file contains any messages produced by compilers while
1501running configure, to aid debugging if configure makes a mistake.
1501running configure, to aid debugging if configure makes a mistake.
1502
1502
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
1504generated by GNU Autoconf 2.71. Invocation command line was
1504generated by GNU Autoconf 2.71. Invocation command line was
1505
1505
1506 $ $0$ac_configure_args_raw
1506 $ $0$ac_configure_args_raw
@@ -3800,7 +3800,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
3800# report actual input values of CONFIG_FILES etc. instead of their
3800# report actual input values of CONFIG_FILES etc. instead of their
3801# values after options handling.
3801# values after options handling.
3802ac_log="
3802ac_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
3804generated by GNU Autoconf 2.71. Invocation command line was
3804generated by GNU Autoconf 2.71. Invocation command line was
3805
3805
3806 CONFIG_FILES = $CONFIG_FILES
3806 CONFIG_FILES = $CONFIG_FILES
@@ -3856,7 +3856,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
3856cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
3856cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
3857ac_cs_config='$ac_cs_config_escaped'
3857ac_cs_config='$ac_cs_config_escaped'
3858ac_cs_version="\\
3858ac_cs_version="\\
3859−streamly config.status 0.10.1
3859+streamly config.status 0.10.0
3860configured by $0, generated by GNU Autoconf 2.71,
3860configured by $0, generated by GNU Autoconf 2.71,
3861 with options \\"\$ac_cs_config\\"
3861 with options \\"\$ac_cs_config\\"
3862
3862
configure.ac+1−1
@@ -3,7 +3,7 @@
3# See https://www.gnu.org/software/autoconf/manual/autoconf.html for help on
3# See https://www.gnu.org/software/autoconf/manual/autoconf.html for help on
4# the macros used in this file.
4# the macros used in this file.
5
5
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])
7
7
8# To suppress "WARNING: unrecognized options: --with-compiler"
8# To suppress "WARNING: unrecognized options: --with-compiler"
9AC_ARG_WITH([compiler], [GHC])
9AC_ARG_WITH([compiler], [GHC])
core/configure+9−9
@@ -1,6 +1,6 @@
1#! /bin/sh
1#! /bin/sh
2# Guess values for system-dependent variables and create Makefiles.
2# 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.1.
4#
4#
5# Report bugs to <streamly@composewell.com>.
5# Report bugs to <streamly@composewell.com>.
6#
6#
@@ -610,8 +610,8 @@ MAKEFLAGS=
610# Identity of this package.
610# Identity of this package.
611PACKAGE_NAME='streamly-core'
611PACKAGE_NAME='streamly-core'
612PACKAGE_TARNAME='streamly-core'
612PACKAGE_TARNAME='streamly-core'
613−PACKAGE_VERSION='0.2.2'
613+PACKAGE_VERSION='0.2.1'
614−PACKAGE_STRING='streamly-core 0.2.2'
614+PACKAGE_STRING='streamly-core 0.2.1'
615PACKAGE_BUGREPORT='streamly@composewell.com'
615PACKAGE_BUGREPORT='streamly@composewell.com'
616PACKAGE_URL='https://streamly.composewell.com'
616PACKAGE_URL='https://streamly.composewell.com'
617
617
@@ -1256,7 +1256,7 @@ if test "$ac_init_help" = "long"; then
1256 # Omit some internal or obsolete options to make the list less imposing.
1256 # Omit some internal or obsolete options to make the list less imposing.
1257 # This message is too long to be a string in the A/UX 3.1 sh.
1257 # This message is too long to be a string in the A/UX 3.1 sh.
1258 cat <<_ACEOF
1258 cat <<_ACEOF
1259−\`configure' configures streamly-core 0.2.2 to adapt to many kinds of systems.
1259+\`configure' configures streamly-core 0.2.1 to adapt to many kinds of systems.
1260
1260
1261Usage: $0 [OPTION]... [VAR=VALUE]...
1261Usage: $0 [OPTION]... [VAR=VALUE]...
1262
1262
@@ -1318,7 +1318,7 @@ fi
1318
1318
1319if test -n "$ac_init_help"; then
1319if test -n "$ac_init_help"; then
1320 case $ac_init_help in
1320 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.1:";;
1322 esac
1322 esac
1323 cat <<\_ACEOF
1323 cat <<\_ACEOF
1324
1324
@@ -1404,7 +1404,7 @@ fi
1404test -n "$ac_init_help" && exit $ac_status
1404test -n "$ac_init_help" && exit $ac_status
1405if $ac_init_version; then
1405if $ac_init_version; then
1406 cat <<\_ACEOF
1406 cat <<\_ACEOF
1407−streamly-core configure 0.2.2
1407+streamly-core configure 0.2.1
1408generated by GNU Autoconf 2.71
1408generated by GNU Autoconf 2.71
1409
1409
1410Copyright (C) 2021 Free Software Foundation, Inc.
1410Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1622,7 +1622,7 @@ cat >config.log <<_ACEOF
1622This file contains any messages produced by compilers while
1622This file contains any messages produced by compilers while
1623running configure, to aid debugging if configure makes a mistake.
1623running configure, to aid debugging if configure makes a mistake.
1624
1624
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.1, which was
1626generated by GNU Autoconf 2.71. Invocation command line was
1626generated by GNU Autoconf 2.71. Invocation command line was
1627
1627
1628 $ $0$ac_configure_args_raw
1628 $ $0$ac_configure_args_raw
@@ -3832,7 +3832,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
3832# report actual input values of CONFIG_FILES etc. instead of their
3832# report actual input values of CONFIG_FILES etc. instead of their
3833# values after options handling.
3833# values after options handling.
3834ac_log="
3834ac_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.1, which was
3836generated by GNU Autoconf 2.71. Invocation command line was
3836generated by GNU Autoconf 2.71. Invocation command line was
3837
3837
3838 CONFIG_FILES = $CONFIG_FILES
3838 CONFIG_FILES = $CONFIG_FILES
@@ -3888,7 +3888,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
3888cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
3888cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
3889ac_cs_config='$ac_cs_config_escaped'
3889ac_cs_config='$ac_cs_config_escaped'
3890ac_cs_version="\\
3890ac_cs_version="\\
3891−streamly-core config.status 0.2.2
3891+streamly-core config.status 0.2.1
3892configured by $0, generated by GNU Autoconf 2.71,
3892configured by $0, generated by GNU Autoconf 2.71,
3893 with options \\"\$ac_cs_config\\"
3893 with options \\"\$ac_cs_config\\"
3894
3894
core/configure.ac+1−1
@@ -3,7 +3,7 @@
3# See https://www.gnu.org/software/autoconf/manual/autoconf.html for help on
3# See https://www.gnu.org/software/autoconf/manual/autoconf.html for help on
4# the macros used in this file.
4# the macros used in this file.
5
5
6−AC_INIT([streamly-core], [0.2.2], [streamly@composewell.com], [streamly-core], [https://streamly.composewell.com])
6+AC_INIT([streamly-core], [0.2.1], [streamly@composewell.com], [streamly-core], [https://streamly.composewell.com])
7
7
8# To suppress "WARNING: unrecognized options: --with-compiler"
8# To suppress "WARNING: unrecognized options: --with-compiler"
9AC_ARG_WITH([compiler], [GHC])
9AC_ARG_WITH([compiler], [GHC])
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+1−3
@@ -1,12 +1,10 @@
1# Changelog
1# Changelog
2
2
3−## 0.2.2 (Jan 2024)
3+## Unreleased
4
4
5* Add fixities `infixr 5` for `cons` and `consM` functions.
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
6* Fix a bug in Array `Eq` instance when the type is a sum type with
7 differently sized constructors.
7 differently sized constructors.
8−* lpackArraysChunksOf, compact, writeChunksWith, putChunksWith now take the
9− buffer size in number of array elements instead of bytes.
10
8
11## 0.2.1 (Dec 2023)
9## 0.2.1 (Dec 2023)
12
10
core/src/DocTestDataArray.hs−2
@@ -11,9 +11,7 @@
11
11
12>>> import qualified Streamly.Data.Array as Array
12>>> import qualified Streamly.Data.Array as Array
13>>> import qualified Streamly.Data.Fold as Fold
13>>> import qualified Streamly.Data.Fold as Fold
14−>>> import qualified Streamly.Data.ParserK as ParserK
15>>> import qualified Streamly.Data.Stream as Stream
14>>> import qualified Streamly.Data.Stream as Stream
16−>>> import qualified Streamly.Data.StreamK as StreamK
17
15
18For APIs that have not been released yet.
16For APIs that have not been released yet.
19
17
core/src/DocTestDataStream.hs−2
@@ -6,7 +6,6 @@
6>>> import Control.Monad.IO.Class (MonadIO (liftIO))
6>>> import Control.Monad.IO.Class (MonadIO (liftIO))
7>>> import Control.Monad.Trans.Class (lift)
7>>> import Control.Monad.Trans.Class (lift)
8>>> import Control.Monad.Trans.Identity (runIdentityT)
8>>> import Control.Monad.Trans.Identity (runIdentityT)
9−>>> import Data.Char (isSpace)
10>>> import Data.Either (fromLeft, fromRight, isLeft, isRight, either)
9>>> import Data.Either (fromLeft, fromRight, isLeft, isRight, either)
11>>> import Data.Maybe (fromJust, isJust)
10>>> import Data.Maybe (fromJust, isJust)
12>>> import Data.Function (fix, (&))
11>>> import Data.Function (fix, (&))
@@ -33,7 +32,6 @@ For APIs that have not been released yet.
33>>> import qualified Streamly.Internal.Data.Fold as Fold
32>>> import qualified Streamly.Internal.Data.Fold as Fold
34>>> import qualified Streamly.Internal.Data.Parser as Parser
33>>> import qualified Streamly.Internal.Data.Parser as Parser
35>>> import qualified Streamly.Internal.Data.Stream as Stream
34>>> import qualified Streamly.Internal.Data.Stream as Stream
36−>>> import qualified Streamly.Internal.Data.StreamK as StreamK
37>>> import qualified Streamly.Internal.Data.Unfold as Unfold
35>>> import qualified Streamly.Internal.Data.Unfold as Unfold
38>>> import qualified Streamly.Internal.FileSystem.Dir as Dir
36>>> import qualified Streamly.Internal.FileSystem.Dir as Dir
39-}
37-}
core/src/DocTestFileSystemHandle.hs+1−1
@@ -8,7 +8,7 @@
8
8
9For APIs that have not been released yet.
9For APIs that have not been released yet.
10
10
11−>>> import qualified Streamly.Internal.Data.Array as Array (unsafeCreateOf)
11+>>> import qualified Streamly.Internal.Data.Array as Array (writeNUnsafe)
12>>> import qualified Streamly.Internal.Data.Unfold as Unfold (first)
12>>> import qualified Streamly.Internal.Data.Unfold as Unfold (first)
13>>> import qualified Streamly.Internal.FileSystem.Handle as Handle
13>>> import qualified Streamly.Internal.FileSystem.Handle as Handle
14>>> import qualified Streamly.Internal.System.IO as IO (defaultChunkSize)
14>>> import qualified Streamly.Internal.System.IO as IO (defaultChunkSize)
core/src/Streamly/Data/Array.hs+27−30
@@ -31,42 +31,42 @@ module Streamly.Data.Array
31 -- * The Array Type
31 -- * The Array Type
32 Array
32 Array
33
33
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−
47 -- * Construction
34 -- * Construction
48 -- | When performance matters, the fastest way to generate an array is
35 -- | 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
50 -- used to conveniently construct arrays from literal values.
37 -- used to conveniently construct arrays from literal values.
51 -- 'OverloadedLists' extension or 'fromList' can be used to construct an
38 -- 'OverloadedLists' extension or 'fromList' can be used to construct an
52 -- array from a list literal. Similarly, 'OverloadedStrings' extension or
39 -- array from a list literal. Similarly, 'OverloadedStrings' extension or
53 -- 'fromList' can be used to construct an array from a string literal.
40 -- 'fromList' can be used to construct an array from a string literal.
54
41
55− -- ** From Stream
56− , createOf
57− , create
58− , writeLastN -- drop old (ring buffer)
59−
60− -- ** From List
42+ -- Pure List APIs
61 , fromListN
43 , fromListN
62 , fromList
44 , fromList
63
45
64− -- * To List
46+ -- Monadic APIs
47+ , writeN -- drop new
48+ , write -- full buffer
49+ , writeLastN -- drop old (ring buffer)
50+
51+ -- * Conversion
65 -- 'GHC.Exts.toList' from "GHC.Exts" can be used to convert an array to a
52 -- 'GHC.Exts.toList' from "GHC.Exts" can be used to convert an array to a
66 -- list.
53 -- list.
67 , toList
54 , toList
68
55
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
70 , read
70 , read
71 , readRev
71 , readRev
72
72
@@ -90,10 +90,6 @@ module Streamly.Data.Array
90 -- * Re-exports
90 -- * Re-exports
91 , Unbox (..)
91 , Unbox (..)
92 , Serialize(..)
92 , Serialize(..)
93−
94− -- * Deprecated
95− , writeN -- drop new
96− , write -- full buffer
97 )
93 )
98where
94where
99
95
@@ -126,7 +122,7 @@ import Prelude hiding (read, length)
126--
122--
127-- Convert array to stream, transform, and fold back to array:
123-- Convert array to stream, transform, and fold back to array:
128--
124--
129−-- >>> amap f arr = Array.read arr & fmap f & Stream.fold (Array.createOf (Array.length arr))
125+-- >>> amap f arr = Array.read arr & fmap f & Stream.fold Array.write
130-- >>> amap (+1) (Array.fromList [1,2,3::Int])
126-- >>> amap (+1) (Array.fromList [1,2,3::Int])
131-- fromList [2,3,4]
127-- fromList [2,3,4]
132--
128--
@@ -153,11 +149,12 @@ import Prelude hiding (read, length)
153-- See the 'fromPureStream' unreleased API to generate an array from an
149-- See the 'fromPureStream' unreleased API to generate an array from an
154-- Identity stream safely without using MonadIO constraint.
150-- Identity stream safely without using MonadIO constraint.
155--
151--
152+--
156-- Note that 'Identity' streams can be generalized to IO streams:
153-- Note that 'Identity' streams can be generalized to IO streams:
157--
154--
158−-- >>> stream = Stream.fromList [1,2,3] :: Stream Identity Int
155+-- >>> pure = Stream.fromList [1,2,3] :: Stream Identity Int
159−-- >>> pure2IO s = Stream.morphInner (return . runIdentity) s :: Stream IO Int
156+-- >>> generally = Stream.morphInner (return . runIdentity)
160−-- >>> Stream.fold Array.create (pure2IO stream)
157+-- >>> Stream.fold Array.write (generally pure :: Stream IO Int)
161-- fromList [1,2,3]
158-- fromList [1,2,3]
162--
159--
163-- == Programming Tips
160-- == Programming Tips
core/src/Streamly/Data/Array/Generic.hs+13−16
@@ -15,37 +15,34 @@ module Streamly.Data.Array.Generic
15 ( Array
15 ( Array
16
16
17 -- * Construction
17 -- * Construction
18− , fromListN
18+ , A.fromListN
19− , fromList
19+ , A.fromList
20
20
21 -- MonadicAPIs
21 -- MonadicAPIs
22− , createOf
22+ , A.writeN
23− , create
23+ , A.write
24
24
25 -- * Conversion
25 -- * Conversion
26− , toList
26+ , A.toList
27
27
28 -- * Streams
28 -- * Streams
29− , read
29+ , A.read
30− , readRev
30+ , A.readRev
31
31
32 -- * Unfolds
32 -- * Unfolds
33− , reader
33+ , A.reader
34 -- , A.readerRev
34 -- , A.readerRev
35
35
36 -- * Random Access
36 -- * Random Access
37− , length
37+ , A.length
38− , getIndex
38+ , A.getIndex
39
39
40 -- -- * Folding Arrays
40 -- -- * Folding Arrays
41 -- , A.streamFold
41 -- , A.streamFold
42 -- , A.fold
42 -- , A.fold
43−
44− -- * Deprecated
45− , writeN
46− , write
47 )
43 )
48where
44where
49
45
50−import Streamly.Internal.Data.Array.Generic
46+import Streamly.Internal.Data.Array.Generic (Array)
51−import Prelude hiding (length, read)
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
32 -- * Construction
32 -- * Construction
33
33
34 -- Uninitialized Arrays
34 -- Uninitialized Arrays
35− , emptyOf
35+ , new
36− , pinnedEmptyOf
36+ , pinnedNew
37
37
38 -- From containers
38 -- From containers
39 , fromListN
39 , fromListN
40 , fromList
40 , fromList
41− , createOf
41+ , writeN -- drop new
42− , create
42+ , write -- full buffer
43 -- writeLastN
43 -- writeLastN
44
44
45 -- * Pinning & Unpinning
45 -- * Pinning & Unpinning
@@ -51,8 +51,8 @@ module Streamly.Data.MutArray
51 , snoc
51 , snoc
52
52
53 -- * Appending streams
53 -- * Appending streams
54− , appendN
54+ , writeAppendN -- XXX Rename to writeSnocN?
55− , append
55+ , writeAppend -- XXX Rename to writeSnoc?
56
56
57 -- * Inplace mutation
57 -- * Inplace mutation
58 , putIndex
58 , putIndex
@@ -88,12 +88,6 @@ module Streamly.Data.MutArray
88
88
89 -- * Deprecated
89 -- * Deprecated
90 , newPinned
90 , newPinned
91− , new
92− , pinnedNew
93− , writeN
94− , write
95− , writeAppendN
96− , writeAppend
97 )
91 )
98where
92where
99
93
core/src/Streamly/Data/MutArray/Generic.hs+3−8
@@ -23,11 +23,11 @@ module Streamly.Data.MutArray.Generic
23 MutArray
23 MutArray
24
24
25 -- * Construction
25 -- * Construction
26− , emptyOf
26+ , new
27 , fromListN
27 , fromListN
28 , fromList
28 , fromList
29− , createOf
29+ , writeN
30− , create
30+ , write
31
31
32 -- * Appending elements
32 -- * Appending elements
33 , snoc
33 , snoc
@@ -56,11 +56,6 @@ module Streamly.Data.MutArray.Generic
56
56
57 -- * Size
57 -- * Size
58 , length
58 , length
59−
60− -- * Deprecated
61− , new
62− , writeN
63− , write
64 )
59 )
65where
60where
66
61
core/src/Streamly/Data/Stream.hs+20−129
@@ -70,15 +70,6 @@ module Streamly.Data.Stream
70
70
71 -- ** From Values
71 -- ** From Values
72 -- | Generate a monadic stream from a seed value or values.
72 -- | 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− --
82 , fromPure
73 , fromPure
83 , fromEffect
74 , fromEffect
84 , repeat
75 , repeat
@@ -221,57 +212,21 @@ module Streamly.Data.Stream
221 -- operations like mapping a function over the stream.
212 -- operations like mapping a function over the stream.
222 , foldrM
213 , foldrM
223 , foldr
214 , foldr
224− -- foldr1
225
215
226 -- ** Specific Folds
216 -- ** Specific Folds
227− -- | Streams are folded using folds in "Streamly.Data.Fold". Here are some
217+ -- | Usually you can use the folds in "Streamly.Data.Fold". However, some
228− -- idioms and equivalents of Data.List APIs using folds:
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:
229 --
222 --
230 -- >>> foldlM' f a = Stream.fold (Fold.foldlM' f a)
223 -- >>> 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)
232 -- >>> foldl' f a = Stream.fold (Fold.foldl' f a)
225 -- >>> foldl' f a = Stream.fold (Fold.foldl' f a)
233 -- >>> drain = Stream.fold Fold.drain
226 -- >>> drain = Stream.fold Fold.drain
234 -- >>> mapM_ f = Stream.fold (Fold.drainMapM f)
227 -- >>> mapM_ f = Stream.fold (Fold.drainMapM f)
235 -- >>> length = Stream.fold Fold.length
228 -- >>> length = Stream.fold Fold.length
236− -- >>> genericLength = Stream.fold Fold.lengthGeneric
237 -- >>> head = Stream.fold Fold.one
229 -- >>> 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
275 , toList
230 , toList
276
231
277 -- * Mapping
232 -- * Mapping
@@ -325,15 +280,6 @@ module Streamly.Data.Stream
325 , scan
280 , scan
326 , postscan
281 , postscan
327 -- XXX postscan1 can be implemented using Monoids or Refolds.
282 -- 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
337
283
338 -- ** Specific scans
284 -- ** Specific scans
339 -- Indexing can be considered as a special type of zipping where we zip a
285 -- Indexing can be considered as a special type of zipping where we zip a
@@ -342,8 +288,6 @@ module Streamly.Data.Stream
342
288
343 -- * Insertion
289 -- * Insertion
344 -- | Add elements to the stream.
290 -- | Add elements to the stream.
345− --
346− -- >>> insert = Stream.insertBy compare
347
291
348 -- Inserting elements is a special case of interleaving/merging streams.
292 -- Inserting elements is a special case of interleaving/merging streams.
349 , insertBy
293 , insertBy
@@ -379,15 +323,12 @@ module Streamly.Data.Stream
379 -- "Streamly.Internal.Data.Fold" can be used along with 'scanMaybe' to
323 -- "Streamly.Internal.Data.Fold" can be used along with 'scanMaybe' to
380 -- perform stateful filtering operations in general.
324 -- perform stateful filtering operations in general.
381 --
325 --
382− -- Idioms and equivalents of Data.List APIs:
326+ -- Useful idioms:
383 --
327 --
384 -- >>> deleteBy cmp x = Stream.scanMaybe (Fold.deleteBy cmp x)
328 -- >>> deleteBy cmp x = Stream.scanMaybe (Fold.deleteBy cmp x)
385− -- >>> deleteBy = Stream.deleteBy -- unreleased API
386− -- >>> delete = deleteBy (==)
387 -- >>> findIndices p = Stream.scanMaybe (Fold.findIndices p)
329 -- >>> findIndices p = Stream.scanMaybe (Fold.findIndices p)
388 -- >>> elemIndices a = findIndices (== a)
330 -- >>> elemIndices a = findIndices (== a)
389 -- >>> uniq = Stream.scanMaybe (Fold.uniqBy (==))
331 -- >>> uniq = Stream.scanMaybe (Fold.uniqBy (==))
390− -- >>> partition p = Stream.fold (Fold.partition Fold.toList Fold.toList) . fmap (if p then Left else Right)
391 , scanMaybe
332 , scanMaybe
392 , take
333 , take
393 , takeWhile
334 , takeWhile
@@ -395,8 +336,6 @@ module Streamly.Data.Stream
395 , drop
336 , drop
396 , dropWhile
337 , dropWhile
397 , dropWhileM
338 , dropWhileM
398− -- XXX write to an array in reverse and then read in reverse
399− -- > dropWhileEnd = reverse . dropWhile p . reverse
400
339
401 -- XXX These are available as scans in folds. We need to check the
340 -- XXX These are available as scans in folds. We need to check the
402 -- performance though. If these are common and we need convenient stream
341 -- performance though. If these are common and we need convenient stream
@@ -433,9 +372,6 @@ module Streamly.Data.Stream
433 -- >>> s = s1 `Stream.append` s2
372 -- >>> s = s1 `Stream.append` s2
434
373
435 -- ** Appending
374 -- ** Appending
436− -- | Equivalent of Data.List append:
437− --
438− -- >>> (++) = Stream.append
439 , append
375 , append
440
376
441 -- ** Interleaving
377 -- ** Interleaving
@@ -446,14 +382,8 @@ module Streamly.Data.Stream
446 , mergeByM
382 , mergeByM
447
383
448 -- ** Zipping
384 -- ** Zipping
449− -- | Idioms and equivalents of Data.List APIs:
450− --
451− -- >>> zip = Stream.zipWith (,)
452− -- >>> unzip = Stream.fold (Fold.unzip Fold.toList Fold.toList)
453 , zipWith
385 , zipWith
454 , zipWithM
386 , zipWithM
455− -- XXX zipWith3,4,5,6,7
456− -- XXX unzip3,4,5,6,7
457 -- , ZipStream (..)
387 -- , ZipStream (..)
458
388
459 -- ** Cross Product
389 -- ** Cross Product
@@ -486,89 +416,48 @@ module Streamly.Data.Stream
486 -- One dimension loops are just a special case of nested loops. For
416 -- One dimension loops are just a special case of nested loops. For
487 -- example, 'concatMap' can degenerate to a simple map operation:
417 -- example, 'concatMap' can degenerate to a simple map operation:
488 --
418 --
489− -- >>> map f m = Stream.concatMap (\x -> Stream.fromPure (f x)) m
419+ -- > map f m = S.concatMap (\x -> S.fromPure (f x)) m
490 --
420 --
491 -- Similarly, 'concatMap' can perform filtering by mapping an element to a
421 -- Similarly, 'concatMap' can perform filtering by mapping an element to a
492 -- 'nil' stream:
422 -- 'nil' stream:
493 --
423 --
494− -- >>> filter p m = Stream.concatMap (\x -> if p x then Stream.fromPure x else Stream.nil) m
424+ -- > filter p m = S.concatMap (\x -> if p x then S.fromPure x else S.nil) m
495− --
496− -- Idioms and equivalents of Data.List APIs:
497 --
425 --
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 " "
503
426
504 , concatEffect
427 , concatEffect
505 , concatMap
428 , concatMap
506 , concatMapM
429 , concatMapM
507
430
508 -- * Repeated Fold
431 -- * Repeated Fold
509− -- | Idioms and equivalents of Data.List APIs:
432+ -- | Useful idioms:
510 --
433 --
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)
511− -- >>> groupsOf n = Stream.foldMany (Fold.take n Fold.toList)
438+ -- >>> groupsOf n f = Stream.foldMany (Fold.take n f)
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 (==)
516 , foldMany -- XXX Rename to foldRepeat
439 , foldMany -- XXX Rename to foldRepeat
517 , groupsOf
440 , groupsOf
518 , parseMany
441 , parseMany
519
442
520 -- * Splitting
443 -- * 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)
530 , splitOn
444 , splitOn
531 , wordsBy
445 , wordsBy
532
446
533 -- * Buffered Operations
447 -- * Buffered Operations
534 -- | Operations that require buffering of the stream.
448 -- | Operations that require buffering of the stream.
535 -- Reverse is essentially a left fold followed by an unfold.
449 -- 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− --
550 , reverse
450 , 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
557
451
558 -- * Multi-Stream folds
452 -- * Multi-Stream folds
559 -- | Operations that consume multiple streams at the same time.
453 -- | Operations that consume multiple streams at the same time.
560 , eqBy
454 , eqBy
561 , cmpBy
455 , cmpBy
562 , isPrefixOf
456 , isPrefixOf
563− , isInfixOf
564− -- , isSuffixOf
565− -- , isSuffixOfUnbox
566 , isSubsequenceOf
457 , isSubsequenceOf
567
458
568 -- trimming sequences
459 -- trimming sequences
569− -- , stripPrefix
460+ , stripPrefix
570− -- , stripSuffix
571− -- , stripSuffixUnbox
572
461
573 -- Exceptions and resource management depend on the "exceptions" package
462 -- Exceptions and resource management depend on the "exceptions" package
574 -- XXX We can have IO Stream operations not depending on "exceptions"
463 -- XXX We can have IO Stream operations not depending on "exceptions"
@@ -632,8 +521,10 @@ where
632import Streamly.Internal.Data.Stream
521import Streamly.Internal.Data.Stream
633import Prelude
522import Prelude
634 hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
523 hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
524+ foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
525+ notElem, maximum, minimum, head, last, tail, length, null,
635− mapM, sequence, reverse, iterate, foldr1, repeat, replicate,
526+ reverse, iterate, init, and, or, lookup, foldr1, (!!),
636− concatMap)
527+ scanl, scanl1, repeat, replicate, concatMap, span)
637
528
638import qualified Streamly.Internal.Data.Array.Type as Array
529import qualified Streamly.Internal.Data.Array.Type as Array
639
530
core/src/Streamly/Internal/Data/Array.hs+8−393
@@ -74,16 +74,9 @@ module Streamly.Internal.Data.Array
74 , interposeSuffix
74 , interposeSuffix
75 , intercalateSuffix
75 , intercalateSuffix
76
76
77− , compactLE
78− , pinnedCompactLE
79 , compactOnByte
77 , compactOnByte
80 , compactOnByteSuffix
78 , compactOnByteSuffix
81
79
82− , foldBreakChunks
83− , foldChunks
84− , foldBreakChunksK
85− , parseBreakChunksK
86−
87 -- * Serialization
80 -- * Serialization
88 , encodeAs
81 , encodeAs
89 , serialize
82 , serialize
@@ -102,42 +95,32 @@ where
102#include "ArrayMacros.h"
95#include "ArrayMacros.h"
103
96
104import Control.Monad.IO.Class (MonadIO(..))
97import Control.Monad.IO.Class (MonadIO(..))
105−-- import Data.Bifunctor (first)
106−-- import Data.Either (fromRight)
107import Data.Functor.Identity (Identity)
98import Data.Functor.Identity (Identity)
108import Data.Proxy (Proxy(..))
99import Data.Proxy (Proxy(..))
109import Data.Word (Word8)
100import Data.Word (Word8)
110import Foreign.C.String (CString)
101import Foreign.C.String (CString)
111import Foreign.Ptr (castPtr)
102import Foreign.Ptr (castPtr)
112import Foreign.Storable (Storable)
103import Foreign.Storable (Storable)
113−import GHC.Types (SPEC(..))
114import Streamly.Internal.Data.Unbox (Unbox(..))
104import Streamly.Internal.Data.Unbox (Unbox(..))
115import Prelude hiding (length, null, last, map, (!!), read, concat)
105import Prelude hiding (length, null, last, map, (!!), read, concat)
116
106
117import Streamly.Internal.Data.MutByteArray.Type (PinnedState(..), MutByteArray)
107import Streamly.Internal.Data.MutByteArray.Type (PinnedState(..), MutByteArray)
118import Streamly.Internal.Data.Serialize.Type (Serialize)
108import Streamly.Internal.Data.Serialize.Type (Serialize)
119import Streamly.Internal.Data.Fold.Type (Fold(..))
109import Streamly.Internal.Data.Fold.Type (Fold(..))
120−import Streamly.Internal.Data.Parser (Parser(..), Initial(..), ParseError(..))
110+import Streamly.Internal.Data.Stream (Stream)
121−import Streamly.Internal.Data.Stream (Stream(..))
122−import Streamly.Internal.Data.StreamK (StreamK)
123−import Streamly.Internal.Data.SVar.Type (adaptState, defState)
111+import Streamly.Internal.Data.SVar.Type (adaptState)
124−import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3Fused'(..))
112+import Streamly.Internal.Data.Tuple.Strict (Tuple3Fused'(..))
125import Streamly.Internal.Data.Unfold.Type (Unfold(..))
113import Streamly.Internal.Data.Unfold.Type (Unfold(..))
126import Streamly.Internal.System.IO (unsafeInlineIO)
114import Streamly.Internal.System.IO (unsafeInlineIO)
127
115
128−import qualified Streamly.Internal.Data.Fold.Type as Fold
129import qualified Streamly.Internal.Data.Serialize.Type as Serialize
116import qualified Streamly.Internal.Data.Serialize.Type as Serialize
130import qualified Streamly.Internal.Data.MutByteArray.Type as MBA
117import qualified Streamly.Internal.Data.MutByteArray.Type as MBA
131import qualified Streamly.Internal.Data.MutArray as MA
118import qualified Streamly.Internal.Data.MutArray as MA
132import qualified Streamly.Internal.Data.Fold as FL
119import qualified Streamly.Internal.Data.Fold as FL
133import qualified Streamly.Internal.Data.Ring as RB
120import 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
136import qualified Streamly.Internal.Data.Stream as D
121import qualified Streamly.Internal.Data.Stream as D
137import qualified Streamly.Internal.Data.Stream as Stream
122import qualified Streamly.Internal.Data.Stream as Stream
138−import qualified Streamly.Internal.Data.StreamK as StreamK
139import qualified Streamly.Internal.Data.Unfold as Unfold
123import qualified Streamly.Internal.Data.Unfold as Unfold
140−import qualified Prelude
141
124
142import Streamly.Internal.Data.Array.Type
125import Streamly.Internal.Data.Array.Type
143
126
@@ -205,8 +188,6 @@ last = getIndexRev 0
205-- Folds with Array as the container
188-- Folds with Array as the container
206-------------------------------------------------------------------------------
189-------------------------------------------------------------------------------
207
190
208−-- XXX We should generate this from Ring.
209−
210-- | @writeLastN n@ folds a maximum of @n@ elements from the end of the input
191-- | @writeLastN n@ folds a maximum of @n@ elements from the end of the input
211-- stream to an 'Array'.
192-- stream to an 'Array'.
212--
193--
@@ -328,7 +309,6 @@ sliceIndexerFromLen from len =
328 Unfold.lmap unsafeThaw (MA.sliceIndexerFromLen from len)
309 Unfold.lmap unsafeThaw (MA.sliceIndexerFromLen from len)
329
310
330{-# DEPRECATED genSlicesFromLen "Please use sliceIndexerFromLen instead." #-}
311{-# DEPRECATED genSlicesFromLen "Please use sliceIndexerFromLen instead." #-}
331−{-# INLINE genSlicesFromLen #-}
332genSlicesFromLen :: forall m a. (Monad m, Unbox a)
312genSlicesFromLen :: forall m a. (Monad m, Unbox a)
333 => Int -- ^ from index
313 => Int -- ^ from index
334 -> Int -- ^ length of the slice
314 -> Int -- ^ length of the slice
@@ -350,7 +330,6 @@ slicerFromLen from len =
350 $ Unfold.lmap unsafeThaw (MA.slicerFromLen from len)
330 $ Unfold.lmap unsafeThaw (MA.slicerFromLen from len)
351
331
352{-# DEPRECATED getSlicesFromLen "Please use slicerFromLen instead." #-}
332{-# DEPRECATED getSlicesFromLen "Please use slicerFromLen instead." #-}
353−{-# INLINE getSlicesFromLen #-}
354getSlicesFromLen :: forall m a. (Monad m, Unbox a)
333getSlicesFromLen :: forall m a. (Monad m, Unbox a)
355 => Int -- ^ from index
334 => Int -- ^ from index
356 -> Int -- ^ length of the slice
335 -> Int -- ^ length of the slice
@@ -401,7 +380,6 @@ indexReader m =
401
380
402-- XXX DO NOT REMOVE, change the signature to use Stream instead of unfold
381-- XXX DO NOT REMOVE, change the signature to use Stream instead of unfold
403{-# DEPRECATED getIndices "Please use getIndices instead." #-}
382{-# DEPRECATED getIndices "Please use getIndices instead." #-}
404−{-# INLINE getIndices #-}
405getIndices :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
383getIndices :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
406getIndices = indexReader
384getIndices = indexReader
407
385
@@ -452,7 +430,7 @@ runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (read arr)
452streamTransform :: forall m a b. (MonadIO m, Unbox a, Unbox b)
430streamTransform :: forall m a b. (MonadIO m, Unbox a, Unbox b)
453 => (Stream m a -> Stream m b) -> Array a -> m (Array b)
431 => (Stream m a -> Stream m b) -> Array a -> m (Array b)
454streamTransform f arr =
432streamTransform f arr =
455− Stream.fold (createWith (length arr)) $ f (read arr)
433+ Stream.fold (writeWith (length arr)) $ f (read arr)
456
434
457-------------------------------------------------------------------------------
435-------------------------------------------------------------------------------
458-- Casts
436-- Casts
@@ -505,8 +483,8 @@ cast arr =
505asCStringUnsafe :: Array a -> (CString -> IO b) -> IO b
483asCStringUnsafe :: Array a -> (CString -> IO b) -> IO b
506asCStringUnsafe arr act = do
484asCStringUnsafe arr act = do
507 let arr1 = asBytes arr <> fromList [0]
485 let arr1 = asBytes arr <> fromList [0]
508− -- unsafePinnedAsPtr makes sure the array is pinned
486+ -- asPtrUnsafe makes sure the array is pinned
509− unsafePinnedAsPtr arr1 $ \ptr -> act (castPtr ptr)
487+ asPtrUnsafe arr1 $ \ptr -> act (castPtr ptr)
510
488
511-------------------------------------------------------------------------------
489-------------------------------------------------------------------------------
512-- Folds
490-- Folds
@@ -598,7 +576,7 @@ data FlattenState s =
598-- >>> interposeSuffix x = Stream.interposeSuffix x Array.reader
576-- >>> interposeSuffix x = Stream.interposeSuffix x Array.reader
599--
577--
600{-# INLINE_NORMAL interposeSuffix #-}
578{-# INLINE_NORMAL interposeSuffix #-}
601−interposeSuffix :: forall m a. (Monad m, Unbox a)
579+interposeSuffix :: forall m a. (MonadIO m, Unbox a)
602 => a -> Stream m (Array a) -> Stream m a
580 => a -> Stream m (Array a) -> Stream m a
603-- This does not require MonadIO constraint.
581-- This does not require MonadIO constraint.
604-- interposeSuffix x = D.interposeSuffix x reader
582-- interposeSuffix x = D.interposeSuffix x reader
@@ -619,7 +597,7 @@ interposeSuffix sep (D.Stream step state) = D.Stream step' (OuterLoop state)
619 return $ D.Yield sep $ OuterLoop st
597 return $ D.Yield sep $ OuterLoop st
620
598
621 step' _ (InnerLoop st contents p end) = do
599 step' _ (InnerLoop st contents p end) = do
622− x <- pure $ unsafeInlineIO $ peekAt p contents
600+ x <- liftIO $ peekAt p contents
623 return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
601 return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
624
602
625-- | Insert the given array after each array and flatten.
603-- | Insert the given array after each array and flatten.
@@ -631,24 +609,6 @@ intercalateSuffix :: (Monad m, Unbox a)
631 => Array a -> Stream m (Array a) -> Stream m a
609 => Array a -> Stream m (Array a) -> Stream m a
632intercalateSuffix = D.intercalateSuffix reader
610intercalateSuffix = D.intercalateSuffix reader
633
611
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
612-- | 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.
613-- and coalescing all the arrays between two separators into a single array.
654--
614--
@@ -671,348 +631,3 @@ compactOnByteSuffix
671 -> Stream m (Array Word8)
631 -> Stream m (Array Word8)
672compactOnByteSuffix byte =
632compactOnByteSuffix byte =
673 fmap unsafeFreeze . MA.compactOnByteSuffix byte . fmap unsafeThaw
633 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
11
11
12 -- * Construction
12 -- * Construction
13 , nil
13 , nil
14− , createOf
14+ , writeN
15− , create
15+ , write
16 , writeWith
16 , writeWith
17 , writeLastN
17 , writeLastN
18
18
@@ -44,10 +44,6 @@ module Streamly.Internal.Data.Array.Generic
44 , getIndex
44 , getIndex
45 , getSliceUnsafe
45 , getSliceUnsafe
46 , strip
46 , strip
47−
48− -- * Deprecated
49− , writeN
50− , write
51 )
47 )
52where
48where
53
49
@@ -108,33 +104,21 @@ nil = unsafePerformIO $ unsafeFreeze <$> MArray.nil
108-- Construction - Folds
104-- Construction - Folds
109-------------------------------------------------------------------------------
105-------------------------------------------------------------------------------
110
106
111−{-# INLINE_NORMAL createOf #-}
107+{-# INLINE_NORMAL writeN #-}
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 #-}
118writeN :: MonadIO m => Int -> Fold m a (Array a)
108writeN :: MonadIO m => Int -> Fold m a (Array a)
119−writeN = createOf
109+writeN = fmap unsafeFreeze <$> MArray.writeN
120
110
121{-# INLINE_NORMAL writeWith #-}
111{-# INLINE_NORMAL writeWith #-}
122writeWith :: MonadIO m => Int -> Fold m a (Array a)
112writeWith :: MonadIO m => Int -> Fold m a (Array a)
123−writeWith elemCount = unsafeFreeze <$> MArray.createWith elemCount
113+writeWith elemCount = unsafeFreeze <$> MArray.writeWith elemCount
124
114
125-- | Fold the whole input to a single array.
115-- | Fold the whole input to a single array.
126--
116--
127-- /Caution! Do not use this on infinite streams./
117-- /Caution! Do not use this on infinite streams./
128--
118--
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." #-}
135{-# INLINE write #-}
119{-# INLINE write #-}
136write :: MonadIO m => Fold m a (Array a)
120write :: MonadIO m => Fold m a (Array a)
137−write = create
121+write = fmap unsafeFreeze MArray.write
138
122
139fromPureStream :: Stream Identity a -> Array a
123fromPureStream :: Stream Identity a -> Array a
140fromPureStream x =
124fromPureStream x =
core/src/Streamly/Internal/Data/Array/Stream.hs+299−4
@@ -12,7 +12,6 @@
12-- keep this as a separate module and release it.
12-- keep this as a separate module and release it.
13--
13--
14module Streamly.Internal.Data.Array.Stream
14module Streamly.Internal.Data.Array.Stream
15−{-# DEPRECATED "Please use \"Streamly.Internal.Data.Array\" instead." #-}
16 (
15 (
17 -- * Creation
16 -- * Creation
18 Array.chunksOf
17 Array.chunksOf
@@ -96,9 +95,11 @@ import Streamly.Internal.Data.Parser (ParseError(..))
96import Streamly.Internal.Data.Stream (Stream)
95import Streamly.Internal.Data.Stream (Stream)
97import Streamly.Internal.Data.StreamK (StreamK, fromStream, toStream)
96import Streamly.Internal.Data.StreamK (StreamK, fromStream, toStream)
98import Streamly.Internal.Data.SVar.Type (adaptState, defState)
97import Streamly.Internal.Data.SVar.Type (adaptState, defState)
98+import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
99
99
100import qualified Streamly.Internal.Data.Array as A
100import qualified Streamly.Internal.Data.Array as A
101import qualified Streamly.Internal.Data.Array as Array
101import qualified Streamly.Internal.Data.Array as Array
102+import qualified Streamly.Internal.Data.Fold.Type as FL (Fold(..), Step(..))
102import qualified Streamly.Internal.Data.Parser as PR
103import qualified Streamly.Internal.Data.Parser as PR
103import qualified Streamly.Internal.Data.Parser as PRD
104import qualified Streamly.Internal.Data.Parser as PRD
104 (Parser(..), Initial(..))
105 (Parser(..), Initial(..))
@@ -180,7 +181,71 @@ splitOnSuffix = Array.compactOnByteSuffix
180{-# INLINE_NORMAL foldBreakD #-}
181{-# INLINE_NORMAL foldBreakD #-}
181foldBreakD :: forall m a b. (MonadIO m, Unbox a) =>
182foldBreakD :: forall m a b. (MonadIO m, Unbox a) =>
182 Fold m a b -> D.Stream m (Array a) -> m (b, D.Stream m (Array a))
183 Fold m a b -> D.Stream m (Array a) -> m (b, D.Stream m (Array a))
183−foldBreakD = Array.foldBreakChunks
184+foldBreakD (FL.Fold fstep initial _ final) stream@(D.Stream step state) = do
185+ res <- initial
186+ case res of
187+ FL.Partial fs -> go SPEC state fs
188+ FL.Done fb -> return $! (fb, stream)
189+
190+ where
191+
192+ {-# INLINE go #-}
193+ go !_ st !fs = do
194+ r <- step defState st
195+ case r of
196+ D.Yield (Array contents start end) s ->
197+ let fp = Tuple' end contents
198+ in goArray SPEC s fp start fs
199+ D.Skip s -> go SPEC s fs
200+ D.Stop -> do
201+ b <- final fs
202+ return (b, D.nil)
203+
204+ goArray !_ s (Tuple' end _) !cur !fs
205+ | cur == end = do
206+ go SPEC s fs
207+ goArray !_ st fp@(Tuple' end contents) !cur !fs = do
208+ x <- liftIO $ peekByteIndex cur contents
209+ res <- fstep fs x
210+ let next = INDEX_NEXT(cur,a)
211+ case res of
212+ FL.Done b -> do
213+ let arr = Array contents next end
214+ return $! (b, D.cons arr (D.Stream step st))
215+ FL.Partial fs1 -> goArray SPEC st fp next fs1
216+
217+{-# INLINE_NORMAL foldBreakK #-}
218+foldBreakK :: forall m a b. (MonadIO m, Unbox a) =>
219+ Fold m a b -> K.StreamK m (Array a) -> m (b, K.StreamK m (Array a))
220+foldBreakK (FL.Fold fstep initial _ final) stream = do
221+ res <- initial
222+ case res of
223+ FL.Partial fs -> go fs stream
224+ FL.Done fb -> return (fb, stream)
225+
226+ where
227+
228+ {-# INLINE go #-}
229+ go !fs st = do
230+ let stop = (, K.nil) <$> final fs
231+ single a = yieldk a K.nil
232+ yieldk (Array contents start end) r =
233+ let fp = Tuple' end contents
234+ in goArray fs r fp start
235+ in K.foldStream defState yieldk single stop st
236+
237+ goArray !fs st (Tuple' end _) !cur
238+ | cur == end = do
239+ go fs st
240+ goArray !fs st fp@(Tuple' end contents) !cur = do
241+ x <- liftIO $ peekByteIndex cur contents
242+ res <- fstep fs x
243+ let next = INDEX_NEXT(cur,a)
244+ case res of
245+ FL.Done b -> do
246+ let arr = Array contents next end
247+ return $! (b, K.cons arr st)
248+ FL.Partial fs1 -> goArray fs1 st fp next
184
249
185-- | Fold an array stream using the supplied 'Fold'. Returns the fold result
250-- | Fold an array stream using the supplied 'Fold'. Returns the fold result
186-- and the unconsumed stream.
251-- and the unconsumed stream.
@@ -206,7 +271,7 @@ foldBreak ::
206 => Fold m a b
271 => Fold m a b
207 -> StreamK m (A.Array a)
272 -> StreamK m (A.Array a)
208 -> m (b, StreamK m (A.Array a))
273 -> m (b, StreamK m (A.Array a))
209−foldBreak = Array.foldBreakChunksK
274+foldBreak = foldBreakK
210--
275--
211-- foldBreak f s = fmap fromStreamD <$> foldBreakD f (toStreamD s)
276-- foldBreak f s = fmap fromStreamD <$> foldBreakD f (toStreamD s)
212--
277--
@@ -270,6 +335,236 @@ splitAtArrayListRev n ls
270{-# ANN type List NoSpecConstr #-}
335{-# ANN type List NoSpecConstr #-}
271newtype List a = List {getList :: [a]}
336newtype List a = List {getList :: [a]}
272
337
338+{-
339+-- This can be generalized to any type provided it can be unfolded to a stream
340+-- and it can be combined using a semigroup operation.
341+--
342+-- XXX This should be written using CPS (as parseK) if we want it to scale wrt
343+-- to the number of times it can be called on the same stream.
344+{-# INLINE_NORMAL parseBreakD #-}
345+parseBreakD ::
346+ forall m a b. (MonadIO m, MonadThrow m, Unbox a)
347+ => PRD.Parser a m b
348+ -> D.Stream m (Array.Array a)
349+ -> m (b, D.Stream m (Array.Array a))
350+parseBreakD
351+ (PRD.Parser pstep initial extract) stream@(D.Stream step state) = do
352+
353+ res <- initial
354+ case res of
355+ PRD.IPartial s -> go SPEC state (List []) s
356+ PRD.IDone b -> return (b, stream)
357+ PRD.IError err -> throwM $ ParseError err
358+
359+ where
360+
361+ -- "backBuf" contains last few items in the stream that we may have to
362+ -- backtrack to.
363+ --
364+ -- XXX currently we are using a dumb list based approach for backtracking
365+ -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
366+ -- That will allow us more efficient random back and forth movement.
367+ go !_ st backBuf !pst = do
368+ r <- step defState st
369+ case r of
370+ D.Yield (Array contents start end) s ->
371+ gobuf SPEC s backBuf
372+ (Tuple' end contents) start pst
373+ D.Skip s -> go SPEC s backBuf pst
374+ D.Stop -> do
375+ b <- extract pst
376+ return (b, D.nil)
377+
378+ -- Use strictness on "cur" to keep it unboxed
379+ gobuf !_ s backBuf (Tuple' end _) !cur !pst
380+ | cur == end = do
381+ go SPEC s backBuf pst
382+ gobuf !_ s backBuf fp@(Tuple' end contents) !cur !pst = do
383+ x <- liftIO $ peekByteIndex contents cur
384+ pRes <- pstep pst x
385+ let next = INDEX_NEXT(cur,a)
386+ case pRes of
387+ PR.Partial 0 pst1 ->
388+ gobuf SPEC s (List []) fp next pst1
389+ PR.Partial n pst1 -> do
390+ assert (n <= Prelude.length (x:getList backBuf)) (return ())
391+ let src0 = Prelude.take n (x:getList backBuf)
392+ arr0 = A.fromListN n (Prelude.reverse src0)
393+ arr1 = Array contents next end
394+ src = arr0 <> arr1
395+ let !(Array cont1 start end1) = src
396+ fp1 = Tuple' end1 cont1
397+ gobuf SPEC s (List []) fp1 start pst1
398+ PR.Continue 0 pst1 ->
399+ gobuf SPEC s (List (x:getList backBuf)) fp next pst1
400+ PR.Continue n pst1 -> do
401+ assert (n <= Prelude.length (x:getList backBuf)) (return ())
402+ let (src0, buf1) = splitAt n (x:getList backBuf)
403+ arr0 = A.fromListN n (Prelude.reverse src0)
404+ arr1 = Array contents next end
405+ src = arr0 <> arr1
406+ let !(Array cont1 start end1) = src
407+ fp1 = Tuple' end1 cont1
408+ gobuf SPEC s (List buf1) fp1 start pst1
409+ PR.Done 0 b -> do
410+ let arr = Array contents next end
411+ return (b, D.cons arr (D.Stream step s))
412+ PR.Done n b -> do
413+ assert (n <= Prelude.length (x:getList backBuf)) (return ())
414+ let src0 = Prelude.take n (x:getList backBuf)
415+ -- XXX create the array in reverse instead
416+ arr0 = A.fromListN n (Prelude.reverse src0)
417+ arr1 = Array contents next end
418+ -- XXX Use StreamK to avoid adding arbitrary layers of
419+ -- constructors every time.
420+ str = D.cons arr0 (D.cons arr1 (D.Stream step s))
421+ return (b, str)
422+ PR.Error err -> throwM $ ParseError err
423+-}
424+
425+{-# INLINE_NORMAL parseBreakK #-}
426+parseBreakK ::
427+ forall m a b. (MonadIO m, Unbox a)
428+ => PRD.Parser a m b
429+ -> K.StreamK m (Array.Array a)
430+ -> m (Either ParseError b, K.StreamK m (Array.Array a))
431+parseBreakK (PRD.Parser pstep initial extract) stream = do
432+ res <- initial
433+ case res of
434+ PRD.IPartial s -> go s stream []
435+ PRD.IDone b -> return (Right b, stream)
436+ PRD.IError err -> return (Left (ParseError err), stream)
437+
438+ where
439+
440+ -- "backBuf" contains last few items in the stream that we may have to
441+ -- backtrack to.
442+ --
443+ -- XXX currently we are using a dumb list based approach for backtracking
444+ -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
445+ -- That will allow us more efficient random back and forth movement.
446+ go !pst st backBuf = do
447+ let stop = goStop pst backBuf -- (, K.nil) <$> extract pst
448+ single a = yieldk a K.nil
449+ yieldk arr r = goArray pst backBuf r arr
450+ in K.foldStream defState yieldk single stop st
451+
452+ -- Use strictness on "cur" to keep it unboxed
453+ goArray !pst backBuf st (Array _ cur end) | cur == end = go pst st backBuf
454+ goArray !pst backBuf st (Array contents cur end) = do
455+ x <- liftIO $ peekByteIndex cur contents
456+ pRes <- pstep pst x
457+ let next = INDEX_NEXT(cur,a)
458+ case pRes of
459+ PR.Partial 0 s ->
460+ goArray s [] st (Array contents next end)
461+ PR.Partial n s -> do
462+ assert (n <= Prelude.length (x:backBuf)) (return ())
463+ let src0 = Prelude.take n (x:backBuf)
464+ arr0 = A.fromListN n (Prelude.reverse src0)
465+ arr1 = Array contents next end
466+ src = arr0 <> arr1
467+ goArray s [] st src
468+ PR.Continue 0 s ->
469+ goArray s (x:backBuf) st (Array contents next end)
470+ PR.Continue n s -> do
471+ assert (n <= Prelude.length (x:backBuf)) (return ())
472+ let (src0, buf1) = splitAt n (x:backBuf)
473+ arr0 = A.fromListN n (Prelude.reverse src0)
474+ arr1 = Array contents next end
475+ src = arr0 <> arr1
476+ goArray s buf1 st src
477+ PR.Done 0 b -> do
478+ let arr = Array contents next end
479+ return (Right b, K.cons arr st)
480+ PR.Done n b -> do
481+ assert (n <= Prelude.length (x:backBuf)) (return ())
482+ let src0 = Prelude.take n (x:backBuf)
483+ -- XXX Use fromListRevN once implemented
484+ -- arr0 = A.fromListRevN n src0
485+ arr0 = A.fromListN n (Prelude.reverse src0)
486+ arr1 = Array contents next end
487+ str = K.cons arr0 (K.cons arr1 st)
488+ return (Right b, str)
489+ PR.Error err -> do
490+ let n = Prelude.length backBuf
491+ arr0 = A.fromListN n (Prelude.reverse backBuf)
492+ arr1 = Array contents cur end
493+ str = K.cons arr0 (K.cons arr1 stream)
494+ return (Left (ParseError err), str)
495+
496+ -- This is a simplified goArray
497+ goExtract !pst backBuf (Array _ cur end)
498+ | cur == end = goStop pst backBuf
499+ goExtract !pst backBuf (Array contents cur end) = do
500+ x <- liftIO $ peekByteIndex cur contents
501+ pRes <- pstep pst x
502+ let next = INDEX_NEXT(cur,a)
503+ case pRes of
504+ PR.Partial 0 s ->
505+ goExtract s [] (Array contents next end)
506+ PR.Partial n s -> do
507+ assert (n <= Prelude.length (x:backBuf)) (return ())
508+ let src0 = Prelude.take n (x:backBuf)
509+ arr0 = A.fromListN n (Prelude.reverse src0)
510+ arr1 = Array contents next end
511+ src = arr0 <> arr1
512+ goExtract s [] src
513+ PR.Continue 0 s ->
514+ goExtract s backBuf (Array contents next end)
515+ PR.Continue n s -> do
516+ assert (n <= Prelude.length (x:backBuf)) (return ())
517+ let (src0, buf1) = splitAt n (x:backBuf)
518+ arr0 = A.fromListN n (Prelude.reverse src0)
519+ arr1 = Array contents next end
520+ src = arr0 <> arr1
521+ goExtract s buf1 src
522+ PR.Done 0 b -> do
523+ let arr = Array contents next end
524+ return (Right b, K.fromPure arr)
525+ PR.Done n b -> do
526+ assert (n <= Prelude.length backBuf) (return ())
527+ let src0 = Prelude.take n backBuf
528+ -- XXX Use fromListRevN once implemented
529+ -- arr0 = A.fromListRevN n src0
530+ arr0 = A.fromListN n (Prelude.reverse src0)
531+ arr1 = Array contents next end
532+ str = K.cons arr0 (K.fromPure arr1)
533+ return (Right b, str)
534+ PR.Error err -> do
535+ let n = Prelude.length backBuf
536+ arr0 = A.fromListN n (Prelude.reverse backBuf)
537+ arr1 = Array contents cur end
538+ str = K.cons arr0 (K.cons arr1 stream)
539+ return (Left (ParseError err), str)
540+
541+ -- This is a simplified goExtract
542+ {-# INLINE goStop #-}
543+ goStop !pst backBuf = do
544+ pRes <- extract pst
545+ case pRes of
546+ PR.Partial _ _ -> error "Bug: parseBreak: Partial in extract"
547+ PR.Continue 0 s ->
548+ goStop s backBuf
549+ PR.Continue n s -> do
550+ assert (n <= Prelude.length backBuf) (return ())
551+ let (src0, buf1) = splitAt n backBuf
552+ arr = A.fromListN n (Prelude.reverse src0)
553+ goExtract s buf1 arr
554+ PR.Done 0 b ->
555+ return (Right b, K.nil)
556+ PR.Done n b -> do
557+ assert (n <= Prelude.length backBuf) (return ())
558+ let src0 = Prelude.take n backBuf
559+ -- XXX Use fromListRevN once implemented
560+ -- arr0 = A.fromListRevN n src0
561+ arr0 = A.fromListN n (Prelude.reverse src0)
562+ return (Right b, K.fromPure arr0)
563+ PR.Error err -> do
564+ let n = Prelude.length backBuf
565+ arr0 = A.fromListN n (Prelude.reverse backBuf)
566+ return (Left (ParseError err), K.fromPure arr0)
567+
273-- | Parse an array stream using the supplied 'Parser'. Returns the parse
568-- | Parse an array stream using the supplied 'Parser'. Returns the parse
274-- result and the unconsumed stream. Throws 'ParseError' if the parse fails.
569-- result and the unconsumed stream. Throws 'ParseError' if the parse fails.
275--
570--
@@ -293,7 +588,7 @@ parseBreak ::
293parseBreak p s =
588parseBreak p s =
294 fmap fromStreamD <$> parseBreakD (PRD.fromParserK p) (toStreamD s)
589 fmap fromStreamD <$> parseBreakD (PRD.fromParserK p) (toStreamD s)
295-}
590-}
296−parseBreak = Array.parseBreakChunksK
591+parseBreak = parseBreakK
297-- parseBreak p = K.parseBreakChunks (ParserK.adaptC p)
592-- parseBreak p = K.parseBreakChunks (ParserK.adaptC p)
298
593
299-------------------------------------------------------------------------------
594-------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Array/Type.hs+46−143
@@ -1,8 +1,4 @@
1{-# LANGUAGE CPP #-}
1{-# 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 #-}
6-- |
2-- |
7-- Module : Streamly.Internal.Data.Array.Type
3-- Module : Streamly.Internal.Data.Array.Type
8-- Copyright : (c) 2020 Composewell Technologies
4-- Copyright : (c) 2020 Composewell Technologies
@@ -32,10 +28,10 @@ module Streamly.Internal.Data.Array.Type
32 , isPinned
28 , isPinned
33
29
34 -- *** Casting
30 -- *** Casting
35− , unsafePinnedAsPtr
31+ , asPtrUnsafe
36
32
37 -- ** Construction
33 -- ** Construction
38− , empty
34+ , nil
39
35
40 -- *** Cloning
36 -- *** Cloning
41 -- XXX Why would we clone an immutable array?
37 -- XXX Why would we clone an immutable array?
@@ -49,13 +45,15 @@ module Streamly.Internal.Data.Array.Type
49
45
50 -- *** Stream Folds
46 -- *** Stream Folds
51 , unsafeMakePure
47 , unsafeMakePure
52− , createOf
48+ , writeWith
53− , pinnedCreateOf
49+ , writeN
54− , unsafeCreateOf
50+ , pinnedWriteN
55− , unsafePinnedCreateOf
51+ , writeNUnsafe
56− , create
52+ , pinnedWriteNUnsafe
57− , pinnedCreate
53+ -- , MA.ArrayUnsafe (..)
58− , createWith
54+ , pinnedWriteNAligned
55+ , write
56+ , pinnedWrite
59
57
60 -- *** From containers
58 -- *** From containers
61 , fromListN
59 , fromListN
@@ -77,8 +75,8 @@ module Streamly.Internal.Data.Array.Type
77 -- ** Reading
75 -- ** Reading
78
76
79 -- *** Indexing
77 -- *** Indexing
80− , unsafeIndexIO -- XXX unsafeGetIndexIO
78+ , unsafeIndexIO -- XXX rename to getIndexUnsafeIO
81− , getIndexUnsafe -- XXX unsafeGetIndex
79+ , getIndexUnsafe
82
80
83 -- *** To Streams
81 -- *** To Streams
84 , read
82 , read
@@ -125,14 +123,12 @@ module Streamly.Internal.Data.Array.Type
125
123
126 -- *** Compact
124 -- *** Compact
127 -- | Append the arrays in a stream to form a stream of larger arrays.
125 -- | Append the arrays in a stream to form a stream of larger arrays.
126+ , compactLE
128 , fCompactGE
127 , fCompactGE
129− , fPinnedCompactGE
130 , lCompactGE
128 , lCompactGE
131− , lPinnedCompactGE
132 , compactGE
129 , compactGE
133
130
134 -- ** Deprecated
131 -- ** Deprecated
135− , asPtrUnsafe
136 , unsafeIndex
132 , unsafeIndex
137 , bufferChunks
133 , bufferChunks
138 , flattenArrays
134 , flattenArrays
@@ -144,15 +140,6 @@ module Streamly.Internal.Data.Array.Type
144 , toStreamDRev
140 , toStreamDRev
145 , toStream
141 , toStream
146 , toStreamRev
142 , toStreamRev
147− , nil
148− , writeWith
149− , writeN
150− , pinnedWriteN
151− , writeNUnsafe
152− , pinnedWriteNUnsafe
153− , pinnedWriteNAligned
154− , write
155− , pinnedWrite
156 )
143 )
157where
144where
158
145
@@ -243,20 +230,15 @@ data Array a =
243
230
244-- | Use an @Array a@ as @Ptr a@.
231-- | Use an @Array a@ as @Ptr a@.
245--
232--
246−-- See 'MA.unsafePinnedAsPtr' in the Mutable array module for more details.
233+-- See 'MA.asPtrUnsafe' in the Mutable array module for more details.
247--
234--
248-- /Unsafe/
235-- /Unsafe/
249--
236--
250-- /Pre-release/
237-- /Pre-release/
251--
238--
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." #-}
257{-# INLINE asPtrUnsafe #-}
239{-# INLINE asPtrUnsafe #-}
258asPtrUnsafe :: MonadIO m => Array a -> (Ptr a -> m b) -> m b
240asPtrUnsafe :: MonadIO m => Array a -> (Ptr a -> m b) -> m b
259−asPtrUnsafe = unsafePinnedAsPtr
241+asPtrUnsafe arr = MA.asPtrUnsafe (unsafeThaw arr)
260
242
261-------------------------------------------------------------------------------
243-------------------------------------------------------------------------------
262-- Freezing and Thawing
244-- Freezing and Thawing
@@ -477,13 +459,12 @@ pinnedChunksOf n str = D.map unsafeFreeze $ MA.pinnedChunksOf n str
477-- >>> concat = Stream.unfoldMany Array.reader
459-- >>> concat = Stream.unfoldMany Array.reader
478--
460--
479{-# INLINE_NORMAL concat #-}
461{-# INLINE_NORMAL concat #-}
480−concat :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
462+concat :: (MonadIO m, Unbox a) => Stream m (Array a) -> Stream m a
481-- XXX this requires MonadIO whereas the unfoldMany version does not
463-- XXX this requires MonadIO whereas the unfoldMany version does not
482−concat = MA.concatWith (pure . unsafeInlineIO) . D.map unsafeThaw
464+concat = MA.concat . D.map unsafeThaw
483-- concat = D.unfoldMany reader
465-- concat = D.unfoldMany reader
484
466
485{-# DEPRECATED flattenArrays "Please use \"unfoldMany reader\" instead." #-}
467{-# DEPRECATED flattenArrays "Please use \"unfoldMany reader\" instead." #-}
486−{-# INLINE flattenArrays #-}
487flattenArrays :: forall m a. (MonadIO m, Unbox a)
468flattenArrays :: forall m a. (MonadIO m, Unbox a)
488 => D.Stream m (Array a) -> D.Stream m a
469 => D.Stream m (Array a) -> D.Stream m a
489flattenArrays = concat
470flattenArrays = concat
@@ -494,14 +475,13 @@ flattenArrays = concat
494-- >>> concatRev = Stream.unfoldMany Array.readerRev
475-- >>> concatRev = Stream.unfoldMany Array.readerRev
495--
476--
496{-# INLINE_NORMAL concatRev #-}
477{-# INLINE_NORMAL concatRev #-}
497−concatRev :: forall m a. (Monad m, Unbox a)
478+concatRev :: forall m a. (MonadIO m, Unbox a)
498 => D.Stream m (Array a) -> D.Stream m a
479 => D.Stream m (Array a) -> D.Stream m a
499-- XXX this requires MonadIO whereas the unfoldMany version does not
480-- XXX this requires MonadIO whereas the unfoldMany version does not
500−concatRev = MA.concatRevWith (pure . unsafeInlineIO) . D.map unsafeThaw
481+concatRev = MA.concatRev . D.map unsafeThaw
501-- concatRev = D.unfoldMany readerRev
482-- concatRev = D.unfoldMany readerRev
502
483
503{-# DEPRECATED flattenArraysRev "Please use \"unfoldMany readerRev\" instead." #-}
484{-# DEPRECATED flattenArraysRev "Please use \"unfoldMany readerRev\" instead." #-}
504−{-# INLINE flattenArraysRev #-}
505flattenArraysRev :: forall m a. (MonadIO m, Unbox a)
485flattenArraysRev :: forall m a. (MonadIO m, Unbox a)
506 => D.Stream m (Array a) -> D.Stream m a
486 => D.Stream m (Array a) -> D.Stream m a
507flattenArraysRev = concatRev
487flattenArraysRev = concatRev
@@ -515,28 +495,26 @@ flattenArraysRev = concatRev
515-- arrays would have no capacity to append, therefore, a copy will be forced
495-- arrays would have no capacity to append, therefore, a copy will be forced
516-- anyway.
496-- anyway.
517
497
498+-- | Scan @compactLE n@ coalesces adjacent arrays in the input stream
499+-- only if the combined size would be less than or equal to n.
500+{-# INLINE_NORMAL compactLE #-}
501+compactLE :: (MonadIO m, Unbox a)
502+ => Int -> Stream m (Array a) -> Stream m (Array a)
503+compactLE n stream =
504+ D.map unsafeFreeze $ MA.rCompactLE n $ D.map unsafeThaw stream
505+
518-- | Fold @fCompactGE n@ coalesces adjacent arrays in the input stream
506-- | Fold @fCompactGE n@ coalesces adjacent arrays in the input stream
519-- until the size becomes greater than or equal to n.
507-- until the size becomes greater than or equal to n.
520--
508--
521−-- Generates unpinned arrays irrespective of the pinning status of input
522−-- arrays.
523{-# INLINE_NORMAL fCompactGE #-}
509{-# INLINE_NORMAL fCompactGE #-}
524fCompactGE :: (MonadIO m, Unbox a) => Int -> Fold m (Array a) (Array a)
510fCompactGE :: (MonadIO m, Unbox a) => Int -> Fold m (Array a) (Array a)
525fCompactGE n = fmap unsafeFreeze $ Fold.lmap unsafeThaw $ MA.fCompactGE n
511fCompactGE n = fmap unsafeFreeze $ Fold.lmap unsafeThaw $ MA.fCompactGE n
526
512
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
513-- | @compactGE n stream@ coalesces adjacent arrays in the @stream@ until
534-- the size becomes greater than or equal to @n@.
514-- the size becomes greater than or equal to @n@.
535--
515--
536-- >>> compactGE n = Stream.foldMany (Array.fCompactGE n)
516-- >>> compactGE n = Stream.foldMany (Array.fCompactGE n)
537--
517--
538−-- Generates unpinned arrays irrespective of the pinning status of input
539−-- arrays.
540{-# INLINE compactGE #-}
518{-# INLINE compactGE #-}
541compactGE ::
519compactGE ::
542 (MonadIO m, Unbox a)
520 (MonadIO m, Unbox a)
@@ -548,21 +526,12 @@ compactGE n stream =
548--
526--
549-- >>> lCompactGE n = Fold.many (Array.fCompactGE n)
527-- >>> lCompactGE n = Fold.many (Array.fCompactGE n)
550--
528--
551−-- Generates unpinned arrays irrespective of the pinning status of input
552−-- arrays.
553{-# INLINE_NORMAL lCompactGE #-}
529{-# INLINE_NORMAL lCompactGE #-}
554lCompactGE :: (MonadIO m, Unbox a)
530lCompactGE :: (MonadIO m, Unbox a)
555 => Int -> Fold m (Array a) () -> Fold m (Array a) ()
531 => Int -> Fold m (Array a) () -> Fold m (Array a) ()
556lCompactGE n fld =
532lCompactGE n fld =
557 Fold.lmap unsafeThaw $ MA.lCompactGE n (Fold.lmap unsafeFreeze fld)
533 Fold.lmap unsafeThaw $ MA.lCompactGE n (Fold.lmap unsafeFreeze fld)
558
534
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-------------------------------------------------------------------------------
535-------------------------------------------------------------------------------
567-- Splitting
536-- Splitting
568-------------------------------------------------------------------------------
537-------------------------------------------------------------------------------
@@ -757,28 +726,17 @@ toList s = build (\c n -> toListFB c n s)
757-- Folds
726-- Folds
758-------------------------------------------------------------------------------
727-------------------------------------------------------------------------------
759
728
760−-- | @createOf n@ folds a maximum of @n@ elements from the input stream to an
729+-- | @writeN n@ folds a maximum of @n@ elements from the input stream to an
761-- 'Array'.
730-- 'Array'.
762--
731--
763−{-# INLINE_NORMAL createOf #-}
732+{-# INLINE_NORMAL writeN #-}
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 #-}
770writeN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
733writeN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
771−writeN = createOf
734+writeN = fmap unsafeFreeze . MA.writeN
772
735
773−-- | Like 'createOf' but creates a pinned array.
736+-- | Like 'fromListN' 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
777−
778−{-# DEPRECATED pinnedWriteN "Please use pinnedCreateOf instead." #-}
779−{-# INLINE pinnedWriteN #-}
737+{-# INLINE_NORMAL pinnedWriteN #-}
780pinnedWriteN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
738pinnedWriteN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
781−pinnedWriteN = pinnedCreateOf
739+pinnedWriteN = fmap unsafeFreeze . MA.pinnedWriteN
782
740
783-- | @pinnedWriteNAligned alignment n@ folds a maximum of @n@ elements from the input
741-- | @pinnedWriteNAligned alignment n@ folds a maximum of @n@ elements from the input
784-- stream to an 'Array' aligned to the given size.
742-- stream to an 'Array' aligned to the given size.
@@ -786,74 +744,44 @@ pinnedWriteN = pinnedCreateOf
786-- /Pre-release/
744-- /Pre-release/
787--
745--
788{-# INLINE_NORMAL pinnedWriteNAligned #-}
746{-# INLINE_NORMAL pinnedWriteNAligned #-}
789−{-# DEPRECATED pinnedWriteNAligned "To be removed." #-}
790pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a)
747pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a)
791 => Int -> Int -> Fold m a (Array a)
748 => Int -> Int -> Fold m a (Array a)
792pinnedWriteNAligned alignSize = fmap unsafeFreeze . MA.pinnedWriteNAligned alignSize
749pinnedWriteNAligned alignSize = fmap unsafeFreeze . MA.pinnedWriteNAligned alignSize
793
750
794−-- | Like 'createOf' but does not check the array bounds when writing. The fold
751+-- | Like 'writeN' but does not check the array bounds when writing. The fold
795-- driver must not call the step function more than 'n' times otherwise it will
752-- driver must not call the step function more than 'n' times otherwise it will
796-- corrupt the memory and crash. This function exists mainly because any
753-- corrupt the memory and crash. This function exists mainly because any
797-- conditional in the step function blocks fusion causing 10x performance
754-- conditional in the step function blocks fusion causing 10x performance
798-- slowdown.
755-- slowdown.
799--
756--
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 #-}
757+{-# INLINE_NORMAL writeNUnsafe #-}
807writeNUnsafe :: forall m a. (MonadIO m, Unbox a)
758writeNUnsafe :: forall m a. (MonadIO m, Unbox a)
808 => Int -> Fold m a (Array a)
759 => Int -> Fold m a (Array a)
809−writeNUnsafe = unsafeCreateOf
760+writeNUnsafe n = unsafeFreeze <$> MA.writeNUnsafe n
810−
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
761
816−{-# DEPRECATED pinnedWriteNUnsafe "Please use unsafePinnedCreateOf instead." #-}
817−{-# INLINE pinnedWriteNUnsafe #-}
762+{-# INLINE_NORMAL pinnedWriteNUnsafe #-}
818pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a)
763pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a)
819 => Int -> Fold m a (Array a)
764 => Int -> Fold m a (Array a)
820−pinnedWriteNUnsafe = unsafePinnedCreateOf
765+pinnedWriteNUnsafe n = unsafeFreeze <$> MA.pinnedWriteNUnsafe n
821
766
822−{-# INLINE_NORMAL createWith #-}
767+{-# INLINE_NORMAL writeWith #-}
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 #-}
830writeWith :: forall m a. (MonadIO m, Unbox a)
768writeWith :: forall m a. (MonadIO m, Unbox a)
831 => Int -> Fold m a (Array a)
769 => Int -> Fold m a (Array a)
832−writeWith = createWith
770+-- writeWith n = FL.rmapM spliceArrays $ toArraysOf n
771+writeWith elemCount = unsafeFreeze <$> MA.writeWith elemCount
833
772
834-- | Fold the whole input to a single array.
773-- | Fold the whole input to a single array.
835--
774--
836-- /Caution! Do not use this on infinite streams./
775-- /Caution! Do not use this on infinite streams./
837--
776--
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." #-}
844{-# INLINE write #-}
777{-# INLINE write #-}
845write :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
778write :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
846−write = create
779+write = fmap unsafeFreeze MA.write
847
780
848−-- | Like 'create' but creates a pinned array.
781+-- | Like 'write' 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." #-}
854{-# INLINE pinnedWrite #-}
782{-# INLINE pinnedWrite #-}
855pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
783pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
856−pinnedWrite = pinnedCreate
784+pinnedWrite = fmap unsafeFreeze MA.pinnedWrite
857
785
858-- | Fold "step" has a dependency on "initial", and each step is dependent on
786-- | Fold "step" has a dependency on "initial", and each step is dependent on
859-- the previous invocation of step due to state passing, finally extract
787-- the previous invocation of step due to state passing, finally extract
@@ -901,19 +829,13 @@ fromPureStream x = unsafePerformIO $ fmap (unsafeFreeze) (MA.fromPureStream x)
901-- fromPureStream = runIdentity . D.fold (unsafeMakePure write)
829-- fromPureStream = runIdentity . D.fold (unsafeMakePure write)
902-- fromPureStream = fromList . runIdentity . D.toList
830-- fromPureStream = fromList . runIdentity . D.toList
903
831
904−-- XXX This should be monadic.
905−
906-- | Copy an immutable 'Ptr Word8' sequence into an array.
832-- | Copy an immutable 'Ptr Word8' sequence into an array.
907--
833--
908-- /Unsafe:/ The caller is responsible for safe addressing.
834-- /Unsafe:/ The caller is responsible for safe addressing.
909--
835--
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.
912fromPtrN :: Int -> Ptr Word8 -> Array Word8
836fromPtrN :: Int -> Ptr Word8 -> Array Word8
913fromPtrN n addr = unsafePerformIO $ fmap unsafeFreeze (MA.fromPtrN n addr)
837fromPtrN n addr = unsafePerformIO $ fmap unsafeFreeze (MA.fromPtrN n addr)
914
838
915−-- XXX This should be monadic.
916−
917-- | Copy a null terminated immutable 'Addr#' Word8 sequence into an array.
839-- | Copy a null terminated immutable 'Addr#' Word8 sequence into an array.
918--
840--
919-- /Unsafe:/ The caller is responsible for safe addressing.
841-- /Unsafe:/ The caller is responsible for safe addressing.
@@ -924,15 +846,9 @@ fromPtrN n addr = unsafePerformIO $ fmap unsafeFreeze (MA.fromPtrN n addr)
924-- >>> Array.toList $ Array.fromByteStr# "\1\2\3\0"#
846-- >>> Array.toList $ Array.fromByteStr# "\1\2\3\0"#
925-- [1,2,3]
847-- [1,2,3]
926--
848--
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.
929fromByteStr# :: Addr# -> Array Word8
849fromByteStr# :: Addr# -> Array Word8
930fromByteStr# addr = unsafePerformIO $ fmap unsafeFreeze (MA.fromByteStr# addr)
850fromByteStr# addr = unsafePerformIO $ fmap unsafeFreeze (MA.fromByteStr# addr)
931
851
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.
936fromByteStr :: Ptr Word8 -> Array Word8
852fromByteStr :: Ptr Word8 -> Array Word8
937fromByteStr (Ptr addr#) = fromByteStr# addr#
853fromByteStr (Ptr addr#) = fromByteStr# addr#
938
854
@@ -1029,16 +945,11 @@ MK_EQ_INSTANCE(Char)
1029MK_EQ_INSTANCE(Word8)
945MK_EQ_INSTANCE(Word8)
1030MK_EQ_INSTANCE(Word16)
946MK_EQ_INSTANCE(Word16)
1031MK_EQ_INSTANCE(Word32)
947MK_EQ_INSTANCE(Word32)
1032−
1033−-- XXX The Word64 default instance should be as fast because we are comparing
1034−-- 64-bit at a time.
1035MK_EQ_INSTANCE(Word64)
948MK_EQ_INSTANCE(Word64)
1036MK_EQ_INSTANCE(Int)
949MK_EQ_INSTANCE(Int)
1037MK_EQ_INSTANCE(Int8)
950MK_EQ_INSTANCE(Int8)
1038MK_EQ_INSTANCE(Int16)
951MK_EQ_INSTANCE(Int16)
1039MK_EQ_INSTANCE(Int32)
952MK_EQ_INSTANCE(Int32)
1040−
1041−-- XXX The Int64 default instance should be as fast.
1042MK_EQ_INSTANCE(Int64)
953MK_EQ_INSTANCE(Int64)
1043
954
1044-- | If the type allows a byte-by-byte comparison this instance can be
955-- | If the type allows a byte-by-byte comparison this instance can be
@@ -1128,20 +1039,12 @@ instance Foldable Array where
1128instance Unbox a => Semigroup (Array a) where
1039instance Unbox a => Semigroup (Array a) where
1129 arr1 <> arr2 = unsafePerformIO $ splice arr1 arr2
1040 arr1 <> arr2 = unsafePerformIO $ splice arr1 arr2
1130
1041
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." #-}
1139nil ::
1042nil ::
1140#ifdef DEVBUILD
1043#ifdef DEVBUILD
1141 Unbox a =>
1044 Unbox a =>
1142#endif
1045#endif
1143 Array a
1046 Array a
1144−nil = empty
1047+nil = Array Unboxed.nil 0 0
1145
1048
1146instance Unbox a => Monoid (Array a) where
1049instance Unbox a => Monoid (Array a) where
1147 mempty = nil
1050 mempty = nil
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 #-}
5-- |
1-- |
6-- Module : Streamly.Internal.Data.IsMap
2-- Module : Streamly.Internal.Data.IsMap
7-- Copyright : (c) 2022 Composewell Technologies
3-- Copyright : (c) 2022 Composewell Technologies
core/src/Streamly/Internal/Data/MutArray.hs+3−24
@@ -14,7 +14,6 @@ module Streamly.Internal.Data.MutArray
14 , sliceIndexerFromLen
14 , sliceIndexerFromLen
15 , slicerFromLen
15 , slicerFromLen
16 , compactLE
16 , compactLE
17− , pinnedCompactLE
18 , compactOnByte
17 , compactOnByte
19 , compactOnByteSuffix
18 , compactOnByteSuffix
20 -- * Unboxed IORef
19 -- * Unboxed IORef
@@ -30,7 +29,6 @@ where
30
29
31import Control.Monad.IO.Class (MonadIO(..))
30import Control.Monad.IO.Class (MonadIO(..))
32import Data.Word (Word8)
31import Data.Word (Word8)
33−import Streamly.Internal.Data.MutByteArray.Type (PinnedState(..))
34import Streamly.Internal.Data.Stream.Type (Stream)
32import Streamly.Internal.Data.Stream.Type (Stream)
35import Streamly.Internal.Data.Unbox (Unbox)
33import Streamly.Internal.Data.Unbox (Unbox)
36import Streamly.Internal.Data.Unfold.Type (Unfold(..))
34import Streamly.Internal.Data.Unfold.Type (Unfold(..))
@@ -89,34 +87,15 @@ getSlicesFromLen :: forall m a. (Monad m, Unbox a)
89 -> Unfold m (MutArray a) (MutArray a)
87 -> Unfold m (MutArray a) (MutArray a)
90getSlicesFromLen = slicerFromLen
88getSlicesFromLen = slicerFromLen
91
89
92−-------------------------------------------------------------------------------
93−-- Compacting Streams of Arrays
94−-------------------------------------------------------------------------------
95−
96−-- | @compactLE maxElems@ coalesces adjacent arrays in the input stream
90+-- | Scan @compactLE n@ coalesces adjacent arrays in the input stream
97−-- only if the combined size would be less than or equal to @maxElems@
91+-- only if the combined size would be less than or equal to n.
98−-- elements. Note that it won't split an array if the original array is already
99−-- larger than maxElems.
100−--
101−-- @maxElems@ must be greater than 0.
102−--
103−-- Generates unpinned arrays irrespective of the pinning status of input
104−-- arrays.
105{-# INLINE compactLE #-}
92{-# INLINE compactLE #-}
106compactLE :: (MonadIO m, Unbox a) =>
93compactLE :: (MonadIO m, Unbox a) =>
107 Int -> Stream m (MutArray a) -> Stream m (MutArray a)
94 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
95-- XXX compactLE can be moved to MutArray/Type if we are not using the parser
109-- to implement it.
96-- 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)
97-- compactLE n = Stream.catRights . Stream.parseManyD (pCompactLE n)
113−
114−-- | Pinned version of 'compactLE'.
98+compactLE = rCompactLE
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
99
121data SplitState s arr
100data SplitState s arr
122 = Initial s
101 = Initial s
core/src/Streamly/Internal/Data/MutArray/Generic.hs+24−59
@@ -19,14 +19,14 @@ module Streamly.Internal.Data.MutArray.Generic
19 , nil
19 , nil
20
20
21 -- *** Uninitialized Arrays
21 -- *** Uninitialized Arrays
22− , emptyOf
22+ , new
23 -- , newArrayWith
23 -- , newArrayWith
24
24
25 -- *** From streams
25 -- *** From streams
26− , unsafeCreateOf
26+ , writeNUnsafe
27− , createOf
27+ , writeN
28− , createWith -- createOfMin/createMin/createGE?
28+ , writeWith
29− , create
29+ , write
30 , fromStreamN
30 , fromStreamN
31 , fromStream
31 , fromStream
32 , fromPureStream
32 , fromPureStream
@@ -160,13 +160,6 @@ module Streamly.Internal.Data.MutArray.Generic
160 -- , appendSliceFrom
160 -- , appendSliceFrom
161
161
162 , clone
162 , clone
163−
164− -- * Deprecated
165− , new
166− , writeNUnsafe
167− , writeN
168− , writeWith
169− , write
170 )
163 )
171where
164where
172
165
@@ -243,13 +236,13 @@ bottomElement =
243-- XXX Would be nice if GHC can provide something like newUninitializedArray# so
236-- XXX Would be nice if GHC can provide something like newUninitializedArray# so
244-- that we do not have to write undefined or error in the whole array.
237-- that we do not have to write undefined or error in the whole array.
245
238
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
247-- up to 'count' items without reallocating.
240-- up to 'count' items without reallocating.
248--
241--
249-- /Pre-release/
242-- /Pre-release/
250−{-# INLINE emptyOf #-}
243+{-# INLINE new #-}
251−emptyOf :: MonadIO m => Int -> m (MutArray a)
244+new :: MonadIO m => Int -> m (MutArray a)
252−emptyOf n@(I# n#) =
245+new n@(I# n#) =
253 liftIO
246 liftIO
254 $ IO
247 $ IO
255 $ \s# ->
248 $ \s# ->
@@ -258,12 +251,6 @@ emptyOf n@(I# n#) =
258 let ma = MutArray arr# 0 0 n
251 let ma = MutArray arr# 0 0 n
259 in (# s1#, ma #)
252 in (# s1#, ma #)
260
253
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−
267-- XXX This could be pure?
254-- XXX This could be pure?
268
255
269-- |
256-- |
@@ -602,16 +589,16 @@ readRev arr@MutArray{..} =
602arrayChunkSize :: Int
589arrayChunkSize :: Int
603arrayChunkSize = 1024
590arrayChunkSize = 1024
604
591
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
606-- driver must not call the step function more than 'n' times otherwise it will
593-- driver must not call the step function more than 'n' times otherwise it will
607-- corrupt the memory and crash. This function exists mainly because any
594-- corrupt the memory and crash. This function exists mainly because any
608-- conditional in the step function blocks fusion causing 10x performance
595-- conditional in the step function blocks fusion causing 10x performance
609-- slowdown.
596-- slowdown.
610--
597--
611-- /Pre-release/
598-- /Pre-release/
612−{-# INLINE_NORMAL unsafeCreateOf #-}
599+{-# INLINE_NORMAL writeNUnsafe #-}
613−unsafeCreateOf :: MonadIO m => Int -> Fold m a (MutArray a)
600+writeNUnsafe :: MonadIO m => Int -> Fold m a (MutArray a)
614−unsafeCreateOf n = Fold step initial return return
601+writeNUnsafe n = Fold step initial return return
615
602
616 where
603 where
617
604
@@ -619,47 +606,36 @@ unsafeCreateOf n = Fold step initial return return
619
606
620 step arr x = FL.Partial <$> snocUnsafe arr x
607 step arr x = FL.Partial <$> snocUnsafe arr x
621
608
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
628-- 'Array'.
610-- 'Array'.
629--
611--
630−-- >>> createOf n = Fold.take n (MutArray.unsafeCreateOf n)
612+-- >>> writeN n = Fold.take n (MutArray.writeNUnsafe n)
631--
613--
632-- /Pre-release/
614-- /Pre-release/
633−{-# INLINE_NORMAL createOf #-}
615+{-# INLINE_NORMAL writeN #-}
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 #-}
640writeN :: MonadIO m => Int -> Fold m a (MutArray a)
616writeN :: MonadIO m => Int -> Fold m a (MutArray a)
641−writeN = createOf
617+writeN n = FL.take n $ writeNUnsafe n
642
618
643-- >>> f n = MutArray.writeAppendWith (* 2) (MutArray.pinnedNew n)
619-- >>> f n = MutArray.writeAppendWith (* 2) (MutArray.pinnedNew n)
644-- >>> writeWith n = Fold.rmapM MutArray.rightSize (f n)
620-- >>> writeWith n = Fold.rmapM MutArray.rightSize (f n)
645-- >>> writeWith n = Fold.rmapM MutArray.fromArrayStreamK (MutArray.writeChunks n)
621-- >>> writeWith n = Fold.rmapM MutArray.fromArrayStreamK (MutArray.writeChunks n)
646
622
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
648-- starts at a size big enough to hold minCount elements, the size is doubled
624-- starts at a size big enough to hold minCount elements, the size is doubled
649-- every time the array needs to be grown.
625-- every time the array needs to be grown.
650--
626--
651-- /Caution! Do not use this on infinite streams./
627-- /Caution! Do not use this on infinite streams./
652--
628--
653-- /Pre-release/
629-- /Pre-release/
654−{-# INLINE_NORMAL createWith #-}
630+{-# INLINE_NORMAL writeWith #-}
655−createWith :: MonadIO m => Int -> Fold m a (MutArray a)
631+writeWith :: MonadIO m => Int -> Fold m a (MutArray a)
656-- writeWith n = FL.rmapM rightSize $ writeAppendWith (* 2) (pinnedNew n)
632-- 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
658
634
659 where
635 where
660
636
661 initial = do
637 initial = do
662− when (elemCount < 0) $ error "createWith: elemCount is negative"
638+ when (elemCount < 0) $ error "writeWith: elemCount is negative"
663 new elemCount
639 new elemCount
664
640
665 step arr@(MutArray _ start end bound) x
641 step arr@(MutArray _ start end bound) x
@@ -673,27 +649,16 @@ createWith elemCount = FL.rmapM extract $ FL.foldlM' step initial
673 -- extract = rightSize
649 -- extract = rightSize
674 extract = return
650 extract = return
675
651
676−{-# DEPRECATED writeWith "Please use createWith instead." #-}
677−{-# INLINE writeWith #-}
678−writeWith :: MonadIO m => Int -> Fold m a (MutArray a)
679−writeWith = createWith
680−
681-- | Fold the whole input to a single array.
652-- | Fold the whole input to a single array.
682--
653--
683−-- Same as 'createWith' using an initial array size of 'arrayChunkSize' bytes
654+-- Same as 'writeWith' using an initial array size of 'arrayChunkSize' bytes
684-- rounded up to the element size.
655-- rounded up to the element size.
685--
656--
686-- /Caution! Do not use this on infinite streams./
657-- /Caution! Do not use this on infinite streams./
687--
658--
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." #-}
694{-# INLINE write #-}
659{-# INLINE write #-}
695write :: MonadIO m => Fold m a (MutArray a)
660write :: MonadIO m => Fold m a (MutArray a)
696−write = create
661+write = writeWith arrayChunkSize
697
662
698-- | Create a 'MutArray' from the first @n@ elements of a stream. The
663-- | Create a 'MutArray' from the first @n@ elements of a stream. The
699-- array is allocated to size @n@, if the stream terminates before @n@
664-- array is allocated to size @n@, if the stream terminates before @n@
core/src/Streamly/Internal/Data/MutArray/Type.hs+285−657
@@ -40,22 +40,22 @@ module Streamly.Internal.Data.MutArray.Type
40
40
41 -- ** Casting
41 -- ** Casting
42 , cast
42 , cast
43− , castUnsafe -- XXX unsafeCast
43+ , castUnsafe
44 , asBytes
44 , asBytes
45− , unsafePinnedAsPtr
45+ , asPtrUnsafe
46− , unsafeAsPtr
46+ , asUnpinnedPtrUnsafe
47
47
48 -- ** Construction
48 -- ** Construction
49− , empty
49+ , nil
50
50
51 -- *** New
51 -- *** New
52 -- | New arrays are always empty arrays with some reserve capacity to
52 -- | New arrays are always empty arrays with some reserve capacity to
53 -- extend the length without reallocating.
53 -- extend the length without reallocating.
54− , emptyOf
54+ , new
55− , newArrayWith -- emptyAlignedWith
55+ , newArrayWith
56− , pinnedEmptyOf
56+ , pinnedNew
57+ , pinnedNewBytes
57− , pinnedNewAligned -- XXX not required
58+ , pinnedNewAligned
58− -- , new -- uninitialized array of specified length
59
59
60 -- *** Cloning
60 -- *** Cloning
61 , clone
61 , clone
@@ -63,25 +63,27 @@ module Streamly.Internal.Data.MutArray.Type
63
63
64 -- *** Slicing
64 -- *** Slicing
65 -- | Get a subarray without copying
65 -- | Get a subarray without copying
66− , getSliceUnsafe -- XXX unsafeGetSlice
66+ , getSliceUnsafe
67 , getSlice
67 , getSlice
68 , splitAt -- XXX should be able to express using getSlice
68 , splitAt -- XXX should be able to express using getSlice
69 , breakOn
69 , breakOn
70
70
71 -- *** Stream Folds
71 -- *** Stream Folds
72 , ArrayUnsafe (..)
72 , ArrayUnsafe (..)
73− , unsafeCreateOfWith
73+ , writeNWithUnsafe
74− , unsafeCreateOf
74+ , writeNWith
75− , unsafePinnedCreateOf
75+ , writeNUnsafe
76− , pinnedCreateOf
76+ , pinnedWriteNUnsafe
77− , createOfWith
77+ , writeN
78− , createOf
78+ , pinnedWriteN
79− , revCreateOf
79+ , pinnedWriteNAligned
80−
80+
81− , pinnedCreate
81+ , writeWith
82− , createWith
82+ , write
83− , create
83+ , pinnedWrite
84− -- , revCreate
84+
85+ , writeRevN
86+ -- , writeRev
85
87
86 -- *** From containers
88 -- *** From containers
87 , fromListN
89 , fromListN
@@ -97,11 +99,11 @@ module Streamly.Internal.Data.MutArray.Type
97 , fromByteStr#
99 , fromByteStr#
98 , fromPtrN
100 , fromPtrN
99 , fromChunksK
101 , fromChunksK
100− , fromChunksRealloced -- fromSmallChunks
102+ , fromChunksRealloced
101
103
102 -- ** Random writes
104 -- ** Random writes
103 , putIndex
105 , putIndex
104− , putIndexUnsafe -- XXX unsafePutIndex
106+ , putIndexUnsafe
105 , putIndices
107 , putIndices
106 -- , putFromThenTo
108 -- , putFromThenTo
107 -- , putFrom -- start writing at the given position
109 -- , putFrom -- start writing at the given position
@@ -109,7 +111,7 @@ module Streamly.Internal.Data.MutArray.Type
109 -- , putFromTo
111 -- , putFromTo
110 -- , putFromRev
112 -- , putFromRev
111 -- , putUptoRev
113 -- , putUptoRev
112− , modifyIndexUnsafe -- XXX unsafeModifyIndex
114+ , modifyIndexUnsafe
113 , modifyIndex
115 , modifyIndex
114 , modifyIndices
116 , modifyIndices
115 , modify
117 , modify
@@ -120,9 +122,9 @@ module Streamly.Internal.Data.MutArray.Type
120
122
121 -- *** Indexing
123 -- *** Indexing
122 , getIndex
124 , getIndex
123− , getIndexUnsafe -- XXX unsafeGetIndex
125+ , getIndexUnsafe
124 -- , getFromThenTo
126 -- , getFromThenTo
125− , getIndexRev -- getRevIndex?
127+ , getIndexRev
126 , indexReader
128 , indexReader
127 , indexReaderWith
129 , indexReaderWith
128
130
@@ -162,9 +164,9 @@ module Streamly.Internal.Data.MutArray.Type
162 , blockSize
164 , blockSize
163 , arrayChunkBytes
165 , arrayChunkBytes
164 , allocBytesToElemCount
166 , allocBytesToElemCount
165− , realloc -- this is "resize"
167+ , realloc
166− , grow
168+ , resize
167− , growExp
169+ , resizeExp
168 , rightSize
170 , rightSize
169
171
170 -- ** Folding
172 -- ** Folding
@@ -193,34 +195,24 @@ module Streamly.Internal.Data.MutArray.Type
193 , snoc
195 , snoc
194 , snocLinear
196 , snocLinear
195 , snocMay
197 , snocMay
196− , snocUnsafe -- XXX unsafeSnoc
198+ , snocUnsafe
197
199
198 -- *** Appending streams
200 -- *** Appending streams
199− , unsafeAppendN
201+ , writeAppendNUnsafe
200− , appendN
202+ , writeAppendN
201− , appendWith
203+ , writeAppendWith
202− , append
204+ , writeAppend
203
205
204 -- *** Appending arrays
206 -- *** Appending arrays
205 , spliceCopy
207 , spliceCopy
206 , spliceWith
208 , spliceWith
207 , splice
209 , splice
208 , spliceExp
210 , spliceExp
209− , spliceUnsafe -- XXX unsafeSplice
211+ , spliceUnsafe
210 -- , putSlice
212 -- , putSlice
211 -- , appendSlice
213 -- , appendSlice
212 -- , appendSliceFrom
214 -- , appendSliceFrom
213
215
214− -- ** Serialization using Unbox
215− , pokeAppend
216− , pokeAppendMay
217− , pokeSkipUnsafe -- unsafePokeSkip
218−
219− -- ** Deserialization using Unbox
220− , peekUncons
221− , peekUnconsUnsafe -- unsafePeekUncons
222− , peekSkipUnsafe -- unsafePeekSkip
223−
224 -- Arrays of arrays
216 -- Arrays of arrays
225 -- We can add dimensionality parameter to the array type to get
217 -- We can add dimensionality parameter to the array type to get
226 -- multidimensional arrays. Multidimensional arrays would just be a
218 -- multidimensional arrays. Multidimensional arrays would just be a
@@ -242,8 +234,6 @@ module Streamly.Internal.Data.MutArray.Type
242
234
243 -- *** Concat
235 -- *** Concat
244 -- | Append the arrays in a stream to form a stream of elements.
236 -- | Append the arrays in a stream to form a stream of elements.
245− , concatWith
246− , concatRevWith
247 , concat
237 , concat
248 , concatRev
238 , concatRev
249
239
@@ -251,12 +241,9 @@ module Streamly.Internal.Data.MutArray.Type
251 -- | Append the arrays in a stream to form a stream of larger arrays.
241 -- | Append the arrays in a stream to form a stream of larger arrays.
252 , SpliceState (..)
242 , SpliceState (..)
253 , pCompactLE
243 , pCompactLE
254− , pPinnedCompactLE
244+ , rCompactLE
255− , compactLeAs
256 , fCompactGE
245 , fCompactGE
257− , fPinnedCompactGE
258 , lCompactGE
246 , lCompactGE
259− , lPinnedCompactGE
260 , compactGE
247 , compactGE
261 , compactEQ
248 , compactEQ
262
249
@@ -267,7 +254,6 @@ module Streamly.Internal.Data.MutArray.Type
267 , c_memchr
254 , c_memchr
268
255
269 -- * Deprecated
256 -- * Deprecated
270− , asPtrUnsafe
271 , writeChunks
257 , writeChunks
272 , flattenArrays
258 , flattenArrays
273 , flattenArraysRev
259 , flattenArraysRev
@@ -277,27 +263,6 @@ module Streamly.Internal.Data.MutArray.Type
277 , cmp
263 , cmp
278 , getIndices
264 , getIndices
279 , getIndicesWith
265 , 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
301 )
266 )
302where
267where
303
268
@@ -479,8 +444,6 @@ isPinned MutArray{..} = Unboxed.isPinned arrContents
479-- we need more than that. See stg_pinnedNewAlignedByteArrayzh and
444-- we need more than that. See stg_pinnedNewAlignedByteArrayzh and
480-- allocatePinned in GHC source.
445-- allocatePinned in GHC source.
481
446
482−-- XXX Rename to emptyAlignedWith, alignSize should be first arg.
483−
484-- | @newArrayWith allocator alignment count@ allocates a new array of zero
447-- | @newArrayWith allocator alignment count@ allocates a new array of zero
485-- length and with a capacity to hold @count@ elements, using @allocator
448-- length and with a capacity to hold @count@ elements, using @allocator
486-- size alignment@ as the memory allocator function.
449-- size alignment@ as the memory allocator function.
@@ -504,25 +467,12 @@ newArrayWith alloc alignSize count = do
504 , arrBound = size
467 , arrBound = size
505 }
468 }
506
469
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." #-}
520nil ::
470nil ::
521#ifdef DEVBUILD
471#ifdef DEVBUILD
522 Unbox a =>
472 Unbox a =>
523#endif
473#endif
524 MutArray a
474 MutArray a
525−nil = empty
475+nil = MutArray Unboxed.nil 0 0 0
526
476
527{-# INLINE newBytesAs #-}
477{-# INLINE newBytesAs #-}
528newBytesAs :: MonadIO m =>
478newBytesAs :: MonadIO m =>
@@ -539,13 +489,12 @@ newBytesAs ps bytes = do
539 , arrBound = bytes
489 , arrBound = bytes
540 }
490 }
541
491
542−-- | Allocates a pinned empty array that with a reserved capacity of bytes.
492+-- | Allocates a pinned empty array that can hold 'count' items. The memory of
543−-- The memory of the array is uninitialized and the allocation is aligned as
493+-- the array is uninitialized and the allocation is aligned as per the
544−-- per the 'Unboxed' instance of the type.
494+-- 'Unboxed' instance of the type.
545--
495--
546-- /Pre-release/
496-- /Pre-release/
547{-# INLINE pinnedNewBytes #-}
497{-# INLINE pinnedNewBytes #-}
548−{-# DEPRECATED pinnedNewBytes "Please use pinnedEmptyOf with appropriate calculation" #-}
549pinnedNewBytes :: MonadIO m =>
498pinnedNewBytes :: MonadIO m =>
550#ifdef DEVBUILD
499#ifdef DEVBUILD
551 Unbox a =>
500 Unbox a =>
@@ -570,31 +519,21 @@ newAs ps =
570 (error "new: alignment is not used in unpinned arrays.")
519 (error "new: alignment is not used in unpinned arrays.")
571
520
572-- XXX can unaligned allocation be more efficient when alignment is not needed?
521-- XXX can unaligned allocation be more efficient when alignment is not needed?
573−
522+--
574−-- | Allocates a pinned array of zero length but growable to the specified
523+-- | Allocates an empty pinned array that can hold 'count' items. The memory of
575−-- capacity without reallocation.
524+-- the array is uninitialized and the allocation is aligned as per the 'Unboxed'
576−{-# INLINE pinnedEmptyOf #-}
525+-- instance of the type.
577−pinnedEmptyOf :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
526+--
578−pinnedEmptyOf = newAs Pinned
579−
580−-- XXX Deprecate in major
581−-- {-# DEPRECATED pinnedNew "Please use pinnedEmptyOf instead." #-}
582{-# INLINE pinnedNew #-}
527{-# INLINE pinnedNew #-}
583pinnedNew :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
528pinnedNew :: forall m a. (MonadIO m, Unbox a) => Int -> m (MutArray a)
584−pinnedNew = pinnedEmptyOf
529+pinnedNew = newAs Pinned
585
530
586−-- | Allocates an unpinned array of zero length but growable to the specified
531+-- | Allocates an empty unpinned array that can hold 'count' items. The memory
587−-- capacity without reallocation.
532+-- of the array is uninitialized.
588--
533--
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." #-}
595{-# INLINE new #-}
534{-# INLINE new #-}
596new :: (MonadIO m, Unbox a) => Int -> m (MutArray a)
535new :: (MonadIO m, Unbox a) => Int -> m (MutArray a)
597−new = emptyOf
536+new = newAs Unpinned
598
537
599-------------------------------------------------------------------------------
538-------------------------------------------------------------------------------
600-- Random writes
539-- Random writes
@@ -842,15 +781,15 @@ roundDownTo elemSize size = size - (size `mod` elemSize)
842-- Since this is not inlined Unboxed consrraint leads to dictionary passing
781-- Since this is not inlined Unboxed consrraint leads to dictionary passing
843-- which complicates some inspection tests.
782-- which complicates some inspection tests.
844--
783--
845−{-# NOINLINE reallocExplicitAs #-}
784+{-# NOINLINE reallocExplicit #-}
846−reallocExplicitAs :: PinnedState -> Int -> Int -> MutArray a -> IO (MutArray a)
785+reallocExplicit :: Int -> Int -> MutArray a -> IO (MutArray a)
847−reallocExplicitAs ps elemSize newCapacityInBytes MutArray{..} = do
786+reallocExplicit elemSize newCapacityInBytes MutArray{..} = do
848 assertM(arrEnd <= arrBound)
787 assertM(arrEnd <= arrBound)
849
788
850 -- Allocate new array
789 -- Allocate new array
851 let newCapMaxInBytes = roundUpLargeArray newCapacityInBytes
790 let newCapMaxInBytes = roundUpLargeArray newCapacityInBytes
852 contents <-
791 contents <-
853− if ps == Pinned
792+ if Unboxed.isPinned arrContents
854 then Unboxed.pinnedNew newCapMaxInBytes
793 then Unboxed.pinnedNew newCapMaxInBytes
855 else Unboxed.new newCapMaxInBytes
794 else Unboxed.new newCapMaxInBytes
856 let !(MutByteArray mbarrFrom#) = arrContents
795 let !(MutByteArray mbarrFrom#) = arrContents
@@ -890,12 +829,7 @@ reallocExplicitAs ps elemSize newCapacityInBytes MutArray{..} = do
890-- If the original array is pinned, the newly allocated array is also pinned.
829-- If the original array is pinned, the newly allocated array is also pinned.
891{-# INLINABLE realloc #-}
830{-# INLINABLE realloc #-}
892realloc :: forall m a. (MonadIO m, Unbox a) => Int -> MutArray a -> m (MutArray a)
831realloc :: 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
832+realloc bytes arr = liftIO $ reallocExplicit (SIZE_OF(a)) bytes arr
899
833
900-- | @reallocWith label capSizer minIncrBytes array@. The label is used
834-- | @reallocWith label capSizer minIncrBytes array@. The label is used
901-- in error messages and the capSizer is used to determine the capacity of the
835-- in error messages and the capSizer is used to determine the capacity of the
@@ -925,7 +859,9 @@ reallocWith label capSizer minIncrBytes arr = do
925 , ". Please check the sizing function passed."
859 , ". Please check the sizing function passed."
926 ]
860 ]
927
861
862+-- XXX should be called expand/extend because it never shortens the array.
863+
928−-- | @grow newCapacity array@ changes the total capacity of the array so that
864+-- | @resize newCapacity array@ changes the total capacity of the array so that
929-- it is enough to hold the specified number of elements. Nothing is done if
865-- it is enough to hold the specified number of elements. Nothing is done if
930-- the specified capacity is less than the length of the array.
866-- the specified capacity is less than the length of the array.
931--
867--
@@ -933,46 +869,36 @@ reallocWith label capSizer minIncrBytes arr = do
933-- the block size (4K).
869-- the block size (4K).
934--
870--
935-- /Pre-release/
871-- /Pre-release/
936−{-# INLINE grow #-}
872+{-# INLINE resize #-}
937−grow :: forall m a. (MonadIO m, Unbox a) =>
873+resize :: forall m a. (MonadIO m, Unbox a) =>
938 Int -> MutArray a -> m (MutArray a)
874 Int -> MutArray a -> m (MutArray a)
939−grow nElems arr@MutArray{..} = do
875+resize nElems arr@MutArray{..} = do
940 let req = SIZE_OF(a) * nElems
876 let req = SIZE_OF(a) * nElems
877+ -- XXX Should use arrBound
941− cap = arrBound - arrStart
878+ len = arrEnd - arrStart
942− if req < cap
879+ if req < len
943 then return arr
880 then return arr
944 else realloc req arr
881 else realloc req arr
945
882
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
883+-- | Like 'resize' but if the requested byte capacity is more than
953-- 'largeObjectThreshold' then it is rounded up to the closest power of 2.
884-- 'largeObjectThreshold' then it is rounded up to the closest power of 2.
954--
885--
955-- /Pre-release/
886-- /Pre-release/
956−{-# INLINE growExp #-}
887+{-# INLINE resizeExp #-}
957−growExp :: forall m a. (MonadIO m, Unbox a) =>
888+resizeExp :: forall m a. (MonadIO m, Unbox a) =>
958 Int -> MutArray a -> m (MutArray a)
889 Int -> MutArray a -> m (MutArray a)
959−growExp nElems arr@MutArray{..} = do
890+resizeExp nElems arr@MutArray{..} = do
960 let req = roundUpLargeArray (SIZE_OF(a) * nElems)
891 let req = roundUpLargeArray (SIZE_OF(a) * nElems)
961 req1 =
892 req1 =
962 if req > largeObjectThreshold
893 if req > largeObjectThreshold
963 then roundUpToPower2 req
894 then roundUpToPower2 req
964 else req
895 else req
896+ -- XXX Should use arrBound
965− cap = arrBound - arrStart
897+ len = arrEnd - arrStart
966− if req1 < cap
898+ if req1 < len
967 then return arr
899 then return arr
968 else realloc req1 arr
900 else realloc req1 arr
969
901
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−
976-- | Resize the allocated memory to drop any reserved free space at the end of
902-- | Resize the allocated memory to drop any reserved free space at the end of
977-- the array and reallocate it to reduce wastage.
903-- the array and reallocate it to reduce wastage.
978--
904--
@@ -1117,126 +1043,6 @@ snoc = snocWith f
1117 then oldSize * 2
1043 then oldSize * 2
1118 else roundUpToPower2 oldSize * 2
1044 else roundUpToPower2 oldSize * 2
1119
1045
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−
1240-------------------------------------------------------------------------------
1046-------------------------------------------------------------------------------
1241-- Random reads
1047-- Random reads
1242-------------------------------------------------------------------------------
1048-------------------------------------------------------------------------------
@@ -1302,7 +1108,6 @@ indexReaderWith liftio (D.Stream stepi sti) = Unfold step inject
1302 D.Stop -> return D.Stop
1108 D.Stop -> return D.Stop
1303
1109
1304{-# DEPRECATED getIndicesWith "Please use indexReaderWith instead." #-}
1110{-# DEPRECATED getIndicesWith "Please use indexReaderWith instead." #-}
1305−{-# INLINE getIndicesWith #-}
1306getIndicesWith :: (Monad m, Unbox a) =>
1111getIndicesWith :: (Monad m, Unbox a) =>
1307 (forall b. IO b -> m b) -> D.Stream m Int -> Unfold m (MutArray a) a
1112 (forall b. IO b -> m b) -> D.Stream m Int -> Unfold m (MutArray a) a
1308getIndicesWith = indexReaderWith
1113getIndicesWith = indexReaderWith
@@ -1318,7 +1123,6 @@ indexReader = indexReaderWith liftIO
1318
1123
1319-- XXX DO NOT REMOVE, change the signature to use Stream instead of unfold
1124-- XXX DO NOT REMOVE, change the signature to use Stream instead of unfold
1320{-# DEPRECATED getIndices "Please use indexReader instead." #-}
1125{-# DEPRECATED getIndices "Please use indexReader instead." #-}
1321−{-# INLINE getIndices #-}
1322getIndices :: (MonadIO m, Unbox a) => Stream m Int -> Unfold m (MutArray a) a
1126getIndices :: (MonadIO m, Unbox a) => Stream m Int -> Unfold m (MutArray a) a
1323getIndices = indexReader
1127getIndices = indexReader
1324
1128
@@ -1615,7 +1419,7 @@ chunksOfAs ps n (D.Stream step state) =
1615--
1419--
1616-- Same as the following but may be more efficient:
1420-- Same as the following but may be more efficient:
1617--
1421--
1618−-- >>> chunksOf n = Stream.foldMany (MutArray.createOf n)
1422+-- >>> chunksOf n = Stream.foldMany (MutArray.writeN n)
1619--
1423--
1620-- /Pre-release/
1424-- /Pre-release/
1621{-# INLINE_NORMAL chunksOf #-}
1425{-# INLINE_NORMAL chunksOf #-}
@@ -1624,14 +1428,14 @@ chunksOf :: forall m a. (MonadIO m, Unbox a)
1624-- XXX the idiomatic implementation leads to large regression in the D.reverse'
1428-- XXX the idiomatic implementation leads to large regression in the D.reverse'
1625-- benchmark. It seems it has difficulty producing optimized code when
1429-- benchmark. It seems it has difficulty producing optimized code when
1626-- converting to StreamK. Investigate GHC optimizations.
1430-- converting to StreamK. Investigate GHC optimizations.
1627−-- chunksOf n = D.foldMany (createOf n)
1431+-- chunksOf n = D.foldMany (writeN n)
1628chunksOf = chunksOfAs Unpinned
1432chunksOf = chunksOfAs Unpinned
1629
1433
1630-- | Like 'chunksOf' but creates pinned arrays.
1434-- | Like 'chunksOf' but creates pinned arrays.
1631{-# INLINE_NORMAL pinnedChunksOf #-}
1435{-# INLINE_NORMAL pinnedChunksOf #-}
1632pinnedChunksOf :: forall m a. (MonadIO m, Unbox a)
1436pinnedChunksOf :: forall m a. (MonadIO m, Unbox a)
1633 => Int -> D.Stream m a -> D.Stream m (MutArray a)
1437 => Int -> D.Stream m a -> D.Stream m (MutArray a)
1634−-- pinnedChunksOf n = D.foldMany (pinnedCreateOf n)
1438+-- pinnedChunksOf n = D.foldMany (pinnedWriteN n)
1635pinnedChunksOf = chunksOfAs Pinned
1439pinnedChunksOf = chunksOfAs Pinned
1636
1440
1637-- | When we are buffering a stream of unknown size into an array we do not
1441-- | When we are buffering a stream of unknown size into an array we do not
@@ -1664,10 +1468,16 @@ data FlattenState s contents a =
1664 OuterLoop s
1468 OuterLoop s
1665 | InnerLoop s contents !Int !Int
1469 | InnerLoop s contents !Int !Int
1666
1470
1471+-- | Use the "reader" unfold instead.
1472+--
1473+-- @concat = unfoldMany reader@
1474+--
1475+-- We can try this if there are any fusion issues in the unfold.
1476+--
1667−{-# INLINE_NORMAL concatWith #-}
1477+{-# INLINE_NORMAL concat #-}
1668−concatWith :: forall m a. (Monad m, Unbox a)
1478+concat :: forall m a. (MonadIO m, Unbox a)
1669− => (forall b. IO b -> m b) -> D.Stream m (MutArray a) -> D.Stream m a
1479+ => D.Stream m (MutArray a) -> D.Stream m a
1670−concatWith liftio (D.Stream step state) = D.Stream step' (OuterLoop state)
1480+concat (D.Stream step state) = D.Stream step' (OuterLoop state)
1671
1481
1672 where
1482 where
1673
1483
@@ -1684,30 +1494,24 @@ concatWith liftio (D.Stream step state) = D.Stream step' (OuterLoop state)
1684 return $ D.Skip $ OuterLoop st
1494 return $ D.Skip $ OuterLoop st
1685
1495
1686 step' _ (InnerLoop st contents p end) = do
1496 step' _ (InnerLoop st contents p end) = do
1687− x <- liftio $ peekAt p contents
1497+ x <- liftIO $ peekAt p contents
1688 return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
1498 return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
1689
1499
1690−-- | Use the "reader" unfold instead.
1691−--
1692−-- @concat = unfoldMany reader@
1693−--
1694−-- We can try this if there are any fusion issues in the unfold.
1695−--
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." #-}
1500{-# DEPRECATED flattenArrays "Please use \"unfoldMany reader\" instead." #-}
1702−{-# INLINE flattenArrays #-}
1703flattenArrays :: forall m a. (MonadIO m, Unbox a)
1501flattenArrays :: forall m a. (MonadIO m, Unbox a)
1704 => D.Stream m (MutArray a) -> D.Stream m a
1502 => D.Stream m (MutArray a) -> D.Stream m a
1705flattenArrays = concat
1503flattenArrays = concat
1706
1504
1505+-- | Use the "readerRev" unfold instead.
1506+--
1507+-- @concat = unfoldMany readerRev@
1508+--
1509+-- We can try this if there are any fusion issues in the unfold.
1510+--
1707−{-# INLINE_NORMAL concatRevWith #-}
1511+{-# INLINE_NORMAL concatRev #-}
1708−concatRevWith :: forall m a. (Monad m, Unbox a)
1512+concatRev :: forall m a. (MonadIO m, Unbox a)
1709− => (forall b. IO b -> m b) -> D.Stream m (MutArray a) -> D.Stream m a
1513+ => D.Stream m (MutArray a) -> D.Stream m a
1710−concatRevWith liftio (D.Stream step state) = D.Stream step' (OuterLoop state)
1514+concatRev (D.Stream step state) = D.Stream step' (OuterLoop state)
1711
1515
1712 where
1516 where
1713
1517
@@ -1725,23 +1529,11 @@ concatRevWith liftio (D.Stream step state) = D.Stream step' (OuterLoop state)
1725 return $ D.Skip $ OuterLoop st
1529 return $ D.Skip $ OuterLoop st
1726
1530
1727 step' _ (InnerLoop st contents p start) = do
1531 step' _ (InnerLoop st contents p start) = do
1728− x <- liftio $ peekAt p contents
1532+ x <- liftIO $ peekAt p contents
1729 let cur = INDEX_PREV(p,a)
1533 let cur = INDEX_PREV(p,a)
1730 return $ D.Yield x (InnerLoop st contents cur start)
1534 return $ D.Yield x (InnerLoop st contents cur start)
1731
1535
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." #-}
1536{-# DEPRECATED flattenArraysRev "Please use \"unfoldMany readerRev\" instead." #-}
1744−{-# INLINE flattenArraysRev #-}
1745flattenArraysRev :: forall m a. (MonadIO m, Unbox a)
1537flattenArraysRev :: forall m a. (MonadIO m, Unbox a)
1746 => D.Stream m (MutArray a) -> D.Stream m a
1538 => D.Stream m (MutArray a) -> D.Stream m a
1747flattenArraysRev = concatRev
1539flattenArraysRev = concatRev
@@ -1973,7 +1765,7 @@ foldr f z arr = D.foldr f z $ read arr
1973
1765
1974-- XXX Keep the bound intact to not lose any free space? Perf impact?
1766-- XXX Keep the bound intact to not lose any free space? Perf impact?
1975
1767
1976−-- | @unsafeAppendN n arr@ appends up to @n@ input items to the supplied
1768+-- | @writeAppendNUnsafe n arr@ appends up to @n@ input items to the supplied
1977-- array.
1769-- array.
1978--
1770--
1979-- Unsafe: Do not drive the fold beyond @n@ elements, it will lead to memory
1771-- Unsafe: Do not drive the fold beyond @n@ elements, it will lead to memory
@@ -1982,12 +1774,13 @@ foldr f z arr = D.foldr f z $ read arr
1982-- Any free space left in the array after appending @n@ elements is lost.
1774-- Any free space left in the array after appending @n@ elements is lost.
1983--
1775--
1984-- /Internal/
1776-- /Internal/
1985−{-# INLINE_NORMAL unsafeAppendN #-}
1777+{-# INLINE_NORMAL writeAppendNUnsafe #-}
1986−unsafeAppendN :: forall m a. (MonadIO m, Unbox a) =>
1778+writeAppendNUnsafe :: forall m a. (MonadIO m, Unbox a) =>
1987 Int
1779 Int
1988 -> m (MutArray a)
1780 -> m (MutArray a)
1989 -> Fold m a (MutArray a)
1781 -> Fold m a (MutArray a)
1782+writeAppendNUnsafe n action =
1990−unsafeAppendN n action = fmap fromArrayUnsafe $ FL.foldlM' step initial
1783+ fmap fromArrayUnsafe $ FL.foldlM' step initial
1991
1784
1992 where
1785 where
1993
1786
@@ -2000,7 +1793,7 @@ unsafeAppendN n action = fmap fromArrayUnsafe $ FL.foldlM' step initial
2000 -- otherwise we lose that space.
1793 -- otherwise we lose that space.
2001 arr1 <-
1794 arr1 <-
2002 if free < needed
1795 if free < needed
2003− then noinline reallocWith "unsafeAppendN" (+ needed) needed arr
1796+ then noinline reallocWith "writeAppendNUnsafeWith" (+ needed) needed arr
2004 else return arr
1797 else return arr
2005 return $ toArrayUnsafe arr1
1798 return $ toArrayUnsafe arr1
2006
1799
@@ -2008,51 +1801,30 @@ unsafeAppendN n action = fmap fromArrayUnsafe $ FL.foldlM' step initial
2008 liftIO $ pokeAt end contents x
1801 liftIO $ pokeAt end contents x
2009 return $ ArrayUnsafe contents start (INDEX_NEXT(end,a))
1802 return $ ArrayUnsafe contents start (INDEX_NEXT(end,a))
2010
1803
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−
2019-- | Append @n@ elements to an existing array. Any free space left in the array
1804-- | Append @n@ elements to an existing array. Any free space left in the array
2020-- after appending @n@ elements is lost.
1805-- after appending @n@ elements is lost.
2021--
1806--
2022−-- >>> appendN n initial = Fold.take n (MutArray.unsafeAppendN n initial)
1807+-- >>> writeAppendN n initial = Fold.take n (MutArray.writeAppendNUnsafe n initial)
2023--
1808--
2024−{-# INLINE_NORMAL appendN #-}
1809+{-# INLINE_NORMAL writeAppendN #-}
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 #-}
2032writeAppendN :: forall m a. (MonadIO m, Unbox a) =>
1810writeAppendN :: forall m a. (MonadIO m, Unbox a) =>
2033 Int -> m (MutArray a) -> Fold m a (MutArray a)
1811 Int -> m (MutArray a) -> Fold m a (MutArray a)
2034−writeAppendN = appendN
1812+writeAppendN n initial = FL.take n (writeAppendNUnsafe n initial)
2035
1813
2036−-- | @appendWith realloc action@ mutates the array generated by @action@ to
1814+-- | @writeAppendWith realloc action@ mutates the array generated by @action@ to
2037-- append the input stream. If there is no reserved space available in the
1815-- append the input stream. If there is no reserved space available in the
2038-- array it is reallocated to a size in bytes determined by @realloc oldSize@,
1816-- array it is reallocated to a size in bytes determined by @realloc oldSize@,
2039-- where @oldSize@ is the current size of the array in bytes.
1817-- where @oldSize@ is the current size of the array in bytes.
2040--
1818--
2041-- Note that the returned array may be a mutated version of original array.
1819-- Note that the returned array may be a mutated version of original array.
2042--
1820--
2043−-- >>> appendWith sizer = Fold.foldlM' (MutArray.snocWith sizer)
1821+-- >>> writeAppendWith sizer = Fold.foldlM' (MutArray.snocWith sizer)
2044--
1822--
2045-- /Pre-release/
1823-- /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." #-}
2052{-# INLINE writeAppendWith #-}
1824{-# INLINE writeAppendWith #-}
2053writeAppendWith :: forall m a. (MonadIO m, Unbox a) =>
1825writeAppendWith :: forall m a. (MonadIO m, Unbox a) =>
2054 (Int -> Int) -> m (MutArray a) -> Fold m a (MutArray a)
1826 (Int -> Int) -> m (MutArray a) -> Fold m a (MutArray a)
2055−writeAppendWith = appendWith
1827+writeAppendWith sizer = FL.foldlM' (snocWith sizer)
2056
1828
2057-- | @append action@ mutates the array generated by @action@ to append the
1829-- | @append action@ mutates the array generated by @action@ to append the
2058-- input stream. If there is no reserved space available in the array it is
1830-- input stream. If there is no reserved space available in the array it is
@@ -2060,33 +1832,26 @@ writeAppendWith = appendWith
2060--
1832--
2061-- Note that the returned array may be a mutated version of original array.
1833-- Note that the returned array may be a mutated version of original array.
2062--
1834--
2063−-- >>> append = MutArray.appendWith (* 2)
1835+-- >>> writeAppend = MutArray.writeAppendWith (* 2)
2064--
1836--
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." #-}
2072{-# INLINE writeAppend #-}
1837{-# INLINE writeAppend #-}
2073writeAppend :: forall m a. (MonadIO m, Unbox a) =>
1838writeAppend :: forall m a. (MonadIO m, Unbox a) =>
2074 m (MutArray a) -> Fold m a (MutArray a)
1839 m (MutArray a) -> Fold m a (MutArray a)
2075−writeAppend = append
1840+writeAppend = writeAppendWith (* 2)
2076
1841
2077-- XXX We can carry bound as well in the state to make sure we do not lose the
1842-- XXX We can carry bound as well in the state to make sure we do not lose the
2078-- remaining capacity. Need to check perf impact.
1843-- remaining capacity. Need to check perf impact.
2079--
1844--
2080−-- | Like 'unsafeCreateOf' but takes a new array allocator @alloc size@
1845+-- | Like 'writeNUnsafe' but takes a new array allocator @alloc size@ function
2081−-- function as argument.
1846+-- as argument.
2082--
1847--
2083−-- >>> unsafeCreateOfWith alloc n = MutArray.unsafeAppendN (alloc n) n
1848+-- >>> writeNWithUnsafe alloc n = MutArray.writeAppendNUnsafe (alloc n) n
2084--
1849--
2085-- /Pre-release/
1850-- /Pre-release/
2086−{-# INLINE_NORMAL unsafeCreateOfWith #-}
1851+{-# INLINE_NORMAL writeNWithUnsafe #-}
2087−unsafeCreateOfWith :: forall m a. (MonadIO m, Unbox a)
1852+writeNWithUnsafe :: forall m a. (MonadIO m, Unbox a)
2088 => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
1853 => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
2089−unsafeCreateOfWith alloc n = fromArrayUnsafe <$> FL.foldlM' step initial
1854+writeNWithUnsafe alloc n = fromArrayUnsafe <$> FL.foldlM' step initial
2090
1855
2091 where
1856 where
2092
1857
@@ -2097,64 +1862,40 @@ unsafeCreateOfWith alloc n = fromArrayUnsafe <$> FL.foldlM' step initial
2097 return
1862 return
2098 $ ArrayUnsafe contents start (INDEX_NEXT(end,a))
1863 $ ArrayUnsafe contents start (INDEX_NEXT(end,a))
2099
1864
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−
2106{-# INLINE_NORMAL writeNUnsafeAs #-}
1865{-# INLINE_NORMAL writeNUnsafeAs #-}
2107writeNUnsafeAs :: forall m a. (MonadIO m, Unbox a)
1866writeNUnsafeAs :: forall m a. (MonadIO m, Unbox a)
2108 => PinnedState -> Int -> Fold m a (MutArray a)
1867 => PinnedState -> Int -> Fold m a (MutArray a)
2109−writeNUnsafeAs ps = unsafeCreateOfWith (newAs ps)
1868+writeNUnsafeAs ps = writeNWithUnsafe (newAs ps)
2110
1869
2111−-- | Like 'createOf' but does not check the array bounds when writing. The fold
1870+-- | Like 'writeN' but does not check the array bounds when writing. The fold
2112-- driver must not call the step function more than 'n' times otherwise it will
1871-- driver must not call the step function more than 'n' times otherwise it will
2113-- corrupt the memory and crash. This function exists mainly because any
1872-- corrupt the memory and crash. This function exists mainly because any
2114-- conditional in the step function blocks fusion causing 10x performance
1873-- conditional in the step function blocks fusion causing 10x performance
2115-- slowdown.
1874-- slowdown.
2116--
1875--
2117−-- >>> unsafeCreateOf = MutArray.unsafeCreateOfWith MutArray.emptyOf
1876+-- >>> writeNUnsafe = MutArray.writeNWithUnsafe MutArray.new
2118--
1877--
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 #-}
1878+{-# INLINE_NORMAL writeNUnsafe #-}
2126writeNUnsafe :: forall m a. (MonadIO m, Unbox a)
1879writeNUnsafe :: forall m a. (MonadIO m, Unbox a)
2127 => Int -> Fold m a (MutArray a)
1880 => Int -> Fold m a (MutArray a)
2128−writeNUnsafe = unsafeCreateOf
1881+writeNUnsafe = writeNUnsafeAs Unpinned
2129−
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
1882
2136−{-# DEPRECATED pinnedWriteNUnsafe "Please use unsafePinnedCreateOf instead." #-}
1883+-- | Like 'writeNUnsafe' but creates a pinned array.
2137−{-# INLINE pinnedWriteNUnsafe #-}
1884+{-# INLINE_NORMAL pinnedWriteNUnsafe #-}
2138pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a)
1885pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a)
2139 => Int -> Fold m a (MutArray a)
1886 => Int -> Fold m a (MutArray a)
2140−pinnedWriteNUnsafe = unsafePinnedCreateOf
1887+pinnedWriteNUnsafe = writeNUnsafeAs Pinned
2141
1888
2142−-- | @createOfWith alloc n@ folds a maximum of @n@ elements into an array
1889+-- | @writeNWith alloc n@ folds a maximum of @n@ elements into an array
2143-- allocated using the @alloc@ function.
1890-- allocated using the @alloc@ function.
2144--
1891--
2145−-- >>> createOfWith alloc n = Fold.take n (MutArray.unsafeCreateOfWith alloc n)
1892+-- >>> writeNWith alloc n = Fold.take n (MutArray.writeNWithUnsafe alloc n)
2146−-- >>> createOfWith alloc n = MutArray.appendN (alloc n) n
1893+-- >>> writeNWith alloc n = MutArray.writeAppendN (alloc n) n
2147--
1894--
2148−{-# INLINE_NORMAL createOfWith #-}
1895+{-# INLINE_NORMAL writeNWith #-}
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 #-}
2155writeNWith :: forall m a. (MonadIO m, Unbox a)
1896writeNWith :: forall m a. (MonadIO m, Unbox a)
2156 => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
1897 => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
2157−writeNWith = createOfWith
1898+writeNWith alloc n = FL.take n (writeNWithUnsafe alloc n)
2158
1899
2159{-# INLINE_NORMAL writeNAs #-}
1900{-# INLINE_NORMAL writeNAs #-}
2160writeNAs ::
1901writeNAs ::
@@ -2162,42 +1903,28 @@ writeNAs ::
2162 => PinnedState
1903 => PinnedState
2163 -> Int
1904 -> Int
2164 -> Fold m a (MutArray a)
1905 -> Fold m a (MutArray a)
2165−writeNAs ps = createOfWith (newAs ps)
1906+writeNAs ps = writeNWith (newAs ps)
2166
1907
2167−-- | @createOf n@ folds a maximum of @n@ elements from the input stream to an
1908+-- | @writeN n@ folds a maximum of @n@ elements from the input stream to an
2168-- 'MutArray'.
1909-- 'MutArray'.
2169--
1910--
2170−-- >>> createOf = MutArray.createOfWith MutArray.new
1911+-- >>> writeN = MutArray.writeNWith MutArray.new
2171−-- >>> createOf n = Fold.take n (MutArray.unsafeCreateOf n)
1912+-- >>> writeN n = Fold.take n (MutArray.writeNUnsafe n)
2172−-- >>> createOf n = MutArray.appendN n (MutArray.emptyOf n)
1913+-- >>> writeN n = MutArray.writeAppendN n (MutArray.new n)
2173--
1914--
2174−{-# INLINE_NORMAL createOf #-}
1915+{-# INLINE_NORMAL writeN #-}
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 #-}
2181writeN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
1916writeN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
2182−writeN = createOf
1917+writeN = writeNAs Unpinned
2183
1918
2184−-- | Like 'createOf' but creates a pinned array.
1919+-- | Like 'writeN' 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
2191−
2192−{-# DEPRECATED pinnedWriteN "Please use pinnedCreateOf instead." #-}
2193−{-# INLINE pinnedWriteN #-}
1920+{-# INLINE_NORMAL pinnedWriteN #-}
2194pinnedWriteN ::
1921pinnedWriteN ::
2195 forall m a. (MonadIO m, Unbox a)
1922 forall m a. (MonadIO m, Unbox a)
2196 => Int
1923 => Int
2197 -> Fold m a (MutArray a)
1924 -> Fold m a (MutArray a)
2198−pinnedWriteN = pinnedCreateOf
1925+pinnedWriteN = writeNAs Pinned
2199
1926
2200−-- | Like unsafeCreateOfWith but writes the array in reverse order.
1927+-- | Like writeNWithUnsafe but writes the array in reverse order.
2201--
1928--
2202-- /Internal/
1929-- /Internal/
2203{-# INLINE_NORMAL writeRevNWithUnsafe #-}
1930{-# INLINE_NORMAL writeRevNWithUnsafe #-}
@@ -2218,7 +1945,7 @@ writeRevNWithUnsafe alloc n = fromArrayUnsafe <$> FL.foldlM' step initial
2218 return
1945 return
2219 $ ArrayUnsafe contents ptr end
1946 $ ArrayUnsafe contents ptr end
2220
1947
2221−-- | Like createOfWith but writes the array in reverse order.
1948+-- | Like writeNWith but writes the array in reverse order.
2222--
1949--
2223-- /Internal/
1950-- /Internal/
2224{-# INLINE_NORMAL writeRevNWith #-}
1951{-# INLINE_NORMAL writeRevNWith #-}
@@ -2226,36 +1953,31 @@ writeRevNWith :: forall m a. (MonadIO m, Unbox a)
2226 => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
1953 => (Int -> m (MutArray a)) -> Int -> Fold m a (MutArray a)
2227writeRevNWith alloc n = FL.take n (writeRevNWithUnsafe alloc n)
1954writeRevNWith alloc n = FL.take n (writeRevNWithUnsafe alloc n)
2228
1955
2229−-- | Like 'createOf' but writes the array in reverse order.
1956+-- | Like writeN but writes the array in reverse order.
2230--
1957--
2231-- /Pre-release/
1958-- /Pre-release/
2232−{-# INLINE_NORMAL revCreateOf #-}
1959+{-# INLINE_NORMAL writeRevN #-}
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 #-}
2238writeRevN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
1960writeRevN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
2239−writeRevN = revCreateOf
1961+writeRevN = writeRevNWith new
2240
1962
2241-- | @pinnedWriteNAligned align n@ folds a maximum of @n@ elements from the
1963-- | @pinnedWriteNAligned align n@ folds a maximum of @n@ elements from the
2242-- input stream to a 'MutArray' aligned to the given size.
1964-- input stream to a 'MutArray' aligned to the given size.
2243--
1965--
2244−-- >>> pinnedWriteNAligned align = MutArray.createOfWith (MutArray.pinnedNewAligned align)
1966+-- >>> pinnedWriteNAligned align = MutArray.writeNWith (MutArray.pinnedNewAligned align)
2245−-- >>> pinnedWriteNAligned align n = MutArray.appendN n (MutArray.pinnedNewAligned align n)
1967+-- >>> pinnedWriteNAligned align n = MutArray.writeAppendN n (MutArray.pinnedNewAligned align n)
2246--
1968--
2247-- /Pre-release/
1969-- /Pre-release/
2248--
1970--
2249{-# INLINE_NORMAL pinnedWriteNAligned #-}
1971{-# INLINE_NORMAL pinnedWriteNAligned #-}
2250pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a)
1972pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a)
2251 => Int -> Int -> Fold m a (MutArray a)
1973 => Int -> Int -> Fold m a (MutArray a)
2252−pinnedWriteNAligned align = createOfWith (pinnedNewAligned align)
1974+pinnedWriteNAligned align = writeNWith (pinnedNewAligned align)
2253
1975
2254-- XXX Buffer to a list instead?
1976-- XXX Buffer to a list instead?
2255
1977
2256-- | Buffer a stream into a stream of arrays.
1978-- | Buffer a stream into a stream of arrays.
2257--
1979--
2258−-- >>> buildChunks n = Fold.many (MutArray.createOf n) Fold.toStreamK
1980+-- >>> buildChunks n = Fold.many (MutArray.writeN n) Fold.toStreamK
2259--
1981--
2260-- Breaking an array into an array stream can be useful to consume a large
1982-- Breaking an array into an array stream can be useful to consume a large
2261-- array sequentially such that memory of the array is released incrementatlly.
1983-- array sequentially such that memory of the array is released incrementatlly.
@@ -2267,10 +1989,9 @@ pinnedWriteNAligned align = createOfWith (pinnedNewAligned align)
2267{-# INLINE_NORMAL buildChunks #-}
1989{-# INLINE_NORMAL buildChunks #-}
2268buildChunks :: (MonadIO m, Unbox a) =>
1990buildChunks :: (MonadIO m, Unbox a) =>
2269 Int -> Fold m a (StreamK n (MutArray a))
1991 Int -> Fold m a (StreamK n (MutArray a))
2270−buildChunks n = FL.many (createOf n) FL.toStreamK
1992+buildChunks n = FL.many (writeN n) FL.toStreamK
2271
1993
2272{-# DEPRECATED writeChunks "Please use buildChunks instead." #-}
1994{-# DEPRECATED writeChunks "Please use buildChunks instead." #-}
2273−{-# INLINE writeChunks #-}
2274writeChunks :: (MonadIO m, Unbox a) =>
1995writeChunks :: (MonadIO m, Unbox a) =>
2275 Int -> Fold m a (StreamK n (MutArray a))
1996 Int -> Fold m a (StreamK n (MutArray a))
2276writeChunks = buildChunks
1997writeChunks = buildChunks
@@ -2278,29 +1999,29 @@ writeChunks = buildChunks
2278{-# INLINE_NORMAL writeWithAs #-}
1999{-# INLINE_NORMAL writeWithAs #-}
2279writeWithAs :: forall m a. (MonadIO m, Unbox a)
2000writeWithAs :: forall m a. (MonadIO m, Unbox a)
2280 => PinnedState -> Int -> Fold m a (MutArray a)
2001 => PinnedState -> Int -> Fold m a (MutArray a)
2281−-- writeWithAs ps n = FL.rmapM rightSize $ appendWith (* 2) (newAs ps n)
2002+-- writeWithAs ps n = FL.rmapM rightSize $ writeAppendWith (* 2) (newAs ps n)
2282writeWithAs ps elemCount =
2003writeWithAs ps elemCount =
2283 FL.rmapM extract $ FL.foldlM' step initial
2004 FL.rmapM extract $ FL.foldlM' step initial
2284
2005
2285 where
2006 where
2286
2007
2287 initial = do
2008 initial = do
2288− when (elemCount < 0) $ error "createWith: elemCount is negative"
2009+ when (elemCount < 0) $ error "writeWith: elemCount is negative"
2289 newAs ps elemCount
2010 newAs ps elemCount
2290
2011
2291 step arr@(MutArray _ start end bound) x
2012 step arr@(MutArray _ start end bound) x
2292 | INDEX_NEXT(end,a) > bound = do
2013 | INDEX_NEXT(end,a) > bound = do
2293 let oldSize = end - start
2014 let oldSize = end - start
2294 newSize = max (oldSize * 2) 1
2015 newSize = max (oldSize * 2) 1
2295− arr1 <- liftIO $ reallocExplicitAs ps (SIZE_OF(a)) newSize arr
2016+ arr1 <- liftIO $ reallocExplicit (SIZE_OF(a)) newSize arr
2296 snocUnsafe arr1 x
2017 snocUnsafe arr1 x
2297 step arr x = snocUnsafe arr x
2018 step arr x = snocUnsafe arr x
2298
2019
2299 extract = liftIO . rightSize
2020 extract = liftIO . rightSize
2300
2021
2301−-- XXX Compare createWith with fromStreamD which uses an array of streams
2022+-- XXX Compare writeWith with fromStreamD which uses an array of streams
2302-- implementation. We can write this using buildChunks above if that is faster.
2023-- implementation. We can write this using buildChunks above if that is faster.
2303−-- If createWith is faster then we should use that to implement
2024+-- If writeWith is faster then we should use that to implement
2304-- fromStreamD.
2025-- fromStreamD.
2305--
2026--
2306-- XXX The realloc based implementation needs to make one extra copy if we use
2027-- XXX The realloc based implementation needs to make one extra copy if we use
@@ -2315,56 +2036,39 @@ writeWithAs ps elemCount =
2315-- XXX check if GHC's memory allocator is efficient enough. We can try the C
2036-- XXX check if GHC's memory allocator is efficient enough. We can try the C
2316-- malloc to compare against.
2037-- malloc to compare against.
2317
2038
2318−-- | @createWith minCount@ folds the whole input to a single array. The array
2039+-- | @writeWith minCount@ folds the whole input to a single array. The array
2319-- starts at a size big enough to hold minCount elements, the size is doubled
2040-- starts at a size big enough to hold minCount elements, the size is doubled
2320-- every time the array needs to be grown.
2041-- every time the array needs to be grown.
2321--
2042--
2322-- /Caution! Do not use this on infinite streams./
2043-- /Caution! Do not use this on infinite streams./
2323--
2044--
2324−-- >>> f n = MutArray.appendWith (* 2) (MutArray.emptyOf n)
2045+-- >>> f n = MutArray.writeAppendWith (* 2) (MutArray.new n)
2325−-- >>> createWith n = Fold.rmapM MutArray.rightSize (f n)
2046+-- >>> writeWith n = Fold.rmapM MutArray.rightSize (f n)
2326−-- >>> createWith n = Fold.rmapM MutArray.fromChunksK (MutArray.buildChunks n)
2047+-- >>> writeWith n = Fold.rmapM MutArray.fromChunksK (MutArray.buildChunks n)
2327--
2048--
2328-- /Pre-release/
2049-- /Pre-release/
2329−{-# INLINE_NORMAL createWith #-}
2050+{-# INLINE_NORMAL writeWith #-}
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 #-}
2337writeWith :: forall m a. (MonadIO m, Unbox a)
2051writeWith :: forall m a. (MonadIO m, Unbox a)
2338 => Int -> Fold m a (MutArray a)
2052 => Int -> Fold m a (MutArray a)
2339−writeWith = createWith
2053+-- writeWith n = FL.rmapM rightSize $ writeAppendWith (* 2) (new n)
2054+writeWith = writeWithAs Unpinned
2340
2055
2341-- | Fold the whole input to a single array.
2056-- | Fold the whole input to a single array.
2342--
2057--
2343−-- Same as 'createWith' using an initial array size of 'arrayChunkBytes' bytes
2058+-- Same as 'writeWith' using an initial array size of 'arrayChunkBytes' bytes
2344-- rounded up to the element size.
2059-- rounded up to the element size.
2345--
2060--
2346-- /Caution! Do not use this on infinite streams./
2061-- /Caution! Do not use this on infinite streams./
2347--
2062--
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." #-}
2354{-# INLINE write #-}
2063{-# INLINE write #-}
2355write :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
2064write :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
2356−write = create
2065+write = writeWith (allocBytesToElemCount (undefined :: a) arrayChunkBytes)
2357
2066
2358−-- | Like 'create' but creates a pinned array.
2067+-- | Like 'write' 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)
2363−
2364−{-# DEPRECATED pinnedWrite "Please use pinnedCreate instead." #-}
2365{-# INLINE pinnedWrite #-}
2068{-# INLINE pinnedWrite #-}
2366pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
2069pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (MutArray a)
2367−pinnedWrite = pinnedCreate
2070+pinnedWrite =
2071+ writeWithAs Pinned (allocBytesToElemCount (undefined :: a) arrayChunkBytes)
2368
2072
2369-------------------------------------------------------------------------------
2073-------------------------------------------------------------------------------
2370-- construct from streams, known size
2074-- construct from streams, known size
@@ -2384,18 +2088,17 @@ fromStreamDNAs ps limit str = do
2384 liftIO $ pokeAt ptr arrContents x
2088 liftIO $ pokeAt ptr arrContents x
2385 return $ INDEX_NEXT(ptr,a)
2089 return $ INDEX_NEXT(ptr,a)
2386
2090
2387−-- | Use the 'createOf' fold instead.
2091+-- | Use the 'writeN' fold instead.
2388--
2092--
2389−-- >>> fromStreamN n = Stream.fold (MutArray.createOf n)
2093+-- >>> fromStreamN n = Stream.fold (MutArray.writeN n)
2390--
2094--
2391{-# INLINE_NORMAL fromStreamN #-}
2095{-# INLINE_NORMAL fromStreamN #-}
2392fromStreamN :: forall m a. (MonadIO m, Unbox a)
2096fromStreamN :: forall m a. (MonadIO m, Unbox a)
2393 => Int -> D.Stream m a -> m (MutArray a)
2097 => Int -> D.Stream m a -> m (MutArray a)
2394−-- fromStreamDN n = D.fold (createOf n)
2098+-- fromStreamDN n = D.fold (writeN n)
2395fromStreamN = fromStreamDNAs Unpinned
2099fromStreamN = fromStreamDNAs Unpinned
2396
2100
2397{-# DEPRECATED fromStreamDN "Please use fromStreamN instead." #-}
2101{-# DEPRECATED fromStreamDN "Please use fromStreamN instead." #-}
2398−{-# INLINE fromStreamDN #-}
2399fromStreamDN :: forall m a. (MonadIO m, Unbox a)
2102fromStreamDN :: forall m a. (MonadIO m, Unbox a)
2400 => Int -> D.Stream m a -> m (MutArray a)
2103 => Int -> D.Stream m a -> m (MutArray a)
2401fromStreamDN = fromStreamN
2104fromStreamDN = fromStreamN
@@ -2418,20 +2121,20 @@ pinnedFromListN n xs = fromStreamDNAs Pinned n $ D.fromList xs
2418-- /Pre-release/
2121-- /Pre-release/
2419{-# INLINE fromListRevN #-}
2122{-# INLINE fromListRevN #-}
2420fromListRevN :: (MonadIO m, Unbox a) => Int -> [a] -> m (MutArray a)
2123fromListRevN :: (MonadIO m, Unbox a) => Int -> [a] -> m (MutArray a)
2421−fromListRevN n xs = D.fold (revCreateOf n) $ D.fromList xs
2124+fromListRevN n xs = D.fold (writeRevN n) $ D.fromList xs
2422
2125
2423-- | Convert a pure stream in Identity monad to a mutable array.
2126-- | Convert a pure stream in Identity monad to a mutable array.
2424{-# INLINABLE fromPureStreamN #-}
2127{-# INLINABLE fromPureStreamN #-}
2425fromPureStreamN :: (MonadIO m, Unbox a) =>
2128fromPureStreamN :: (MonadIO m, Unbox a) =>
2426 Int -> Stream Identity a -> m (MutArray a)
2129 Int -> Stream Identity a -> m (MutArray a)
2427fromPureStreamN n xs =
2130fromPureStreamN n xs =
2428− D.fold (createOf n) $ D.morphInner (return . runIdentity) xs
2131+ D.fold (writeN n) $ D.morphInner (return . runIdentity) xs
2429
2132
2430-- | Convert a pure stream in Identity monad to a mutable array.
2133-- | Convert a pure stream in Identity monad to a mutable array.
2431{-# INLINABLE fromPureStream #-}
2134{-# INLINABLE fromPureStream #-}
2432fromPureStream :: (MonadIO m, Unbox a) => Stream Identity a -> m (MutArray a)
2135fromPureStream :: (MonadIO m, Unbox a) => Stream Identity a -> m (MutArray a)
2433fromPureStream xs =
2136fromPureStream xs =
2434− D.fold create $ D.morphInner (return . runIdentity) xs
2137+ D.fold write $ D.morphInner (return . runIdentity) xs
2435
2138
2436{-# INLINABLE fromPtrN #-}
2139{-# INLINABLE fromPtrN #-}
2437fromPtrN :: MonadIO m => Int -> Ptr Word8 -> m (MutArray Word8)
2140fromPtrN :: MonadIO m => Int -> Ptr Word8 -> m (MutArray Word8)
@@ -2440,7 +2143,7 @@ fromPtrN len addr = do
2440 -- XXX We can implement a stream copy in a similar way by streaming Word64
2143 -- XXX We can implement a stream copy in a similar way by streaming Word64
2441 -- first and then remaining Word8.
2144 -- first and then remaining Word8.
2442 arr <- new len
2145 arr <- new len
2443− _ <- unsafeAsPtr arr
2146+ _ <- asUnpinnedPtrUnsafe arr
2444 (\ptr -> liftIO $ c_memcpy ptr addr (fromIntegral len))
2147 (\ptr -> liftIO $ c_memcpy ptr addr (fromIntegral len))
2445 return (arr {arrEnd = len})
2148 return (arr {arrEnd = len})
2446
2149
@@ -2456,7 +2159,7 @@ fromByteStr# addr = do
2456 len <- liftIO $ c_strlen (Ptr addr)
2159 len <- liftIO $ c_strlen (Ptr addr)
2457 let lenInt = fromIntegral len
2160 let lenInt = fromIntegral len
2458 arr <- new lenInt
2161 arr <- new lenInt
2459− _ <- unsafeAsPtr arr (\ptr -> liftIO $ c_memcpy ptr (Ptr addr) len)
2162+ _ <- asUnpinnedPtrUnsafe arr (\ptr -> liftIO $ c_memcpy ptr (Ptr addr) len)
2460 return (arr {arrEnd = lenInt})
2163 return (arr {arrEnd = lenInt})
2461
2164
2462-------------------------------------------------------------------------------
2165-------------------------------------------------------------------------------
@@ -2515,7 +2218,6 @@ fromChunksK :: (Unbox a, MonadIO m) =>
2515fromChunksK = fromChunkskAs Unpinned
2218fromChunksK = fromChunkskAs Unpinned
2516
2219
2517{-# DEPRECATED fromArrayStreamK "Please use fromChunksK instead." #-}
2220{-# DEPRECATED fromArrayStreamK "Please use fromChunksK instead." #-}
2518−{-# INLINE fromArrayStreamK #-}
2519fromArrayStreamK :: (Unbox a, MonadIO m) =>
2221fromArrayStreamK :: (Unbox a, MonadIO m) =>
2520 StreamK m (MutArray a) -> m (MutArray a)
2222 StreamK m (MutArray a) -> m (MutArray a)
2521fromArrayStreamK = fromChunksK
2223fromArrayStreamK = fromChunksK
@@ -2527,7 +2229,7 @@ fromStreamDAs ps m =
2527 arrayStreamKFromStreamDAs Unpinned m >>= fromChunkskAs ps
2229 arrayStreamKFromStreamDAs Unpinned m >>= fromChunkskAs ps
2528
2230
2529-- | Create an 'Array' from a stream. This is useful when we want to create a
2231-- | 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
2232+-- single array from a stream of unknown size. 'writeN' is at least twice
2531-- as efficient when the size is already known.
2233-- as efficient when the size is already known.
2532--
2234--
2533-- Note that if the input stream is too large memory allocation for the array
2235-- Note that if the input stream is too large memory allocation for the array
@@ -2539,19 +2241,19 @@ fromStreamDAs ps m =
2539fromStream :: (MonadIO m, Unbox a) => Stream m a -> m (MutArray a)
2241fromStream :: (MonadIO m, Unbox a) => Stream m a -> m (MutArray a)
2540fromStream = fromStreamDAs Unpinned
2242fromStream = fromStreamDAs Unpinned
2541
2243
2542−-- fromStream (Stream m) = P.fold create m
2244+-- fromStream (Stream m) = P.fold write m
2543-- CAUTION: a very large number (millions) of arrays can degrade performance
2245-- CAUTION: a very large number (millions) of arrays can degrade performance
2544-- due to GC overhead because we need to buffer the arrays before we flatten
2246-- due to GC overhead because we need to buffer the arrays before we flatten
2545-- all the arrays.
2247-- all the arrays.
2546--
2248--
2547−-- XXX Compare if this is faster or "fold create".
2249+-- XXX Compare if this is faster or "fold write".
2548--
2250--
2549-- | We could take the approach of doubling the memory allocation on each
2251-- | We could take the approach of doubling the memory allocation on each
2550-- overflow. This would result in more or less the same amount of copying as in
2252-- overflow. This would result in more or less the same amount of copying as in
2551-- the chunking approach. However, if we have to shrink in the end then it may
2253-- the chunking approach. However, if we have to shrink in the end then it may
2552-- result in an extra copy of the entire data.
2254-- result in an extra copy of the entire data.
2553--
2255--
2554−-- >>> fromStreamD = StreamD.fold MutArray.create
2256+-- >>> fromStreamD = StreamD.fold MutArray.write
2555--
2257--
2556{-# INLINE fromStreamD #-}
2258{-# INLINE fromStreamD #-}
2557{-# DEPRECATED fromStreamD "Please use fromStream instead." #-}
2259{-# DEPRECATED fromStreamD "Please use fromStream instead." #-}
@@ -2581,10 +2283,6 @@ fromListRev xs = fromListRevN (Prelude.length xs) xs
2581-- Cloning
2283-- Cloning
2582-------------------------------------------------------------------------------
2284-------------------------------------------------------------------------------
2583
2285
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−
2588{-# INLINE cloneAs #-}
2286{-# INLINE cloneAs #-}
2589cloneAs ::
2287cloneAs ::
2590 ( MonadIO m
2288 ( MonadIO m
@@ -2676,7 +2374,7 @@ spliceWith :: forall m a. (MonadIO m, Unbox a) =>
2676 (Int -> Int -> Int) -> MutArray a -> MutArray a -> m (MutArray a)
2374 (Int -> Int -> Int) -> MutArray a -> MutArray a -> m (MutArray a)
2677spliceWith sizer dst@(MutArray _ start end bound) src = do
2375spliceWith sizer dst@(MutArray _ start end bound) src = do
2678{-
2376{-
2679− let f = appendWith (`sizer` byteLength src) (return dst)
2377+ let f = writeAppendWith (`sizer` byteLength src) (return dst)
2680 in D.fold f (toStreamD src)
2378 in D.fold f (toStreamD src)
2681-}
2379-}
2682 assert (end <= bound) (return ())
2380 assert (end <= bound) (return ())
@@ -2744,7 +2442,7 @@ splitOn predicate arr =
2744{-# INLINE breakOn #-}
2442{-# INLINE breakOn #-}
2745breakOn :: MonadIO m
2443breakOn :: MonadIO m
2746 => Word8 -> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
2444 => Word8 -> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
2747−breakOn sep arr@MutArray{..} = unsafeAsPtr arr $ \p -> liftIO $ do
2445+breakOn sep arr@MutArray{..} = asUnpinnedPtrUnsafe arr $ \p -> liftIO $ do
2748 -- XXX We do not need memchr here, we can use a Haskell equivalent.
2446 -- XXX We do not need memchr here, we can use a Haskell equivalent.
2749 -- Need efficient stream based primitives that work on Word64.
2447 -- Need efficient stream based primitives that work on Word64.
2750 loc <- c_memchr p sep (fromIntegral $ byteLength arr)
2448 loc <- c_memchr p sep (fromIntegral $ byteLength arr)
@@ -2767,41 +2465,33 @@ breakOn sep arr@MutArray{..} = unsafeAsPtr arr $ \p -> liftIO $ do
2767 }
2465 }
2768 )
2466 )
2769
2467
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−
2792-- | Create two slices of an array without copying the original array. The
2468-- | Create two slices of an array without copying the original array. The
2793-- specified index @i@ is the first index of the second slice.
2469-- specified index @i@ is the first index of the second slice.
2794--
2470--
2795{-# INLINE splitAt #-}
2471{-# INLINE splitAt #-}
2796splitAt :: forall a. Unbox a => Int -> MutArray a -> (MutArray a, MutArray a)
2472splitAt :: forall a. Unbox a => Int -> MutArray a -> (MutArray a, MutArray a)
2797−splitAt i arr =
2473+splitAt i arr@MutArray{..} =
2798 let maxIndex = length arr - 1
2474 let maxIndex = length arr - 1
2799 in if i < 0
2475 in if i < 0
2800 then error "sliceAt: negative array index"
2476 then error "sliceAt: negative array index"
2801 else if i > maxIndex
2477 else if i > maxIndex
2802 then error $ "sliceAt: specified array index " ++ show i
2478 then error $ "sliceAt: specified array index " ++ show i
2803 ++ " is beyond the maximum index " ++ show maxIndex
2479 ++ " is beyond the maximum index " ++ show maxIndex
2804− else unsafeSplitAt i arr
2480+ else let off = i * SIZE_OF(a)
2481+ p = arrStart + off
2482+ in ( MutArray
2483+ { arrContents = arrContents
2484+ , arrStart = arrStart
2485+ , arrEnd = p
2486+ , arrBound = p
2487+ }
2488+ , MutArray
2489+ { arrContents = arrContents
2490+ , arrStart = p
2491+ , arrEnd = arrEnd
2492+ , arrBound = arrBound
2493+ }
2494+ )
2805
2495
2806-------------------------------------------------------------------------------
2496-------------------------------------------------------------------------------
2807-- Casting
2497-- Casting
@@ -2851,13 +2541,9 @@ cast arr =
2851-- guarantees that unsafe calls will be performed in the calling thread. Making
2541-- guarantees that unsafe calls will be performed in the calling thread. Making
2852-- it safe to pass heap-allocated objects to unsafe functions.
2542-- it safe to pass heap-allocated objects to unsafe functions.
2853
2543
2854−-- XXX Should we just name it asPtr, the unsafety is implicit for any pointer
2544+-- Should we just name it asPtr, the unsafety is implicit for any pointer
2855-- operations. And we are safe from Haskell perspective because we will be
2545-- operations. And we are safe from Haskell perspective because we will be
2856-- pinning the memory.
2546-- 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.
2861
2547
2862-- | Use a @MutArray a@ as @Ptr a@. This is useful when we want to pass an
2548-- | Use a @MutArray a@ as @Ptr a@. This is useful when we want to pass an
2863-- array as a pointer to some operating system call or to a "safe" FFI call.
2549-- array as a pointer to some operating system call or to a "safe" FFI call.
@@ -2875,21 +2561,16 @@ cast arr =
2875--
2561--
2876-- /Pre-release/
2562-- /Pre-release/
2877--
2563--
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." #-}
2885{-# INLINE asPtrUnsafe #-}
2564{-# INLINE asPtrUnsafe #-}
2886asPtrUnsafe :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
2565asPtrUnsafe :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
2887−asPtrUnsafe = unsafePinnedAsPtr
2566+asPtrUnsafe arr f =
2567+ Unboxed.asPtrUnsafe
2568+ (arrContents arr) (\ptr -> f (ptr `plusPtr` arrStart arr))
2888
2569
2889−{-# INLINE unsafeAsPtr #-}
2570+{-# INLINE asUnpinnedPtrUnsafe #-}
2890−unsafeAsPtr :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
2571+asUnpinnedPtrUnsafe :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b
2891−unsafeAsPtr arr f =
2572+asUnpinnedPtrUnsafe arr f =
2892− Unboxed.unsafeAsPtr
2573+ Unboxed.asUnpinnedPtrUnsafe
2893 (arrContents arr) (\ptr -> f (ptr `plusPtr` arrStart arr))
2574 (arrContents arr) (\ptr -> f (ptr `plusPtr` arrStart arr))
2894
2575
2895-------------------------------------------------------------------------------
2576-------------------------------------------------------------------------------
@@ -2946,48 +2627,46 @@ byteEq arr1 arr2 = fmap (EQ ==) $ byteCmp arr1 arr2
2946-- Compact
2627-- Compact
2947-------------------------------------------------------------------------------
2628-------------------------------------------------------------------------------
2948
2629
2949−-- Note: LE versions avoid an extra copy compared to GE. LE parser trades
2630+-- | Parser @pCompactLE n@ coalesces adjacent arrays in the input stream
2950−-- backtracking one array in lieu of avoiding a copy. However, LE and GE both
2631+-- only if the combined size would be less than or equal to n.
2951−-- can leave some memory unused. They can split the last array to fit it
2632+--
2952−-- exactly in the space.
2633+-- /Internal/
2953−
2954−{-# INLINE_NORMAL pCompactLeAs #-}
2634+{-# INLINE_NORMAL pCompactLE #-}
2955−pCompactLeAs ::
2635+pCompactLE ::
2956 forall m a. (MonadIO m, Unbox a)
2636 forall m a. (MonadIO m, Unbox a)
2957− => PinnedState -> Int -> Parser (MutArray a) m (MutArray a)
2637+ => Int -> Parser (MutArray a) m (MutArray a)
2958−pCompactLeAs ps maxElems = Parser step initial extract
2638+pCompactLE n = Parser step initial extract
2959
2639
2960 where
2640 where
2961
2641
2962− maxBytes = maxElems * SIZE_OF(a)
2642+ nBytes = n * SIZE_OF(a)
2963
2643
2964 functionName = "Streamly.Internal.Data.MutArray.pCompactLE"
2644 functionName = "Streamly.Internal.Data.MutArray.pCompactLE"
2965
2645
2966 initial =
2646 initial =
2967 return
2647 return
2968− $ if maxElems <= 0
2648+ $ if n <= 0
2969 then error
2649 then error
2970 $ functionName
2650 $ functionName
2971 ++ ": the size of arrays ["
2651 ++ ": the size of arrays ["
2972− ++ show maxElems ++ "] must be a natural number"
2652+ ++ show n ++ "] must be a natural number"
2973 else Parser.IPartial Nothing
2653 else Parser.IPartial Nothing
2974
2654
2975 step Nothing arr =
2655 step Nothing arr =
2976 return
2656 return
2977 $ let len = byteLength arr
2657 $ let len = byteLength arr
2978− in if len >= maxBytes
2658+ in if len >= nBytes
2979 then Parser.Done 0 arr
2659 then Parser.Done 0 arr
2980 else Parser.Partial 0 (Just arr)
2660 else Parser.Partial 0 (Just arr)
2981− -- XXX Split the last array to use the space more compactly.
2982 step (Just buf) arr =
2661 step (Just buf) arr =
2983 let len = byteLength buf + byteLength arr
2662 let len = byteLength buf + byteLength arr
2984− in if len > maxBytes
2663+ in if len > nBytes
2985 then return $ Parser.Done 1 buf
2664 then return $ Parser.Done 1 buf
2986 else do
2665 else do
2666+ -- XXX check this in the Nothing case
2987 buf1 <-
2667 buf1 <-
2988− if byteCapacity buf < maxBytes
2668+ if byteCapacity buf < nBytes
2989− then liftIO $ reallocExplicitAs
2669+ then liftIO $ realloc nBytes buf
2990− ps (SIZE_OF(a)) maxBytes buf
2991 else return buf
2670 else return buf
2992 buf2 <- spliceUnsafe buf1 arr
2671 buf2 <- spliceUnsafe buf1 arr
2993 return $ Parser.Partial 0 (Just buf2)
2672 return $ Parser.Partial 0 (Just buf2)
@@ -2995,30 +2674,6 @@ pCompactLeAs ps maxElems = Parser step initial extract
2995 extract Nothing = return $ Parser.Done 0 nil
2674 extract Nothing = return $ Parser.Done 0 nil
2996 extract (Just buf) = return $ Parser.Done 0 buf
2675 extract (Just buf) = return $ Parser.Done 0 buf
2997
2676
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−
3022data SpliceState s arr
2677data SpliceState s arr
3023 = SpliceInitial s
2678 = SpliceInitial s
3024 | SpliceBuffering s arr
2679 | SpliceBuffering s arr
@@ -3030,47 +2685,48 @@ data SpliceState s arr
3030-- immutable array never has additional space so a new array is allocated
2685-- immutable array never has additional space so a new array is allocated
3031-- instead of mutating it.
2686-- instead of mutating it.
3032
2687
2688+-- | Scan @rCompactLE n@ coalesces adjacent arrays in the input stream
2689+-- only if the combined size would be less than or equal to n.
2690+--
2691+-- /Internal/
3033−{-# INLINE_NORMAL compactLeAs #-}
2692+{-# INLINE_NORMAL rCompactLE #-}
3034−compactLeAs :: forall m a. (MonadIO m, Unbox a)
2693+rCompactLE :: (MonadIO m, Unbox a)
3035− => PinnedState -> Int -> D.Stream m (MutArray a) -> D.Stream m (MutArray a)
2694+ => Int -> D.Stream m (MutArray a) -> D.Stream m (MutArray a)
3036−compactLeAs ps maxElems (D.Stream step state) =
2695+rCompactLE n (D.Stream step state) =
3037 D.Stream step' (SpliceInitial state)
2696 D.Stream step' (SpliceInitial state)
3038
2697
3039 where
2698 where
3040
2699
3041− maxBytes = maxElems * SIZE_OF(a)
3042−
3043 functionName = "Streamly.Internal.Data.MutArray.rCompactLE"
2700 functionName = "Streamly.Internal.Data.MutArray.rCompactLE"
3044
2701
3045 {-# INLINE_LATE step' #-}
2702 {-# INLINE_LATE step' #-}
3046 step' gst (SpliceInitial st) = do
2703 step' gst (SpliceInitial st) = do
3047− when (maxElems <= 0) $
2704+ when (n <= 0) $
3048 -- XXX we can pass the module string from the higher level API
2705 -- XXX we can pass the module string from the higher level API
3049− error $ functionName ++ ": the size of arrays [" ++ show maxElems
2706+ error $ functionName ++ ": the size of arrays [" ++ show n
3050 ++ "] must be a natural number"
2707 ++ "] must be a natural number"
3051 r <- step gst st
2708 r <- step gst st
3052 case r of
2709 case r of
3053 D.Yield arr s -> return $
2710 D.Yield arr s -> return $
3054 let len = byteLength arr
2711 let len = byteLength arr
3055− in if len >= maxBytes
2712+ in if len >= n
3056 then D.Skip (SpliceYielding arr (SpliceInitial s))
2713 then D.Skip (SpliceYielding arr (SpliceInitial s))
3057 else D.Skip (SpliceBuffering s arr)
2714 else D.Skip (SpliceBuffering s arr)
3058 D.Skip s -> return $ D.Skip (SpliceInitial s)
2715 D.Skip s -> return $ D.Skip (SpliceInitial s)
3059 D.Stop -> return D.Stop
2716 D.Stop -> return D.Stop
3060
2717
3061− -- XXX Split the last array to use the space more compactly.
3062 step' gst (SpliceBuffering st buf) = do
2718 step' gst (SpliceBuffering st buf) = do
3063 r <- step gst st
2719 r <- step gst st
3064 case r of
2720 case r of
3065 D.Yield arr s -> do
2721 D.Yield arr s -> do
3066 let len = byteLength buf + byteLength arr
2722 let len = byteLength buf + byteLength arr
3067− if len > maxBytes
2723+ if len > n
3068 then return $
2724 then return $
3069 D.Skip (SpliceYielding buf (SpliceBuffering s arr))
2725 D.Skip (SpliceYielding buf (SpliceBuffering s arr))
3070 else do
2726 else do
2727+ -- XXX check this in the SpliceInitial case
3071− buf1 <- if byteCapacity buf < maxBytes
2728+ buf1 <- if byteCapacity buf < n
3072− then liftIO $ reallocExplicitAs
2729+ then liftIO $ realloc n buf
3073− ps (SIZE_OF(a)) maxBytes buf
3074 else return buf
2730 else return buf
3075 buf2 <- spliceUnsafe buf1 arr
2731 buf2 <- spliceUnsafe buf1 arr
3076 return $ D.Skip (SpliceBuffering s buf2)
2732 return $ D.Skip (SpliceBuffering s buf2)
@@ -3081,119 +2737,108 @@ compactLeAs ps maxElems (D.Stream step state) =
3081
2737
3082 step' _ (SpliceYielding arr next) = return $ D.Yield arr next
2738 step' _ (SpliceYielding arr next) = return $ D.Yield arr next
3083
2739
3084−
2740+-- | Fold @fCompactGE n@ coalesces adjacent arrays in the input stream
2741+-- until the size becomes greater than or equal to n.
2742+--
3085−{-# INLINE_NORMAL fCompactGeAs #-}
2743+{-# INLINE_NORMAL fCompactGE #-}
3086−fCompactGeAs ::
2744+fCompactGE ::
3087 forall m a. (MonadIO m, Unbox a)
2745 forall m a. (MonadIO m, Unbox a)
3088− => PinnedState -> Int -> FL.Fold m (MutArray a) (MutArray a)
2746+ => Int -> FL.Fold m (MutArray a) (MutArray a)
3089−fCompactGeAs ps minElems = Fold step initial extract extract
2747+fCompactGE n = Fold step initial extract extract
3090
2748
3091 where
2749 where
3092
2750
3093− minBytes = minElems * SIZE_OF(a)
2751+ nBytes = n * SIZE_OF(a)
3094
2752
3095 functionName = "Streamly.Internal.Data.MutArray.fCompactGE"
2753 functionName = "Streamly.Internal.Data.MutArray.fCompactGE"
3096
2754
3097 initial =
2755 initial =
3098 return
2756 return
3099− $ if minElems < 0
2757+ $ if n < 0
3100 then error
2758 then error
3101 $ functionName
2759 $ functionName
3102 ++ ": the size of arrays ["
2760 ++ ": the size of arrays ["
3103− ++ show minElems ++ "] must be a natural number"
2761+ ++ show n ++ "] must be a natural number"
3104 else FL.Partial Nothing
2762 else FL.Partial Nothing
3105
2763
3106 step Nothing arr =
2764 step Nothing arr =
3107 return
2765 return
3108 $ let len = byteLength arr
2766 $ let len = byteLength arr
3109− in if len >= minBytes
2767+ in if len >= nBytes
3110 then FL.Done arr
2768 then FL.Done arr
3111 else FL.Partial (Just arr)
2769 else FL.Partial (Just arr)
3112− -- XXX Buffer arrays as a list to avoid copy and reallocations
3113 step (Just buf) arr = do
2770 step (Just buf) arr = do
3114 let len = byteLength buf + byteLength arr
2771 let len = byteLength buf + byteLength arr
3115 buf1 <-
2772 buf1 <-
3116 if byteCapacity buf < len
2773 if byteCapacity buf < len
3117− then liftIO $ reallocExplicitAs
2774+ then liftIO $ realloc (max len nBytes) buf
3118− ps (SIZE_OF(a)) (max minBytes len) buf
3119 else return buf
2775 else return buf
3120 buf2 <- spliceUnsafe buf1 arr
2776 buf2 <- spliceUnsafe buf1 arr
3121− if len >= minBytes
2777+ if len >= n
3122 then return $ FL.Done buf2
2778 then return $ FL.Done buf2
3123 else return $ FL.Partial (Just buf2)
2779 else return $ FL.Partial (Just buf2)
3124
2780
3125 extract Nothing = return nil
2781 extract Nothing = return nil
3126 extract (Just buf) = return buf
2782 extract (Just buf) = return buf
3127
2783
3128−-- | Fold @fCompactGE minElems@ coalesces adjacent arrays in the input stream
2784+-- | Like 'compactGE' but for transforming folds instead of stream.
3129−-- until the size becomes greater than or equal to @minElems@.
3130--
2785--
3131−-- Generates unpinned arrays irrespective of the pinning status of input
2786+-- >>> lCompactGE n = Fold.many (MutArray.fCompactGE n)
3132−-- arrays.
2787+--
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 #-}
2788+{-# INLINE_NORMAL lCompactGE #-}
3147−lCompactGeAs :: forall m a. (MonadIO m, Unbox a)
2789+lCompactGE :: (MonadIO m, Unbox a)
3148− => PinnedState -> Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
2790+ => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
3149−-- The fold version turns out to be a little bit slower.
2791+-- lCompactGE n = Fold.many (fCompactGE n)
3150−-- lCompactGeAs ps n = FL.many (fCompactGeAs ps n)
3151−lCompactGeAs ps minElems (Fold step1 initial1 _ final1) =
2792+lCompactGE n (Fold step1 initial1 _ final1) =
3152 Fold step initial extract final
2793 Fold step initial extract final
3153
2794
3154 where
2795 where
3155
2796
3156− minBytes = minElems * SIZE_OF(a)
3157−
3158 functionName = "Streamly.Internal.Data.MutArray.lCompactGE"
2797 functionName = "Streamly.Internal.Data.MutArray.lCompactGE"
3159
2798
3160 initial = do
2799 initial = do
3161− when (minElems <= 0) $
2800+ when (n <= 0) $
3162 -- XXX we can pass the module string from the higher level API
2801 -- XXX we can pass the module string from the higher level API
3163 error $ functionName ++ ": the size of arrays ["
2802 error $ functionName ++ ": the size of arrays ["
3164− ++ show minElems ++ "] must be a natural number"
2803+ ++ show n ++ "] must be a natural number"
3165
2804
3166 r <- initial1
2805 r <- initial1
3167 return $ first (Tuple' Nothing) r
2806 return $ first (Tuple' Nothing) r
3168
2807
3169− {-# INLINE runInner #-}
2808+ step (Tuple' Nothing r1) arr =
3170− runInner len acc buf =
2809+ let len = byteLength arr
2810+ in if len >= n
2811+ then do
2812+ r <- step1 r1 arr
2813+ case r of
2814+ FL.Done _ -> return $ FL.Done ()
2815+ FL.Partial s -> do
2816+ _ <- final1 s
2817+ res <- initial1
2818+ return $ first (Tuple' Nothing) res
2819+ else return $ FL.Partial $ Tuple' (Just arr) r1
2820+
2821+ step (Tuple' (Just buf) r1) arr = do
2822+ let len = byteLength buf + byteLength arr
2823+ buf1 <- if byteCapacity buf < len
2824+ then liftIO $ realloc (max n len) buf
2825+ else return buf
2826+ buf2 <- spliceUnsafe buf1 arr
2827+
2828+ -- XXX this is common in both the equations of step
3171− if len >= minBytes
2829+ if len >= n
3172 then do
2830 then do
3173− r <- step1 acc buf
2831+ r <- step1 r1 buf2
3174 case r of
2832 case r of
3175 FL.Done _ -> return $ FL.Done ()
2833 FL.Done _ -> return $ FL.Done ()
3176 FL.Partial s -> do
2834 FL.Partial s -> do
3177 _ <- final1 s
2835 _ <- final1 s
3178 res <- initial1
2836 res <- initial1
3179 return $ first (Tuple' Nothing) res
2837 return $ first (Tuple' Nothing) res
3180− else return $ FL.Partial $ Tuple' (Just buf) acc
2838+ else return $ FL.Partial $ Tuple' (Just buf2) r1
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
2839
3195 -- XXX Several folds do extract >=> final, therefore, we need to make final
2840 -- 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
2841+ -- return "m b" rather than using extract post it if we want extract to be
3197 -- partial.
2842 -- partial.
3198 --
2843 --
3199 -- extract forces the pending buffer to be sent to the fold which is not
2844 -- extract forces the pending buffer to be sent to the fold which is not
@@ -3207,23 +2852,6 @@ lCompactGeAs ps minElems (Fold step1 initial1 _ final1) =
3207 FL.Partial rr -> final1 rr
2852 FL.Partial rr -> final1 rr
3208 FL.Done _ -> return ()
2853 FL.Done _ -> return ()
3209
2854
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
2855-- | @compactGE n stream@ coalesces adjacent arrays in the @stream@ until
3228-- the size becomes greater than or equal to @n@.
2856-- the size becomes greater than or equal to @n@.
3229--
2857--
core/src/Streamly/Internal/Data/MutByteArray/Type.hs+16−37
@@ -13,7 +13,7 @@ module Streamly.Internal.Data.MutByteArray.Type
13 -- ** MutByteArray
13 -- ** MutByteArray
14 MutByteArray(..)
14 MutByteArray(..)
15 , MutableByteArray
15 , MutableByteArray
16− , getMutableByteArray# -- XXX getMutByteArray#
16+ , getMutableByteArray#
17
17
18 -- ** Pinning
18 -- ** Pinning
19 , PinnedState(..)
19 , PinnedState(..)
@@ -22,24 +22,20 @@ module Streamly.Internal.Data.MutByteArray.Type
22 , unpin
22 , unpin
23
23
24 -- ** Allocation
24 -- ** Allocation
25− , empty
25+ , nil
26− , newBytesAs -- XXX should be removed
26+ , newBytesAs
27 , new
27 , new
28 , pinnedNew
28 , pinnedNew
29− , pinnedNewAlignedBytes -- XXX should be removed
29+ , pinnedNewAlignedBytes
30
30
31 -- ** Access
31 -- ** Access
32− , sizeOfMutableByteArray -- XXX length
32+ , sizeOfMutableByteArray
33 , putSliceUnsafe
33 , putSliceUnsafe
34 , cloneSliceUnsafeAs
34 , cloneSliceUnsafeAs
35 , cloneSliceUnsafe
35 , cloneSliceUnsafe
36 , pinnedCloneSliceUnsafe
36 , pinnedCloneSliceUnsafe
37− , unsafePinnedAsPtr
38− , unsafeAsPtr
39−
40− -- ** Deprecated
41 , asPtrUnsafe
37 , asPtrUnsafe
42− , nil
38+ , asUnpinnedPtrUnsafe
43 ) where
39 ) where
44
40
45import Control.Monad.IO.Class (MonadIO(..))
41import Control.Monad.IO.Class (MonadIO(..))
@@ -58,7 +54,7 @@ import GHC.Exts
58
54
59data PinnedState
55data PinnedState
60 = Pinned
56 = Pinned
61− | Unpinned deriving (Show, Eq)
57+ | Unpinned
62
58
63-- XXX can use UnliftedNewtypes
59-- XXX can use UnliftedNewtypes
64
60
@@ -118,9 +114,9 @@ touch (MutByteArray contents) =
118--
114--
119-- /Pre-release/
115-- /Pre-release/
120--
116--
121−{-# INLINE unsafePinnedAsPtr #-}
117+{-# INLINE asPtrUnsafe #-}
122−unsafePinnedAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
118+asPtrUnsafe :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
123−unsafePinnedAsPtr arr f = do
119+asPtrUnsafe arr f = do
124 contents <- liftIO $ pin arr
120 contents <- liftIO $ pin arr
125 let !ptr = Ptr (byteArrayContents#
121 let !ptr = Ptr (byteArrayContents#
126 (unsafeCoerce# (getMutableByteArray# contents)))
122 (unsafeCoerce# (getMutableByteArray# contents)))
@@ -128,15 +124,10 @@ unsafePinnedAsPtr arr f = do
128 liftIO $ touch contents
124 liftIO $ touch contents
129 return r
125 return r
130
126
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.
127-- | For use with unsafe FFI functions. Does not force pin the array memory.
137−{-# INLINE unsafeAsPtr #-}
128+{-# INLINE asUnpinnedPtrUnsafe #-}
138−unsafeAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
129+asUnpinnedPtrUnsafe :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
139−unsafeAsPtr arr f = do
130+asUnpinnedPtrUnsafe arr f = do
140 let !ptr = Ptr (byteArrayContents#
131 let !ptr = Ptr (byteArrayContents#
141 (unsafeCoerce# (getMutableByteArray# arr)))
132 (unsafeCoerce# (getMutableByteArray# arr)))
142 r <- f ptr
133 r <- f ptr
@@ -147,16 +138,10 @@ unsafeAsPtr arr f = do
147-- Creation
138-- Creation
148--------------------------------------------------------------------------------
139--------------------------------------------------------------------------------
149
140
150−{-# NOINLINE empty #-}
141+{-# NOINLINE nil #-}
151−empty :: MutByteArray
152−empty = unsafePerformIO $ new 0
153−
154−{-# DEPRECATED nil "Please use empty instead" #-}
155nil :: MutByteArray
142nil :: MutByteArray
156−nil = empty
143+nil = unsafePerformIO $ new 0
157
144
158−-- XXX add "newRounded" to round up the large size to the next page boundary
159−-- and return the allocated size.
160{-# INLINE new #-}
145{-# INLINE new #-}
161new :: Int -> IO MutByteArray
146new :: Int -> IO MutByteArray
162new nbytes | nbytes < 0 =
147new nbytes | nbytes < 0 =
@@ -170,7 +155,7 @@ new (I# nbytes) = IO $ \s ->
170{-# INLINE pinnedNew #-}
155{-# INLINE pinnedNew #-}
171pinnedNew :: Int -> IO MutByteArray
156pinnedNew :: Int -> IO MutByteArray
172pinnedNew nbytes | nbytes < 0 =
157pinnedNew nbytes | nbytes < 0 =
173− errorWithoutStackTrace "pinnedNew: size must be >= 0"
158+ errorWithoutStackTrace "pinnedNewByteArray: size must be >= 0"
174pinnedNew (I# nbytes) = IO $ \s ->
159pinnedNew (I# nbytes) = IO $ \s ->
175 case newPinnedByteArray# nbytes s of
160 case newPinnedByteArray# nbytes s of
176 (# s', mbarr# #) ->
161 (# s', mbarr# #) ->
@@ -196,12 +181,6 @@ newBytesAs Pinned = pinnedNew
196-- Copying
181-- Copying
197-------------------------------------------------------------------------------
182-------------------------------------------------------------------------------
198
183
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−
205-- | Put a sub range of a source array into a subrange of a destination array.
184-- | Put a sub range of a source array into a subrange of a destination array.
206-- This is not safe as it does not check the bounds of neither the src array
185-- This is not safe as it does not check the bounds of neither the src array
207-- nor the destination array.
186-- nor the destination array.
core/src/Streamly/Internal/Data/Serialize/TH.hs+1−5
@@ -7,11 +7,7 @@
7-- Maintainer : streamly@composewell.com
7-- Maintainer : streamly@composewell.com
8-- Stability : experimental
8-- Stability : experimental
9-- Portability : GHC
9-- Portability : GHC
10−
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−
15module Streamly.Internal.Data.Serialize.TH
11module Streamly.Internal.Data.Serialize.TH
16 (
12 (
17 -- Deriving
13 -- Deriving
core/src/Streamly/Internal/Data/Stream/Container.hs+48−56
@@ -11,17 +11,16 @@
11
11
12module Streamly.Internal.Data.Stream.Container
12module Streamly.Internal.Data.Stream.Container
13 (
13 (
14− -- * Deduplication
14+ nub
15− ordNub
16
15
17− -- * Joins
16+ -- * Joins for unconstrained types
18− , leftJoin
17+ , joinLeftGeneric
19− , outerJoin
18+ , joinOuterGeneric
20
19
21− -- * Ord Joins
20+ -- * Joins with Ord constraint
22− , innerOrdJoin
21+ , joinInner
23− , leftOrdJoin
22+ , joinLeft
24− , outerOrdJoin
23+ , joinOuter
25 )
24 )
26where
25where
27
26
@@ -48,15 +47,12 @@ import qualified Streamly.Internal.Data.Stream.Transformer as Stream
48
47
49#include "DocTestDataStream.hs"
48#include "DocTestDataStream.hs"
50
49
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
50+-- | 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
51+-- stream. If we want to limit the memory we can just use "take" to limit the
56−-- stream to limit the unique elements in the stream.
52+-- uniq elements in the stream.
57−{-# INLINE_NORMAL ordNub #-}
53+{-# INLINE_NORMAL nub #-}
58−ordNub :: (Monad m, Ord a) => Stream m a -> Stream m a
54+nub :: (Monad m, Ord a) => Stream m a -> Stream m a
59−ordNub (Stream step1 state1) = Stream step (Set.empty, state1)
55+nub (Stream step1 state1) = Stream step (Set.empty, state1)
60
56
61 where
57 where
62
58
@@ -82,8 +78,8 @@ toMap =
82--
78--
83-- XXX An IntMap may be faster when the keys are Int.
79-- XXX An IntMap may be faster when the keys are Int.
84-- XXX Use hashmap instead of map?
80-- XXX Use hashmap instead of map?
85−
81+--
86−-- | 'innerJoin' specialized to 'Ord' types for better performance.
82+-- | Like 'joinInner' but uses a 'Map' for efficiency.
87--
83--
88-- If the input streams have duplicate keys, the behavior is undefined.
84-- If the input streams have duplicate keys, the behavior is undefined.
89--
85--
@@ -94,10 +90,10 @@ toMap =
94-- Time: O(m + n)
90-- Time: O(m + n)
95--
91--
96-- /Pre-release/
92-- /Pre-release/
97−{-# INLINE innerOrdJoin #-}
93+{-# INLINE joinInner #-}
98−innerOrdJoin :: (Monad m, Ord k) =>
94+joinInner :: (Monad m, Ord k) =>
99 Stream m (k, a) -> Stream m (k, b) -> Stream m (k, a, b)
95 Stream m (k, a) -> Stream m (k, b) -> Stream m (k, a, b)
100−innerOrdJoin s1 s2 =
96+joinInner s1 s2 =
101 Stream.concatEffect $ do
97 Stream.concatEffect $ do
102 km <- toMap s2
98 km <- toMap s2
103 pure $ Stream.mapMaybe (joinAB km) s1
99 pure $ Stream.mapMaybe (joinAB km) s1
@@ -110,33 +106,32 @@ innerOrdJoin s1 s2 =
110 Nothing -> Nothing
106 Nothing -> Nothing
111
107
112-- XXX We can do this concurrently.
108-- XXX We can do this concurrently.
113−-- XXX Check performance of StreamD vs StreamK
114-- XXX If the second stream is sorted and passed as an Array or a seek capable
109-- XXX If the second stream is sorted and passed as an Array or a seek capable
115-- stream then we could use binary search if we have an Ord instance or
110-- stream then we could use binary search if we have an Ord instance or
116-- Ordering returning function. The time complexity would then become (m x log
111-- Ordering returning function. The time complexity would then become (m x log
117-- n).
112-- n).
118
113
119−-- | Like 'innerJoin' but emits @(a, Just b)@ whenever a and b are equal, for
114+-- XXX Check performance of StreamD vs StreamK
115+
116+-- | Like 'joinInner' but emit @(a, Just b)@, and additionally, for those @a@'s
120−-- those @a@'s that are not equal to any @b@ emits @(a, Nothing)@.
117+-- that are not equal to any @b@ emit @(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.
125--
118--
126−-- All the caveats mentioned in 'innerJoin' apply here as well. Right join is
119+-- The second stream is evaluated multiple times. If the stream is a
127−-- not provided because it is just a flipped left join:
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.
128--
123--
129−-- >>> rightJoin eq = flip (Stream.leftJoin eq)
124+-- >>> joinRightGeneric eq = flip (Stream.joinLeftGeneric eq)
130--
125--
131-- Space: O(n) assuming the second stream is cached in memory.
126-- Space: O(n) assuming the second stream is cached in memory.
132--
127--
133-- Time: O(m x n)
128-- Time: O(m x n)
134--
129--
135-- /Unimplemented/
130-- /Unimplemented/
136−{-# INLINE leftJoin #-}
131+{-# INLINE joinLeftGeneric #-}
137−leftJoin :: Monad m =>
132+joinLeftGeneric :: Monad m =>
138 (a -> b -> Bool) -> Stream m a -> Stream m b -> Stream m (a, Maybe b)
133 (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
140 a <- mkCross (Stream.liftInner s1)
135 a <- mkCross (Stream.liftInner s1)
141 -- XXX should we use StreamD monad here?
136 -- XXX should we use StreamD monad here?
142 -- XXX Is there a better way to perform some action at the end of a loop
137 -- 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
157 else mkCross Stream.nil
152 else mkCross Stream.nil
158 Nothing -> return (a, Nothing)
153 Nothing -> return (a, Nothing)
159
154
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.
161--
158--
162-- Space: O(n)
159-- Space: O(n)
163--
160--
164-- Time: O(m + n)
161-- Time: O(m + n)
165--
162--
166-- /Pre-release/
163-- /Pre-release/
167−{-# INLINE leftOrdJoin #-}
164+{-# INLINE joinLeft #-}
168−leftOrdJoin :: (Ord k, Monad m) =>
165+joinLeft :: (Ord k, Monad m) =>
169 Stream m (k, a) -> Stream m (k, b) -> Stream m (k, a, Maybe b)
166 Stream m (k, a) -> Stream m (k, b) -> Stream m (k, a, Maybe b)
170−leftOrdJoin s1 s2 =
167+joinLeft s1 s2 =
171 Stream.concatEffect $ do
168 Stream.concatEffect $ do
172 km <- toMap s2
169 km <- toMap s2
173 return $ fmap (joinAB km) s1
170 return $ fmap (joinAB km) s1
@@ -180,19 +177,14 @@ leftOrdJoin s1 s2 =
180 Nothing -> (k, a, Nothing)
177 Nothing -> (k, a, Nothing)
181
178
182-- XXX We can do this concurrently.
179-- XXX We can do this concurrently.
183−-- XXX Check performance of StreamD vs StreamK cross operation.
184
180
181+-- XXX Check performance of StreamD vs StreamK
182+
185−-- | Like 'leftJoin' but emits a @(Just a, Just b)@. Like 'leftJoin', for those
183+-- | Like 'joinLeft' but emits a @(Just a, Just b)@. Like 'joinLeft', for those
186-- @a@'s that are not equal to any @b@ emit @(Just a, Nothing)@, but
184-- @a@'s that are not equal to any @b@ emit @(Just a, Nothing)@, but
187-- additionally, for those @b@'s that are not equal to any @a@ emit @(Nothing,
185-- additionally, for those @b@'s that are not equal to any @a@ emit @(Nothing,
188-- Just b)@.
186-- Just b)@.
189--
187--
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−--
196-- For space efficiency use the smaller stream as the second stream.
188-- For space efficiency use the smaller stream as the second stream.
197--
189--
198-- Space: O(n)
190-- Space: O(n)
@@ -200,15 +192,15 @@ leftOrdJoin s1 s2 =
200-- Time: O(m x n)
192-- Time: O(m x n)
201--
193--
202-- /Pre-release/
194-- /Pre-release/
203−{-# INLINE outerJoin #-}
195+{-# INLINE joinOuterGeneric #-}
204−outerJoin :: MonadIO m =>
196+joinOuterGeneric :: MonadIO m =>
205 (a -> b -> Bool)
197 (a -> b -> Bool)
206 -> Stream m a
198 -> Stream m a
207 -> Stream m b
199 -> Stream m b
208 -> Stream m (Maybe a, Maybe b)
200 -> Stream m (Maybe a, Maybe b)
209−outerJoin eq s1 s2 =
201+joinOuterGeneric eq s1 s =
210 Stream.concatEffect $ do
202 Stream.concatEffect $ do
211− inputArr <- Array.fromStream s2
203+ inputArr <- Array.fromStream s
212 let len = Array.length inputArr
204 let len = Array.length inputArr
213 foundArr <-
205 foundArr <-
214 Stream.fold
206 Stream.fold
@@ -262,18 +254,18 @@ outerJoin eq s1 s2 =
262-- a flag. At the end go through @Stream m b@ and find those that are not in that
254-- a flag. At the end go through @Stream m b@ and find those that are not in that
263-- hash to return (Nothing, b).
255-- hash to return (Nothing, b).
264
256
265−-- | 'outerJoin' specialized to 'Ord' types for better performance.
257+-- | Like 'joinOuter' but uses a 'Map' for efficiency.
266--
258--
267-- Space: O(m + n)
259-- Space: O(m + n)
268--
260--
269-- Time: O(m + n)
261-- Time: O(m + n)
270--
262--
271-- /Pre-release/
263-- /Pre-release/
272−{-# INLINE outerOrdJoin #-}
264+{-# INLINE joinOuter #-}
273−outerOrdJoin ::
265+joinOuter ::
274 (Ord k, MonadIO m) =>
266 (Ord k, MonadIO m) =>
275 Stream m (k, a) -> Stream m (k, b) -> Stream m (k, Maybe a, Maybe b)
267 Stream m (k, a) -> Stream m (k, b) -> Stream m (k, Maybe a, Maybe b)
276−outerOrdJoin s1 s2 =
268+joinOuter s1 s2 =
277 Stream.concatEffect $ do
269 Stream.concatEffect $ do
278 km1 <- kvFold s1
270 km1 <- kvFold s1
279 km2 <- kvFold s2
271 km2 <- kvFold s2
core/src/Streamly/Internal/Data/Stream/Eliminate.hs+25−33
@@ -13,24 +13,36 @@
13--
13--
14module Streamly.Internal.Data.Stream.Eliminate
14module Streamly.Internal.Data.Stream.Eliminate
15 (
15 (
16− -- * Running a Parser
16+ -- * Running a 'Fold'
17+ fold
18+
19+ -- -- * Running a 'Parser'
17− parse
20+ , parse
18 , parseD
21 , parseD
19 , parseBreak
22 , parseBreak
20 , parseBreakD
23 , parseBreakD
21
24
22− -- * Deconstruction
25+ -- * Stream Deconstruction
23 , uncons
26 , uncons
24
27
25 -- * Right Folds
28 -- * Right Folds
29+ , foldrM
30+ , foldr
31+ , foldrMx
26 , foldr1
32 , foldr1
27
33
34+ -- * Left Folds
35+ , foldlM'
36+ , foldl'
37+ , foldlMx'
38+ , foldlx'
39+
28 -- * Specific Fold Functions
40 -- * Specific Fold Functions
41+ , drain
29 , mapM_ -- Map and Fold
42 , mapM_ -- Map and Fold
30 , null
43 , null
31 , head
44 , head
32 , headElse
45 , headElse
33− , init
34 , tail
46 , tail
35 , last
47 , last
36 , elem
48 , elem
@@ -48,9 +60,16 @@ module Streamly.Internal.Data.Stream.Eliminate
48 , the
60 , the
49
61
50 -- * To containers
62 -- * To containers
63+ , toList
51 , toListRev
64 , toListRev
52
65
53 -- * Multi-Stream Folds
66 -- * Multi-Stream Folds
67+ -- ** Comparisons
68+ -- | These should probably be expressed using zipping operations.
69+ , eqBy
70+ , cmpBy
71+
72+ -- ** Substreams
54 -- | These should probably be expressed using parsers.
73 -- | These should probably be expressed using parsers.
55 , isPrefixOf
74 , isPrefixOf
56 , isInfixOf
75 , isInfixOf
@@ -71,7 +90,7 @@ import Foreign.Storable (Storable)
71import GHC.Exts (SpecConstrAnnotation(..))
90import GHC.Exts (SpecConstrAnnotation(..))
72import GHC.Types (SPEC(..))
91import GHC.Types (SPEC(..))
73import Streamly.Internal.Data.Parser (ParseError(..))
92import Streamly.Internal.Data.Parser (ParseError(..))
74−import Streamly.Internal.Data.SVar.Type (adaptState, defState)
93+import Streamly.Internal.Data.SVar.Type (defState)
75import Streamly.Internal.Data.Unbox (Unbox)
94import Streamly.Internal.Data.Unbox (Unbox)
76
95
77import Streamly.Internal.Data.Maybe.Strict (Maybe'(..))
96import Streamly.Internal.Data.Maybe.Strict (Maybe'(..))
@@ -86,7 +105,7 @@ import qualified Streamly.Internal.Data.Stream.Transform as StreamD
86
105
87import Prelude hiding
106import Prelude hiding
88 ( Foldable(..), all, any, head, last, lookup, mapM, mapM_
107 ( Foldable(..), all, any, head, last, lookup, mapM, mapM_
89− , notElem, splitAt, init, tail, (!!))
108+ , notElem, splitAt, tail, (!!))
90import Data.Foldable (length)
109import Data.Foldable (length)
91import Streamly.Internal.Data.Stream.Type
110import Streamly.Internal.Data.Stream.Type
92
111
@@ -372,35 +391,9 @@ head = foldrM (\x _ -> return (Just x)) (return Nothing)
372headElse :: Monad m => a -> Stream m a -> m a
391headElse :: Monad m => a -> Stream m a -> m a
373headElse a = foldrM (\x _ -> return x) (return a)
392headElse a = foldrM (\x _ -> return x) (return a)
374
393
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−--
398-- Does not fuse, has the same performance as the StreamK version.
394-- Does not fuse, has the same performance as the StreamK version.
399−--
400{-# INLINE_NORMAL tail #-}
395{-# INLINE_NORMAL tail #-}
401tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
396tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
402−tail = fmap (fmap snd) . uncons
403−{-
404tail (UnStream step state) = go SPEC state
397tail (UnStream step state) = go SPEC state
405 where
398 where
406 go !_ st = do
399 go !_ st = do
@@ -409,7 +402,6 @@ tail (UnStream step state) = go SPEC state
409 Yield _ s -> return (Just $ Stream step s)
402 Yield _ s -> return (Just $ Stream step s)
410 Skip s -> go SPEC s
403 Skip s -> go SPEC s
411 Stop -> return Nothing
404 Stop -> return Nothing
412−-}
413
405
414-- XXX will it fuse? need custom impl?
406-- XXX will it fuse? need custom impl?
415{-# INLINE_NORMAL last #-}
407{-# INLINE_NORMAL last #-}
core/src/Streamly/Internal/Data/Stream/Exception.hs+6−9
@@ -9,20 +9,17 @@
9
9
10module Streamly.Internal.Data.Stream.Exception
10module Streamly.Internal.Data.Stream.Exception
11 (
11 (
12− -- * Resources
13− before
14− , afterIO
15− , afterUnsafe
16− , finallyIO
17− , finallyUnsafe
18− , gbracket_
12+ gbracket_
19 , gbracket
13 , gbracket
14+ , before
15+ , afterUnsafe
16+ , afterIO
20 , bracketUnsafe
17 , bracketUnsafe
21 , bracketIO3
18 , bracketIO3
22 , bracketIO
19 , bracketIO
23−
24− -- * Exceptions
25 , onException
20 , onException
21+ , finallyUnsafe
22+ , finallyIO
26 , ghandle
23 , ghandle
27 , handle
24 , handle
28 )
25 )
core/src/Streamly/Internal/Data/Stream/Generate.hs+12
@@ -16,13 +16,20 @@ module Streamly.Internal.Data.Stream.Generate
16 (
16 (
17 -- * Primitives
17 -- * Primitives
18 nil
18 nil
19+ , nilM
19 , cons
20 , cons
21+ , consM
22+
23+ -- * From 'Unfold'
24+ , unfold
20
25
21 -- * Unfolding
26 -- * Unfolding
22 , unfoldr
27 , unfoldr
23 , unfoldrM
28 , unfoldrM
24
29
25 -- * From Values
30 -- * From Values
31+ , fromPure
32+ , fromEffect
26 , repeat
33 , repeat
27 , repeatM
34 , repeatM
28 , replicate
35 , replicate
@@ -88,6 +95,7 @@ module Streamly.Internal.Data.Stream.Generate
88 -- * From Containers
95 -- * From Containers
89 -- | Transform an input structure into a stream.
96 -- | Transform an input structure into a stream.
90
97
98+ , fromList
91 , fromListM
99 , fromListM
92 , fromFoldable
100 , fromFoldable
93 , fromFoldableM
101 , fromFoldableM
@@ -96,6 +104,10 @@ module Streamly.Internal.Data.Stream.Generate
96 , fromPtr
104 , fromPtr
97 , fromPtrN
105 , fromPtrN
98 , fromByteStr#
106 , fromByteStr#
107+
108+ -- * Conversions
109+ , fromStreamK
110+ , toStreamK
99 )
111 )
100where
112where
101
113
core/src/Streamly/Internal/Data/Stream/Nesting.hs+64−10
@@ -55,6 +55,11 @@ module Streamly.Internal.Data.Stream.Nesting
55 -- yields an element. A special case of unfoldRoundRobin.
55 -- yields an element. A special case of unfoldRoundRobin.
56 , roundRobin -- interleaveFair?/ParallelFair
56 , roundRobin -- interleaveFair?/ParallelFair
57
57
58+ -- *** Zipping
59+ -- | Zip corresponding elements of two streams.
60+ , zipWith
61+ , zipWithM
62+
58 -- *** Merging
63 -- *** Merging
59 -- | Interleave elements from two streams based on a condition.
64 -- | Interleave elements from two streams based on a condition.
60 , mergeBy
65 , mergeBy
@@ -71,10 +76,17 @@ module Streamly.Internal.Data.Stream.Nesting
71 -- unfoldMany: Unfold m a b -> t m a -> t m b
76 -- unfoldMany: Unfold m a b -> t m a -> t m b
72 -- @
77 -- @
73
78
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+
74 -- *** ConcatUnfold
85 -- *** ConcatUnfold
75 -- | Generate streams by using an unfold on each element of an input
86 -- | Generate streams by using an unfold on each element of an input
76 -- stream, append the resulting streams and flatten. A special case of
87 -- stream, append the resulting streams and flatten. A special case of
77 -- gintercalate.
88 -- gintercalate.
89+ , unfoldMany
78 , ConcatUnfoldInterleaveState (..)
90 , ConcatUnfoldInterleaveState (..)
79 , unfoldInterleave
91 , unfoldInterleave
80 , unfoldRoundRobin
92 , unfoldRoundRobin
@@ -106,8 +118,11 @@ module Streamly.Internal.Data.Stream.Nesting
106
118
107 -- ** Folding
119 -- ** Folding
108 -- | Apply folds on a stream.
120 -- | Apply folds on a stream.
121+ , foldMany
122+ , refoldMany
109 , foldSequence
123 , foldSequence
110 , foldIterateM
124 , foldIterateM
125+ , refoldIterateM
111
126
112 -- ** Parsing
127 -- ** Parsing
113 -- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
128 -- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
@@ -124,6 +139,7 @@ module Streamly.Internal.Data.Stream.Nesting
124
139
125 -- ** Grouping
140 -- ** Grouping
126 -- | Group segments of a stream and fold. Special case of parsing.
141 -- | Group segments of a stream and fold. Special case of parsing.
142+ , groupsOf
127 , groupsBy
143 , groupsBy
128 , groupsWhile
144 , groupsWhile
129 , groupsRollingBy
145 , groupsRollingBy
@@ -131,8 +147,8 @@ module Streamly.Internal.Data.Stream.Nesting
131 -- ** Splitting
147 -- ** Splitting
132 -- | A special case of parsing.
148 -- | A special case of parsing.
133 , wordsBy
149 , wordsBy
134− , splitOnSeq -- XXX splitOnSeg
150+ , splitOnSeq
135− , splitOnSuffixSeq -- XXX splitOnSegSuffix, splitOnTrailer
151+ , splitOnSuffixSeq
136
152
137 -- XXX Implement these as folds or parsers instead.
153 -- XXX Implement these as folds or parsers instead.
138 , splitOnSuffixSeqAny
154 , splitOnSuffixSeqAny
@@ -141,8 +157,9 @@ module Streamly.Internal.Data.Stream.Nesting
141
157
142 -- * Transform (Nested Containers)
158 -- * Transform (Nested Containers)
143 -- | Opposite to compact in ArrayStream
159 -- | Opposite to compact in ArrayStream
144− , splitInnerBy -- XXX innerSplitOn
160+ , splitInnerBy
145− , splitInnerBySuffix -- XXX innerSplitOnSuffix
161+ , splitInnerBySuffix
162+ , intersectBySorted
146
163
147 -- * Reduce By Streams
164 -- * Reduce By Streams
148 , dropPrefix
165 , dropPrefix
@@ -592,6 +609,49 @@ mergeFstBy :: -- Monad m =>
592mergeFstBy _f _m1 _m2 = undefined
609mergeFstBy _f _m1 _m2 = undefined
593 -- fromStreamK $ D.mergeFstBy f (toStreamD m1) (toStreamD m2)
610 -- fromStreamK $ D.mergeFstBy f (toStreamD m1) (toStreamD m2)
594
611
612+-------------------------------------------------------------------------------
613+-- Intersection of sorted streams
614+-------------------------------------------------------------------------------
615+
616+-- Assuming the streams are sorted in ascending order
617+{-# INLINE_NORMAL intersectBySorted #-}
618+intersectBySorted :: Monad m
619+ => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
620+intersectBySorted cmp (Stream stepa ta) (Stream stepb tb) =
621+ Stream step
622+ ( ta -- left stream state
623+ , tb -- right stream state
624+ , Nothing -- left value
625+ , Nothing -- right value
626+ )
627+
628+ where
629+
630+ {-# INLINE_LATE step #-}
631+ -- step 1, fetch the first value
632+ step gst (sa, sb, Nothing, b) = do
633+ r <- stepa gst sa
634+ return $ case r of
635+ Yield a sa' -> Skip (sa', sb, Just a, b) -- step 2/3
636+ Skip sa' -> Skip (sa', sb, Nothing, b)
637+ Stop -> Stop
638+
639+ -- step 2, fetch the second value
640+ step gst (sa, sb, a@(Just _), Nothing) = do
641+ r <- stepb gst sb
642+ return $ case r of
643+ Yield b sb' -> Skip (sa, sb', a, Just b) -- step 3
644+ Skip sb' -> Skip (sa, sb', a, Nothing)
645+ Stop -> Stop
646+
647+ -- step 3, compare the two values
648+ step _ (sa, sb, Just a, Just b) = do
649+ let res = cmp a b
650+ return $ case res of
651+ GT -> Skip (sa, sb, Just a, Nothing) -- step 2
652+ LT -> Skip (sa, sb, Nothing, Just b) -- step 1
653+ EQ -> Yield a (sa, sb, Nothing, Just b) -- step 1
654+
595------------------------------------------------------------------------------
655------------------------------------------------------------------------------
596-- Combine N Streams - unfoldMany
656-- Combine N Streams - unfoldMany
597------------------------------------------------------------------------------
657------------------------------------------------------------------------------
@@ -2986,8 +3046,6 @@ splitInnerBySuffix isEmpty splitter joiner (Stream step1 state1) =
2986--
3046--
2987-- Space: @O(1)@
3047-- Space: @O(1)@
2988--
3048--
2989−-- See also stripPrefix.
2990−--
2991-- /Unimplemented/
3049-- /Unimplemented/
2992{-# INLINE dropPrefix #-}
3050{-# INLINE dropPrefix #-}
2993dropPrefix ::
3051dropPrefix ::
@@ -3000,8 +3058,6 @@ dropPrefix = error "Not implemented yet!"
3000--
3058--
3001-- Space: @O(n)@ where n is the length of the infix.
3059-- Space: @O(n)@ where n is the length of the infix.
3002--
3060--
3003−-- See also stripInfix.
3004−--
3005-- /Unimplemented/
3061-- /Unimplemented/
3006{-# INLINE dropInfix #-}
3062{-# INLINE dropInfix #-}
3007dropInfix ::
3063dropInfix ::
@@ -3014,8 +3070,6 @@ dropInfix = error "Not implemented yet!"
3014--
3070--
3015-- Space: @O(n)@ where n is the length of the suffix.
3071-- Space: @O(n)@ where n is the length of the suffix.
3016--
3072--
3017−-- See also stripSuffix.
3018−--
3019-- /Unimplemented/
3073-- /Unimplemented/
3020{-# INLINE dropSuffix #-}
3074{-# INLINE dropSuffix #-}
3021dropSuffix ::
3075dropSuffix ::
core/src/Streamly/Internal/Data/Stream/Top.hs+115−243
@@ -8,73 +8,38 @@
8-- Portability : GHC
8-- Portability : GHC
9--
9--
10-- Top level module that can depend on all other lower level Stream modules.
10-- 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.
48
11
49module Streamly.Internal.Data.Stream.Top
12module Streamly.Internal.Data.Stream.Top
50 (
13 (
14+ -- * Transformation
51− -- * Sampling
15+ -- ** Sampling
52 -- | Value agnostic filtering.
16 -- | Value agnostic filtering.
53 strideFromThen
17 strideFromThen
54
18
55− -- * Straight Joins
19+ -- * Nesting
20+ -- ** Set like operations
56− -- | These are set-like operations but not exactly set operations because
21+ -- | These are not exactly set operations because streams are not
57− -- streams are not necessarily sets, they may have duplicated elements.
22+ -- necessarily sets, they may have duplicated elements. These operations
58− -- These operations are generic i.e. they work on streams of unconstrained
23+ -- are generic i.e. they work on streams of unconstrained types, therefore,
59− -- types, therefore, they have quadratic performance characterstics. For
24+ -- they have quadratic performance characterstics. For better performance
60− -- better performance using Set or Map structures see the
61− -- Streamly.Internal.Data.Stream.Container module.
25+ -- using Set structures see the Streamly.Internal.Data.Stream.Container
62− , intersectBy
26+ -- module.
63− , deleteFirstsBy
27+ , filterInStreamGenericBy
64− , unionBy
28+ , deleteInStreamGenericBy
65−
29+ , unionWithStreamGenericBy
30+
66− -- Set like operations on sorted streams
31+ -- ** Set like operations on sorted streams
67− , sortedIntersectBy
32+ , filterInStreamAscBy
68− , sortedDeleteFirstsBy
33+ , deleteInStreamAscBy
69− , sortedUnionBy
34+ , unionWithStreamAscBy
70−
35+
71− -- * Cross Joins
36+ -- ** Join operations
72− , innerJoin
37+ , joinInnerGeneric
73−
38+
74− -- Joins on sorted stream
39+ -- * Joins on sorted stream
75− , innerSortedJoin
40+ , joinInnerAscBy
76− , leftSortedJoin
41+ , joinLeftAscBy
77− , outerSortedJoin
42+ , joinOuterAscBy
78 )
43 )
79where
44where
80
45
@@ -83,7 +48,7 @@ where
83import Control.Monad.IO.Class (MonadIO(..))
48import Control.Monad.IO.Class (MonadIO(..))
84import Data.IORef (newIORef, readIORef, modifyIORef')
49import Data.IORef (newIORef, readIORef, modifyIORef')
85import Streamly.Internal.Data.Fold.Type (Fold)
50import 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)
87
52
88import qualified Data.List as List
53import qualified Data.List as List
89import qualified Streamly.Internal.Data.Fold as Fold
54import qualified Streamly.Internal.Data.Fold as Fold
@@ -145,40 +110,29 @@ strideFromThen offset stride =
145-- binary search if we have an Ord instance or Ordering returning function. The
110-- binary search if we have an Ord instance or Ordering returning function. The
146-- time complexity would then become (m x log n).
111-- time complexity would then become (m x log n).
147
112
148−-- | Like 'cross' but emits only those tuples where @a == b@ using the supplied
113+-- | Like 'cross' but emits only those tuples where @a == b@ using the
149−-- equality predicate. This is essentially a @cross intersection@ of two
114+-- supplied equality predicate.
150−-- streams.
151--
115--
152-- Definition:
116-- Definition:
153--
117--
154−-- >>> innerJoin eq s1 s2 = Stream.filter (\(a, b) -> a `eq` b) $ Stream.cross s1 s2
118+-- >>> joinInnerGeneric 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.
162--
119--
163−-- If you care about performance this function should be your last choice among
120+-- You should almost always prefer @joinInnerOrd@ over 'joinInnerGeneric' if
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
121+-- possible. @joinInnerOrd@ is an order of magnitude faster but may take more
167−-- the type has an 'Ord' instance.
122+-- space for caching the second stream.
168--
123--
169−-- Note: Conceptually, this is a commutative operation. Result includes all the
124+-- See 'Streamly.Internal.Data.Unfold.joinInnerGeneric' for a much faster fused
170−-- elements from the left and the right stream. The order of streams can be
125+-- alternative.
171−-- changed without affecting results, except for the ordering within the tuple.
172--
126--
173-- Time: O(m x n)
127-- Time: O(m x n)
174--
128--
175-- /Pre-release/
129-- /Pre-release/
176−{-# INLINE innerJoin #-}
130+{-# INLINE joinInnerGeneric #-}
177−innerJoin :: Monad m =>
131+joinInnerGeneric :: Monad m =>
178 (a -> b -> Bool) -> Stream m a -> Stream m b -> Stream m (a, b)
132 (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
180{-
134{-
181−innerJoin eq s1 s2 = do
135+joinInnerGeneric eq s1 s2 = do
182 -- ConcatMap works faster than bind
136 -- ConcatMap works faster than bind
183 Stream.concatMap (\a ->
137 Stream.concatMap (\a ->
184 Stream.concatMap (\b ->
138 Stream.concatMap (\b ->
@@ -189,44 +143,44 @@ innerJoin eq s1 s2 = do
189 ) s1
143 ) s1
190-}
144-}
191
145
192−-- | A more efficient 'innerJoin' for sorted streams.
146+-- | A more efficient 'joinInner' for sorted streams.
193--
147--
194-- Space: O(1)
148-- Space: O(1)
195--
149--
196-- Time: O(m + n)
150-- Time: O(m + n)
197--
151--
198-- /Unimplemented/
152-- /Unimplemented/
199−{-# INLINE innerSortedJoin #-}
153+{-# INLINE joinInnerAscBy #-}
200−innerSortedJoin ::
154+joinInnerAscBy ::
201 (a -> b -> Ordering) -> Stream m a -> Stream m b -> Stream m (a, b)
155 (a -> b -> Ordering) -> Stream m a -> Stream m b -> Stream m (a, b)
202−innerSortedJoin = undefined
156+joinInnerAscBy = undefined
203
157
204−-- | A more efficient 'leftJoin' for sorted streams.
158+-- | A more efficient 'joinLeft' for sorted streams.
205--
159--
206-- Space: O(1)
160-- Space: O(1)
207--
161--
208-- Time: O(m + n)
162-- Time: O(m + n)
209--
163--
210-- /Unimplemented/
164-- /Unimplemented/
211−{-# INLINE leftSortedJoin #-}
165+{-# INLINE joinLeftAscBy #-}
212−leftSortedJoin :: -- Monad m =>
166+joinLeftAscBy :: -- Monad m =>
213 (a -> b -> Ordering) -> Stream m a -> Stream m b -> Stream m (a, Maybe b)
167 (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
215
169
216−-- | A more efficient 'outerJoin' for sorted streams.
170+-- | A more efficient 'joinOuter' for sorted streams.
217--
171--
218-- Space: O(1)
172-- Space: O(1)
219--
173--
220-- Time: O(m + n)
174-- Time: O(m + n)
221--
175--
222-- /Unimplemented/
176-- /Unimplemented/
223−{-# INLINE outerSortedJoin #-}
177+{-# INLINE joinOuterAscBy #-}
224−outerSortedJoin :: -- Monad m =>
178+joinOuterAscBy :: -- Monad m =>
225 (a -> b -> Ordering)
179 (a -> b -> Ordering)
226 -> Stream m a
180 -> Stream m a
227 -> Stream m b
181 -> Stream m b
228 -> Stream m (Maybe a, Maybe b)
182 -> Stream m (Maybe a, Maybe b)
229−outerSortedJoin _eq _s1 _s2 = undefined
183+joinOuterAscBy _eq _s1 _s2 = undefined
230
184
231------------------------------------------------------------------------------
185------------------------------------------------------------------------------
232-- Set operations (special joins)
186-- Set operations (special joins)
@@ -236,8 +190,8 @@ outerSortedJoin _eq _s1 _s2 = undefined
236-- the best would be to use an Array with linear search. If the second stream
190-- the best would be to use an Array with linear search. If the second stream
237-- is sorted we can also use a binary search, using Ord constraint.
191-- is sorted we can also use a binary search, using Ord constraint.
238
192
239−-- | Keep only those elements in the first stream that are present in the
193+-- | Keep only those elements in the second stream that are present in the
240−-- second stream too. The second stream is folded to a container using the
194+-- first stream too. The first stream is folded to a container using the
241-- supplied fold and then the elements in the container are looked up using the
195-- supplied fold and then the elements in the container are looked up using the
242-- supplied lookup function.
196-- supplied lookup function.
243--
197--
@@ -252,30 +206,23 @@ filterStreamWith :: Monad m =>
252filterStreamWith fld member s1 s2 =
206filterStreamWith fld member s1 s2 =
253 Stream.concatEffect
207 Stream.concatEffect
254 $ do
208 $ do
255− xs <- Stream.fold fld s2
209+ xs <- Stream.fold fld s1
256− return $ Stream.filter (`member` xs) s1
210+ return $ Stream.filter (`member` xs) s2
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.
266
211
267−-- | 'intersectBy' returns a subsequence of the first stream which intersects
212+-- | 'filterInStreamGenericBy' retains only those elements in the second stream that
268−-- with the second stream. Note that this is not a commutative operation unlike
213+-- are present in the first stream.
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'.
272--
214--
273−-- >>> f s1 s2 = Stream.fold Fold.toList $ Stream.intersectBy (==) (Stream.fromList s1) (Stream.fromList s2)
215+-- >>> Stream.fold Fold.toList $ Stream.filterInStreamGenericBy (==) (Stream.fromList [1,2,2,4]) (Stream.fromList [2,1,1,3])
274−-- >>> f [1,3,4,4,5]) [2,3,4,5,5]
216+-- [2,1,1]
275−-- [3,4,4,5]
276--
217--
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+--
277−-- First stream can be infinite, the second stream must be finite and must be
224+-- The first stream must be finite and must not block. Second stream is
278−-- capable of multiple evaluations.
225+-- processed only after the first stream is fully realized.
279--
226--
280-- Space: O(n) where @n@ is the number of elements in the second stream.
227-- Space: O(n) where @n@ is the number of elements in the second stream.
281--
228--
@@ -283,87 +230,46 @@ filterStreamWith fld member s1 s2 =
283-- @n@ is the number of elements in the second stream.
230-- @n@ is the number of elements in the second stream.
284--
231--
285-- /Pre-release/
232-- /Pre-release/
286−{-# INLINE intersectBy #-}
233+{-# INLINE filterInStreamGenericBy #-}
287−intersectBy :: Monad m =>
234+filterInStreamGenericBy :: Monad m =>
288 (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
235 (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
289−intersectBy eq =
236+filterInStreamGenericBy eq =
290 -- XXX Use an (unboxed) array instead.
237 -- XXX Use an (unboxed) array instead.
291 filterStreamWith
238 filterStreamWith
292 (Fold.scanMaybe (Fold.uniqBy eq) Fold.toListRev)
239 (Fold.scanMaybe (Fold.uniqBy eq) Fold.toListRev)
293 (List.any . eq)
240 (List.any . eq)
294
241
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
304-- ascending order. To use it on streams sorted in descending order pass an
243-- ascending order. To use it on streams sorted in descending order pass an
305-- inverted comparison function returning GT for less than and LT for greater
244-- inverted comparison function returning GT for less than and LT for greater
306-- than.
245-- than.
307--
246--
308−-- Both streams can be infinite.
309−--
310-- Space: O(1)
247-- Space: O(1)
311--
248--
312-- Time: O(m+n)
249-- Time: O(m+n)
313--
250--
314-- /Pre-release/
251-- /Pre-release/
315−{-# INLINE_NORMAL sortedIntersectBy #-}
252+{-# INLINE filterInStreamAscBy #-}
316−sortedIntersectBy :: Monad m =>
253+filterInStreamAscBy :: Monad m =>
317 (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
254 (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
318−sortedIntersectBy cmp (Stream stepa ta) (Stream stepb tb) =
255+filterInStreamAscBy eq s1 s2 = Stream.intersectBySorted eq s2 s1
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
327
256
328− {-# INLINE_LATE step #-}
257+-- | Delete all elements of the first stream from the seconds stream. If an
329− -- step 1, fetch the first value
258+-- element occurs multiple times in the first stream as many occurrences of it
330− step gst (sa, sb, Nothing, b) = do
259+-- are deleted from the second stream.
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'.
356--
260--
357−-- >>> f xs ys = Stream.fold Fold.toList $ Stream.deleteFirstsBy (==) (Stream.fromList xs) (Stream.fromList ys)
261+-- >>> Stream.fold Fold.toList $ Stream.deleteInStreamGenericBy (==) (Stream.fromList [1,2,3]) (Stream.fromList [1,2,2])
358−-- >>> f [1,2,2,3,3,5] [1,2,2,3,4]
359−-- [2,3,5]
262+-- [2]
360--
263--
361−-- The following holds:
264+-- The following laws hold:
362--
265--
363−-- > deleteFirstsBy (==) (Stream.nub s2 `append` s1) s2 === s1
266+-- > deleteInStreamGenericBy (==) s1 (s1 `append` s2) === s2
364−-- > deleteFirstsBy (==) (Stream.nub s2 `interleave` s1) s2 === s1
267+-- > deleteInStreamGenericBy (==) s1 (s1 `interleave` s2) === s2
365--
268--
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.
367--
273--
368-- Space: O(m) where @m@ is the number of elements in the first stream.
274-- Space: O(m) where @m@ is the number of elements in the first stream.
369--
275--
@@ -371,83 +277,58 @@ sortedIntersectBy cmp (Stream stepa ta) (Stream stepb tb) =
371-- @n@ is the number of elements in the second stream.
277-- @n@ is the number of elements in the second stream.
372--
278--
373-- /Pre-release/
279-- /Pre-release/
374−{-# INLINE deleteFirstsBy #-}
280+{-# INLINE deleteInStreamGenericBy #-}
375−deleteFirstsBy :: Monad m =>
281+deleteInStreamGenericBy :: Monad m =>
376 (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
282 (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
377−deleteFirstsBy eq s2 s1 =
283+deleteInStreamGenericBy eq s1 s2 =
378− -- XXX s2 can be a sorted mutable array and we can use binary
284+ Stream.concatEffect
379− -- search to find. Mark the element deleted, count the deletions
285+ $ do
380− -- and reconsolidate the array when a min number of elements is
286+ -- This may work well if s1 is small
381− -- deleted.
287+ -- If s1 is big we can go through s1, deleting elements from s2 and
382−
288+ -- not emitting an element if it was successfully deleted from s2.
383− -- XXX Use StreamK or list as second argument instead of Stream to avoid
289+ -- we will need a deleteBy that can return whether the element was
384− -- concatEffect?
290+ -- deleted or not.
385− Stream.concatEffect $ do
386− xs <- Stream.toList s1
291+ xs <- Stream.fold Fold.toList s2
387− -- It reverses the list but that is fine.
292+ let f = Fold.foldl' (flip (List.deleteBy eq)) xs
388− let del x =
293+ fmap Stream.fromList $ Stream.fold f s1
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
402
294
403−-- | A more efficient 'deleteFirstsBy' for streams sorted in ascending order.
295+-- | A more efficient 'deleteInStreamGenericBy' for streams sorted in ascending order.
404−--
405−-- Both streams can be infinite.
406--
296--
407-- Space: O(1)
297-- Space: O(1)
408--
298--
409-- /Unimplemented/
299-- /Unimplemented/
410−{-# INLINE sortedDeleteFirstsBy #-}
300+{-# INLINE deleteInStreamAscBy #-}
411−sortedDeleteFirstsBy :: -- (Monad m) =>
301+deleteInStreamAscBy :: -- (Monad m) =>
412 (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
302 (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
413−sortedDeleteFirstsBy _eq _s1 _s2 = undefined
303+deleteInStreamAscBy _eq _s1 _s2 = undefined
414
304
415-- XXX Remove the MonadIO constraint. We can just cache one stream and then
305-- XXX Remove the MonadIO constraint. We can just cache one stream and then
416-- implement using differenceEqBy.
306-- implement using differenceEqBy.
417
307
418−-- | Returns the first stream appended with those unique elements from the
308+-- | This essentially appends to the second stream all the occurrences of
419−-- second stream that are not already present in the first stream. Note that
309+-- elements in the first stream that are not already present in the second
420−-- this is not a commutative operation unlike a set union, argument order
310+-- stream.
421−-- matters. The behavior is similar to the 'Data.List.unionBy'.
422--
311--
423-- Equivalent to the following except that @s2@ is evaluated only once:
312-- Equivalent to the following except that @s2@ is evaluated only once:
424--
313--
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)
426--
315--
427-- Example:
316-- Example:
428--
317--
429−-- >>> f s1 s2 = Stream.fold Fold.toList $ Stream.unionBy (==) (Stream.fromList s1) (Stream.fromList s2)
318+-- >>> Stream.fold Fold.toList $ Stream.unionWithStreamGenericBy (==) (Stream.fromList [1,1,2,3]) (Stream.fromList [1,2,2,4])
430−-- >>> f [1,2,2,4] [1,1,2,3,3]
431-- [1,2,2,4,3]
319-- [1,2,2,4,3]
432--
320--
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−--
438-- Space: O(n)
321-- Space: O(n)
439--
322--
440-- Time: O(m x n)
323-- Time: O(m x n)
441--
324--
442-- /Pre-release/
325-- /Pre-release/
443−{-# INLINE unionBy #-}
326+{-# INLINE unionWithStreamGenericBy #-}
444−unionBy :: MonadIO m =>
327+unionWithStreamGenericBy :: MonadIO m =>
445 (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
328 (a -> a -> Bool) -> Stream m a -> Stream m a -> Stream m a
446−unionBy eq s2 s1 =
329+unionWithStreamGenericBy eq s1 s2 =
447 Stream.concatEffect
330 Stream.concatEffect
448 $ do
331 $ 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.
451 xs <- Stream.fold Fold.toList s1
332 xs <- Stream.fold Fold.toList s1
452 -- XXX we can use postscanlMAfter' instead of IORef
333 -- XXX we can use postscanlMAfter' instead of IORef
453 ref <- liftIO $ newIORef $! List.nubBy eq xs
334 ref <- liftIO $ newIORef $! List.nubBy eq xs
@@ -460,21 +341,12 @@ unionBy eq s2 s1 =
460 return $ Stream.fromList xs1
341 return $ Stream.fromList xs1
461 return $ Stream.mapM f s2 `Stream.append` s3
342 return $ Stream.mapM f s2 `Stream.append` s3
462
343
463−-- | A more efficient 'unionBy' for sorted streams.
344+-- | A more efficient 'unionWithStreamGenericBy' 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.
471--
345--
472-- Space: O(1)
346-- Space: O(1)
473--
347--
474−-- Both streams can be infinite.
475−--
476-- /Unimplemented/
348-- /Unimplemented/
477−{-# INLINE sortedUnionBy #-}
349+{-# INLINE unionWithStreamAscBy #-}
478−sortedUnionBy :: -- (Monad m) =>
350+unionWithStreamAscBy :: -- (Monad m) =>
479 (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
351 (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+26−52
@@ -21,6 +21,8 @@ module Streamly.Internal.Data.Stream.Transform
21
21
22 -- * Mapping
22 -- * Mapping
23 -- | Stateless one-to-one maps.
23 -- | Stateless one-to-one maps.
24+ , map
25+ , mapM
24 , sequence
26 , sequence
25
27
26 -- * Mapping Effects
28 -- * Mapping Effects
@@ -73,7 +75,7 @@ module Streamly.Internal.Data.Stream.Transform
73 , scanMaybe
75 , scanMaybe
74 , filter
76 , filter
75 , filterM
77 , filterM
76− , deleteBy -- deleteOnceBy?
78+ , deleteBy
77 , uniqBy
79 , uniqBy
78 , uniq
80 , uniq
79 , prune
81 , prune
@@ -81,8 +83,9 @@ module Streamly.Internal.Data.Stream.Transform
81
83
82 -- * Trimming
84 -- * Trimming
83 -- | Produce a subset of the stream trimmed at ends.
85 -- | Produce a subset of the stream trimmed at ends.
84− , initNonEmpty
86+ , take
85− , tailNonEmpty
87+ , takeWhile
88+ , takeWhileM
86 , takeWhileLast
89 , takeWhileLast
87 , takeWhileAround
90 , takeWhileAround
88 , drop
91 , drop
@@ -129,6 +132,7 @@ module Streamly.Internal.Data.Stream.Transform
129 -- * Searching
132 -- * Searching
130 , findIndices
133 , findIndices
131 , elemIndices
134 , elemIndices
135+ , slicesBy
132
136
133 -- * Rolling map
137 -- * Rolling map
134 -- | Map using the previous element.
138 -- | Map using the previous element.
@@ -1070,55 +1074,6 @@ repeated = undefined
1070-- Trimming
1074-- Trimming
1071------------------------------------------------------------------------------
1075------------------------------------------------------------------------------
1072
1076
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−
1122-- | Take all consecutive elements at the end of the stream for which the
1077-- | Take all consecutive elements at the end of the stream for which the
1123-- predicate is true.
1078-- predicate is true.
1124--
1079--
@@ -1754,6 +1709,25 @@ findIndices p (Stream step state) = Stream step' (state, 0)
1754elemIndices :: (Monad m, Eq a) => a -> Stream m a -> Stream m Int
1709elemIndices :: (Monad m, Eq a) => a -> Stream m a -> Stream m Int
1755elemIndices a = findIndices (== a)
1710elemIndices a = findIndices (== a)
1756
1711
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+
1757------------------------------------------------------------------------------
1731------------------------------------------------------------------------------
1758-- Rolling map
1732-- Rolling map
1759------------------------------------------------------------------------------
1733------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Stream/Transformer.hs+1−2
@@ -11,11 +11,10 @@
11
11
12module Streamly.Internal.Data.Stream.Transformer
12module Streamly.Internal.Data.Stream.Transformer
13 (
13 (
14− -- * Fold to Transformer Monad
15 foldlT
14 foldlT
16 , foldrT
15 , foldrT
17
16
18− -- * Inner Monad Operations
17+ -- * Transform Inner Monad
19 , liftInner
18 , liftInner
20 , runReaderT
19 , runReaderT
21 , usingReaderT
20 , usingReaderT
core/src/Streamly/Internal/Data/Stream/Type.hs+3−37
@@ -1,11 +1,5 @@
1{-# LANGUAGE CPP #-}
1{-# 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 #-}
7{-# LANGUAGE UndecidableInstances #-}
2{-# LANGUAGE UndecidableInstances #-}
8−{-# LANGUAGE ViewPatterns #-}
9
3
10-- |
4-- |
11-- Module : Streamly.Internal.Data.Stream.Type
5-- Module : Streamly.Internal.Data.Stream.Type
@@ -22,18 +16,18 @@
22
16
23module Streamly.Internal.Data.Stream.Type
17module Streamly.Internal.Data.Stream.Type
24 (
18 (
25− -- * Type
19+ -- * The stream type
26 Step (..)
20 Step (..)
27 -- XXX UnStream is exported to avoid a performance issue in some
21 -- XXX UnStream is exported to avoid a performance issue in some
28 -- combinators if we use the pattern synonym "Stream".
22 -- combinators if we use the pattern synonym "Stream".
29 , Stream (Stream, UnStream)
23 , Stream (Stream, UnStream)
30
24
31− -- * CrossStream
25+ -- * CrossStream type wrapper
32 , CrossStream
26 , CrossStream
33 , unCross
27 , unCross
34 , mkCross
28 , mkCross
35
29
36− -- * To StreamK
30+ -- * Conversion to StreamK
37 , fromStreamK
31 , fromStreamK
38 , toStreamK
32 , toStreamK
39
33
@@ -91,7 +85,6 @@ module Streamly.Internal.Data.Stream.Type
91
85
92 -- * Combining Two Streams
86 -- * Combining Two Streams
93 -- ** Zipping
87 -- ** Zipping
94− -- | Zip corresponding elements of two streams.
95 , zipWithM
88 , zipWithM
96 , zipWith
89 , zipWith
97
90
@@ -107,8 +100,6 @@ module Streamly.Internal.Data.Stream.Type
107 , unfoldMany
100 , unfoldMany
108
101
109 -- * Concat
102 -- * Concat
110− -- | Generate streams by mapping a stream generator on each element of an
111− -- input stream, append the resulting streams and flatten.
112 , concatEffect
103 , concatEffect
113 , concatMap
104 , concatMap
114 , concatMapM
105 , concatMapM
@@ -142,7 +133,6 @@ module Streamly.Internal.Data.Stream.Type
142 , indexOnSuffix
133 , indexOnSuffix
143
134
144 -- * Multi-stream folds
135 -- * Multi-stream folds
145− -- | These should probably be expressed using zipping operations.
146 , eqBy
136 , eqBy
147 , cmpBy
137 , cmpBy
148
138
@@ -572,12 +562,8 @@ foldAdd f =
572-- >>> Stream.foldrM step (return False) s
562-- >>> Stream.foldrM step (return False) s
573-- True
563-- True
574--
564--
575−-- >>> import Control.Monad (join)
576−-- >>> foldrM f z = join $ Stream.foldr f z
577−--
578{-# INLINE_NORMAL foldrM #-}
565{-# INLINE_NORMAL foldrM #-}
579foldrM :: Monad m => (a -> m b -> m b) -> m b -> Stream m a -> m b
566foldrM :: 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
581foldrM f z (Stream step state) = go SPEC state
567foldrM f z (Stream step state) = go SPEC state
582 where
568 where
583 {-# INLINE_LATE go #-}
569 {-# INLINE_LATE go #-}
@@ -2076,26 +2062,6 @@ indexOnSuffix predicate =
2076 (indexerBy (FL.takeEndBy_ predicate FL.length) 1)
2062 (indexerBy (FL.takeEndBy_ predicate FL.length) 1)
2077 (return (-1, 0))
2063 (return (-1, 0))
2078
2064
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." #-}
2065{-# DEPRECATED sliceOnSuffix "Please use indexOnSuffix instead." #-}
2100sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
2066sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
2101sliceOnSuffix = indexOnSuffix
2067sliceOnSuffix = indexOnSuffix
core/src/Streamly/Internal/Data/StreamK.hs+8−19
@@ -16,15 +16,16 @@ module Streamly.Internal.Data.StreamK
16 --
16 --
17 -- $setup
17 -- $setup
18
18
19+ -- * The stream type
19 module Streamly.Internal.Data.StreamK.Type
20 module Streamly.Internal.Data.StreamK.Type
20− -- * Transformer
21 , module Streamly.Internal.Data.StreamK.Transformer
21 , module Streamly.Internal.Data.StreamK.Transformer
22
22
23− -- * From containers
23+ , StreamK(..)
24 , fromList
24 , fromList
25 , fromStream
25 , fromStream
26+ , toStream
26
27
27− -- * Specialized Generation
28+ -- ** Specialized Generation
28 , repeatM
29 , repeatM
29 , replicate
30 , replicate
30 , replicateM
31 , replicateM
@@ -66,13 +67,13 @@ module Streamly.Internal.Data.StreamK
66 , find
67 , find
67 , (!!)
68 , (!!)
68
69
69− -- ** To Containers
70− , toList
71− , toStream
72−
73 -- ** Map and Fold
70 -- ** Map and Fold
74 , mapM_
71 , mapM_
75
72
73+ -- ** Conversions
74+ , toList
75+ , hoist
76+
76 -- * Transformation
77 -- * Transformation
77 -- ** By folding (scans)
78 -- ** By folding (scans)
78 , scanl'
79 , scanl'
@@ -99,7 +100,6 @@ module Streamly.Internal.Data.StreamK
99
100
100 -- ** Reordering
101 -- ** Reordering
101 , sortBy
102 , sortBy
102− , sortOn
103
103
104 -- ** Map and Filter
104 -- ** Map and Filter
105 , mapMaybe
105 , mapMaybe
@@ -115,9 +115,6 @@ module Streamly.Internal.Data.StreamK
115 -- ** Transformation comprehensions
115 -- ** Transformation comprehensions
116 , the
116 , the
117
117
118− -- ** Transforming Inner Monad
119− , hoist
120−
121 -- * Exceptions
118 -- * Exceptions
122 , handle
119 , handle
123
120
@@ -134,7 +131,6 @@ import Control.Exception (mask_, Exception)
134import Control.Monad (void, join)
131import Control.Monad (void, join)
135import Control.Monad.Catch (MonadCatch)
132import Control.Monad.Catch (MonadCatch)
136import Control.Monad.IO.Class (MonadIO(..))
133import Control.Monad.IO.Class (MonadIO(..))
137−import Data.Ord (comparing)
138import Data.Proxy (Proxy(..))
134import Data.Proxy (Proxy(..))
139import GHC.Types (SPEC(..))
135import GHC.Types (SPEC(..))
140import Streamly.Internal.Data.Array.Type (Array(..))
136import Streamly.Internal.Data.Array.Type (Array(..))
@@ -1721,10 +1717,3 @@ sortBy cmp =
1721 . Stream.catRights -- its a non-failing backtracking parser
1717 . Stream.catRights -- its a non-failing backtracking parser
1722 . Stream.parseMany (fmap (either id id) p)
1718 . Stream.parseMany (fmap (either id id) p)
1723 . Stream.fromStreamK
1719 . 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−60
@@ -1,8 +1,4 @@
1{-# LANGUAGE CPP #-}
1{-# 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 #-}
6{-# LANGUAGE UndecidableInstances #-}
2{-# LANGUAGE UndecidableInstances #-}
7-- |
3-- |
8-- Module : Streamly.Internal.Data.StreamK.Type
4-- Module : Streamly.Internal.Data.StreamK.Type
@@ -97,11 +93,8 @@ module Streamly.Internal.Data.StreamK.Type
97 -- ** Specific Folds
93 -- ** Specific Folds
98 , drain
94 , drain
99 , null
95 , null
100− , headNonEmpty
101 , tail
96 , tail
102− , tailNonEmpty
103 , init
97 , init
104− , initNonEmpty
105
98
106 -- * Mapping
99 -- * Mapping
107 , map
100 , map
@@ -1814,42 +1807,14 @@ iterateMWith cns step = go
1814 !next <- s
1807 !next <- s
1815 foldStreamShared st stp sng yld (return next `cns` go (step next))
1808 foldStreamShared st stp sng yld (return next `cns` go (step next))
1816
1809
1817−-- | head for non-empty streams, fails for empty stream case.
1810+{-# INLINE headPartial #-}
1818−--
1819−{-# INLINE headNonEmpty #-}
1820−headNonEmpty :: Monad m => StreamK m a -> m a
1811+headPartial :: Monad m => StreamK m a -> m a
1821−headNonEmpty = foldrM (\x _ -> return x) (error "headNonEmpty: empty stream")
1812+headPartial = foldrM (\x _ -> return x) (error "head of nil")
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
1843
1813
1844−-- | tail for non-empty streams, fails for empty stream case.
1814+{-# INLINE tailPartial #-}
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
1815+tailPartial :: StreamK m a -> StreamK m a
1851−tailNonEmpty m = mkStream $ \st yld sng stp ->
1816+tailPartial m = mkStream $ \st yld sng stp ->
1852− let stop = error "tailNonEmpty: empty stream"
1817+ let stop = error "tail of nil"
1853 single _ = stp
1818 single _ = stp
1854 yieldk _ r = foldStream st yld sng stp r
1819 yieldk _ r = foldStream st yld sng stp r
1855 in foldStream st yieldk single stop m
1820 in foldStream st yieldk single stop m
@@ -1914,10 +1879,10 @@ mfix f = mkStream $ \st yld sng stp ->
1914 where
1879 where
1915
1880
1916 -- fix the head element of the stream
1881 -- fix the head element of the stream
1917− xs = fix (f . headNonEmpty)
1882+ xs = fix (f . headPartial)
1918
1883
1919 -- now fix the tail recursively
1884 -- now fix the tail recursively
1920− ys = mfix (tailNonEmpty . f)
1885+ ys = mfix (tailPartial . f)
1921
1886
1922-------------------------------------------------------------------------------
1887-------------------------------------------------------------------------------
1923-- Conversions
1888-- Conversions
@@ -1948,15 +1913,6 @@ uncons m =
1948 yieldk a r = pure (Just (a, r))
1913 yieldk a r = pure (Just (a, r))
1949 in foldStream defState yieldk single stop m
1914 in foldStream defState yieldk single stop m
1950
1915
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−--
1960{-# INLINE tail #-}
1916{-# INLINE tail #-}
1961tail :: Applicative m => StreamK m a -> m (Maybe (StreamK m a))
1917tail :: Applicative m => StreamK m a -> m (Maybe (StreamK m a))
1962tail =
1918tail =
@@ -1965,14 +1921,9 @@ tail =
1965 yieldk _ r = pure $ Just r
1921 yieldk _ r = pure $ Just r
1966 in foldStream defState yieldk single stop
1922 in foldStream defState yieldk single stop
1967
1923
1968−-- Note that this is not a StreamK -> StreamK because then we cannot handle the
1924+-- | Extract all but the last element of the stream, if any.
1969−-- empty stream case without making this a partial function.
1970--
1925--
1971−-- XXX How do we implement unsnoc? Make StreamK a monad and return the
1926+-- Note: This will end up buffering the entire stream.
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.
1976--
1927--
1977-- /Pre-release/
1928-- /Pre-release/
1978{-# INLINE init #-}
1929{-# 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+
1-- |
5-- |
2-- Module : Streamly.Internal.Data.Time.Units
6-- Module : Streamly.Internal.Data.Time.Units
3-- Copyright : (c) 2019 Composewell Technologies
7-- Copyright : (c) 2019 Composewell Technologies
core/src/Streamly/Internal/Data/Unbox.hs+1−4
@@ -1,8 +1,5 @@
1{-# LANGUAGE DataKinds #-}
1{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE DefaultSignatures #-}
3−-- Must come after TypeFamilies, otherwise it is re-enabled.
4−-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
5−{-# LANGUAGE NoMonoLocalBinds #-}
6{-# LANGUAGE UnboxedTuples #-}
3{-# LANGUAGE UnboxedTuples #-}
7{-# LANGUAGE UndecidableInstances #-}
4{-# LANGUAGE UndecidableInstances #-}
8
5
core/src/Streamly/Internal/Data/Unfold.hs+4−6
@@ -82,7 +82,7 @@ module Streamly.Internal.Data.Unfold
82 , dropWhileM
82 , dropWhileM
83
83
84 -- ** Cross product
84 -- ** Cross product
85− , innerJoin
85+ , joinInnerGeneric
86
86
87 -- ** Resource Management
87 -- ** Resource Management
88 -- | 'bracket' is the most general resource management operation, all other
88 -- | 'bracket' is the most general resource management operation, all other
@@ -677,12 +677,10 @@ dropWhileM f (Unfold step inject) = Unfold step' inject'
677dropWhile :: Monad m => (b -> Bool) -> Unfold m a b -> Unfold m a b
677dropWhile :: Monad m => (b -> Bool) -> Unfold m a b -> Unfold m a b
678dropWhile f = dropWhileM (return . f)
678dropWhile f = dropWhileM (return . f)
679
679
680−-- | Cross intersection of two unfolds. See
681−-- 'Streamly.Internal.Data.Stream.innerJoin' for more details.
682−{-# INLINE_NORMAL innerJoin #-}
680+{-# INLINE_NORMAL joinInnerGeneric #-}
683−innerJoin :: Monad m =>
681+joinInnerGeneric :: Monad m =>
684 (b -> c -> Bool) -> Unfold m a b -> Unfold m a c -> Unfold m a (b, c)
682 (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
686
684
687------------------------------------------------------------------------------
685------------------------------------------------------------------------------
688-- Exceptions
686-- Exceptions
core/src/Streamly/Internal/FileSystem/File.hs+9−4
@@ -103,14 +103,15 @@ import qualified Control.Monad.Catch as MC
103import qualified System.IO as SIO
103import qualified System.IO as SIO
104
104
105import Streamly.Data.Fold (groupsOf, drain)
105import Streamly.Data.Fold (groupsOf, drain)
106−import Streamly.Internal.Data.Array.Type (Array(..))
106+import Streamly.Internal.Data.Array.Type (Array(..), pinnedWriteNUnsafe)
107import Streamly.Internal.Data.Fold.Type (Fold(..))
107import Streamly.Internal.Data.Fold.Type (Fold(..))
108import Streamly.Data.Stream (Stream)
108import Streamly.Data.Stream (Stream)
109+import Streamly.Internal.Data.Unbox (Unbox)
109import Streamly.Internal.Data.Unfold.Type (Unfold(..))
110import Streamly.Internal.Data.Unfold.Type (Unfold(..))
110-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
111-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
111import Streamly.Internal.System.IO (defaultChunkSize)
112import Streamly.Internal.System.IO (defaultChunkSize)
112
113
113−import qualified Streamly.Internal.Data.Array as A
114+import qualified Streamly.Data.Array as A
114import qualified Streamly.Data.Stream as S
115import qualified Streamly.Data.Stream as S
115import qualified Streamly.Data.Unfold as UF
116import qualified Streamly.Data.Unfold as UF
116import qualified Streamly.Internal.Data.Array.Type as IA (pinnedChunksOf)
117import qualified Streamly.Internal.Data.Array.Type as IA (pinnedChunksOf)
@@ -338,6 +339,10 @@ readWithBufferOf = readerWith
338reader :: (MonadIO m, MonadCatch m) => Unfold m FilePath Word8
339reader :: (MonadIO m, MonadCatch m) => Unfold m FilePath Word8
339reader = UF.many A.reader (usingFile FH.chunkReader)
340reader = UF.many A.reader (usingFile FH.chunkReader)
340
341
342+{-# INLINE concatChunks #-}
343+concatChunks :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
344+concatChunks = S.unfoldMany A.reader
345+
341-- | Generate a stream of bytes from a file specified by path. The stream ends
346-- | Generate a stream of bytes from a file specified by path. The stream ends
342-- when EOF is encountered. File is locked using multiple reader and single
347-- when EOF is encountered. File is locked using multiple reader and single
343-- writer locking mode.
348-- writer locking mode.
@@ -346,7 +351,7 @@ reader = UF.many A.reader (usingFile FH.chunkReader)
346--
351--
347{-# INLINE read #-}
352{-# INLINE read #-}
348read :: (MonadIO m, MonadCatch m) => FilePath -> Stream m Word8
353read :: (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
350
355
351{-# DEPRECATED toBytes "Please use 'read' instead" #-}
356{-# DEPRECATED toBytes "Please use 'read' instead" #-}
352{-# INLINE toBytes #-}
357{-# INLINE toBytes #-}
@@ -462,7 +467,7 @@ writeChunks path = Fold step initial extract final
462writeWith :: (MonadIO m, MonadCatch m)
467writeWith :: (MonadIO m, MonadCatch m)
463 => Int -> FilePath -> Fold m Word8 ()
468 => Int -> FilePath -> Fold m Word8 ()
464writeWith n path =
469writeWith n path =
465− groupsOf n (A.unsafePinnedCreateOf n) (writeChunks path)
470+ groupsOf n (pinnedWriteNUnsafe n) (writeChunks path)
466
471
467{-# DEPRECATED writeWithBufferOf "Please use 'writeWith' instead" #-}
472{-# DEPRECATED writeWithBufferOf "Please use 'writeWith' instead" #-}
468{-# INLINE writeWithBufferOf #-}
473{-# INLINE writeWithBufferOf #-}
core/src/Streamly/Internal/FileSystem/Handle.hs+28−21
@@ -40,8 +40,8 @@ module Streamly.Internal.FileSystem.Handle
40
40
41 -- * Streams
41 -- * Streams
42 , read
42 , read
43− , readWith -- readConcatChunksOf
43+ , readWith
44− , readChunksWith -- readChunksOf
44+ , readChunksWith
45 , readChunks
45 , readChunks
46
46
47 -- * Unfolds
47 -- * Unfolds
@@ -59,10 +59,10 @@ module Streamly.Internal.FileSystem.Handle
59 -- , writeUtf8ByLines
59 -- , writeUtf8ByLines
60 -- , writeByFrames
60 -- , writeByFrames
61 -- , writeLines
61 -- , writeLines
62− , writeWith -- writeChunksOf
62+ , writeWith
63 , writeChunks
63 , writeChunks
64− , writeChunksWith -- writeCompactChunksOf
64+ , writeChunksWith
65− , writeMaybesWith -- writeCompactJustsOf
65+ , writeMaybesWith
66
66
67 -- * Refolds
67 -- * Refolds
68 , writer
68 , writer
@@ -131,13 +131,16 @@ import Streamly.Internal.Data.Fold (Fold)
131import Streamly.Internal.Data.Refold.Type (Refold(..))
131import Streamly.Internal.Data.Refold.Type (Refold(..))
132import Streamly.Internal.Data.Unfold.Type (Unfold(..))
132import Streamly.Internal.Data.Unfold.Type (Unfold(..))
133import Streamly.Internal.Data.Array.Type
133import Streamly.Internal.Data.Array.Type
134− (Array(..), unsafeFreezeWithShrink, byteLength)
134+ (Array(..), pinnedWriteNUnsafe, unsafeFreezeWithShrink, byteLength)
135import Streamly.Internal.Data.Stream.Type (Stream)
135import Streamly.Internal.Data.Stream.Type (Stream)
136+import Streamly.Internal.Data.Array.Stream (lpackArraysChunksOf)
136-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
137-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
137import Streamly.Internal.System.IO (defaultChunkSize)
138import Streamly.Internal.System.IO (defaultChunkSize)
138
139
139import qualified Streamly.Data.Fold as FL
140import 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
141import qualified Streamly.Internal.Data.MutArray.Type as MArray
144import qualified Streamly.Internal.Data.MutArray.Type as MArray
142import qualified Streamly.Internal.Data.Refold.Type as Refold
145import qualified Streamly.Internal.Data.Refold.Type as Refold
143import qualified Streamly.Internal.Data.Fold.Type as FL(refoldMany)
146import qualified Streamly.Internal.Data.Fold.Type as FL(refoldMany)
@@ -166,8 +169,6 @@ import qualified Streamly.Internal.Data.StreamK.Type as K (mkStream)
166-- Array IO (Input)
169-- Array IO (Input)
167-------------------------------------------------------------------------------
170-------------------------------------------------------------------------------
168
171
169−-- XXX add an API that compacts the arrays to an exact size.
170−
171-- | Read a 'ByteArray' consisting of one or more bytes from a file handle. If
172-- | Read a 'ByteArray' consisting of one or more bytes from a file handle. If
172-- no data is available on the handle it blocks until at least one byte becomes
173-- no data is available on the handle it blocks until at least one byte becomes
173-- available. If any data is available then it immediately returns that data
174-- 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)
177{-# INLINABLE getChunk #-}
178{-# INLINABLE getChunk #-}
178getChunk :: MonadIO m => Int -> Handle -> m (Array Word8)
179getChunk :: MonadIO m => Int -> Handle -> m (Array Word8)
179getChunk size h = liftIO $ do
180getChunk size h = liftIO $ do
180− arr :: MArray.MutArray Word8 <- MArray.pinnedEmptyOf size
181+ arr <- MArray.pinnedNewBytes size
181 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
182 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
182− MArray.unsafePinnedAsPtr arr $ \p -> do
183+ MArray.asPtrUnsafe arr $ \p -> do
183 n <- hGetBufSome h p size
184 n <- hGetBufSome h p size
184 -- XXX shrink only if the diff is significant
185 -- XXX shrink only if the diff is significant
185 return $
186 return $
@@ -337,6 +338,10 @@ readerWith = UF.many A.reader chunkReaderWith
337readWithBufferOf :: MonadIO m => Unfold m (Int, Handle) Word8
338readWithBufferOf :: MonadIO m => Unfold m (Int, Handle) Word8
338readWithBufferOf = readerWith
339readWithBufferOf = readerWith
339
340
341+{-# INLINE concatChunks #-}
342+concatChunks :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
343+concatChunks = S.unfoldMany A.reader
344+
340-- | @readWith bufsize handle@ reads a byte stream from a file
345-- | @readWith bufsize handle@ reads a byte stream from a file
341-- handle, reads are performed in chunks of up to @bufsize@.
346-- handle, reads are performed in chunks of up to @bufsize@.
342--
347--
@@ -345,7 +350,7 @@ readWithBufferOf = readerWith
345-- /Pre-release/
350-- /Pre-release/
346{-# INLINE readWith #-}
351{-# INLINE readWith #-}
347readWith :: MonadIO m => Int -> Handle -> Stream m Word8
352readWith :: MonadIO m => Int -> Handle -> Stream m Word8
348−readWith size h = A.concat $ readChunksWith size h
353+readWith size h = concatChunks $ readChunksWith size h
349
354
350-- | Unfolds a file handle into a byte stream. IO requests to the device are
355-- | Unfolds a file handle into a byte stream. IO requests to the device are
351-- performed in sizes of
356-- performed in sizes of
@@ -364,7 +369,7 @@ reader = UF.many A.reader chunkReader
364-- /Pre-release/
369-- /Pre-release/
365{-# INLINE read #-}
370{-# INLINE read #-}
366read :: MonadIO m => Handle -> Stream m Word8
371read :: MonadIO m => Handle -> Stream m Word8
367−read = A.concat . readChunks
372+read = concatChunks . readChunks
368
373
369-------------------------------------------------------------------------------
374-------------------------------------------------------------------------------
370-- Writing
375-- Writing
@@ -379,12 +384,12 @@ read = A.concat . readChunks
379{-# INLINABLE putChunk #-}
384{-# INLINABLE putChunk #-}
380putChunk :: MonadIO m => Handle -> Array a -> m ()
385putChunk :: MonadIO m => Handle -> Array a -> m ()
381putChunk _ arr | byteLength arr == 0 = return ()
386putChunk _ arr | byteLength arr == 0 = return ()
382−putChunk h arr = A.unsafePinnedAsPtr arr $ \ptr ->
387+putChunk h arr = A.asPtrUnsafe arr $ \ptr ->
383 liftIO $ hPutBuf h ptr aLen
388 liftIO $ hPutBuf h ptr aLen
384
389
385 where
390 where
386
391
387− -- XXX We should have the length passed by unsafePinnedAsPtr itself.
392+ -- XXX We should have the length passed by asPtrUnsafe itself.
388 aLen = A.byteLength arr
393 aLen = A.byteLength arr
389
394
390-------------------------------------------------------------------------------
395-------------------------------------------------------------------------------
@@ -416,7 +421,7 @@ putChunks h = S.fold (FL.drainMapM (putChunk h))
416{-# INLINE putChunksWith #-}
421{-# INLINE putChunksWith #-}
417putChunksWith :: (MonadIO m, Unbox a)
422putChunksWith :: (MonadIO m, Unbox a)
418 => Int -> Handle -> Stream m (Array a) -> m ()
423 => 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
420
425
421-- > putBytesWith n h m = Handle.putChunks h $ A.pinnedChunksOf n m
426-- > putBytesWith n h m = Handle.putChunks h $ A.pinnedChunksOf n m
422
427
@@ -456,6 +461,8 @@ writeChunks h = FL.drainMapM (putChunk h)
456chunkWriter :: MonadIO m => Refold m Handle (Array a) ()
461chunkWriter :: MonadIO m => Refold m Handle (Array a) ()
457chunkWriter = Refold.drainBy putChunk
462chunkWriter = Refold.drainBy putChunk
458
463
464+-- XXX lpackArraysChunksOf should be written idiomatically
465+
459-- | @writeChunksWith bufsize handle@ writes a stream of arrays
466-- | @writeChunksWith bufsize handle@ writes a stream of arrays
460-- to @handle@ after coalescing the adjacent arrays in chunks of @bufsize@.
467-- to @handle@ after coalescing the adjacent arrays in chunks of @bufsize@.
461-- We never split an array, if a single array is bigger than the specified size
468-- We never split an array, if a single array is bigger than the specified size
@@ -465,7 +472,7 @@ chunkWriter = Refold.drainBy putChunk
465{-# INLINE writeChunksWith #-}
472{-# INLINE writeChunksWith #-}
466writeChunksWith :: (MonadIO m, Unbox a)
473writeChunksWith :: (MonadIO m, Unbox a)
467 => Int -> Handle -> Fold m (Array a) ()
474 => Int -> Handle -> Fold m (Array a) ()
468−writeChunksWith n h = A.lCompactGE n (writeChunks h)
475+writeChunksWith n h = lpackArraysChunksOf n (writeChunks h)
469
476
470-- | Same as 'writeChunksWith'
477-- | Same as 'writeChunksWith'
471--
478--
@@ -489,11 +496,11 @@ writeChunksWithBufferOf = writeChunksWith
489-- Bytes in the input stream are collected into a buffer until we have a chunk
496-- Bytes in the input stream are collected into a buffer until we have a chunk
490-- of @reqSize@ and then written to the IO device.
497-- of @reqSize@ and then written to the IO device.
491--
498--
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)
493--
500--
494{-# INLINE writeWith #-}
501{-# INLINE writeWith #-}
495writeWith :: MonadIO m => Int -> Handle -> Fold m Word8 ()
502writeWith :: 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)
497
504
498-- | Same as 'writeWith'
505-- | Same as 'writeWith'
499--
506--
@@ -511,7 +518,7 @@ writeWithBufferOf = writeWith
511writeMaybesWith :: (MonadIO m )
518writeMaybesWith :: (MonadIO m )
512 => Int -> Handle -> Fold m (Maybe Word8) ()
519 => Int -> Handle -> Fold m (Maybe Word8) ()
513writeMaybesWith n h =
520writeMaybesWith n h =
514− let writeNJusts = FL.lmap fromJust $ A.pinnedCreateOf n
521+ let writeNJusts = FL.lmap fromJust $ A.pinnedWriteN n
515 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
522 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
516 in FL.many writeOnNothing (writeChunks h)
523 in FL.many writeOnNothing (writeChunks h)
517
524
@@ -521,7 +528,7 @@ writeMaybesWith n h =
521{-# INLINE writerWith #-}
528{-# INLINE writerWith #-}
522writerWith :: MonadIO m => Int -> Refold m Handle Word8 ()
529writerWith :: MonadIO m => Int -> Refold m Handle Word8 ()
523writerWith n =
530writerWith n =
524− FL.refoldMany (FL.take n $ A.unsafePinnedCreateOf n) chunkWriter
531+ FL.refoldMany (FL.take n $ pinnedWriteNUnsafe n) chunkWriter
525
532
526-- | Write a byte stream to a file handle. Accumulates the input in chunks of
533-- | Write a byte stream to a file handle. Accumulates the input in chunks of
527-- up to 'Streamly.Internal.Data.Array.Type.defaultChunkSize' before writing
534-- up to 'Streamly.Internal.Data.Array.Type.defaultChunkSize' before writing
core/src/Streamly/Internal/FileSystem/Path.hs+4−36
@@ -36,7 +36,7 @@
36module Streamly.Internal.FileSystem.Path
36module Streamly.Internal.FileSystem.Path
37 (
37 (
38 -- * Path Types
38 -- * Path Types
39− Path (..)
39+ Path
40 , File
40 , File
41 , Dir
41 , Dir
42 , Abs
42 , Abs
@@ -82,11 +82,6 @@ module Streamly.Internal.FileSystem.Path
82 , toChars
82 , toChars
83
83
84 -- * Operations
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
85 , extendPath
91 , extendDir
86 , extendDir
92 )
87 )
@@ -94,7 +89,6 @@ where
94
89
95import Control.Exception (Exception)
90import Control.Exception (Exception)
96import Control.Monad.Catch (MonadThrow(..))
91import Control.Monad.Catch (MonadThrow(..))
97−import Data.Char (chr)
98import Data.Functor.Identity (Identity(..))
92import Data.Functor.Identity (Identity(..))
99import Data.Word (Word8)
93import Data.Word (Word8)
100#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
94#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
@@ -157,15 +151,6 @@ instance Exception PathException
157-- | A type representing file system paths for directories or files.
151-- | A type representing file system paths for directories or files.
158newtype Path = Path (Array WORD_TYPE) -- deriving Eq
152newtype Path = Path (Array WORD_TYPE) -- deriving Eq
159
153
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
154-- 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,
155-- 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
156-- length restriction. A file name cannot be "." or "..". We can use the types
@@ -453,25 +438,8 @@ mkRelFile = undefined
453-- Operations
438-- Operations
454------------------------------------------------------------------------------
439------------------------------------------------------------------------------
455
440
456−separatorWord :: WORD_TYPE
441+separator :: WORD_TYPE
457−separatorWord = SEPARATOR
442+separator = 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
443
476-- If we append an absolute path it may fail with an error if the 'Path'
444-- 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).
445-- implementation stores absolute path information (a leading separator char).
@@ -497,7 +465,7 @@ extendPath (Path a) (Path b) =
497 newArr = unsafePerformIO $ do
465 newArr = unsafePerformIO $ do
498 arr <- MutArray.new len
466 arr <- MutArray.new len
499 arr1 <- MutArray.spliceUnsafe arr (Array.unsafeThaw a)
467 arr1 <- MutArray.spliceUnsafe arr (Array.unsafeThaw a)
500− arr2 <- MutArray.snocUnsafe arr1 separatorWord
468+ arr2 <- MutArray.snocUnsafe arr1 separator
501 arr3 <- MutArray.spliceUnsafe arr2 (Array.unsafeThaw b)
469 arr3 <- MutArray.spliceUnsafe arr2 (Array.unsafeThaw b)
502 return (Array.unsafeFreeze arr3)
470 return (Array.unsafeFreeze arr3)
503 in Path newArr
471 in Path newArr
core/src/Streamly/Internal/Unicode/Stream.hs+1−1
@@ -1057,7 +1057,7 @@ stripHead = Stream.dropWhile isSpace
1057-- >>> Stream.fold Fold.toList $ Unicode.lines Fold.toList (Stream.fromList "lines\nthis\nstring\n\n\n")
1057-- >>> Stream.fold Fold.toList $ Unicode.lines Fold.toList (Stream.fromList "lines\nthis\nstring\n\n\n")
1058-- ["lines","this","string","",""]
1058-- ["lines","this","string","",""]
1059--
1059--
1060−-- >>> lines f = Stream.foldMany (Fold.takeEndBy_ (== '\n') f)
1060+-- > lines = Stream.splitOnSuffix (== '\n')
1061--
1061--
1062-- /Pre-release/
1062-- /Pre-release/
1063{-# INLINE lines #-}
1063{-# INLINE lines #-}
core/src/Streamly/Internal/Unicode/String.hs+7−7
@@ -39,14 +39,14 @@ module Streamly.Internal.Unicode.String
39 --
39 --
40 -- $setup
40 -- $setup
41
41
42− str
42+ str
43 ) where
43 ) where
44
44
45
45
46import Control.Applicative (Alternative(..))
46import Control.Applicative (Alternative(..))
47import Control.Exception (displayException)
47import Control.Exception (displayException)
48import Data.Functor.Identity (runIdentity)
48import Data.Functor.Identity (runIdentity)
49−import Streamly.Internal.Data.Parser (Parser, ParseError)
49+import Streamly.Internal.Data.Parser (Parser)
50
50
51import Language.Haskell.TH
51import Language.Haskell.TH
52import Language.Haskell.TH.Quote
52import Language.Haskell.TH.Quote
@@ -106,12 +106,9 @@ strSegmentExp (StrVar name) = do
106strExp :: [StrSegment] -> Q Exp
106strExp :: [StrSegment] -> Q Exp
107strExp xs = appE [| concat |] $ listE $ map strSegmentExp xs
107strExp xs = appE [| concat |] $ listE $ map strSegmentExp xs
108
108
109−parseStr :: String -> Either ParseError [StrSegment]
110−parseStr = runIdentity . Stream.parse strParser . Stream.fromList
111−
112expandVars :: String -> Q Exp
109expandVars :: String -> Q Exp
113−expandVars input =
110+expandVars ln =
114− case parseStr input of
111+ case runIdentity $ Stream.parse strParser (Stream.fromList ln) of
115 Left e ->
112 Left e ->
116 fail $ "str QuasiQuoter parse error: " ++ displayException e
113 fail $ "str QuasiQuoter parse error: " ++ displayException e
117 Right x ->
114 Right x ->
@@ -144,6 +141,9 @@ expandVars input =
144-- :}
141-- :}
145-- "hello world!"
142-- "hello world!"
146--
143--
144+-- Bugs: because of a bug in parsers, a lone # at the end of input gets
145+-- removed.
146+--
147str :: QuasiQuoter
147str :: QuasiQuoter
148str =
148str =
149 QuasiQuoter
149 QuasiQuoter
core/streamly-core.cabal+10−14
@@ -1,6 +1,6 @@
1cabal-version: 2.2
1cabal-version: 2.2
2name: streamly-core
2name: streamly-core
3−version: 0.2.2
3+version: 0.2.1
4synopsis: Streaming, parsers, arrays, serialization and more
4synopsis: Streaming, parsers, arrays, serialization and more
5description:
5description:
6 For upgrading to streamly-0.9.0+ please read the
6 For upgrading to streamly-0.9.0+ please read the
@@ -116,7 +116,6 @@ extra-doc-files:
116 docs/*.md
116 docs/*.md
117 docs/ApiChangelogs/0.1.0.txt
117 docs/ApiChangelogs/0.1.0.txt
118 docs/ApiChangelogs/0.1.0-0.2.0.txt
118 docs/ApiChangelogs/0.1.0-0.2.0.txt
119− docs/ApiChangelogs/0.2.0-0.2.2.txt
120
119
121source-repository head
120source-repository head
122 type: git
121 type: git
@@ -218,6 +217,8 @@ common compile-options
218common default-extensions
217common default-extensions
219 default-extensions:
218 default-extensions:
220 BangPatterns
219 BangPatterns
220+ CApiFFI
221+ CPP
221 ConstraintKinds
222 ConstraintKinds
222 DeriveDataTypeable
223 DeriveDataTypeable
223 DeriveGeneric
224 DeriveGeneric
@@ -228,29 +229,24 @@ common default-extensions
228 GeneralizedNewtypeDeriving
229 GeneralizedNewtypeDeriving
229 InstanceSigs
230 InstanceSigs
230 KindSignatures
231 KindSignatures
232+ LambdaCase
233+ MagicHash
231 MultiParamTypeClasses
234 MultiParamTypeClasses
235+ PatternSynonyms
232 RankNTypes
236 RankNTypes
237+ RecordWildCards
233 ScopedTypeVariables
238 ScopedTypeVariables
234 StandaloneDeriving
239 StandaloneDeriving
235 TupleSections
240 TupleSections
236 TypeApplications
241 TypeApplications
242+ TypeFamilies
237 TypeOperators
243 TypeOperators
244+ ViewPatterns
238
245
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
250 -- MonoLocalBinds, enabled by TypeFamilies, causes performance
246 -- MonoLocalBinds, enabled by TypeFamilies, causes performance
251 -- regressions. Disable it. This must come after TypeFamilies,
247 -- regressions. Disable it. This must come after TypeFamilies,
252 -- otherwise TypeFamilies will enable it again.
248 -- otherwise TypeFamilies will enable it again.
253− -- NoMonoLocalBinds
249+ NoMonoLocalBinds
254
250
255 -- UndecidableInstances -- Does not show any perf impact
251 -- UndecidableInstances -- Does not show any perf impact
256 -- UnboxedTuples -- interferes with (#.)
252 -- UnboxedTuples -- interferes with (#.)
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
191itself, in fact we may have to occasionally use a `NOINLINE` so that the
191itself, in fact we may have to occasionally use a `NOINLINE` so that the
192compiler does not inline it.
192compiler does not inline it.
193
193
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−
206### NoSpecConstr
194### NoSpecConstr
207
195
208It is not always useful to specialize function calls for all constructors, some
196It is not always useful to specialize function calls for all constructors, some
docs/User/Project/Changelog.md+1−1
@@ -2,7 +2,7 @@
2
2
3<!-- See rendered changelog at https://streamly.composewell.com -->
3<!-- See rendered changelog at https://streamly.composewell.com -->
4
4
5−## 0.10.1 (Jan 2024)
5+## Unreleased
6
6
7* Fix TH macros in `Streamly.Data.Stream.MkType` for GHC 9.6 and above.
7* Fix TH macros in `Streamly.Data.Stream.MkType` for GHC 9.6 and above.
8
8
docs/User/Project/README.md−1
@@ -1,7 +1,6 @@
1# [Streamly][]: Idiomatic Haskell with C-Like Performance
1# [Streamly][]: Idiomatic Haskell with C-Like Performance
2
2
3[![Gitter chat](https://badges.gitter.im/composewell/gitter.svg)](https://gitter.im/composewell/streamly)
3[![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)
5[![Hackage](https://img.shields.io/hackage/v/streamly.svg?style=flat)](https://hackage.haskell.org/package/streamly)
4[![Hackage](https://img.shields.io/hackage/v/streamly.svg?style=flat)](https://hackage.haskell.org/package/streamly)
6
5
7## Upgrading to 0.9.0+
6## Upgrading to 0.9.0+
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−
6{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
7
2
8-- |
3-- |
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−
6{-# OPTIONS_GHC -Wno-deprecations #-}
1{-# OPTIONS_GHC -Wno-deprecations #-}
7
2
8-- |
3-- |
src/Streamly/Internal/Data/Stream/IsStream/Top.hs+1−1
@@ -649,7 +649,7 @@ intersectBySorted :: (IsStream t, Monad m) =>
649 (a -> a -> Ordering) -> t m a -> t m a -> t m a
649 (a -> a -> Ordering) -> t m a -> t m a -> t m a
650intersectBySorted eq s1 =
650intersectBySorted eq s1 =
651 IsStream.fromStreamD
651 IsStream.fromStreamD
652− . StreamD.sortedIntersectBy eq (IsStream.toStreamD s1)
652+ . StreamD.intersectBySorted eq (IsStream.toStreamD s1)
653 . IsStream.toStreamD
653 . IsStream.toStreamD
654
654
655-- Roughly joinLeft s1 s2 = s1 `difference` s2 + s1 `intersection` s2
655-- Roughly joinLeft s1 s2 = s1 `difference` s2 + s1 `intersection` s2
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 #-}
5{-# LANGUAGE UndecidableInstances #-}
1{-# LANGUAGE UndecidableInstances #-}
6−
7{-# OPTIONS_GHC -Wno-deprecations #-}
2{-# OPTIONS_GHC -Wno-deprecations #-}
8{-# OPTIONS_GHC -Wno-redundant-constraints #-}
3{-# OPTIONS_GHC -Wno-redundant-constraints #-}
9
4
src/Streamly/Internal/Data/Stream/Zip.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 #-}
5{-# LANGUAGE UndecidableInstances #-}
1{-# LANGUAGE UndecidableInstances #-}
6−
7{-# OPTIONS_GHC -Wno-deprecations #-}
2{-# OPTIONS_GHC -Wno-deprecations #-}
8
3
9-- |
4-- |
src/Streamly/Internal/FileSystem/Event.hs−3
@@ -20,9 +20,6 @@
20-- * "Streamly.Internal.FileSystem.Event.Linux"
20-- * "Streamly.Internal.FileSystem.Event.Linux"
21-- * "Streamly.Internal.FileSystem.Event.Windows"
21-- * "Streamly.Internal.FileSystem.Event.Windows"
22
22
23−-- XXX Need to ensure that the signatures of the exported APIs are same on all
24−-- platforms.
25−
26module Streamly.Internal.FileSystem.Event
23module Streamly.Internal.FileSystem.Event
27 (
24 (
28 -- * Creating a Watch
25 -- * Creating a Watch
src/Streamly/Internal/FileSystem/Event/Darwin.hs+1−1
@@ -451,7 +451,7 @@ openWatch Config{..} paths = do
451
451
452 withPathName :: Array Word8 -> (PathName -> IO a) -> IO a
452 withPathName :: Array Word8 -> (PathName -> IO a) -> IO a
453 withPathName arr act = do
453 withPathName arr act = do
454− A.unsafePinnedAsPtr arr $ \ptr ->
454+ A.asPtrUnsafe arr $ \ptr ->
455 let pname = PathName (castPtr ptr) (fromIntegral (A.length arr))
455 let pname = PathName (castPtr ptr) (fromIntegral (A.length arr))
456 in act pname
456 in act pname
457
457
src/Streamly/Internal/FileSystem/Event/Linux.hs+2−2
@@ -188,7 +188,7 @@ import qualified Streamly.FileSystem.Handle as FH
188import qualified Streamly.Unicode.Stream as U
188import qualified Streamly.Unicode.Stream as U
189
189
190import qualified Streamly.Internal.Data.Array as A
190import qualified Streamly.Internal.Data.Array as A
191− ( fromStream, asCStringUnsafe, unsafePinnedAsPtr
191+ ( fromStream, asCStringUnsafe, asPtrUnsafe
192 , getSliceUnsafe, read
192 , getSliceUnsafe, read
193 )
193 )
194import qualified Streamly.Internal.FileSystem.Dir as Dir (readDirs)
194import qualified Streamly.Internal.FileSystem.Dir as Dir (readDirs)
@@ -809,7 +809,7 @@ readOneEvent :: Config -> Watch -> Parser Word8 IO Event
809readOneEvent cfg wt@(Watch _ wdMap) = do
809readOneEvent cfg wt@(Watch _ wdMap) = do
810 let headerLen = sizeOf (undefined :: CInt) + 12
810 let headerLen = sizeOf (undefined :: CInt) + 12
811 arr <- PR.takeEQ headerLen (A.writeN headerLen)
811 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
813 -- XXX need the "initial" in parsers to return a step type so that "take 0"
813 -- XXX need the "initial" in parsers to return a step type so that "take 0"
814 -- can return without an input. otherwise if pathLen is 0 we will keep
814 -- can return without an input. otherwise if pathLen is 0 we will keep
815 -- waiting to read one more char before we return this event.
815 -- waiting to read one more char before we return this event.
src/Streamly/Internal/FileSystem/FD.hs+5−5
@@ -130,7 +130,7 @@ import qualified GHC.IO.Device as RawIO
130import Streamly.Data.Array (Array, Unbox)
130import Streamly.Data.Array (Array, Unbox)
131import Streamly.Data.Stream (Stream)
131import Streamly.Data.Stream (Stream)
132
132
133−import Streamly.Internal.Data.Array (byteLength, unsafeFreeze, unsafePinnedAsPtr)
133+import Streamly.Internal.Data.Array (byteLength, unsafeFreeze, asPtrUnsafe)
134import Streamly.Internal.System.IO (defaultChunkSize)
134import Streamly.Internal.System.IO (defaultChunkSize)
135
135
136#if !defined(mingw32_HOST_OS)
136#if !defined(mingw32_HOST_OS)
@@ -147,7 +147,7 @@ import qualified Streamly.Internal.System.IOVec.Type as RawIO
147import qualified Streamly.Data.Array as A
147import qualified Streamly.Data.Array as A
148import qualified Streamly.Data.Fold as FL
148import qualified Streamly.Data.Fold as FL
149import qualified Streamly.Internal.Data.MutArray as MArray
149import qualified Streamly.Internal.Data.MutArray as MArray
150− (MutArray(..), unsafePinnedAsPtr, pinnedNewBytes)
150+ (MutArray(..), asPtrUnsafe, pinnedNewBytes)
151import qualified Streamly.Internal.Data.Array.Stream as AS
151import qualified Streamly.Internal.Data.Array.Stream as AS
152import qualified Streamly.Internal.Data.Stream as S
152import qualified Streamly.Internal.Data.Stream as S
153import qualified Streamly.Internal.Data.Stream as D
153import qualified Streamly.Internal.Data.Stream as D
@@ -220,7 +220,7 @@ readArrayUpto :: Int -> Handle -> IO (Array Word8)
220readArrayUpto size (Handle fd) = do
220readArrayUpto size (Handle fd) = do
221 arr <- MArray.pinnedNewBytes size
221 arr <- MArray.pinnedNewBytes size
222 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
222 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
223− MArray.unsafePinnedAsPtr arr $ \p -> do
223+ MArray.asPtrUnsafe arr $ \p -> do
224 -- n <- hGetBufSome h p size
224 -- n <- hGetBufSome h p size
225#if MIN_VERSION_base(4,15,0)
225#if MIN_VERSION_base(4,15,0)
226 n <- RawIO.read fd p 0 size
226 n <- RawIO.read fd p 0 size
@@ -244,7 +244,7 @@ readArrayUpto size (Handle fd) = do
244writeArray :: Unbox a => Handle -> Array a -> IO ()
244writeArray :: Unbox a => Handle -> Array a -> IO ()
245writeArray _ arr | A.length arr == 0 = return ()
245writeArray _ arr | A.length arr == 0 = return ()
246writeArray (Handle fd) arr =
246writeArray (Handle fd) arr =
247− unsafePinnedAsPtr arr $ \p ->
247+ asPtrUnsafe arr $ \p ->
248 -- RawIO.writeAll fd (castPtr p) aLen
248 -- RawIO.writeAll fd (castPtr p) aLen
249#if MIN_VERSION_base(4,15,0)
249#if MIN_VERSION_base(4,15,0)
250 RawIO.write fd (castPtr p) 0 aLen
250 RawIO.write fd (castPtr p) 0 aLen
@@ -270,7 +270,7 @@ writeArray (Handle fd) arr =
270writeIOVec :: Handle -> Array RawIO.IOVec -> IO ()
270writeIOVec :: Handle -> Array RawIO.IOVec -> IO ()
271writeIOVec _ iov | A.length iov == 0 = return ()
271writeIOVec _ iov | A.length iov == 0 = return ()
272writeIOVec (Handle fd) iov =
272writeIOVec (Handle fd) iov =
273− unsafePinnedAsPtr iov $ \p ->
273+ asPtrUnsafe iov $ \p ->
274 RawIO.writevAll fd p (A.length iov)
274 RawIO.writevAll fd p (A.length iov)
275-}
275-}
276#endif
276#endif
src/Streamly/Internal/Network/Inet/TCP.hs+3−3
@@ -116,6 +116,7 @@ import Prelude hiding (read)
116import Streamly.Internal.Control.Concurrent (MonadAsync)
116import Streamly.Internal.Control.Concurrent (MonadAsync)
117import Streamly.Internal.Control.ForkLifted (fork)
117import Streamly.Internal.Control.ForkLifted (fork)
118import Streamly.Data.Array (Array)
118import Streamly.Data.Array (Array)
119+import Streamly.Internal.Data.Array (pinnedWriteNUnsafe)
119import Streamly.Internal.Data.Fold ( Fold(..) )
120import Streamly.Internal.Data.Fold ( Fold(..) )
120import Streamly.Data.Stream (Stream)
121import Streamly.Data.Stream (Stream)
121import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
122import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
@@ -131,8 +132,7 @@ import qualified Streamly.Data.Array as A
131import qualified Streamly.Data.Fold as FL
132import qualified Streamly.Data.Fold as FL
132import qualified Streamly.Data.Stream as S
133import qualified Streamly.Data.Stream as S
133import qualified Streamly.Data.Unfold as UF
134import qualified Streamly.Data.Unfold as UF
134−import qualified Streamly.Internal.Data.Array as A
135+import qualified Streamly.Internal.Data.Array as A (pinnedChunksOf)
135− (pinnedChunksOf, unsafePinnedCreateOf)
136import qualified Streamly.Internal.Data.Unfold as UF (bracketIO)
136import qualified Streamly.Internal.Data.Unfold as UF (bracketIO)
137import qualified Streamly.Internal.Data.Fold as FL (Step(..), reduce)
137import qualified Streamly.Internal.Data.Fold as FL (Step(..), reduce)
138
138
@@ -435,7 +435,7 @@ writeWithBufferOf
435 -> PortNumber
435 -> PortNumber
436 -> Fold m Word8 ()
436 -> Fold m Word8 ()
437writeWithBufferOf n addr port =
437writeWithBufferOf n addr port =
438− FL.groupsOf n (A.unsafePinnedCreateOf n) (writeChunks addr port)
438+ FL.groupsOf n (pinnedWriteNUnsafe n) (writeChunks addr port)
439
439
440-- | Write a stream to the supplied IPv4 host address and port number.
440-- | Write a stream to the supplied IPv4 host address and port number.
441--
441--
src/Streamly/Internal/Network/Socket.hs+10−11
@@ -87,6 +87,7 @@ import Prelude hiding (read)
87import qualified Network.Socket as Net
87import qualified Network.Socket as Net
88
88
89import Streamly.Internal.Data.Array (Array(..))
89import Streamly.Internal.Data.Array (Array(..))
90+import Streamly.Internal.Data.Array.Stream (lpackArraysChunksOf)
90import Streamly.Data.Fold (Fold)
91import Streamly.Data.Fold (Fold)
91import Streamly.Data.Stream (Stream)
92import Streamly.Data.Stream (Stream)
92import Streamly.Internal.Data.Unfold (Unfold(..))
93import Streamly.Internal.Data.Unfold (Unfold(..))
@@ -98,10 +99,10 @@ import qualified Streamly.Data.Fold as FL
98import qualified Streamly.Data.Stream as S
99import qualified Streamly.Data.Stream as S
99import qualified Streamly.Data.Unfold as UF
100import qualified Streamly.Data.Unfold as UF
100import qualified Streamly.Internal.Data.Array as A
101import qualified Streamly.Internal.Data.Array as A
101− ( unsafeFreeze, unsafePinnedAsPtr, byteLength, pinnedChunksOf,
102+ ( unsafeFreeze, asPtrUnsafe, byteLength, pinnedChunksOf,
102− pinnedCreateOf, unsafePinnedCreateOf, lCompactGE )
103+ pinnedWriteN, pinnedWriteNUnsafe )
103import qualified Streamly.Internal.Data.MutArray as MArray
104import qualified Streamly.Internal.Data.MutArray as MArray
104− (MutArray(..), unsafePinnedAsPtr, pinnedEmptyOf)
105+ (MutArray(..), asPtrUnsafe, pinnedNewBytes)
105import qualified Streamly.Internal.Data.Stream as S (fromStreamK, Stream(..), Step(..))
106import qualified Streamly.Internal.Data.Stream as S (fromStreamK, Stream(..), Step(..))
106import qualified Streamly.Internal.Data.StreamK as K (mkStream)
107import qualified Streamly.Internal.Data.StreamK as K (mkStream)
107
108
@@ -252,8 +253,6 @@ accept tcpListenQ spec addr =
252-- Array IO (Input)
253-- Array IO (Input)
253-------------------------------------------------------------------------------
254-------------------------------------------------------------------------------
254
255
255−-- XXX add an API that compacts the arrays to an exact size.
256−
257{-# INLINABLE readArrayUptoWith #-}
256{-# INLINABLE readArrayUptoWith #-}
258readArrayUptoWith
257readArrayUptoWith
259 :: (h -> Ptr Word8 -> Int -> IO Int)
258 :: (h -> Ptr Word8 -> Int -> IO Int)
@@ -261,9 +260,9 @@ readArrayUptoWith
261 -> h
260 -> h
262 -> IO (Array Word8)
261 -> IO (Array Word8)
263readArrayUptoWith f size h = do
262readArrayUptoWith f size h = do
264− arr <- MArray.pinnedEmptyOf size
263+ arr <- MArray.pinnedNewBytes size
265 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
264 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
266− MArray.unsafePinnedAsPtr arr $ \p -> do
265+ MArray.asPtrUnsafe arr $ \p -> do
267 n <- f h p size
266 n <- f h p size
268 let v = A.unsafeFreeze
267 let v = A.unsafeFreeze
269 $ arr { MArray.arrEnd = n, MArray.arrBound = size }
268 $ arr { MArray.arrEnd = n, MArray.arrBound = size }
@@ -311,7 +310,7 @@ writeArrayWith :: Unbox a
311 -> Array a
310 -> Array a
312 -> IO ()
311 -> IO ()
313writeArrayWith _ _ arr | A.length arr == 0 = return ()
312writeArrayWith _ _ arr | A.length arr == 0 = return ()
314−writeArrayWith f h arr = A.unsafePinnedAsPtr arr $ \ptr -> f h (castPtr ptr) aLen
313+writeArrayWith f h arr = A.asPtrUnsafe arr $ \ptr -> f h (castPtr ptr) aLen
315
314
316 where
315 where
317
316
@@ -474,7 +473,7 @@ writeChunks h = FL.drainMapM (liftIO . putChunk h)
474{-# INLINE writeChunksWith #-}
473{-# INLINE writeChunksWith #-}
475writeChunksWith :: (MonadIO m, Unbox a)
474writeChunksWith :: (MonadIO m, Unbox a)
476 => Int -> Socket -> Fold m (Array a) ()
475 => Int -> Socket -> Fold m (Array a) ()
477−writeChunksWith n h = A.lCompactGE n (writeChunks h)
476+writeChunksWith n h = lpackArraysChunksOf n (writeChunks h)
478
477
479-- | Same as 'writeChunksWith'
478-- | Same as 'writeChunksWith'
480--
479--
@@ -505,7 +504,7 @@ putBytesWith n h m = putChunks h $ A.pinnedChunksOf n m
505--
504--
506{-# INLINE writeWith #-}
505{-# INLINE writeWith #-}
507writeWith :: MonadIO m => Int -> Socket -> Fold m Word8 ()
506writeWith :: MonadIO m => Int -> Socket -> Fold m Word8 ()
508−writeWith n h = FL.groupsOf n (A.unsafePinnedCreateOf n) (writeChunks h)
507+writeWith n h = FL.groupsOf n (A.pinnedWriteNUnsafe n) (writeChunks h)
509
508
510-- | Same as 'writeWith'
509-- | Same as 'writeWith'
511--
510--
@@ -523,7 +522,7 @@ writeWithBufferOf = writeWith
523writeMaybesWith :: (MonadIO m )
522writeMaybesWith :: (MonadIO m )
524 => Int -> Socket -> Fold m (Maybe Word8) ()
523 => Int -> Socket -> Fold m (Maybe Word8) ()
525writeMaybesWith n h =
524writeMaybesWith n h =
526− let writeNJusts = FL.lmap fromJust $ A.pinnedCreateOf n
525+ let writeNJusts = FL.lmap fromJust $ A.pinnedWriteN n
527 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
526 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
528 in FL.many writeOnNothing (writeChunks h)
527 in FL.many writeOnNothing (writeChunks h)
529
528
streamly.cabal+11−11
@@ -1,6 +1,6 @@
1cabal-version: 2.2
1cabal-version: 2.2
2name: streamly
2name: streamly
3−version: 0.10.1
3+version: 0.10.0
4synopsis: Streaming, dataflow programming and declarative concurrency
4synopsis: Streaming, dataflow programming and declarative concurrency
5description:
5description:
6 For upgrading to streamly-0.9.0+ please read the
6 For upgrading to streamly-0.9.0+ please read the
@@ -294,6 +294,8 @@ common compile-options
294common default-extensions
294common default-extensions
295 default-extensions:
295 default-extensions:
296 BangPatterns
296 BangPatterns
297+ CApiFFI
298+ CPP
297 ConstraintKinds
299 ConstraintKinds
298 DeriveDataTypeable
300 DeriveDataTypeable
299 DeriveGeneric
301 DeriveGeneric
@@ -304,25 +306,23 @@ common default-extensions
304 GeneralizedNewtypeDeriving
306 GeneralizedNewtypeDeriving
305 InstanceSigs
307 InstanceSigs
306 KindSignatures
308 KindSignatures
309+ LambdaCase
310+ MagicHash
307 MultiParamTypeClasses
311 MultiParamTypeClasses
312+ PatternSynonyms
308 RankNTypes
313 RankNTypes
314+ RecordWildCards
309 ScopedTypeVariables
315 ScopedTypeVariables
310 TupleSections
316 TupleSections
311 TypeApplications
317 TypeApplications
318+ TypeFamilies
312 TypeOperators
319 TypeOperators
320+ ViewPatterns
313
321
314− -- Not GHC2021
315− CApiFFI
316− CPP
317− LambdaCase
318− MagicHash
319− RecordWildCards
320−
321− -- TypeFamilies -- required by IsHashMap type class
322 -- MonoLocalBinds, enabled by TypeFamilies, causes performance
322 -- MonoLocalBinds, enabled by TypeFamilies, causes performance
323 -- regressions. Disable it. This must come after TypeFamilies,
323 -- regressions. Disable it. This must come after TypeFamilies,
324 -- otherwise TypeFamilies will enable it again.
324 -- otherwise TypeFamilies will enable it again.
325− -- NoMonoLocalBinds
325+ NoMonoLocalBinds
326
326
327 -- UndecidableInstances -- Does not show any perf impact
327 -- UndecidableInstances -- Does not show any perf impact
328 -- UnboxedTuples -- interferes with (#.)
328 -- UnboxedTuples -- interferes with (#.)
@@ -513,7 +513,7 @@ library
513 , template-haskell >= 2.14 && < 2.22
513 , template-haskell >= 2.14 && < 2.22
514
514
515 -- The core streamly package
515 -- The core streamly package
516− , streamly-core == 0.2.2
516+ , streamly-core >= 0.2.0 && < 0.2.2
517
517
518 , hashable >= 1.3 && < 1.5
518 , hashable >= 1.3 && < 1.5
519 , unordered-containers >= 0.2 && < 0.3
519 , unordered-containers >= 0.2 && < 0.3
test/Streamly/Test/Data/Array.hs+2−2
@@ -185,7 +185,7 @@ testUnsafeIndxedFromList inp =
185testAsPtrUnsafeMA :: IO ()
185testAsPtrUnsafeMA :: IO ()
186testAsPtrUnsafeMA = do
186testAsPtrUnsafeMA = do
187 arr <- MA.fromList ([0 .. 99] :: [Int])
187 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]
189
189
190 where
190 where
191
191
@@ -229,7 +229,7 @@ main =
229 prop "read . write === id" testFoldUnfold
229 prop "read . write === id" testFoldUnfold
230 prop "fromList" testFromList
230 prop "fromList" testFromList
231 prop "foldMany with writeNUnsafe concats to original"
231 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)))
233 describe "unsafeSlice" $ do
233 describe "unsafeSlice" $ do
234 it "partial" $ unsafeSlice 2 4 [1..10]
234 it "partial" $ unsafeSlice 2 4 [1..10]
235 it "none" $ unsafeSlice 10 0 [1..10]
235 it "none" $ unsafeSlice 10 0 [1..10]