streamly 0.10.0 → 0.10.1
raw patch · 36 files changed
+290/−163 lines, 36 filesdep ~basedep ~hashabledep ~network
Dependency ranges changed: base, hashable, network, streamly-core, template-haskell, unicode-data
Files
- CHANGELOG.md +4/−0
- benchmark/Streamly/Benchmark/Data/Fold.hs +2/−2
- benchmark/Streamly/Benchmark/Data/Serialize.hs +10/−15
- benchmark/Streamly/Benchmark/Data/Serialize/TH.hs +3/−3
- benchmark/Streamly/Benchmark/Data/Stream/Eliminate.hs +2/−0
- benchmark/Streamly/Benchmark/Data/Stream/StreamKAlt.hs +1/−1
- benchmark/Streamly/Benchmark/Data/Stream/ToStreamK.hs +1/−1
- benchmark/Streamly/Benchmark/FileSystem/Handle/Read.hs +7/−8
- benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs +8/−9
- benchmark/Streamly/Benchmark/Unicode/Stream.hs +4/−3
- benchmark/streamly-benchmarks.cabal +1/−1
- configure +9/−9
- configure.ac +1/−1
- docs/Developer/paths.rst +25/−2
- docs/User/Project/Changelog.md +4/−0
- src/Streamly/Data/Stream/Prelude.hs +24/−14
- src/Streamly/Internal/Data/Stream/Concurrent.hs +18/−10
- src/Streamly/Internal/Data/Stream/IsStream/Common.hs +1/−1
- src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs +1/−1
- src/Streamly/Internal/Data/Stream/MkType.hs +33/−34
- src/Streamly/Internal/FileSystem/Event/Darwin.hs +1/−1
- src/Streamly/Internal/FileSystem/Event/Linux.hs +2/−2
- src/Streamly/Internal/FileSystem/FD.hs +5/−5
- src/Streamly/Internal/Network/Inet/TCP.hs +3/−3
- src/Streamly/Internal/Network/Socket.hs +11/−10
- src/Streamly/Internal/Unicode/Char.hs +3/−3
- src/Streamly/Network/Inet/TCP.hs +28/−0
- src/Streamly/Network/Socket.hs +3/−4
- streamly.cabal +10/−6
- test/Streamly/Test/Data/Array.hs +2/−2
- test/Streamly/Test/Data/Fold.hs +7/−6
- test/Streamly/Test/Data/Serialize.hs +32/−1
- test/Streamly/Test/Data/Serialize/TH.hs +2/−2
- test/Streamly/Test/Data/Unbox.hs +19/−0
- test/Streamly/Test/FileSystem/Handle.hs +2/−2
- test/Streamly/Test/Unicode/Char.hs +1/−1
CHANGELOG.md view
@@ -2,6 +2,10 @@ <!-- See rendered changelog at https://streamly.composewell.com --> +## 0.10.1 (Jan 2024)++* Fix TH macros in `Streamly.Data.Stream.MkType` for GHC 9.6 and above.+ ## 0.10.0 (Nov 2023) See
benchmark/Streamly/Benchmark/Data/Fold.hs view
@@ -269,13 +269,13 @@ {-# INLINE unzipWithFstM #-} unzipWithFstM :: Monad m => Stream m Int -> m (Int, Int) unzipWithFstM = do- let f = \a -> return (a + 1, a)+ let f a = return (a + 1, a) Stream.fold (FL.unzipWithFstM f FL.sum FL.length) {-# INLINE unzipWithMinM #-} unzipWithMinM :: Monad m => Stream m Int -> m (Int, Int) unzipWithMinM = do- let f = \a -> return (a + 1, a)+ let f a = return (a + 1, a) Stream.fold (FL.unzipWithMinM f FL.sum FL.length) -------------------------------------------------------------------------------
benchmark/Streamly/Benchmark/Data/Serialize.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE TemplateHaskell #-}+{- HLINT ignore -} #undef FUSION_CHECK #ifdef FUSION_CHECK@@ -18,6 +19,7 @@ ------------------------------------------------------------------------------- import Control.DeepSeq (NFData(..), deepseq)+import Control.Monad (when, void) import GHC.Generics (Generic) import System.Random (randomRIO) #ifndef USE_UNBOX@@ -264,13 +266,14 @@ instance NFData a => NFData (BinTree a) where {-# INLINE rnf #-} rnf (Leaf a) = rnf a `seq` ()- rnf (Tree l r) = rnf l `seq` rnf r `seq` ()+ rnf (Tree l r) = rnf l `seq` rnf r +-- XXX This may not terminate, or could become really large. instance Arbitrary a => Arbitrary (BinTree a) where arbitrary = oneof [Leaf <$> arbitrary, Tree <$> arbitrary <*> arbitrary] mkBinTree :: (Arbitrary a) => Int -> IO (BinTree a)-mkBinTree = go (generate $ arbitrary)+mkBinTree = go (generate arbitrary) where @@ -295,16 +298,14 @@ -- Common helpers ------------------------------------------------------------------------------- +{- HLINT ignore "Eta reduce" -} -- Parts of "f" that are dependent on val will not be optimized out. {-# INLINE loop #-} loop :: Int -> (a -> IO b) -> a -> IO () loop count f val = go count val where - go n x = do- if n > 0- then f x >> go (n-1) x- else return ()+ go n x = when (n > 0) $ f x >> go (n-1) x -- The first arg of "f" is the environment which is not threaded around in the -- loop.@@ -313,10 +314,7 @@ loopWith count f e val = go count val where - go n x = do- if n > 0- then f e x >> go (n-1) x- else return ()+ go n x = when (n > 0) $ f e x >> go (n-1) x benchSink :: NFData b => String -> Int -> (Int -> IO b) -> Benchmark benchSink name times f = bench name (nfIO (randomRIO (times, times) >>= f))@@ -342,7 +340,7 @@ {-# INLINE poke #-} poke :: SERIALIZE_CLASS a => MutByteArray -> a -> IO ()-poke arr val = SERIALIZE_OP 0 arr val >> return ()+poke arr val = void (SERIALIZE_OP 0 arr val) {-# INLINE pokeTimes #-} pokeTimes :: SERIALIZE_CLASS a => a -> Int -> IO ()@@ -356,7 +354,7 @@ encode val = do let n = getSize val arr <- MBA.new n- SERIALIZE_OP 0 arr val >> return ()+ void (SERIALIZE_OP 0 arr val) {-# INLINE encodeTimes #-} encodeTimes :: SERIALIZE_CLASS a => a -> Int -> IO ()@@ -562,8 +560,6 @@ let !len = length lInt -- evaluate the list #endif #ifndef FUSION_CHECK- -- This can take too much memory/CPU, need to restrict the test- -- runQC #ifdef USE_UNBOX runWithCLIOpts defaultStreamSize allBenchmarks #else@@ -571,7 +567,6 @@ `seq` runWithCLIOpts defaultStreamSize (allBenchmarks tInt lInt recL recR)- #endif #else -- Enable FUSION_CHECK macro at the beginning of the file
benchmark/Streamly/Benchmark/Data/Serialize/TH.hs view
@@ -18,7 +18,7 @@ genLargeRecord :: String -> Int -> Q [Dec] genLargeRecord tyName numFields = sequence- ([ dataD+ [ dataD (pure []) (mkName tyName) []@@ -28,7 +28,7 @@ , mkValueSigDec , mkValueDec , nfDataInstance tyName- ])+ ] where @@ -64,7 +64,7 @@ (foldl (\b a -> [|$(b) $(a)|]) (conE (mkName tyName))- (const (conE '()) <$> [0 .. (numFields - 1)])))+ (conE '() <$ [0 .. (numFields - 1)]))) [] ] mkCon nm = recC (mkName nm) (mkField <$> [0 .. (numFields - 1)])
benchmark/Streamly/Benchmark/Data/Stream/Eliminate.hs view
@@ -132,12 +132,14 @@ foldableAny value n = Prelude.any (> (value + 1)) (sourceUnfoldr value n :: Stream Identity Int) +{- HLINT ignore "Use all"-} {-# INLINE foldableAnd #-} foldableAnd :: Int -> Int -> Bool foldableAnd value n = Prelude.and $ fmap (<= (value + 1)) (sourceUnfoldr value n :: Stream Identity Int) +{- HLINT ignore "Use any"-} {-# INLINE foldableOr #-} foldableOr :: Int -> Int -> Bool foldableOr value n =
benchmark/Streamly/Benchmark/Data/Stream/StreamKAlt.hs view
@@ -452,4 +452,4 @@ ] main :: IO ()-main = defaultMain $ concat [o_1_space]+main = defaultMain [o_1_space]
benchmark/Streamly/Benchmark/Data/Stream/ToStreamK.hs view
@@ -120,7 +120,7 @@ {-# INLINE fromFoldableM #-} fromFoldableM :: Monad m => Int -> Int -> Stream m Int fromFoldableM streamLen n =- Prelude.foldr S.consM S.nil (Prelude.fmap return [n..n+streamLen])+ Prelude.foldr (S.consM . return) S.nil [n .. n + streamLen] {- {-# INLINABLE concatMapFoldableWith #-}
benchmark/Streamly/Benchmark/FileSystem/Handle/Read.hs view
@@ -33,7 +33,6 @@ import qualified Streamly.Data.Fold as Fold import qualified Streamly.FileSystem.Handle as FH import qualified Streamly.Internal.Data.Array as A-import qualified Streamly.Internal.Data.Array as AT import qualified Streamly.Internal.Data.Fold as FL import qualified Streamly.Internal.Data.Stream as IP import qualified Streamly.Internal.FileSystem.Handle as IFH@@ -48,7 +47,7 @@ #ifdef INSPECTION import Streamly.Internal.Data.Stream (Step(..), FoldMany) -import qualified Streamly.Internal.Data.MutArray as MA+import qualified Streamly.Internal.Data.MutArray as MutArray import qualified Streamly.Internal.Data.Stream as D import qualified Streamly.Internal.Data.Unfold as IUF @@ -69,7 +68,7 @@ inspect $ hasNoTypeClasses 'readLast inspect $ 'readLast `hasNoType` ''Step -- S.unfold inspect $ 'readLast `hasNoType` ''IUF.ConcatState -- FH.read/UF.many-inspect $ 'readLast `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read+inspect $ 'readLast `hasNoType` ''MutArray.ArrayUnsafe -- FH.read/A.read #endif -- assert that flattenArrays constructors are not present@@ -81,7 +80,7 @@ inspect $ hasNoTypeClasses 'readCountBytes inspect $ 'readCountBytes `hasNoType` ''Step -- S.unfold inspect $ 'readCountBytes `hasNoType` ''IUF.ConcatState -- FH.read/UF.many-inspect $ 'readCountBytes `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read+inspect $ 'readCountBytes `hasNoType` ''MutArray.ArrayUnsafe -- FH.read/A.read #endif -- | Count the number of lines in a file.@@ -96,7 +95,7 @@ inspect $ hasNoTypeClasses 'readCountLines inspect $ 'readCountLines `hasNoType` ''Step inspect $ 'readCountLines `hasNoType` ''IUF.ConcatState -- FH.read/UF.many-inspect $ 'readCountLines `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read+inspect $ 'readCountLines `hasNoType` ''MutArray.ArrayUnsafe -- FH.read/A.read #endif -- | Count the number of words in a file.@@ -120,7 +119,7 @@ inspect $ hasNoTypeClasses 'readSumBytes inspect $ 'readSumBytes `hasNoType` ''Step inspect $ 'readSumBytes `hasNoType` ''IUF.ConcatState -- FH.read/UF.many-inspect $ 'readSumBytes `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read+inspect $ 'readSumBytes `hasNoType` ''MutArray.ArrayUnsafe -- FH.read/A.read #endif -- XXX When we mark this with INLINE and we have two benchmarks using S.drain@@ -236,13 +235,13 @@ groupsOf n inh = -- writeNUnsafe gives 2.5x boost here over writeN. S.fold Fold.length- $ IP.groupsOf n (AT.writeNUnsafe n) (S.unfold FH.reader inh)+ $ IP.groupsOf n (A.writeNUnsafe n) (S.unfold FH.reader inh) #ifdef INSPECTION inspect $ hasNoTypeClasses 'groupsOf inspect $ 'groupsOf `hasNoType` ''Step inspect $ 'groupsOf `hasNoType` ''FoldMany-inspect $ 'groupsOf `hasNoType` ''AT.ArrayUnsafe -- AT.writeNUnsafe+inspect $ 'groupsOf `hasNoType` ''MutArray.ArrayUnsafe -- AT.writeNUnsafe -- FH.read/A.read inspect $ 'groupsOf `hasNoType` ''IUF.ConcatState -- FH.read/UF.many #endif
benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs view
@@ -42,8 +42,7 @@ import qualified Streamly.Internal.Data.Stream as D import qualified Streamly.Internal.Data.Tuple.Strict as Strict-import qualified Streamly.Internal.Data.MutArray.Stream as MAS-import qualified Streamly.Internal.Data.Array as AT+import qualified Streamly.Internal.Data.MutArray as MutArray import Test.Inspection #endif@@ -83,7 +82,7 @@ inspect $ hasNoTypeClasses 'copyStream inspect $ 'copyStream `hasNoType` ''Step -- S.unfold inspect $ 'copyStream `hasNoType` ''IUF.ConcatState -- FH.read/UF.many-inspect $ 'copyStream `hasNoType` ''AT.ArrayUnsafe -- FH.write/writeNUnsafe+inspect $ 'copyStream `hasNoType` ''MutArray.ArrayUnsafe -- FH.write/writeNUnsafe -- FH.read/A.read inspect $ 'copyStream `hasNoType` ''Strict.Tuple3' -- FH.write/chunksOf #endif@@ -109,8 +108,8 @@ #ifdef INSPECTION inspect $ hasNoTypeClasses 'readFromBytesNull inspect $ 'readFromBytesNull `hasNoType` ''Step-inspect $ 'readFromBytesNull `hasNoType` ''MAS.SpliceState-inspect $ 'readFromBytesNull `hasNoType` ''AT.ArrayUnsafe -- FH.fromBytes/S.chunksOf+inspect $ 'readFromBytesNull `hasNoType` ''MutArray.SpliceState+inspect $ 'readFromBytesNull `hasNoType` ''MutArray.ArrayUnsafe -- FH.fromBytes/S.chunksOf inspect $ 'readFromBytesNull `hasNoType` ''D.FoldMany #endif @@ -123,8 +122,8 @@ #ifdef INSPECTION inspect $ hasNoTypeClasses 'readWithFromBytesNull inspect $ 'readWithFromBytesNull `hasNoType` ''Step-inspect $ 'readWithFromBytesNull `hasNoType` ''MAS.SpliceState-inspect $ 'readWithFromBytesNull `hasNoType` ''AT.ArrayUnsafe -- FH.fromBytes/S.chunksOf+inspect $ 'readWithFromBytesNull `hasNoType` ''MutArray.SpliceState+inspect $ 'readWithFromBytesNull `hasNoType` ''MutArray.ArrayUnsafe -- FH.fromBytes/S.chunksOf inspect $ 'readWithFromBytesNull `hasNoType` ''D.FoldMany #endif @@ -171,7 +170,7 @@ inspect $ hasNoTypeClasses 'writeReadWith inspect $ 'writeReadWith `hasNoType` ''Step inspect $ 'writeReadWith `hasNoType` ''IUF.ConcatState -- FH.read/UF.many-inspect $ 'writeReadWith `hasNoType` ''AT.ArrayUnsafe -- FH.write/writeNUnsafe+inspect $ 'writeReadWith `hasNoType` ''MutArray.ArrayUnsafe -- FH.write/writeNUnsafe -- FH.read/A.read #endif @@ -188,7 +187,7 @@ inspect $ hasNoTypeClasses 'writeRead inspect $ 'writeRead `hasNoType` ''Step inspect $ 'writeRead `hasNoType` ''IUF.ConcatState -- FH.read/UF.many-inspect $ 'writeRead `hasNoType` ''AT.ArrayUnsafe -- FH.write/writeNUnsafe+inspect $ 'writeRead `hasNoType` ''MutArray.ArrayUnsafe -- FH.write/writeNUnsafe -- FH.read/A.read #endif
benchmark/Streamly/Benchmark/Unicode/Stream.hs view
@@ -45,9 +45,10 @@ #ifdef INSPECTION import Streamly.Internal.Data.MutByteArray (Unbox) import Streamly.Internal.Data.Stream (Step(..))+import qualified Streamly.Internal.Data.Array as Array+import qualified Streamly.Internal.Data.MutArray as MutArray import qualified Streamly.Internal.Data.Fold as Fold import qualified Streamly.Internal.Data.Tuple.Strict as Strict-import qualified Streamly.Internal.Data.Array as Array import Test.Inspection #endif@@ -223,7 +224,7 @@ inspect $ 'copyStreamLatin1' `hasNoType` ''Unfold.ConcatState -- Handle.read/UF.many inspect $ 'copyStreamLatin1' `hasNoType` ''Fold.Step-inspect $ 'copyStreamLatin1' `hasNoType` ''Array.ArrayUnsafe -- Handle.write/writeNUnsafe+inspect $ 'copyStreamLatin1' `hasNoType` ''MutArray.ArrayUnsafe -- Handle.write/writeNUnsafe -- Handle.read/Array.read inspect $ 'copyStreamLatin1' `hasNoType` ''Strict.Tuple3' -- Handle.write/chunksOf #endif@@ -244,7 +245,7 @@ inspect $ 'copyStreamLatin1 `hasNoType` ''Fold.ManyState inspect $ 'copyStreamLatin1 `hasNoType` ''Fold.Step-inspect $ 'copyStreamLatin1 `hasNoType` ''Array.ArrayUnsafe -- Handle.write/writeNUnsafe+inspect $ 'copyStreamLatin1 `hasNoType` ''MutArray.ArrayUnsafe -- Handle.write/writeNUnsafe -- Handle.read/Array.read inspect $ 'copyStreamLatin1 `hasNoType` ''Strict.Tuple3' -- Handle.write/chunksOf #endif
benchmark/streamly-benchmarks.cabal view
@@ -188,7 +188,7 @@ , unordered-containers >= 0.2 && < 0.3 , process >= 1.4 && < 1.7 , directory >= 1.2.2 && < 1.4- , filepath >= 1.4.1 && < 1.5+ , filepath >= 1.4.1 && < 1.6 , ghc-prim >= 0.4 && < 0.12 , tasty-bench >= 0.3 && < 0.4 , tasty >= 1.4.1 && < 1.6
configure view
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles.-# Generated by GNU Autoconf 2.71 for streamly 0.10.0.+# Generated by GNU Autoconf 2.71 for streamly 0.10.1. # # Report bugs to <streamly@composewell.com>. #@@ -610,8 +610,8 @@ # Identity of this package. PACKAGE_NAME='streamly' PACKAGE_TARNAME='streamly'-PACKAGE_VERSION='0.10.0'-PACKAGE_STRING='streamly 0.10.0'+PACKAGE_VERSION='0.10.1'+PACKAGE_STRING='streamly 0.10.1' PACKAGE_BUGREPORT='streamly@composewell.com' PACKAGE_URL='https://streamly.composewell.com' @@ -1224,7 +1224,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF-\`configure' configures streamly 0.10.0 to adapt to many kinds of systems.+\`configure' configures streamly 0.10.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1286,7 +1286,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in- short | recursive ) echo "Configuration of streamly 0.10.0:";;+ short | recursive ) echo "Configuration of streamly 0.10.1:";; esac cat <<\_ACEOF @@ -1372,7 +1372,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF-streamly configure 0.10.0+streamly configure 0.10.1 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc.@@ -1500,7 +1500,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by streamly $as_me 0.10.0, which was+It was created by streamly $as_me 0.10.1, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw@@ -3800,7 +3800,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log="-This file was extended by streamly $as_me 0.10.0, which was+This file was extended by streamly $as_me 0.10.1, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES@@ -3856,7 +3856,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\-streamly config.status 0.10.0+streamly config.status 0.10.1 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\"
configure.ac view
@@ -3,7 +3,7 @@ # See https://www.gnu.org/software/autoconf/manual/autoconf.html for help on # the macros used in this file. -AC_INIT([streamly], [0.10.0], [streamly@composewell.com], [streamly], [https://streamly.composewell.com])+AC_INIT([streamly], [0.10.1], [streamly@composewell.com], [streamly], [https://streamly.composewell.com]) # To suppress "WARNING: unrecognized options: --with-compiler" AC_ARG_WITH([compiler], [GHC])
docs/Developer/paths.rst view
@@ -140,12 +140,35 @@ it differently, the user may use the displayed result to find the file and may not find it. +OS Specific Path Encodings+--------------------------++In general, the OS does not have to look inside the path components+other than the ability to recognize the separator char to parse the+path into components and to construct it from components. However, in+some cases the OS may may have to look inside the path e.g. "." or ".."+special paths on Unix.++On Unix a path component is just a blob of bytes. The user can encode+and decode this blob of bytes as they desire. All they need to care+about is that the path separator byte is respected. However, the the+path component blobs may be changed by the underlying filesystem+e.g. apple HFS may normalize the path before storing, therefore, the+representation may change when it is returned back to the user.++On modern Windows systems a path component is UTF16-LE+encoded. Theoretically, from the OS perspective, it does not have to+look inside the path components other than determining whether a 16-bit+unit represents the separator character, therefore, users can use any+encoding as long as it encodes to 16-bit multiples and the separator is+preserved as equivalent to the UTF16-LE representation.+ Type Safety Requirements ------------------------ * Safety against using an absolute path where a relative path is to be- used and vice-versa. - + used and vice-versa.+ * Validations for absolute or relative path when constructing a path. * We cannot append an absolute path to another path * Safety against using a file name where a directory name is to be used and
docs/User/Project/Changelog.md view
@@ -2,6 +2,10 @@ <!-- See rendered changelog at https://streamly.composewell.com --> +## 0.10.1 (Jan 2024)++* Fix TH macros in `Streamly.Data.Stream.MkType` for GHC 9.6 and above.+ ## 0.10.0 (Nov 2023) See
src/Streamly/Data/Stream/Prelude.hs view
@@ -6,6 +6,11 @@ -- Stability : experimental -- Portability : GHC --+-- For upgrading to streamly-0.9.0+ please read the+-- <https://github.com/composewell/streamly/blob/streamly-0.10.0/docs/User/Project/Upgrading-0.8-to-0.9.md Streamly-0.9.0 upgrade guide>.+-- Also, see the "Streamly.Data.Stream.MkType" module for direct replacement of+-- stream types that have been removed in 0.9.0.+-- -- All Stream related combinators including the streamly-core -- "Streamly.Data.Stream" module, concurrency, time and lifted -- exception operations. For more pre-release operations also see@@ -56,25 +61,28 @@ -- | Stream combinators using a concurrent channel. -- *** Evaluate- -- | Evaluates a serial stream asynchronously using a concurency channel.+ -- | Evaluate a stream as a whole concurrently with respect to the consumer+ -- of the stream. , parEval -- *** Generate- -- | Uses a concurrency channel to evaluate multiple actions concurrently.+ -- | Generate a stream by evaluating multiple actions concurrently. , parRepeatM , parReplicateM , fromCallback -- *** Map- -- | Uses a concurrency channel to evaluate multiple mapped actions- -- concurrently.+ -- | Map actions on a stream such that the mapped actions are evaluated+ -- concurrently with each other. , parMapM , parSequence -- *** Combine two- -- | Use a channel for each pair.+ -- | Combine two streams such that each stream as a whole is evaluated+ -- concurrently with respect to the other stream as well as the consumer of+ -- the resulting stream. , parZipWithM , parZipWith , parMergeByM@@ -152,16 +160,18 @@ -- 'parConcatMap', and 'parConcatIterate', all concurrency combinators can be -- expressed in terms of these. ----- 'parEval', evaluates a single stream asynchronously, a worker thread runs--- the stream and buffers the results, and the consumer of the stream runs in--- another thread consuming it from the buffer, thus decoupling the production--- and consumption of the stream. This can be used to run different stages of a--- pipeline concurrently.+-- 'parEval' evaluates a stream as a whole asynchronously with respect to+-- the consumer of the stream. A worker thread evaluates multiple elements of+-- the stream ahead of time and buffers the results; the consumer of the stream+-- runs in another thread consuming the elements from the buffer, thus+-- decoupling the production and consumption of the stream. 'parEval' can be+-- used to run different stages of a pipeline concurrently. ----- 'parConcatMap' is used to evaluate multiple streams concurrently and combine--- the results. A stream generator function is mapped to the input stream and--- all the generated streams are then evaluated concurrently, and the results--- are combined.+-- 'parConcatMap' is used to evaluate multiple actions in a stream concurrently+-- with respect to each other or to evaluate multiple streams concurrently and+-- combine the results. A stream generator function is mapped to the input+-- stream and all the generated streams are then evaluated concurrently, and+-- the results are combined. -- -- 'parConcatIterate' is like 'parConcatMap' but iterates a stream generator -- function recursively over the stream. This can be used to traverse trees or
src/Streamly/Internal/Data/Stream/Concurrent.hs view
@@ -147,16 +147,24 @@ D.Stop -> D.Stop -} --- | Evaluate a stream asynchronously. In a serial stream, each element of the--- stream is generated as it is demanded by the consumer. `parEval` evaluates--- multiple elements of the stream ahead of time and serves the results from a--- buffer.+-- | 'parEval' evaluates a stream as a whole asynchronously with respect to+-- the consumer of the stream. A worker thread evaluates multiple elements of+-- the stream ahead of time and buffers the results; the consumer of the stream+-- runs in another thread consuming the elements from the buffer, thus+-- decoupling the production and consumption of the stream. 'parEval' can be+-- used to run different stages of a pipeline concurrently. ----- Note that the evaluation requires only one thread as only one stream needs--- to be evaluated. Therefore, the concurrency options that are relevant to--- multiple streams won't apply here e.g. maxThreads, eager, interleaved,--- ordered, stopWhen options won't have any effect.+-- It is important to note that 'parEval' does not evaluate individual actions+-- in the stream concurrently with respect to each other, it merely evaluates+-- the stream serially but in a different thread than the consumer thread,+-- thus the consumer and producer can run concurrently. See 'parMapM' and+-- 'parSequence' to evaluate actions in the stream concurrently. --+-- The evaluation requires only one thread as only one stream needs to be+-- evaluated. Therefore, the concurrency options that are relevant to multiple+-- streams do not apply here e.g. maxThreads, eager, interleaved, ordered,+-- stopWhen options do not have any effect on 'parEval'.+-- -- Useful idioms: -- -- >>> parUnfoldrM step = Stream.parEval id . Stream.unfoldrM step@@ -646,8 +654,8 @@ where - iterateStream channel stream =- parConcatMapChanKGeneric modifier channel (generate channel) stream+ iterateStream channel =+ parConcatMapChanKGeneric modifier channel (generate channel) generate channel x = -- XXX The channel q should be FIFO for DFS, otherwise it is BFS
src/Streamly/Internal/Data/Stream/IsStream/Common.hs view
@@ -529,7 +529,7 @@ -- reverse' s = fromStreamD $ D.reverse' $ toStreamD s reverse' = fromStreamD- . A.flattenArraysRev -- unfoldMany A.readRev+ . A.concatRev -- unfoldMany A.readerRev . D.fromStreamK . K.reverse . D.toStreamK
src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs view
@@ -1624,4 +1624,4 @@ -> t m (f a) -> t m (f a) splitInnerBySuffix splitter joiner xs =- fromStreamD $ D.splitInnerBySuffix splitter joiner $ toStreamD xs+ fromStreamD $ D.splitInnerBySuffix (== mempty) splitter joiner $ toStreamD xs
src/Streamly/Internal/Data/Stream/MkType.hs view
@@ -334,10 +334,14 @@ [ clause [] (normalB- (infixE- (Just (varE _lift))- (varE _dotOp)- (Just (varE _throwM))))+ (infixE+ (Just (conE _Type))+ (varE _dotOp)+ (Just+ (infixE+ (Just (varE (mkName "Stream.fromEffect")))+ (varE _dotOp)+ (Just (varE _throwM)))))) [] ] ]@@ -504,7 +508,7 @@ -- >>> expr <- runQ (mkZipType "ZipStream" "zipApply" False) -- >>> putStrLn $ pprint expr -- newtype ZipStream m a--- = ZipStream (Stream.Stream m a)+-- = ZipStream (Stream.Stream m a) -- deriving Foldable -- mkZipStream :: Stream.Stream m a -> ZipStream m a -- mkZipStream = ZipStream@@ -516,19 +520,17 @@ -- deriving instance GHC.Classes.Eq a => Eq (ZipStream Identity a) -- deriving instance GHC.Classes.Ord a => Ord (ZipStream Identity a) -- instance Show a => Show (ZipStream Identity a)--- where {-# INLINE show #-}--- show (ZipStream strm) = show strm+-- where {{-# INLINE show #-}; show (ZipStream strm) = show strm} -- instance Read a => Read (ZipStream Identity a)--- where {-# INLINE readPrec #-}--- readPrec = fmap ZipStream readPrec+-- where {{-# INLINE readPrec #-}; readPrec = fmap ZipStream readPrec} -- instance Monad m => Functor (ZipStream m)--- where {-# INLINE fmap #-}--- fmap f (ZipStream strm) = ZipStream (fmap f strm)+-- where {{-# INLINE fmap #-};+-- fmap f (ZipStream strm) = ZipStream (fmap f strm)} -- instance Monad m => Applicative (ZipStream m)--- where {-# INLINE pure #-}--- pure = ZipStream . Stream.repeat--- {-# INLINE (<*>) #-}--- (<*>) (ZipStream strm1) (ZipStream strm2) = ZipStream (zipApply strm1 strm2)+-- where {{-# INLINE pure #-};+-- pure = ZipStream . Stream.repeat;+-- {-# INLINE (<*>) #-};+-- (<*>) (ZipStream strm1) (ZipStream strm2) = ZipStream (zipApply strm1 strm2)} mkZipType :: String -- ^ Name of the type -> String -- ^ Function to use for (\<*\>)@@ -577,27 +579,25 @@ -- unParallel :: Parallel m a -> Stream.Stream m a -- unParallel (Parallel strm) = strm -- instance Monad m => Functor (Parallel m)--- where {-# INLINE fmap #-}--- fmap f (Parallel strm) = Parallel (fmap f strm)+-- where {{-# INLINE fmap #-};+-- fmap f (Parallel strm) = Parallel (fmap f strm)} -- instance Stream.MonadAsync m => Monad (Parallel m)--- where {-# INLINE (>>=) #-}--- (>>=) (Parallel strm1) f = let f1 a = unParallel (f a)--- in Parallel (parBind strm1 f1)+-- where {{-# INLINE (>>=) #-};+-- (>>=) (Parallel strm1) f = let f1 a = unParallel (f a)+-- in Parallel (parBind strm1 f1)} -- instance Stream.MonadAsync m => Applicative (Parallel m)--- where {-# INLINE pure #-}--- pure = Parallel . Stream.fromPure--- {-# INLINE (<*>) #-}--- (<*>) = ap+-- where {{-# INLINE pure #-};+-- pure = Parallel . Stream.fromPure;+-- {-# INLINE (<*>) #-};+-- (<*>) = ap} -- instance (Monad (Parallel m), MonadIO m) => MonadIO (Parallel m)--- where {-# INLINE liftIO #-}--- liftIO = Parallel . (Stream.fromEffect . liftIO)--- instance MonadTrans Parallel--- where {-# INLINE lift #-}--- lift = Parallel . Stream.fromEffect+-- where {{-# INLINE liftIO #-};+-- liftIO = Parallel . (Stream.fromEffect . liftIO)} -- instance (Monad (Parallel m), -- MonadThrow m) => MonadThrow (Parallel m)--- where {-# INLINE throwM #-}--- throwM = lift . throwM+-- where {{-# INLINE throwM #-};+-- throwM = Parallel . (Stream.fromEffect . throwM)}+ mkCrossType :: String -- ^ Name of the type -> String -- ^ Function to use for (>>=)@@ -617,7 +617,7 @@ , readInstance _Type ] else []- , sequence+ , sequence $ [ functorInstance _Type , mkStreamMonad dtNameStr classConstraints bindOpStr , mkStreamApplicative@@ -627,10 +627,9 @@ "Stream.fromPure" "ap" , monadioInstance _Type- , monadtransInstance _Type , monadthrowInstance _Type -- , monadreaderInstance _Type- ]+ ] ++ [monadtransInstance _Type | not isConcurrent] ] where
src/Streamly/Internal/FileSystem/Event/Darwin.hs view
@@ -451,7 +451,7 @@ withPathName :: Array Word8 -> (PathName -> IO a) -> IO a withPathName arr act = do- A.asPtrUnsafe arr $ \ptr ->+ A.unsafePinnedAsPtr arr $ \ptr -> let pname = PathName (castPtr ptr) (fromIntegral (A.length arr)) in act pname
src/Streamly/Internal/FileSystem/Event/Linux.hs view
@@ -188,7 +188,7 @@ import qualified Streamly.Unicode.Stream as U import qualified Streamly.Internal.Data.Array as A- ( fromStream, asCStringUnsafe, asPtrUnsafe+ ( fromStream, asCStringUnsafe, unsafePinnedAsPtr , getSliceUnsafe, read ) import qualified Streamly.Internal.FileSystem.Dir as Dir (readDirs)@@ -809,7 +809,7 @@ readOneEvent cfg wt@(Watch _ wdMap) = do let headerLen = sizeOf (undefined :: CInt) + 12 arr <- PR.takeEQ headerLen (A.writeN headerLen)- (ewd, eflags, cookie, pathLen) <- PR.fromEffect $ A.asPtrUnsafe arr readHeader+ (ewd, eflags, cookie, pathLen) <- PR.fromEffect $ A.unsafePinnedAsPtr arr readHeader -- XXX need the "initial" in parsers to return a step type so that "take 0" -- can return without an input. otherwise if pathLen is 0 we will keep -- waiting to read one more char before we return this event.
src/Streamly/Internal/FileSystem/FD.hs view
@@ -130,7 +130,7 @@ import Streamly.Data.Array (Array, Unbox) import Streamly.Data.Stream (Stream) -import Streamly.Internal.Data.Array (byteLength, unsafeFreeze, asPtrUnsafe)+import Streamly.Internal.Data.Array (byteLength, unsafeFreeze, unsafePinnedAsPtr) import Streamly.Internal.System.IO (defaultChunkSize) #if !defined(mingw32_HOST_OS)@@ -147,7 +147,7 @@ import qualified Streamly.Data.Array as A import qualified Streamly.Data.Fold as FL import qualified Streamly.Internal.Data.MutArray as MArray- (MutArray(..), asPtrUnsafe, pinnedNewBytes)+ (MutArray(..), unsafePinnedAsPtr, pinnedNewBytes) import qualified Streamly.Internal.Data.Array.Stream as AS import qualified Streamly.Internal.Data.Stream as S import qualified Streamly.Internal.Data.Stream as D@@ -220,7 +220,7 @@ readArrayUpto size (Handle fd) = do arr <- MArray.pinnedNewBytes size -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))- MArray.asPtrUnsafe arr $ \p -> do+ MArray.unsafePinnedAsPtr arr $ \p -> do -- n <- hGetBufSome h p size #if MIN_VERSION_base(4,15,0) n <- RawIO.read fd p 0 size@@ -244,7 +244,7 @@ writeArray :: Unbox a => Handle -> Array a -> IO () writeArray _ arr | A.length arr == 0 = return () writeArray (Handle fd) arr =- asPtrUnsafe arr $ \p ->+ unsafePinnedAsPtr arr $ \p -> -- RawIO.writeAll fd (castPtr p) aLen #if MIN_VERSION_base(4,15,0) RawIO.write fd (castPtr p) 0 aLen@@ -270,7 +270,7 @@ writeIOVec :: Handle -> Array RawIO.IOVec -> IO () writeIOVec _ iov | A.length iov == 0 = return () writeIOVec (Handle fd) iov =- asPtrUnsafe iov $ \p ->+ unsafePinnedAsPtr iov $ \p -> RawIO.writevAll fd p (A.length iov) -} #endif
src/Streamly/Internal/Network/Inet/TCP.hs view
@@ -116,7 +116,6 @@ import Streamly.Internal.Control.Concurrent (MonadAsync) import Streamly.Internal.Control.ForkLifted (fork) import Streamly.Data.Array (Array)-import Streamly.Internal.Data.Array (pinnedWriteNUnsafe) import Streamly.Internal.Data.Fold ( Fold(..) ) import Streamly.Data.Stream (Stream) import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))@@ -132,7 +131,8 @@ import qualified Streamly.Data.Fold as FL import qualified Streamly.Data.Stream as S import qualified Streamly.Data.Unfold as UF-import qualified Streamly.Internal.Data.Array as A (pinnedChunksOf)+import qualified Streamly.Internal.Data.Array as A+ (pinnedChunksOf, unsafePinnedCreateOf) import qualified Streamly.Internal.Data.Unfold as UF (bracketIO) import qualified Streamly.Internal.Data.Fold as FL (Step(..), reduce) @@ -435,7 +435,7 @@ -> PortNumber -> Fold m Word8 () writeWithBufferOf n addr port =- FL.groupsOf n (pinnedWriteNUnsafe n) (writeChunks addr port)+ FL.groupsOf n (A.unsafePinnedCreateOf n) (writeChunks addr port) -- | Write a stream to the supplied IPv4 host address and port number. --
src/Streamly/Internal/Network/Socket.hs view
@@ -87,7 +87,6 @@ import qualified Network.Socket as Net import Streamly.Internal.Data.Array (Array(..))-import Streamly.Internal.Data.Array.Stream (lpackArraysChunksOf) import Streamly.Data.Fold (Fold) import Streamly.Data.Stream (Stream) import Streamly.Internal.Data.Unfold (Unfold(..))@@ -99,10 +98,10 @@ import qualified Streamly.Data.Stream as S import qualified Streamly.Data.Unfold as UF import qualified Streamly.Internal.Data.Array as A- ( unsafeFreeze, asPtrUnsafe, byteLength, pinnedChunksOf,- pinnedWriteN, pinnedWriteNUnsafe )+ ( unsafeFreeze, unsafePinnedAsPtr, byteLength, pinnedChunksOf,+ pinnedCreateOf, unsafePinnedCreateOf, lCompactGE ) import qualified Streamly.Internal.Data.MutArray as MArray- (MutArray(..), asPtrUnsafe, pinnedNewBytes)+ (MutArray(..), unsafePinnedAsPtr, pinnedEmptyOf) import qualified Streamly.Internal.Data.Stream as S (fromStreamK, Stream(..), Step(..)) import qualified Streamly.Internal.Data.StreamK as K (mkStream) @@ -253,6 +252,8 @@ -- Array IO (Input) ------------------------------------------------------------------------------- +-- XXX add an API that compacts the arrays to an exact size.+ {-# INLINABLE readArrayUptoWith #-} readArrayUptoWith :: (h -> Ptr Word8 -> Int -> IO Int)@@ -260,9 +261,9 @@ -> h -> IO (Array Word8) readArrayUptoWith f size h = do- arr <- MArray.pinnedNewBytes size+ arr <- MArray.pinnedEmptyOf size -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))- MArray.asPtrUnsafe arr $ \p -> do+ MArray.unsafePinnedAsPtr arr $ \p -> do n <- f h p size let v = A.unsafeFreeze $ arr { MArray.arrEnd = n, MArray.arrBound = size }@@ -310,7 +311,7 @@ -> Array a -> IO () writeArrayWith _ _ arr | A.length arr == 0 = return ()-writeArrayWith f h arr = A.asPtrUnsafe arr $ \ptr -> f h (castPtr ptr) aLen+writeArrayWith f h arr = A.unsafePinnedAsPtr arr $ \ptr -> f h (castPtr ptr) aLen where @@ -473,7 +474,7 @@ {-# INLINE writeChunksWith #-} writeChunksWith :: (MonadIO m, Unbox a) => Int -> Socket -> Fold m (Array a) ()-writeChunksWith n h = lpackArraysChunksOf n (writeChunks h)+writeChunksWith n h = A.lCompactGE n (writeChunks h) -- | Same as 'writeChunksWith' --@@ -504,7 +505,7 @@ -- {-# INLINE writeWith #-} writeWith :: MonadIO m => Int -> Socket -> Fold m Word8 ()-writeWith n h = FL.groupsOf n (A.pinnedWriteNUnsafe n) (writeChunks h)+writeWith n h = FL.groupsOf n (A.unsafePinnedCreateOf n) (writeChunks h) -- | Same as 'writeWith' --@@ -522,7 +523,7 @@ writeMaybesWith :: (MonadIO m ) => Int -> Socket -> Fold m (Maybe Word8) () writeMaybesWith n h =- let writeNJusts = FL.lmap fromJust $ A.pinnedWriteN n+ let writeNJusts = FL.lmap fromJust $ A.pinnedCreateOf n writeOnNothing = FL.takeEndBy_ isNothing writeNJusts in FL.many writeOnNothing (writeChunks h)
src/Streamly/Internal/Unicode/Char.hs view
@@ -227,13 +227,13 @@ Stop -> Skip $ YieldList rbuf ComposeStop {-# INLINE initHangul #-}- initHangul c st = ComposeJamo (Hangul c) st+ initHangul c = ComposeJamo (Hangul c) {-# INLINE initJamo #-}- initJamo c st = ComposeJamo (Jamo c) st+ initJamo c = ComposeJamo (Jamo c) {-# INLINE initReg #-}- initReg !c st = ComposeReg 0 [c] st+ initReg !c = ComposeReg 0 [c] {-# INLINE composeNone #-} composeNone ch st
src/Streamly/Network/Inet/TCP.hs view
@@ -11,6 +11,34 @@ -- -- >>> import qualified Streamly.Network.Inet.TCP as TCP --+-- = Examples+--+-- Following is a short example of a concurrent echo server.+--+-- >>> import Control.Monad.Catch (finally)+-- >>> import Data.Function ((&))+-- >>> import Network.Socket (Socket)+-- >>>+-- >>> import qualified Network.Socket as Net+-- >>> import qualified Streamly.Data.Fold as Fold+-- >>> import qualified Streamly.Data.Stream.Prelude as Stream+-- >>> import qualified Streamly.Network.Inet.TCP as TCP+-- >>> import qualified Streamly.Network.Socket as Socket+-- >>>+-- >>> :{+-- main :: IO ()+-- main =+-- TCP.accept 8091 -- Stream IO Socket+-- & Stream.parMapM id (handleExceptions echo) -- Stream IO ()+-- & Stream.fold Fold.drain -- IO ()+-- where+-- echo :: Socket -> IO ()+-- echo sk =+-- Socket.readChunksWith 32768 sk -- Stream IO (Array Word8)+-- & Stream.fold (Socket.writeChunks sk) -- IO ()+-- handleExceptions :: (Socket -> IO ()) -> Socket -> IO ()+-- handleExceptions f sk = finally (f sk) (Net.close sk)+-- :} module Streamly.Network.Inet.TCP (
src/Streamly/Network/Socket.hs view
@@ -10,13 +10,13 @@ -- This module provides socket based streaming APIs to to receive connections -- from remote hosts, and to read and write from and to network sockets. ----- For basic socket types and operations please consult the @Network.Socket@+-- For basic socket types and non-streaming operations please consult the @Network.Socket@ -- module of the <http://hackage.haskell.org/package/network network> package. -- -- = Examples ----- To write a server, use the 'acceptor' unfold to start listening for--- connections from clients. 'acceptor' generates a stream of connected+-- To write a server, use the 'accept' stream to start listening for+-- connections from clients. 'accept' generates a stream of connected -- sockets. We can map an effectful action on this socket stream to handle the -- connections. The action would typically use socket reading and writing -- operations to communicate with the remote host. We can read/write a stream@@ -33,7 +33,6 @@ -- >>> import Streamly.Network.Socket (SockSpec(..)) -- >>> -- >>> import qualified Streamly.Data.Fold as Fold--- >>> import qualified Streamly.Data.Stream as Stream -- >>> import qualified Streamly.Data.Stream.Prelude as Stream -- >>> import qualified Streamly.Network.Socket as Socket -- >>>
streamly.cabal view
@@ -1,12 +1,14 @@ cabal-version: 2.2 name: streamly-version: 0.10.0+version: 0.10.1 synopsis: Streaming, dataflow programming and declarative concurrency description: For upgrading to streamly-0.9.0+ please read the <https://github.com/composewell/streamly/blob/streamly-0.10.0/docs/User/Project/Upgrading-0.8-to-0.9.md Streamly-0.9.0 upgrade guide>. .- Streamly comprises two packages, the+ Streamly is a standard library for Haskell that focuses on C-like+ performance, modular combinators, and streaming data flow model.+ Streamly consists of two packages, the <https://hackage.haskell.org/package/streamly-core streamly-core> package provides functionality that depends only on boot libraries, and the <https://hackage.haskell.org/package/streamly streamly> package@@ -427,9 +429,11 @@ , Streamly.Internal.FileSystem.FD if flag(dev)- exposed-modules: Streamly.Data.SmallArray- , Streamly.Internal.Data.SmallArray- other-modules: Streamly.Internal.Data.SmallArray.Type+ exposed-modules: Streamly.Internal.Data.SmallArray+ -- Exposed modules show up on hackage irrespective of the flag, so keep+ -- it hidden.+ other-modules: Streamly.Data.SmallArray+ , Streamly.Internal.Data.SmallArray.Type if os(windows) exposed-modules: Streamly.Internal.FileSystem.Event.Windows@@ -509,7 +513,7 @@ , template-haskell >= 2.14 && < 2.22 -- The core streamly package- , streamly-core == 0.2.0+ , streamly-core == 0.2.2 , hashable >= 1.3 && < 1.5 , unordered-containers >= 0.2 && < 0.3
test/Streamly/Test/Data/Array.hs view
@@ -185,7 +185,7 @@ testAsPtrUnsafeMA :: IO () testAsPtrUnsafeMA = do arr <- MA.fromList ([0 .. 99] :: [Int])- MA.asPtrUnsafe arr (getList (0 :: Int)) `shouldReturn` [0 .. 99]+ MA.unsafePinnedAsPtr arr (getList (0 :: Int)) `shouldReturn` [0 .. 99] where @@ -229,7 +229,7 @@ prop "read . write === id" testFoldUnfold prop "fromList" testFromList prop "foldMany with writeNUnsafe concats to original"- (foldManyWith (\n -> Fold.take n (A.writeNUnsafe n)))+ (foldManyWith (\n -> Fold.take n (A.unsafeCreateOf n))) describe "unsafeSlice" $ do it "partial" $ unsafeSlice 2 4 [1..10] it "none" $ unsafeSlice 10 0 [1..10]
test/Streamly/Test/Data/Fold.hs view
@@ -2,7 +2,8 @@ module Main (main) where -import Data.List (sort)+import Data.List (sort, sortBy)+import Data.Ord (comparing, Down(..)) import Data.Semigroup (Sum(..), getSum) import Streamly.Test.Common (checkListEqual, listEquals) import Test.QuickCheck@@ -412,7 +413,7 @@ where action ls = do- let f = \x -> if odd x then return (Left x) else return (Right x)+ let f x = if odd x then return (Left x) else return (Right x) v1 <- run $ Stream.fold (Fold.partitionByM f Fold.length Fold.length)@@ -429,7 +430,7 @@ where action _ = do- let f = \x -> if odd x then return (Left x) else return (Right x)+ let f x = if odd x then return (Left x) else return (Right x) v1 <- run $ Stream.fold@@ -447,7 +448,7 @@ where action _ = do- let f = \x -> if odd x then return (Left x) else return (Right x)+ let f x = if odd x then return (Left x) else return (Right x) v1 <- run $ Stream.fold@@ -465,7 +466,7 @@ where action _ = do- let f = \x -> if odd x then return (Left x) else return (Right x)+ let f x = if odd x then return (Left x) else return (Right x) v1 <- run $ Stream.fold@@ -690,7 +691,7 @@ if isTop then do lst <- Stream.fold (Fold.top n) (Stream.fromList ls) >>= MArray.toList- assert ((Prelude.take n . Prelude.reverse . sort) ls == lst)+ assert ((Prelude.take n . sortBy (comparing Down)) ls == lst) else do lst <- Stream.fold (Fold.bottom n) (Stream.fromList ls) >>= MArray.toList assert ((Prelude.take n . sort) ls == lst)
test/Streamly/Test/Data/Serialize.hs view
@@ -21,6 +21,8 @@ -- Imports -------------------------------------------------------------------------------- +import Data.Foldable (forM_)+import Data.Word (Word8) import System.Random (randomRIO) import Streamly.Internal.Data.MutByteArray (MutByteArray) import GHC.Generics (Generic)@@ -107,9 +109,19 @@ CONF [d|instance Serialize a => Serialize (BinTree a)|]) +-- XXX This may not terminate, or could become really large. instance Arbitrary a => Arbitrary (BinTree a) where arbitrary = oneof [Leaf <$> arbitrary, Tree <$> arbitrary <*> arbitrary] +-- Make a balanced tree of given level+mkBinTree :: (Arbitrary a) => Int -> IO (BinTree a)+mkBinTree = go (generate arbitrary)++ where++ go r 0 = Leaf <$> r+ go r n = Tree <$> go r (n - 1) <*> go r (n - 1)+ -------------------------------------------------------------------------------- -- Record syntax type --------------------------------------------------------------------------------@@ -170,8 +182,18 @@ serStartOff = randomOff serEndOff = randomOff + sz arr <- Serialize.new arrSize+ arr2 <- Serialize.new arrSize+ -- Re-initialize the array with random value+ forM_ [0..(arrSize - 1)] $ \i -> Serialize.pokeAt i arr2 (8 :: Word8) off1 <- Serialize.serializeAt serStartOff arr val+ off2 <- Serialize.serializeAt 0 arr2 val++ let slice1 = Array.Array arr serStartOff off1 :: Array.Array Word8+ slice2 = Array.Array arr2 0 off2 :: Array.Array Word8+ -- The serialized representation should be the same+ slice1 `shouldBe` slice2+ off1 `shouldBe` serEndOff pure (arr, serStartOff, serEndOff) @@ -195,6 +217,10 @@ -> IO () roundtrip val = do + -- For debugging large size generated by arbitrary+ -- let sz = Serialize.addSizeTo 0 val+ -- putStrLn $ "Size is: " ++ show sz+ val `shouldBe` Array.deserialize (Array.pinnedSerialize val) res <- poke val@@ -258,7 +284,12 @@ $ \(x :: [CustomDatatype]) -> roundtrip x limitQC- $ prop "BinTree" $ \(x :: BinTree Int) -> roundtrip x+ $ prop "BinTree"+ $ forAll (elements [1..15])+ (\(x :: Int) -> do+ (r :: BinTree Int) <- mkBinTree x+ roundtrip r+ ) where
test/Streamly/Test/Data/Serialize/TH.hs view
@@ -26,7 +26,7 @@ genDatatype :: String -> Int -> Q [Dec] genDatatype tyName numCons = sequence- ([ dataD+ [ dataD (pure []) (mkName tyName) []@@ -49,7 +49,7 @@ [] ] ]- ])+ ] where
test/Streamly/Test/Data/Unbox.hs view
@@ -20,6 +20,12 @@ -- Imports -------------------------------------------------------------------------------- +#ifdef USE_SERIALIZE+import Data.Foldable (forM_)+import Data.Word (Word8)+import qualified Streamly.Internal.Data.Array as Array+#endif+ import Data.Complex (Complex ((:+))) import Data.Functor.Const (Const (..)) import Data.Functor.Identity (Identity (..))@@ -201,6 +207,19 @@ #endif arr <- MBA.new len nextOff <- POKE(0, arr, val)+#ifdef USE_SERIALIZE+ arr2 <- MBA.new len+ -- Re-initialize the array with random value+ forM_ [0..(len - 1)] $ \i -> POKE(i, arr2, (8 :: Word8))+ _ <- POKE(0, arr2, val)+ let slice1 = Array.Array arr 0 len :: Array.Array Word8+ slice2 = Array.Array arr2 0 len :: Array.Array Word8+ -- The serialized representation should be the same+ slice1 `shouldBe` slice2+ -- The serialized representation is not the same for "Unbox" as the Array+ -- might not be fully utilized in case of "Unbox". This is because different+ -- constructors might have different lengths.+#endif (nextOff1, val1) <- PEEK(0, arr, len) val1 `shouldBe` val nextOff1 `shouldBe` len
test/Streamly/Test/FileSystem/Handle.hs view
@@ -75,7 +75,7 @@ readWithBufferFromHandle :: IO (Stream IO Char) readWithBufferFromHandle =- let f1 = (\h -> (1024, h))+ let f1 h = (1024, h) f2 = Unicode.decodeUtf8 . Stream.unfold Handle.readerWith . f1 in executor f2 @@ -88,7 +88,7 @@ readChunksWithBuffer :: IO (Stream IO Char) readChunksWithBuffer =- let f1 = (\h -> (1024, h))+ let f1 h = (1024, h) f2 = Unicode.decodeUtf8 . Stream.concatMap Array.read
test/Streamly/Test/Unicode/Char.hs view
@@ -54,7 +54,7 @@ checkOp :: String -> NormalizationMode -> [(Text, Text)] -> IO Bool checkOp name op pairs = do res <- mapM (checkEqual name (normalize op)) pairs- return $ all (== True) res+ return $ and res checkNFC :: (Text, Text, Text, Text, Text) -> IO Bool checkNFC (c1, c2, c3, c4, c5) =