on master help sign in
167 lines 5.2 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 Array
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
47 -- * Construction
48 -- | When performance matters, the fastest way to generate an array is
49 -- 'createOf'. 'IsList' and 'IsString' instances can be
50 -- used to conveniently construct arrays from literal values.
51 -- 'OverloadedLists' extension or 'fromList' can be used to construct an
52 -- array from a list literal. Similarly, 'OverloadedStrings' extension or
53 -- 'fromList' can be used to construct an array from a string literal.
55 -- ** From Stream
56 , createOf
57 , create
58 , writeLastN -- drop old (ring buffer)
60 -- ** From List
61 , fromListN
62 , fromList
64 -- * To List
65 -- 'GHC.Exts.toList' from "GHC.Exts" can be used to convert an array to a
66 -- list.
67 , toList
69 -- * To Stream
70 , read
71 , readRev
73 -- * Unfolds
74 , reader
75 , readerRev
77 -- * Casting
78 , cast
79 , asBytes
81 -- * Random Access
82 , length
83 -- , (!!)
84 , getIndex
86 -- * Serialization
87 , pinnedSerialize
88 , deserialize
90 -- * Re-exports
91 , Unbox (..)
92 , Serialize(..)
94 -- * Deprecated
95 , writeN -- drop new
96 , write -- full buffer
97 )
98where
100#include "inline.hs"
102import Streamly.Internal.Data.Array
103import Streamly.Internal.Data.MutByteArray (Unbox(..), Serialize(..))
105import Prelude hiding (read, length)
107#include "DocTestDataArray.hs"
109-- $overview
110--
111-- This module provides APIs to create and use unboxed immutable arrays. Once
112-- created, their contents cannot be modified. Only types that are unboxable
113-- via the 'Unbox' type class can be stored in these arrays. Note that the
114-- array memory grows automatically when creating a new array, therefore, an
115-- array can be created from a variable length stream.
116--
117-- == Folding Arrays
118--
119-- Convert array to stream, and fold the stream:
120--
121-- >>> fold f arr = Array.read arr & Stream.fold f
122-- >>> fold Fold.sum (Array.fromList [1,2,3::Int])
123-- 6
124--
125-- == Transforming Arrays
126--
127-- Convert array to stream, transform, and fold back to array:
128--
129-- >>> amap f arr = Array.read arr & fmap f & Stream.fold (Array.createOf (Array.length arr))
130-- >>> amap (+1) (Array.fromList [1,2,3::Int])
131-- fromList [2,3,4]
132--
133-- == Pinned and Unpinned Arrays
134--
135-- The array type can use both pinned and unpinned memory under the hood. The
136-- default array creation operations create unpinned arrays. IO operations
137-- automatically copy an array to pinned memory if the array passed to it is
138-- unpinned. Programmers can use appropriate pinned array generation APIs to
139-- reduce the copying if it happens.
140--
141-- Unpinned arrays have the advantage of allowing automatic defragmentation of
142-- the memory by GC. Whereas pinned arrays have the advantage of not requiring
143-- a copy by GC. Normally you would want to use unpinned arrays. However, in
144-- some cases, for example, for long lived large data storage, and for
145-- interfacing with the operating system or foreign (non-Haskell) consumers you
146-- may want to use pinned arrays.
147--
148-- == Creating Arrays from Non-IO Streams
149--
150-- Array creation folds require 'MonadIO' otherwise the compiler may
151-- incorrectly share the array memory thinking it is pure.
152--
153-- See the 'fromPureStream' unreleased API to generate an array from an
154-- Identity stream safely without using MonadIO constraint.
155--
156-- Note that 'Identity' streams can be generalized to IO streams:
157--
158-- >>> stream = Stream.fromList [1,2,3] :: Stream Identity Int
159-- >>> pure2IO s = Stream.morphInner (return . runIdentity) s :: Stream IO Int
160-- >>> Stream.fold Array.create (pure2IO stream)
161-- fromList [1,2,3]
162--
163-- == Programming Tips
164--
165-- This module is designed to be imported qualified:
166--
167-- >>> import qualified Streamly.Data.Array as Array