@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12-- |
23-- Module : Streamly.Data.Array
34-- Copyright : (c) 2019 Composewell Technologies
@@ -7,84 +8,26 @@
78-- Stability : released
89-- Portability : GHC
910--
10−-- This module provides APIs to create and use unboxed immutable arrays. Once
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.
15−--
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.
20−--
21−-- = Folding Arrays
22−--
23−-- Convert array to stream, and fold the stream:
24−--
25−-- >>> fold f arr = Stream.unfold Array.reader arr & Stream.fold f
26−-- >>> fold Fold.sum (Array.fromList [1,2,3::Int])
27−-- 6
28−--
29−-- = Transforming Arrays
11+-- Unboxed immutable arrays with streaming interfaces.
3012--
31−-- Convert array to stream, transform, and fold back to array:
13+-- Please refer to "Streamly.Internal.Data.Array" for functions that have not
14+-- yet been released.
3215--
33−-- >>> amap f arr = Stream.unfold Array.reader arr & fmap f & Stream.fold Array.write
34−-- >>> amap (+1) (Array.fromList [1,2,3::Int])
35−-- fromList [2,3,4]
36−--
37−-- = Pinned and Unpinned Arrays
38−--
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
44−-- unreleased APIs.
45−--
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.
52−--
53−-- = Creating Arrays from Non-IO Streams
54−--
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:
58−--
59−-- The 'MonadIO' based folds can be morphed to 'Identity' stream folds:
60−--
61−-- >>> purely = Fold.morphInner (Identity . unsafePerformIO)
62−-- >>> Stream.fold (purely Array.write) $ Stream.fromList [1,2,3::Int]
63−-- Identity fromList [1,2,3]
64−--
65−-- Since it is a pure stream we can use 'unsafePerformIO' to extract the result
66−-- of fold from IO.
67−--
68−-- Alternatively, 'Identity' streams can be generalized to IO streams:
69−--
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)
73−-- fromList [1,2,3]
74−--
75−-- = Programming Tips
76−--
77−-- This module is designed to be imported qualified:
78−--
79−-- >>> import qualified Streamly.Data.Array as Array
80−--
81−-- For experimental APIs see "Streamly.Internal.Data.Array".
16+-- For arrays that work on boxed types, not requiring the 'Unbox' constraint,
17+-- please refer to "Streamly.Data.Array.Generic". For arrays that can be
18+-- mutated in-place, please see "Streamly.Data.MutArray".
8219
8320module Streamly.Data.Array
8421 (
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.
25+ --
8626 -- $setup
8727
28+ -- * Overview
29+ -- $overview
30+
8831 -- * The Array Type
8932 A.Array
9033
@@ -140,17 +83,75 @@ import Streamly.Internal.Data.Array as A hiding (read, readRev)
14083import Streamly.Internal.Data.Unboxed (Unbox (..))
14184import Prelude hiding (read)
14285
143−-- $setup
144−-- >>> :m
145−-- >>> :set -XFlexibleContexts
146−-- >>> import Data.Function ((&))
147−-- >>> import Data.Functor.Identity (Identity(..))
148−-- >>> import Streamly.Data.Array (Array)
149−-- >>> import Streamly.Data.Stream (Stream)
150−-- >>> import System.IO.Unsafe (unsafePerformIO)
86+#include "DocTestDataArray.hs"
87+
88+-- $overview
89+--
90+-- This module provides APIs to create and use unboxed immutable arrays. Once
91+-- created, their contents cannot be modified. Only types that are unboxable
92+-- via the 'Unbox' type class can be stored in these arrays. Note that the
93+-- array memory grows automatically when creating a new array, therefore, an
94+-- array can be created from a variable length stream.
95+--
96+-- == Folding Arrays
97+--
98+-- Convert array to stream, and fold the stream:
99+--
100+-- >>> fold f arr = Stream.unfold Array.reader arr & Stream.fold f
101+-- >>> fold Fold.sum (Array.fromList [1,2,3::Int])
102+-- 6
103+--
104+-- == Transforming Arrays
105+--
106+-- Convert array to stream, transform, and fold back to array:
107+--
108+-- >>> amap f arr = Stream.unfold Array.reader arr & fmap f & Stream.fold Array.write
109+-- >>> amap (+1) (Array.fromList [1,2,3::Int])
110+-- fromList [2,3,4]
111+--
112+-- == Pinned and Unpinned Arrays
113+--
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
119+-- unreleased APIs.
120+--
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.
127+--
128+-- == Creating Arrays from Non-IO Streams
129+--
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:
133+--
134+-- The 'MonadIO' based folds can be morphed to 'Identity' stream folds:
135+--
136+-- >>> purely = Fold.morphInner (Identity . unsafePerformIO)
137+-- >>> Stream.fold (purely Array.write) $ Stream.fromList [1,2,3::Int]
138+-- Identity fromList [1,2,3]
139+--
140+-- Since it is a pure stream we can use 'unsafePerformIO' to extract the result
141+-- of fold from IO.
142+--
143+-- Alternatively, 'Identity' streams can be generalized to IO streams:
144+--
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)
148+-- fromList [1,2,3]
149+--
150+-- == Programming Tips
151+--
152+-- This module is designed to be imported qualified:
153+--
151154-- >>> import qualified Streamly.Data.Array as Array
152−-- >>> import qualified Streamly.Data.Fold as Fold
153−-- >>> import qualified Streamly.Data.Stream as Stream
154155
155156-- | Same as 'reader'
156157--