{-# OPTIONS_GHC -Wno-orphans #-} #include "inline.hs" -- | -- Module : Streamly.Data.Array.Foreign -- Copyright : (c) 2019 Composewell Technologies -- -- License : BSD3 -- Maintainer : streamly@composewell.com -- Stability : released -- Portability : GHC -- -- This module provides immutable arrays in pinned memory (non GC memory) -- suitable for long lived data storage, random access and for interfacing with -- the operating system. -- -- Arrays in this module are chunks of pinned memory that hold a sequence of -- 'Storable' values of a given type, they cannot store non-serializable data -- like functions. Once created an array cannot be modified. Pinned memory -- allows efficient buffering of long lived data without adding any impact to -- GC. One array is just one pointer visible to GC and it does not have to be -- copied across generations. Moreover, pinned memory allows communication -- with foreign consumers and producers (e.g. file or network IO) without -- copying the data. -- -- = Programmer Notes -- -- Array creation APIs require a 'MonadIO' Monad, except 'fromList' which is a -- pure API. To operate on streams in pure Monads like 'Identity' you can hoist -- it to IO monad as follows: -- -- >>> import Data.Functor.Identity (Identity, runIdentity) -- >>> s = Stream.fromList [1..10] :: SerialT Identity Int -- >>> s1 = Stream.hoist (return . runIdentity) s :: SerialT IO Int -- >>> Stream.fold Array.write s1 :: IO (Array Int) -- fromList [1,2,3,4,5,6,7,8,9,10] -- -- 'unsafePerformIO' can be used to get a pure API from IO, as long as you know -- it is safe to do so: -- -- >>> import System.IO.Unsafe (unsafePerformIO) -- >>> unsafePerformIO $ Stream.fold Array.write s1 :: Array Int -- fromList [1,2,3,4,5,6,7,8,9,10] -- -- To apply a transformation to an array use 'read' to unfold the array into a -- stream, apply a transformation on the stream and then use 'write' to fold it -- back to an array. -- -- This module is designed to be imported qualified: -- -- > import qualified Streamly.Data.Array as Array -- -- For experimental APIs see "Streamly.Internal.Data.Array". module Streamly.Data.Array.Foreign {-# DEPRECATED "Please use Streamly.Data.Array module from the streamly-core package." #-} ( A.Array -- * Arrays -- ** Construction -- | When performance matters, the fastest way to generate an array is -- 'writeN'. '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. -- Pure List APIs , A.fromListN , A.fromList -- Monadic APIs , A.writeN -- drop new , A.write -- full buffer , writeLastN -- drop old (ring buffer) -- ** Elimination -- 'GHC.Exts.toList' from "GHC.Exts" can be used to convert an array to a -- list. , A.toList , A.read , A.readRev -- ** Casting , cast , asBytes -- ** Random Access , A.length -- , (!!) , A.getIndex ) where import Control.DeepSeq (NFData(..), NFData1(..)) import Streamly.Internal.Data.Array as A -- $setup -- >>> :m -- >>> :set -fno-warn-deprecations -- >>> :set -XFlexibleContexts -- >>> :set -package streamly -- >>> import Streamly.Prelude (SerialT) -- >>> import Streamly.Data.Array (Array) -- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream -- >>> import qualified Streamly.Data.Array as Array -- Orphan instances for backward compatibility -- Since this is an Unbox array we cannot have unevaluated data in it so -- this is just a no op. instance NFData (Array a) where {-# INLINE rnf #-} rnf :: Array a -> () rnf Array a _ = () instance NFData1 Array where liftRnf :: forall a. (a -> ()) -> Array a -> () liftRnf a -> () _ Array a _ = ()