on d29030f help sign in
170 lines 5.1 kB history raw
1{-# LANGUAGE CPP #-}
2-- |
3-- Module : Streamly.Data.Array
4-- Copyright : (c) 2019 Composewell Technologies
5--
6-- License : BSD3
7-- Maintainer : streamly@composewell.com
8-- Stability : released
9-- Portability : GHC
10--
11-- Unboxed immutable arrays with streaming interfaces.
12--
13-- Please refer to "Streamly.Internal.Data.Array" for functions that have not
14-- yet been released.
15--
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".
20module Streamly.Data.Array
21 (
22 -- * Setup
23 -- | To execute the code examples provided in this module in ghci, please
24 -- run the following commands first.
25 --
26 -- $setup
28 -- * Overview
29 -- $overview
31 -- * The Array Type
32 A.Array
34 -- * Construction
35 -- | When performance matters, the fastest way to generate an array is
36 -- 'writeN'. 'IsList' and 'IsString' instances can be
37 -- used to conveniently construct arrays from literal values.
38 -- 'OverloadedLists' extension or 'fromList' can be used to construct an
39 -- array from a list literal. Similarly, 'OverloadedStrings' extension or
40 -- 'fromList' can be used to construct an array from a string literal.
42 -- Pure List APIs
43 , A.fromListN
44 , A.fromList
46 -- Monadic APIs
47 , A.writeN -- drop new
48 , A.write -- full buffer
49 , writeLastN -- drop old (ring buffer)
51 -- * Conversion
52 -- 'GHC.Exts.toList' from "GHC.Exts" can be used to convert an array to a
53 -- list.
54 , A.toList
56 -- * Unfolds
57 , A.reader
58 , A.readerRev
60 -- * Casting
61 , cast
62 , asBytes
64 -- * Random Access
65 , A.length
66 -- , (!!)
67 , A.getIndex
69 -- * Unbox Type Class
70 , Unbox (..)
72 -- * Pinning & Unpinning
73 , pin
74 , unpin
76 -- * Deprecated
77 , read
78 , readRev
79 )
80where
82#include "inline.hs"
84import Streamly.Internal.Data.Unfold (Unfold)
85import Streamly.Internal.Data.Array as A hiding (read, readRev)
86import Streamly.Internal.Data.Array.Type (pin, unpin)
88import Streamly.Internal.Data.Unbox (Unbox (..))
89import Prelude hiding (read)
91#include "DocTestDataArray.hs"
93-- $overview
94--
95-- This module provides APIs to create and use unboxed immutable arrays. Once
96-- created, their contents cannot be modified. Only types that are unboxable
97-- via the 'Unbox' type class can be stored in these arrays. Note that the
98-- array memory grows automatically when creating a new array, therefore, an
99-- array can be created from a variable length stream.
100--
101-- == Folding Arrays
102--
103-- Convert array to stream, and fold the stream:
104--
105-- >>> fold f arr = Stream.unfold Array.reader arr & Stream.fold f
106-- >>> fold Fold.sum (Array.fromList [1,2,3::Int])
107-- 6
108--
109-- == Transforming Arrays
110--
111-- Convert array to stream, transform, and fold back to array:
112--
113-- >>> amap f arr = Stream.unfold Array.reader arr & fmap f & Stream.fold Array.write
114-- >>> amap (+1) (Array.fromList [1,2,3::Int])
115-- fromList [2,3,4]
116--
117-- == Pinned and Unpinned Arrays
118--
119-- The array type can use both pinned and unpinned memory under the hood. The
120-- arrays are unpinned by default and are only pinned while doing any I/O
121-- operations.
122--
123-- Unpinned arrays have the advantage of allowing automatic defragmentation of
124-- the memory by GC. Whereas pinned arrays have the advantage of not requiring
125-- a copy by GC. Normally you would want to use unpinned arrays. However, in
126-- some cases, for example, for long lived large data storage, and for
127-- interfacing with the operating system or foreign (non-Haskell) consumers you
128-- may want to use pinned arrays.
129--
130-- == Creating Arrays from Non-IO Streams
131--
132-- Array creation folds require 'MonadIO' because they need to sequence effects
133-- in IO streams. To operate on streams in pure Monads like 'Identity' you can
134-- morph it to IO monad as follows:
135--
136-- The 'MonadIO' based folds can be morphed to 'Identity' stream folds:
137--
138-- >>> purely = Fold.morphInner (Identity . unsafePerformIO)
139-- >>> Stream.fold (purely Array.write) $ Stream.fromList [1,2,3::Int]
140-- Identity fromList [1,2,3]
141--
142-- Since it is a pure stream we can use 'unsafePerformIO' to extract the result
143-- of fold from IO.
144--
145-- Alternatively, 'Identity' streams can be generalized to IO streams:
146--
147-- >>> pure = Stream.fromList [1,2,3] :: Stream Identity Int
148-- >>> generally = Stream.morphInner (return . runIdentity)
149-- >>> Stream.fold Array.write (generally pure :: Stream IO Int)
150-- fromList [1,2,3]
151--
152-- == Programming Tips
153--
154-- This module is designed to be imported qualified:
155--
156-- >>> import qualified Streamly.Data.Array as Array
158-- | Same as 'reader'
159--
160{-# DEPRECATED read "Please use 'reader' instead" #-}
161{-# INLINE_NORMAL read #-}
162read :: (Monad m, Unbox a) => Unfold m (Array a) a
163read = reader
165-- | Same as 'readerRev'
166--
167{-# DEPRECATED readRev "Please use 'readerRev' instead" #-}
168{-# INLINE_NORMAL readRev #-}
169readRev :: (Monad m, Unbox a) => Unfold m (Array a) a
170readRev = readerRev