on 0833f53 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/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+5−30
@@ -74,8 +74,6 @@ 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
@@ -205,8 +203,6 @@ last = getIndexRev 0
205-- Folds with Array as the container
203-- Folds with Array as the container
206-------------------------------------------------------------------------------
204-------------------------------------------------------------------------------
207
205
208−-- XXX We should generate this from Ring.
209−
210-- | @writeLastN n@ folds a maximum of @n@ elements from the end of the input
206-- | @writeLastN n@ folds a maximum of @n@ elements from the end of the input
211-- stream to an 'Array'.
207-- stream to an 'Array'.
212--
208--
@@ -328,7 +324,6 @@ sliceIndexerFromLen from len =
328 Unfold.lmap unsafeThaw (MA.sliceIndexerFromLen from len)
324 Unfold.lmap unsafeThaw (MA.sliceIndexerFromLen from len)
329
325
330{-# DEPRECATED genSlicesFromLen "Please use sliceIndexerFromLen instead." #-}
326{-# DEPRECATED genSlicesFromLen "Please use sliceIndexerFromLen instead." #-}
331−{-# INLINE genSlicesFromLen #-}
332genSlicesFromLen :: forall m a. (Monad m, Unbox a)
327genSlicesFromLen :: forall m a. (Monad m, Unbox a)
333 => Int -- ^ from index
328 => Int -- ^ from index
334 -> Int -- ^ length of the slice
329 -> Int -- ^ length of the slice
@@ -350,7 +345,6 @@ slicerFromLen from len =
350 $ Unfold.lmap unsafeThaw (MA.slicerFromLen from len)
345 $ Unfold.lmap unsafeThaw (MA.slicerFromLen from len)
351
346
352{-# DEPRECATED getSlicesFromLen "Please use slicerFromLen instead." #-}
347{-# DEPRECATED getSlicesFromLen "Please use slicerFromLen instead." #-}
353−{-# INLINE getSlicesFromLen #-}
354getSlicesFromLen :: forall m a. (Monad m, Unbox a)
348getSlicesFromLen :: forall m a. (Monad m, Unbox a)
355 => Int -- ^ from index
349 => Int -- ^ from index
356 -> Int -- ^ length of the slice
350 -> Int -- ^ length of the slice
@@ -401,7 +395,6 @@ indexReader m =
401
395
402-- XXX DO NOT REMOVE, change the signature to use Stream instead of unfold
396-- XXX DO NOT REMOVE, change the signature to use Stream instead of unfold
403{-# DEPRECATED getIndices "Please use getIndices instead." #-}
397{-# DEPRECATED getIndices "Please use getIndices instead." #-}
404−{-# INLINE getIndices #-}
405getIndices :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
398getIndices :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
406getIndices = indexReader
399getIndices = indexReader
407
400
@@ -452,7 +445,7 @@ runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (read arr)
452streamTransform :: forall m a b. (MonadIO m, Unbox a, Unbox b)
445streamTransform :: forall m a b. (MonadIO m, Unbox a, Unbox b)
453 => (Stream m a -> Stream m b) -> Array a -> m (Array b)
446 => (Stream m a -> Stream m b) -> Array a -> m (Array b)
454streamTransform f arr =
447streamTransform f arr =
455− Stream.fold (createWith (length arr)) $ f (read arr)
448+ Stream.fold (writeWith (length arr)) $ f (read arr)
456
449
457-------------------------------------------------------------------------------
450-------------------------------------------------------------------------------
458-- Casts
451-- Casts
@@ -505,8 +498,8 @@ cast arr =
505asCStringUnsafe :: Array a -> (CString -> IO b) -> IO b
498asCStringUnsafe :: Array a -> (CString -> IO b) -> IO b
506asCStringUnsafe arr act = do
499asCStringUnsafe arr act = do
507 let arr1 = asBytes arr <> fromList [0]
500 let arr1 = asBytes arr <> fromList [0]
508− -- unsafePinnedAsPtr makes sure the array is pinned
501+ -- asPtrUnsafe makes sure the array is pinned
509− unsafePinnedAsPtr arr1 $ \ptr -> act (castPtr ptr)
502+ asPtrUnsafe arr1 $ \ptr -> act (castPtr ptr)
510
503
511-------------------------------------------------------------------------------
504-------------------------------------------------------------------------------
512-- Folds
505-- Folds
@@ -598,7 +591,7 @@ data FlattenState s =
598-- >>> interposeSuffix x = Stream.interposeSuffix x Array.reader
591-- >>> interposeSuffix x = Stream.interposeSuffix x Array.reader
599--
592--
600{-# INLINE_NORMAL interposeSuffix #-}
593{-# INLINE_NORMAL interposeSuffix #-}
601−interposeSuffix :: forall m a. (Monad m, Unbox a)
594+interposeSuffix :: forall m a. (MonadIO m, Unbox a)
602 => a -> Stream m (Array a) -> Stream m a
595 => a -> Stream m (Array a) -> Stream m a
603-- This does not require MonadIO constraint.
596-- This does not require MonadIO constraint.
604-- interposeSuffix x = D.interposeSuffix x reader
597-- interposeSuffix x = D.interposeSuffix x reader
@@ -619,7 +612,7 @@ interposeSuffix sep (D.Stream step state) = D.Stream step' (OuterLoop state)
619 return $ D.Yield sep $ OuterLoop st
612 return $ D.Yield sep $ OuterLoop st
620
613
621 step' _ (InnerLoop st contents p end) = do
614 step' _ (InnerLoop st contents p end) = do
622− x <- pure $ unsafeInlineIO $ peekAt p contents
615+ x <- liftIO $ peekAt p contents
623 return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
616 return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
624
617
625-- | Insert the given array after each array and flatten.
618-- | Insert the given array after each array and flatten.
@@ -631,24 +624,6 @@ intercalateSuffix :: (Monad m, Unbox a)
631 => Array a -> Stream m (Array a) -> Stream m a
624 => Array a -> Stream m (Array a) -> Stream m a
632intercalateSuffix = D.intercalateSuffix reader
625intercalateSuffix = D.intercalateSuffix reader
633
626
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
627-- | 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.
628-- and coalescing all the arrays between two separators into a single array.
654--
629--
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/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−20
@@ -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(..))
@@ -93,30 +91,15 @@ getSlicesFromLen = slicerFromLen
93-- Compacting Streams of Arrays
91-- Compacting Streams of Arrays
94-------------------------------------------------------------------------------
92-------------------------------------------------------------------------------
95
93
96−-- | @compactLE maxElems@ coalesces adjacent arrays in the input stream
94+-- | Scan @compactLE n@ coalesces adjacent arrays in the input stream
97−-- only if the combined size would be less than or equal to @maxElems@
95+-- 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 #-}
96{-# INLINE compactLE #-}
106compactLE :: (MonadIO m, Unbox a) =>
97compactLE :: (MonadIO m, Unbox a) =>
107 Int -> Stream m (MutArray a) -> Stream m (MutArray a)
98 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
99-- XXX compactLE can be moved to MutArray/Type if we are not using the parser
109-- to implement it.
100-- 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)
101-- compactLE n = Stream.catRights . Stream.parseManyD (pCompactLE n)
113−
114−-- | Pinned version of 'compactLE'.
102+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
103
121data SplitState s arr
104data SplitState s arr
122 = Initial s
105 = 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+2−2
@@ -103,7 +103,7 @@ 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)
109import Streamly.Internal.Data.Unfold.Type (Unfold(..))
109import Streamly.Internal.Data.Unfold.Type (Unfold(..))
@@ -462,7 +462,7 @@ writeChunks path = Fold step initial extract final
462writeWith :: (MonadIO m, MonadCatch m)
462writeWith :: (MonadIO m, MonadCatch m)
463 => Int -> FilePath -> Fold m Word8 ()
463 => Int -> FilePath -> Fold m Word8 ()
464writeWith n path =
464writeWith n path =
465− groupsOf n (A.unsafePinnedCreateOf n) (writeChunks path)
465+ groupsOf n (pinnedWriteNUnsafe n) (writeChunks path)
466
466
467{-# DEPRECATED writeWithBufferOf "Please use 'writeWith' instead" #-}
467{-# DEPRECATED writeWithBufferOf "Please use 'writeWith' instead" #-}
468{-# INLINE writeWithBufferOf #-}
468{-# INLINE writeWithBufferOf #-}
core/src/Streamly/Internal/FileSystem/Handle.hs+16−17
@@ -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,14 @@ 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.String (encodeUtf8, decodeUtf8, foldLines)
136-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
137import Streamly.Internal.System.IO (defaultChunkSize)
137import Streamly.Internal.System.IO (defaultChunkSize)
138
138
139import qualified Streamly.Data.Fold as FL
139import qualified Streamly.Data.Fold as FL
140−import qualified Streamly.Internal.Data.Array as A
140+import qualified Streamly.Data.Array as A
141+import qualified Streamly.Internal.Data.Array.Type as A
141import qualified Streamly.Internal.Data.MutArray.Type as MArray
142import qualified Streamly.Internal.Data.MutArray.Type as MArray
142import qualified Streamly.Internal.Data.Refold.Type as Refold
143import qualified Streamly.Internal.Data.Refold.Type as Refold
143import qualified Streamly.Internal.Data.Fold.Type as FL(refoldMany)
144import qualified Streamly.Internal.Data.Fold.Type as FL(refoldMany)
@@ -166,8 +167,6 @@ import qualified Streamly.Internal.Data.StreamK.Type as K (mkStream)
166-- Array IO (Input)
167-- Array IO (Input)
167-------------------------------------------------------------------------------
168-------------------------------------------------------------------------------
168
169
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
170-- | 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
171-- 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
172-- available. If any data is available then it immediately returns that data
@@ -177,9 +176,9 @@ import qualified Streamly.Internal.Data.StreamK.Type as K (mkStream)
177{-# INLINABLE getChunk #-}
176{-# INLINABLE getChunk #-}
178getChunk :: MonadIO m => Int -> Handle -> m (Array Word8)
177getChunk :: MonadIO m => Int -> Handle -> m (Array Word8)
179getChunk size h = liftIO $ do
178getChunk size h = liftIO $ do
180− arr :: MArray.MutArray Word8 <- MArray.pinnedEmptyOf size
179+ arr <- MArray.pinnedNewBytes size
181 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
180 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
182− MArray.unsafePinnedAsPtr arr $ \p -> do
181+ MArray.asPtrUnsafe arr $ \p -> do
183 n <- hGetBufSome h p size
182 n <- hGetBufSome h p size
184 -- XXX shrink only if the diff is significant
183 -- XXX shrink only if the diff is significant
185 return $
184 return $
@@ -379,12 +378,12 @@ read = A.concat . readChunks
379{-# INLINABLE putChunk #-}
378{-# INLINABLE putChunk #-}
380putChunk :: MonadIO m => Handle -> Array a -> m ()
379putChunk :: MonadIO m => Handle -> Array a -> m ()
381putChunk _ arr | byteLength arr == 0 = return ()
380putChunk _ arr | byteLength arr == 0 = return ()
382−putChunk h arr = A.unsafePinnedAsPtr arr $ \ptr ->
381+putChunk h arr = A.asPtrUnsafe arr $ \ptr ->
383 liftIO $ hPutBuf h ptr aLen
382 liftIO $ hPutBuf h ptr aLen
384
383
385 where
384 where
386
385
387− -- XXX We should have the length passed by unsafePinnedAsPtr itself.
386+ -- XXX We should have the length passed by asPtrUnsafe itself.
388 aLen = A.byteLength arr
387 aLen = A.byteLength arr
389
388
390-------------------------------------------------------------------------------
389-------------------------------------------------------------------------------
@@ -489,11 +488,11 @@ writeChunksWithBufferOf = writeChunksWith
489-- Bytes in the input stream are collected into a buffer until we have a chunk
488-- 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.
489-- of @reqSize@ and then written to the IO device.
491--
490--
492−-- >>> writeWith n h = Fold.groupsOf n (Array.unsafeCreateOf n) (Handle.writeChunks h)
491+-- >>> writeWith n h = Fold.groupsOf n (Array.writeNUnsafe n) (Handle.writeChunks h)
493--
492--
494{-# INLINE writeWith #-}
493{-# INLINE writeWith #-}
495writeWith :: MonadIO m => Int -> Handle -> Fold m Word8 ()
494writeWith :: MonadIO m => Int -> Handle -> Fold m Word8 ()
496−writeWith n h = FL.groupsOf n (A.unsafePinnedCreateOf n) (writeChunks h)
495+writeWith n h = FL.groupsOf n (pinnedWriteNUnsafe n) (writeChunks h)
497
496
498-- | Same as 'writeWith'
497-- | Same as 'writeWith'
499--
498--
@@ -511,7 +510,7 @@ writeWithBufferOf = writeWith
511writeMaybesWith :: (MonadIO m )
510writeMaybesWith :: (MonadIO m )
512 => Int -> Handle -> Fold m (Maybe Word8) ()
511 => Int -> Handle -> Fold m (Maybe Word8) ()
513writeMaybesWith n h =
512writeMaybesWith n h =
514− let writeNJusts = FL.lmap fromJust $ A.pinnedCreateOf n
513+ let writeNJusts = FL.lmap fromJust $ A.pinnedWriteN n
515 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
514 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
516 in FL.many writeOnNothing (writeChunks h)
515 in FL.many writeOnNothing (writeChunks h)
517
516
@@ -521,7 +520,7 @@ writeMaybesWith n h =
521{-# INLINE writerWith #-}
520{-# INLINE writerWith #-}
522writerWith :: MonadIO m => Int -> Refold m Handle Word8 ()
521writerWith :: MonadIO m => Int -> Refold m Handle Word8 ()
523writerWith n =
522writerWith n =
524− FL.refoldMany (FL.take n $ A.unsafePinnedCreateOf n) chunkWriter
523+ FL.refoldMany (FL.take n $ pinnedWriteNUnsafe n) chunkWriter
525
524
526-- | Write a byte stream to a file handle. Accumulates the input in chunks of
525-- | 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
526-- 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+8−10
@@ -98,10 +98,10 @@ import qualified Streamly.Data.Fold as FL
98import qualified Streamly.Data.Stream as S
98import qualified Streamly.Data.Stream as S
99import qualified Streamly.Data.Unfold as UF
99import qualified Streamly.Data.Unfold as UF
100import qualified Streamly.Internal.Data.Array as A
100import qualified Streamly.Internal.Data.Array as A
101− ( unsafeFreeze, unsafePinnedAsPtr, byteLength, pinnedChunksOf,
101+ ( unsafeFreeze, asPtrUnsafe, byteLength, pinnedChunksOf,
102− pinnedCreateOf, unsafePinnedCreateOf, lCompactGE )
102+ pinnedWriteN, pinnedWriteNUnsafe, lCompactGE )
103import qualified Streamly.Internal.Data.MutArray as MArray
103import qualified Streamly.Internal.Data.MutArray as MArray
104− (MutArray(..), unsafePinnedAsPtr, pinnedEmptyOf)
104+ (MutArray(..), asPtrUnsafe, pinnedNewBytes)
105import qualified Streamly.Internal.Data.Stream as S (fromStreamK, Stream(..), Step(..))
105import qualified Streamly.Internal.Data.Stream as S (fromStreamK, Stream(..), Step(..))
106import qualified Streamly.Internal.Data.StreamK as K (mkStream)
106import qualified Streamly.Internal.Data.StreamK as K (mkStream)
107
107
@@ -252,8 +252,6 @@ accept tcpListenQ spec addr =
252-- Array IO (Input)
252-- Array IO (Input)
253-------------------------------------------------------------------------------
253-------------------------------------------------------------------------------
254
254
255−-- XXX add an API that compacts the arrays to an exact size.
256−
257{-# INLINABLE readArrayUptoWith #-}
255{-# INLINABLE readArrayUptoWith #-}
258readArrayUptoWith
256readArrayUptoWith
259 :: (h -> Ptr Word8 -> Int -> IO Int)
257 :: (h -> Ptr Word8 -> Int -> IO Int)
@@ -261,9 +259,9 @@ readArrayUptoWith
261 -> h
259 -> h
262 -> IO (Array Word8)
260 -> IO (Array Word8)
263readArrayUptoWith f size h = do
261readArrayUptoWith f size h = do
264− arr <- MArray.pinnedEmptyOf size
262+ arr <- MArray.pinnedNewBytes size
265 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
263 -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))
266− MArray.unsafePinnedAsPtr arr $ \p -> do
264+ MArray.asPtrUnsafe arr $ \p -> do
267 n <- f h p size
265 n <- f h p size
268 let v = A.unsafeFreeze
266 let v = A.unsafeFreeze
269 $ arr { MArray.arrEnd = n, MArray.arrBound = size }
267 $ arr { MArray.arrEnd = n, MArray.arrBound = size }
@@ -311,7 +309,7 @@ writeArrayWith :: Unbox a
311 -> Array a
309 -> Array a
312 -> IO ()
310 -> IO ()
313writeArrayWith _ _ arr | A.length arr == 0 = return ()
311writeArrayWith _ _ arr | A.length arr == 0 = return ()
314−writeArrayWith f h arr = A.unsafePinnedAsPtr arr $ \ptr -> f h (castPtr ptr) aLen
312+writeArrayWith f h arr = A.asPtrUnsafe arr $ \ptr -> f h (castPtr ptr) aLen
315
313
316 where
314 where
317
315
@@ -505,7 +503,7 @@ putBytesWith n h m = putChunks h $ A.pinnedChunksOf n m
505--
503--
506{-# INLINE writeWith #-}
504{-# INLINE writeWith #-}
507writeWith :: MonadIO m => Int -> Socket -> Fold m Word8 ()
505writeWith :: MonadIO m => Int -> Socket -> Fold m Word8 ()
508−writeWith n h = FL.groupsOf n (A.unsafePinnedCreateOf n) (writeChunks h)
506+writeWith n h = FL.groupsOf n (A.pinnedWriteNUnsafe n) (writeChunks h)
509
507
510-- | Same as 'writeWith'
508-- | Same as 'writeWith'
511--
509--
@@ -523,7 +521,7 @@ writeWithBufferOf = writeWith
523writeMaybesWith :: (MonadIO m )
521writeMaybesWith :: (MonadIO m )
524 => Int -> Socket -> Fold m (Maybe Word8) ()
522 => Int -> Socket -> Fold m (Maybe Word8) ()
525writeMaybesWith n h =
523writeMaybesWith n h =
526− let writeNJusts = FL.lmap fromJust $ A.pinnedCreateOf n
524+ let writeNJusts = FL.lmap fromJust $ A.pinnedWriteN n
527 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
525 writeOnNothing = FL.takeEndBy_ isNothing writeNJusts
528 in FL.many writeOnNothing (writeChunks h)
526 in FL.many writeOnNothing (writeChunks h)
529
527
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]