streamly-core-0.3.0: src/Streamly/Data/Array.hs
{-# LANGUAGE CPP #-}
-- |
-- Module : Streamly.Data.Array
-- Copyright : (c) 2019 Composewell Technologies
--
-- License : BSD3
-- Maintainer : streamly@composewell.com
-- Stability : released
-- Portability : GHC
--
-- Unboxed immutable arrays with streaming interfaces.
--
-- Please refer to "Streamly.Internal.Data.Array" for functions that have not
-- yet been released.
--
-- For arrays that work on boxed types, not requiring the 'Unbox' constraint,
-- please refer to "Streamly.Data.Array.Generic". For arrays that can be
-- mutated in-place, please see "Streamly.Data.MutArray".
module Streamly.Data.Array
(
-- * Setup
-- | To execute the code examples provided in this module in ghci, please
-- run the following commands first.
--
-- $setup
-- * Overview
-- $overview
-- * The Array Type
Array
-- * Pinning & Unpinning
-- | Arrays are created unpinned by default unless pinned versions of
-- creation APIs are used. Look for APIs with @pinned@ prefix in
-- "Streamly.Internal.Data.Array" for some unreleased pinned creation APIs.
-- If an array is to be sent to the OS without any further modification
-- then it should be created pinned in the first place instead of pinning
-- it later. Pinning an unpinned array has a copy overhead. OS interfacing
-- APIs create a pinned array directly or convert an unpinned array to
-- pinned array before sending it to the OS.
, pin
, unpin
, isPinned
-- * Construction
-- | When performance matters, the fastest way to generate an array is
-- 'createOf'. 'IsList' and 'IsString' instances can be
-- used to conveniently construct arrays from literal values.
-- 'OverloadedLists' extension or 'fromList' can be used to construct an
-- array from a list literal. Similarly, 'OverloadedStrings' extension or
-- 'fromList' can be used to construct an array from a string literal.
-- ** From Stream
, createOf
, create
, createOfLast -- drop old (ring buffer)
-- ** From List
, fromListN
, fromList
-- * To List
-- 'GHC.Exts.toList' from "GHC.Exts" can be used to convert an array to a
-- list.
, toList
-- * To Stream
, read
, readRev
-- * Unfolds
, reader
, readerRev
-- * Stream of Arrays
, chunksOf
, toParserK
, parse
, parseBreak
, parsePos
, parseBreakPos
-- * Casting
, cast
, asBytes
-- * Random Access
, length
-- , (!!)
, getIndex
-- * Serialization
, serialize'
, deserialize
-- * Re-exports
, Unbox (..)
, Serialize(..)
-- * Deprecated
, pinnedSerialize
, writeN -- drop new
, write -- full buffer
, writeLastN
)
where
import Streamly.Internal.Data.Array
import Streamly.Internal.Data.MutByteArray (Unbox(..), Serialize(..))
import Prelude hiding (read, length)
#include "DocTestDataArray.hs"
-- $overview
--
-- This module provides APIs to create and use unboxed immutable arrays. Once
-- created, their contents cannot be modified. Only types that are unboxable
-- via the 'Unbox' type class can be stored in these arrays. Note that the
-- array memory grows automatically when creating a new array, therefore, an
-- array can be created from a variable length stream.
--
-- == Folding Arrays
--
-- Convert array to stream, and fold the stream:
--
-- >>> fold f arr = Array.read arr & Stream.fold f
-- >>> fold Fold.sum (Array.fromList [1,2,3::Int])
-- 6
--
-- == Transforming Arrays
--
-- Convert array to stream, transform, and fold back to array:
--
-- >>> amap f arr = Array.read arr & fmap f & Stream.fold (Array.createOf (Array.length arr))
-- >>> amap (+1) (Array.fromList [1,2,3::Int])
-- fromList [2,3,4]
--
-- == Pinned and Unpinned Arrays
--
-- The array type can use both pinned and unpinned memory under the hood. The
-- default array creation operations create unpinned arrays. IO operations
-- automatically copy an array to pinned memory if the array passed to it is
-- unpinned. Programmers can use appropriate pinned array generation APIs to
-- reduce the copying if it happens.
--
-- Unpinned arrays have the advantage of allowing automatic defragmentation of
-- the memory by GC. Whereas pinned arrays have the advantage of not requiring
-- a copy by GC. Normally you would want to use unpinned arrays. However, in
-- some cases, for example, for long lived large data storage, and for
-- interfacing with the operating system or foreign (non-Haskell) consumers you
-- may want to use pinned arrays.
--
-- == Creating Arrays from Non-IO Streams
--
-- Array creation folds require 'MonadIO' otherwise the compiler may
-- incorrectly share the array memory thinking it is pure.
--
-- See the 'fromPureStream' unreleased API to generate an array from an
-- Identity stream safely without using MonadIO constraint.
--
-- >>> fromPureStream = Stream.fold Array.create . Stream.generalizeInner
--
-- >>> stream = Stream.fromList [1,2,3] :: Stream Identity Int
-- >>> fromPureStream stream
-- fromList [1,2,3]
--
-- == Performance Considerations
--
-- If you are consuming an array piecemeal (uncons, unsnoc) or by slicing,
-- immutable Array type may be a tiny bit better than MutArray because it uses
-- a smaller constructor size.
--
-- == Programming Tips
--
-- This module is designed to be imported qualified:
--
-- >>> import qualified Streamly.Data.Array as Array