@@ -1,3 +1,4 @@
2-- Module : Streamly.Data.Array
3-- Module : Streamly.Data.Array
3-- Copyright : (c) 2019 Composewell Technologies
4-- Copyright : (c) 2019 Composewell Technologies
@@ -7,84 +8,26 @@
7-- Stability : released
8-- Stability : released
8-- Portability : GHC
9-- Portability : GHC
10−-- This module provides APIs to create and use unboxed immutable arrays. Once
11+-- Unboxed immutable arrays with streaming interfaces.
11−-- created, their contents cannot be modified. Only types that are unboxable
12−-- via the 'Unbox' type class can be stored in these arrays. Note that the
13−-- array memory grows automatically when creating a new array, therefore, an
14−-- array can be created from a variable length stream.
16−-- See "Streamly.Internal.Data.Array" for more, unreleased APIs. See
17−-- "Streamly.Data.Array.Generic" for arrays that work for boxed types i.e. not
18−-- requiring the 'Unbox' constraint. See "Streamly.Data.MutArray" for arrays
19−-- that can be mutated in-place.
23−-- Convert array to stream, and fold the stream:
25−-- >>> fold f arr = Stream.unfold Array.reader arr & Stream.fold f
26−-- >>> fold Fold.sum (Array.fromList [1,2,3::Int])
29−-- = Transforming Arrays
31−-- Convert array to stream, transform, and fold back to array:
13+-- Please refer to "Streamly.Internal.Data.Array" for functions that have not
33−-- >>> amap f arr = Stream.unfold Array.reader arr & fmap f & Stream.fold Array.write
16+-- For arrays that work on boxed types, not requiring the 'Unbox' constraint,
34−-- >>> amap (+1) (Array.fromList [1,2,3::Int])
17+-- please refer to "Streamly.Data.Array.Generic". For arrays that can be
35−-- fromList [2,3,4]
18+-- mutated in-place, please see "Streamly.Data.MutArray".
37−-- = Pinned and Unpinned Arrays
39−-- The array type can use both pinned and unpinned memory under the hood.
40−-- Currently the array creation APIs create arrays in pinned memory but it will
41−-- change to unpinned in future releases. The change should not affect users
42−-- functionally unless they are directly accessing the internal memory of the
43−-- array via internal APIs. As of now unpinned arrays can be created using
46−-- Unpinned arrays have the advantage of allowing automatic defragmentation of
47−-- the memory by GC. Whereas pinned arrays have the advantage of not requiring
48−-- a copy by GC. Normally you would want to use unpinned arrays. However, in
49−-- some cases, for example, for long lived large data storage, and for
50−-- interfacing with the operating system or foreign (non-Haskell) consumers you
51−-- may want to use pinned arrays.
53−-- = Creating Arrays from Non-IO Streams
55−-- Array creation folds require 'MonadIO' because they need to sequence effects
56−-- in IO streams. To operate on streams in pure Monads like 'Identity' you can
57−-- morph it to IO monad as follows:
59−-- The 'MonadIO' based folds can be morphed to 'Identity' stream folds:
61−-- >>> purely = Fold.morphInner (Identity . unsafePerformIO)
62−-- >>> Stream.fold (purely Array.write) $ Stream.fromList [1,2,3::Int]
63−-- Identity fromList [1,2,3]
65−-- Since it is a pure stream we can use 'unsafePerformIO' to extract the result
68−-- Alternatively, 'Identity' streams can be generalized to IO streams:
70−-- >>> pure = Stream.fromList [1,2,3] :: Stream Identity Int
71−-- >>> generally = Stream.morphInner (return . runIdentity)
72−-- >>> Stream.fold Array.write (generally pure :: Stream IO Int)
77−-- This module is designed to be imported qualified:
79−-- >>> import qualified Streamly.Data.Array as Array
81−-- For experimental APIs see "Streamly.Internal.Data.Array".
83module Streamly.Data.Array
20module Streamly.Data.Array
85− -- * Imports for Examples
22+ -- * Setup
23+ -- | To execute the code examples provided in this module in ghci, please
24+ -- run the following commands first.
88 -- * The Array Type
31 -- * The Array Type
@@ -140,17 +83,75 @@ import Streamly.Internal.Data.Array as A hiding (read, readRev)
140import Streamly.Internal.Data.Unboxed (Unbox (..))
83import Streamly.Internal.Data.Unboxed (Unbox (..))
141import Prelude hiding (read)
84import Prelude hiding (read)
143−-- $setup
86+#include "DocTestDataArray.hs"
145−-- >>> :set -XFlexibleContexts
88+-- $overview
146−-- >>> import Data.Function ((&))
89+--
147−-- >>> import Data.Functor.Identity (Identity(..))
90+-- This module provides APIs to create and use unboxed immutable arrays. Once
148−-- >>> import Streamly.Data.Array (Array)
91+-- created, their contents cannot be modified. Only types that are unboxable
149−-- >>> import Streamly.Data.Stream (Stream)
92+-- via the 'Unbox' type class can be stored in these arrays. Note that the
150−-- >>> import System.IO.Unsafe (unsafePerformIO)
93+-- array memory grows automatically when creating a new array, therefore, an
94+-- array can be created from a variable length stream.
98+-- Convert array to stream, and fold the stream:
100+-- >>> fold f arr = Stream.unfold Array.reader arr & Stream.fold f
101+-- >>> fold Fold.sum (Array.fromList [1,2,3::Int])
104+-- == Transforming Arrays
106+-- Convert array to stream, transform, and fold back to array:
108+-- >>> amap f arr = Stream.unfold Array.reader arr & fmap f & Stream.fold Array.write
109+-- >>> amap (+1) (Array.fromList [1,2,3::Int])
112+-- == Pinned and Unpinned Arrays
114+-- The array type can use both pinned and unpinned memory under the hood.
115+-- Currently the array creation APIs create arrays in pinned memory but it will
116+-- change to unpinned in future releases. The change should not affect users
117+-- functionally unless they are directly accessing the internal memory of the
118+-- array via internal APIs. As of now unpinned arrays can be created using
121+-- Unpinned arrays have the advantage of allowing automatic defragmentation of
122+-- the memory by GC. Whereas pinned arrays have the advantage of not requiring
123+-- a copy by GC. Normally you would want to use unpinned arrays. However, in
124+-- some cases, for example, for long lived large data storage, and for
125+-- interfacing with the operating system or foreign (non-Haskell) consumers you
126+-- may want to use pinned arrays.
128+-- == Creating Arrays from Non-IO Streams
130+-- Array creation folds require 'MonadIO' because they need to sequence effects
131+-- in IO streams. To operate on streams in pure Monads like 'Identity' you can
132+-- morph it to IO monad as follows:
134+-- The 'MonadIO' based folds can be morphed to 'Identity' stream folds:
136+-- >>> purely = Fold.morphInner (Identity . unsafePerformIO)
137+-- >>> Stream.fold (purely Array.write) $ Stream.fromList [1,2,3::Int]
138+-- Identity fromList [1,2,3]
140+-- Since it is a pure stream we can use 'unsafePerformIO' to extract the result
143+-- Alternatively, 'Identity' streams can be generalized to IO streams:
145+-- >>> pure = Stream.fromList [1,2,3] :: Stream Identity Int
146+-- >>> generally = Stream.morphInner (return . runIdentity)
147+-- >>> Stream.fold Array.write (generally pure :: Stream IO Int)
150+-- == Programming Tips
152+-- This module is designed to be imported qualified:
151-- >>> import qualified Streamly.Data.Array as Array
154-- >>> import qualified Streamly.Data.Array as Array
152−-- >>> import qualified Streamly.Data.Fold as Fold
153−-- >>> import qualified Streamly.Data.Stream as Stream
155-- | Same as 'reader'
156-- | Same as 'reader'